From 7ce5f8ab6fb7c13f4954e33e21d5fcbef1ea472c Mon Sep 17 00:00:00 2001 From: Hileb <107909747+Ecdcaeb@users.noreply.github.com> Date: Thu, 2 May 2024 18:51:43 +0800 Subject: [PATCH 1/2] reborn idf --- gradle.properties | 10 +- .../somebody/idlframewok/IdlFramework.java | 150 +++ .../java/com/somebody/idlframewok/TODO.txt | 15 + .../idlframewok/blocks/BlockBase.java | 49 + .../idlframewok/blocks/BlockTeleporter.java | 26 + .../Furnitures/BlockExtractionDoorTest.java | 514 +++++++++ .../idlframewok/blocks/ModBlocks.java | 20 + .../blocks/blockBasic/BlockDeboomOrb.java | 56 + .../blocks/blockBasic/BlockGeneralOrb.java | 64 ++ .../blocks/blockBasic/BlockNullifyOrb.java | 64 ++ .../blocks/blockBasic/DivineOre.java | 40 + .../blocks/blockBasic/IdeallandLight.java | 41 + .../blocks/blockBasic/ModBlockGlassBase.java | 61 ++ .../blocks/blockBasic/PureOre.java | 33 + .../blocks/blockMisc/BlockArtifactHead.java | 237 +++++ .../blocks/blockMoroon/BlockMoroonBase.java | 11 + .../blocks/builder/BlockBuilderBase.java | 42 + .../blocks/builder/BlockBuilderOne.java | 32 + .../builder/TileEntityBuilderBase.java | 208 ++++ .../builder/TileEntityBuilderOne.java | 24 + .../builderAction/BuilderActionBase.java | 37 + .../builderAction/BuilderActionBlock.java | 73 ++ .../BuilderActionBlockBrutal.java | 68 ++ .../builderAction/BuilderActionBlockSafe.java | 69 ++ .../BuilderActionSummonEntity.java | 55 + .../tileEntity/orbs/TileEntityDeArrowOrb.java | 90 ++ .../tileEntity/orbs/TileEntityDeBoomOrb.java | 30 + .../orbs/TileEntityEarthMender.java | 112 ++ .../tileEntity/orbs/TileEntityNullifyOrb.java | 44 + .../orbs/TileEntityNullifyOrbMor.java | 40 + .../tileEntity/orbs/TileEntityOrbBase.java | 148 +++ .../command/CommandDimTeleport.java | 73 ++ .../idlframewok/command/ModCommands.java | 4 + .../enchantments/ModEnchantmentBase.java | 288 +++++ .../enchantments/ModEnchantmentInit.java | 119 +++ .../ModEnchantmentProtection.java | 16 + .../idlframewok/entity/BuildingCore.java | 179 ++++ .../idlframewok/entity/ModEntityInit.java | 51 + .../idlframewok/entity/RenderHandler.java | 19 + .../entity/creatures/EntityModUnit.java | 473 +++++++++ .../entity/creatures/ai/BulletMode.java | 7 + .../ai/EntityAIAttackRangedSniper.java | 14 + .../creatures/ai/EntityAIBulletAttack.java | 161 +++ .../ai/EntityAIStrafeRangedAttack.java | 197 ++++ .../creatures/ai/EntityAITurretAttack.java | 126 +++ .../creatures/ai/RangedAttackArguments.java | 11 + .../buildings/EntityIdlBuildingBase.java | 96 ++ .../buildings/EntityIdlBuildingRoom.java | 52 + .../EntityIdeallandUnitBase.java | 72 ++ .../creatures/misc/EntityEternalZombie.java | 35 + .../creatures/misc/EntityHiredSkeleton.java | 49 + .../creatures/misc/EntityTurretPrototype.java | 205 ++++ .../misc/EntityTurretPrototype2.java | 63 ++ .../entity/creatures/model/ModelCentaur.java | 114 ++ .../creatures/model/ModelIDLConstruction.java | 162 +++ .../creatures/model/ModelMoroonBeacon.java | 88 ++ .../creatures/model/ModelTurretPrototype.java | 72 ++ .../moroon/EntityMorBlindingAssassin.java | 173 +++ .../moroon/EntityMoroonFlickFighter.java | 161 +++ .../moroon/EntityMoroonGhostArcher.java | 209 ++++ .../moroon/EntityMoroonMindMage.java | 284 +++++ .../moroon/EntityMoroonStandardInfantry.java | 184 ++++ .../creatures/moroon/EntityMoroonTainter.java | 100 ++ .../moroon/EntityMoroonTideMaker.java | 116 ++ .../moroon/EntityMoroonUnitBase.java | 183 ++++ .../creatures/moroon/EntityMoroonVampire.java | 202 ++++ .../entity/creatures/render/RenderBullet.java | 67 ++ .../creatures/render/RenderConstruction.java | 29 + .../creatures/render/RenderModUnit.java | 42 + .../render/RenderMoroonHumanoid.java | 52 + .../entity/creatures/render/RenderTurret.java | 29 + .../creatures/render/RenderTurret2.java | 28 + .../projectiles/EntityIdlProjectile.java | 354 +++++++ .../entity/projectiles/ProjectileArgs.java | 38 + .../idlframewok/events/ModStarterEvents.java | 31 + .../idlframewok/gui/ModGuiElementLoader.java | 48 + .../idlframewok/gui/expOne/ContainerDemo.java | 193 ++++ .../gui/expOne/GuiContainerDemo.java | 134 +++ .../somebody/idlframewok/init/InitBiome.java | 29 + .../idlframewok/init/InitDimension.java | 10 + .../idlframewok/init/ModAchivements.java | 7 + .../idlframewok/init/ModAnvilEvents.java | 64 ++ .../somebody/idlframewok/init/ModConfig.java | 59 ++ .../idlframewok/init/ModCreativeTab.java | 18 + .../idlframewok/init/ModLootList.java | 61 ++ .../somebody/idlframewok/init/ModRecipes.java | 28 + .../somebody/idlframewok/init/ModSpawn.java | 103 ++ .../idlframewok/init/RegistryHandler.java | 95 ++ .../idlframewok/item/IGuaEnhance.java | 7 + .../idlframewok/item/ItemAdaptingBase.java | 119 +++ .../idlframewok/item/ItemArmorBase.java | 215 ++++ .../item/ItemArmorLivingMetalBase.java | 121 +++ .../idlframewok/item/ItemAxeBase.java | 170 +++ .../somebody/idlframewok/item/ItemBase.java | 230 ++++ .../somebody/idlframewok/item/ItemDebug.java | 136 +++ .../idlframewok/item/ItemHoeBase.java | 170 +++ .../idlframewok/item/ItemPickaxeBase.java | 170 +++ .../idlframewok/item/ItemSpadeBase.java | 170 +++ .../idlframewok/item/ItemSwordBase.java | 172 +++ .../somebody/idlframewok/item/ModItems.java | 74 ++ .../item/armorMaterials/ModArmorMaterial.java | 7 + .../item/consumables/ItemConsumableBase.java | 42 + .../item/consumables/ItemFightBread.java | 10 + .../item/consumables/ItemLevelUpBadge.java | 35 + .../item/consumables/ItemPowerUpModular.java | 87 ++ .../ItemPowerUpModularPercent.java | 87 ++ .../item/consumables/ItemRainCall.java | 39 + .../autoConsume/ItemAutoConsumeBase.java | 27 + .../autoConsume/ItemAutoConsumeHeal.java | 18 + .../idlframewok/item/food/ItemFoodBase.java | 156 +++ .../item/goblet/ItemDigGoblet.java | 93 ++ .../item/goblet/ItemFlameGoblet.java | 60 ++ .../item/goblet/ItemGobletBase.java | 147 +++ .../item/goblet/ItemHealGoblet.java | 59 ++ .../item/goblet/ItemKnockBackGoblet.java | 81 ++ .../item/goblet/ItemP2WGoblet.java | 9 + .../item/goblet/ItemWaterGoblet.java | 54 + .../item/misc/ItemAttrMeasure.java | 36 + .../item/misc/ItemBasicBinary.java | 24 + .../idlframewok/item/misc/ItemBasicGua.java | 24 + .../item/misc/ItemKinshipSword.java | 221 ++++ .../idlframewok/item/misc/ItemNanoMender.java | 42 + .../idlframewok/item/misc/ItemPackage.java | 57 + .../item/misc/ItemSpaceAnchor.java | 120 +++ .../idlframewok/item/misc/ItemSummon.java | 71 ++ .../item/misc/ItemSummonEternal.java | 42 + .../idlframewok/item/misc/ItemYiJianMei.java | 29 + .../misc/armor/ItemArmorUnderfootGeta.java | 140 +++ .../item/misc/armor/ItemArmorXieGeta.java | 186 ++++ .../idlframewok/item/potions/PotionBase.java | 25 + .../item/skills/ItemCreatureRadar.java | 172 +++ .../item/skills/ItemHateDetector.java | 103 ++ .../item/skills/ItemMirrorWork.java | 38 + .../item/skills/ItemSkillAquireItems.java | 36 + .../item/skills/ItemSkillAttackBoost.java | 54 + .../item/skills/ItemSkillBase.java | 344 ++++++ .../item/skills/ItemSkillBlessedArmor.java | 87 ++ .../item/skills/ItemSkillBulletStrike.java | 53 + .../item/skills/ItemSkillCloneBlock.java | 56 + .../item/skills/ItemSkillCloneEgg.java | 41 + .../item/skills/ItemSkillDecodeItem.java | 55 + .../ItemSkillExperienceDamageAbsorption.java | 102 ++ .../ItemSkillExperiencePrideShield.java | 92 ++ .../skills/ItemSkillExperienceStrike.java | 37 + .../item/skills/ItemSkillFireBall.java | 69 ++ .../item/skills/ItemSkillFireBlast.java | 65 ++ .../item/skills/ItemSkillGambit.java | 47 + .../item/skills/ItemSkillModListStrike.java | 55 + .../item/skills/ItemSkillRepairArmor.java | 86 ++ .../item/skills/ItemSkillSacrifce2020.java | 58 + .../item/skills/ItemSkillSheepTransform.java | 52 + .../item/skills/ItemSkillTauntNearby.java | 44 + .../skills/ItemSkillTauntNearbyToGiven.java | 44 + .../item/skills/ItemSkillThunderFall.java | 100 ++ .../item/skills/ItemSkillTimeCutFixed.java | 61 ++ .../item/skills/ItemSkillTimeCutPercent.java | 60 ++ .../item/skills/ItemSkillVanquishWeak.java | 34 + .../item/skills/ItemSkillWindWalk.java | 51 + .../arknights/ItemArknightsSkillBase.java | 238 +++++ .../skills/arknights/ItemSkillTrueSL.java | 164 +++ .../arrowrain/ItemSkillArrowRainBase.java | 75 ++ .../item/skills/martial/BuffTuple.java | 12 + .../item/skills/martial/ItemSkillGuaPalm.java | 211 ++++ .../martial/ItemSkillMartialAttack.java | 106 ++ .../item/weapon/ItemEtherealSword.java | 67 ++ .../item/weapon/ItemHealingGun.java | 92 ++ .../item/weapon/ItemPistolBase.java | 89 ++ .../item/weapon/ItemSmashShield.java | 115 ++ .../idlframewok/keys/KeyboardManager.java | 61 ++ .../idlframewok/keys/ModKeyBinding.java | 15 + .../somebody/idlframewok/meta/MetaUtil.java | 46 + .../idlframewok/network/NetworkHandler.java | 32 + .../network/protocols/PacketTest.java | 68 ++ .../idlframewok/potion/EffectTuple.java | 37 + .../idlframewok/potion/ModPotions.java | 46 + .../potion/PotionEventHandler.java | 245 +++++ .../idlframewok/potion/buff/BasePotion.java | 173 +++ .../potion/buff/BaseSimplePotion.java | 62 ++ .../potion/buff/PotionBlastResist.java | 48 + .../idlframewok/potion/buff/PotionDeadly.java | 18 + .../potion/buff/PotionErosion.java | 34 + .../potion/buff/PotionInsidiousDisease.java | 51 + .../potion/buff/PotionMagicResist.java | 46 + .../potion/buff/PotionUndying.java | 36 + .../potion/buff/PotionZenHeart.java | 7 + .../idlframewok/proxy/ClientProxy.java | 25 + .../somebody/idlframewok/proxy/ProxyBase.java | 14 + .../idlframewok/proxy/ServerProxy.java | 8 + .../idlframewok/recipe/special/BasicGua8.java | 94 ++ .../recipe/special/GobletDigBlockAssign.java | 104 ++ .../recipe/special/GobletFill.java | 102 ++ .../recipe/special/GuaEnhanceByCrafting.java | 122 +++ .../recipe/special/SkillUpgrade.java | 117 +++ .../somebody/idlframewok/util/AchvDef.java | 9 + .../somebody/idlframewok/util/CommonDef.java | 56 + .../idlframewok/util/CommonFunctions.java | 342 ++++++ .../somebody/idlframewok/util/EntityUtil.java | 591 +++++++++++ .../somebody/idlframewok/util/IDLGeneral.java | 47 + .../com/somebody/idlframewok/util/IDLNBT.java | 164 +++ .../idlframewok/util/IDLSkillNBT.java | 322 ++++++ .../somebody/idlframewok/util/IHasModel.java | 5 + .../somebody/idlframewok/util/MessageDef.java | 17 + .../idlframewok/util/ModSoundHandler.java | 25 + .../idlframewok/util/NBTStrDef/IDLNBTDef.java | 164 +++ .../util/NBTStrDef/IDLNBTUtil.java | 558 ++++++++++ .../somebody/idlframewok/util/PlayerUtil.java | 80 ++ .../somebody/idlframewok/util/Reference.java | 10 + .../somebody/idlframewok/util/StringUtil.java | 10 + .../somebody/idlframewok/util/Teleport.java | 52 + .../idlframewok/util/sound/ModSoundEvent.java | 14 + .../world/biome/BiomeForDimOne.java | 43 + .../idlframewok/world/biome/BiomeOne.java | 44 + .../world/dimension/DimensionOne.java | 37 + .../hexcube/ChunkGeneratorHexCube16.java | 390 +++++++ .../dimension/hexcube/HexCubeHelper.java | 48 + .../hexcube/structure/GenCubeBase.java | 58 + .../hexcube/structure/GenCubeSoilRoom.java | 54 + .../hexcube/structure/GenCubeTorchRoom.java | 57 + .../hexcube/structure/GenCubeTreasure.java | 63 ++ .../hexcube/structure/GenCubeWoodRoom.java | 49 + .../world/structure/ModGenStructure.java | 215 ++++ .../world/structure/TestStructurePieces.java | 989 ++++++++++++++++++ .../world/tree/WorldGenTestTree.java | 19 + .../world/types/WorldTypeCustom.java | 23 + .../idlframewok/world/types/WorldTypeOne.java | 25 + .../world/types/layer/GenLayerCustom.java | 139 +++ .../idlframewok/worldgen/ModWorldGenNew.java | 109 ++ .../idlframewok/worldgen/ModWorldGenOld.java | 52 + .../java/mods/somebody/example/Example.java | 16 - .../idlframework/blockstates/backup.json | 12 + .../idlframework/blockstates/block_fence.json | 5 + .../blockstates/builder_farm.json | 5 + .../blockstates/builder_farm_sin.json | 5 + .../blockstates/builder_house.json | 5 + .../idlframework/blockstates/builder_one.json | 5 + .../blockstates/building_zabeen_site.json | 5 + .../blockstates/construction_site.json | 5 + .../blockstates/de_arrow_orb.json | 5 + .../idlframework/blockstates/de_boom_orb.json | 5 + .../blockstates/de_water_orb.json | 5 + .../idlframework/blockstates/divine_ore.json | 5 + .../blockstates/earth_mender_basic.json | 5 + .../idlframework/blockstates/fence_brick.json | 5 + .../idlframework/blockstates/grid_dark_2.json | 5 + .../idlframework/blockstates/grid_lamp.json | 5 + .../idlframework/blockstates/grid_normal.json | 5 + .../idealland_extraction_door.json | 20 + .../blockstates/idealland_light_basic.json | 5 + .../idlframework/blockstates/idl_glass.json | 5 + .../blockstates/moroon_block.json | 5 + .../idlframework/blockstates/nullify_orb.json | 5 + .../blockstates/nullify_orb_mor.json | 5 + .../idlframework/blockstates/pure_ore.json | 5 + .../assets/idlframework/blockstates/test.json | 5 + .../assets/idlframework/lang/en_us.lang | 83 ++ .../assets/idlframework/lang/zh_cn.lang | 67 ++ .../chests/abandoned_mineshaft.json | 276 +++++ .../assets/idlframework/loot_table/empty.json | 1 + .../entities/mor_orbital_beacon.json | 30 + .../models/block/construction_site.json | 6 + .../idlframework/models/item/skill_base.json | 5 + .../assets/idlframework/recipes/emp_site.json | 32 + .../idlframework/recipes/matter_original.json | 32 + .../resources/assets/idlframework/sounds.json | 14 + .../sounds/entity/moroon/ambient.ogg | Bin 0 -> 15382 bytes .../sounds/entity/moroon/hurt.ogg | Bin 0 -> 15382 bytes .../textures/blocks/builder_farm.png | Bin 0 -> 1589 bytes .../idlframework/textures/blocks/test.png | Bin 0 -> 232 bytes .../idlframework/textures/entity/centaur.png | Bin 0 -> 7042 bytes .../textures/entity/moroon_humanoid.png | Bin 0 -> 4675 bytes .../entity/projectiles/bullet_mor.png | Bin 0 -> 4925 bytes .../entity/projectiles/bullet_norm.png | Bin 0 -> 5136 bytes .../textures/gui/container/gui_demo.png | Bin 0 -> 1627 bytes .../textures/gui/container/gui_research.png | Bin 0 -> 4739 bytes .../textures/gui/container/test_gui.png | Bin 0 -> 115212 bytes .../textures/items/basic/gua_0.png | Bin 0 -> 898 bytes .../textures/items/basic/gua_1.png | Bin 0 -> 1280 bytes .../textures/items/basic/gua_2.png | Bin 0 -> 1594 bytes .../textures/items/basic/gua_3.png | Bin 0 -> 1175 bytes .../textures/items/basic/gua_4.png | Bin 0 -> 1278 bytes .../textures/items/basic/gua_5.png | Bin 0 -> 1276 bytes .../textures/items/basic/gua_6.png | Bin 0 -> 928 bytes .../textures/items/basic/gua_7.png | Bin 0 -> 930 bytes .../textures/items/basic/matter_original.png | Bin 0 -> 4663 bytes .../textures/items/basic/yang_sign.png | Bin 0 -> 1898 bytes .../textures/items/basic/yin_sign.png | Bin 0 -> 1902 bytes .../textures/items/builder/build_blank.png | Bin 0 -> 3283 bytes .../textures/items/misc/blood_iron_ingot.png | Bin 0 -> 3050 bytes .../textures/items/misc/war_bread.png | Bin 0 -> 1847 bytes .../textures/items/misc/water_caster.png | Bin 0 -> 2269 bytes .../textures/items/skill/skill_base.png | Bin 0 -> 2415 bytes .../textures/items/weapon/healing_gun.png | Bin 0 -> 3382 bytes .../idlframework/textures/misc/potions.png | Bin 0 -> 12101 bytes .../models/armor/armor_qsh_layer_1.png | Bin 0 -> 5873 bytes .../models/armor/armor_qsh_layer_2.png | Bin 0 -> 5170 bytes 295 files changed, 22566 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/somebody/idlframewok/IdlFramework.java create mode 100644 src/main/java/com/somebody/idlframewok/TODO.txt create mode 100644 src/main/java/com/somebody/idlframewok/blocks/BlockBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/BlockTeleporter.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/Furnitures/BlockExtractionDoorTest.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/ModBlocks.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockDeboomOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockGeneralOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockNullifyOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/DivineOre.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/IdeallandLight.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/ModBlockGlassBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockBasic/PureOre.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockMisc/BlockArtifactHead.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/blockMoroon/BlockMoroonBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderOne.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderOne.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBase.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlock.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockBrutal.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockSafe.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionSummonEntity.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeArrowOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeBoomOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityEarthMender.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrb.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrbMor.java create mode 100644 src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityOrbBase.java create mode 100644 src/main/java/com/somebody/idlframewok/command/CommandDimTeleport.java create mode 100644 src/main/java/com/somebody/idlframewok/command/ModCommands.java create mode 100644 src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentBase.java create mode 100644 src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentInit.java create mode 100644 src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentProtection.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/BuildingCore.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/ModEntityInit.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/RenderHandler.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/EntityModUnit.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/BulletMode.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIAttackRangedSniper.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIBulletAttack.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIStrafeRangedAttack.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAITurretAttack.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ai/RangedAttackArguments.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingBase.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingRoom.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/ideallandTeam/EntityIdeallandUnitBase.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityEternalZombie.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityHiredSkeleton.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype2.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelCentaur.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelIDLConstruction.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelMoroonBeacon.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelTurretPrototype.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMorBlindingAssassin.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonFlickFighter.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonGhostArcher.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonMindMage.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonStandardInfantry.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTainter.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTideMaker.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonUnitBase.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonVampire.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderBullet.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderConstruction.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderModUnit.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderMoroonHumanoid.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret2.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/projectiles/EntityIdlProjectile.java create mode 100644 src/main/java/com/somebody/idlframewok/entity/projectiles/ProjectileArgs.java create mode 100644 src/main/java/com/somebody/idlframewok/events/ModStarterEvents.java create mode 100644 src/main/java/com/somebody/idlframewok/gui/ModGuiElementLoader.java create mode 100644 src/main/java/com/somebody/idlframewok/gui/expOne/ContainerDemo.java create mode 100644 src/main/java/com/somebody/idlframewok/gui/expOne/GuiContainerDemo.java create mode 100644 src/main/java/com/somebody/idlframewok/init/InitBiome.java create mode 100644 src/main/java/com/somebody/idlframewok/init/InitDimension.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModAchivements.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModAnvilEvents.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModConfig.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModCreativeTab.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModLootList.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModRecipes.java create mode 100644 src/main/java/com/somebody/idlframewok/init/ModSpawn.java create mode 100644 src/main/java/com/somebody/idlframewok/init/RegistryHandler.java create mode 100644 src/main/java/com/somebody/idlframewok/item/IGuaEnhance.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemAdaptingBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemArmorBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemArmorLivingMetalBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemAxeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemDebug.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemHoeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemPickaxeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemSpadeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ItemSwordBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/ModItems.java create mode 100644 src/main/java/com/somebody/idlframewok/item/armorMaterials/ModArmorMaterial.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemConsumableBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemFightBread.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemLevelUpBadge.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModular.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModularPercent.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/ItemRainCall.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeHeal.java create mode 100644 src/main/java/com/somebody/idlframewok/item/food/ItemFoodBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemDigGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemFlameGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemGobletBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemHealGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemKnockBackGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemP2WGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/goblet/ItemWaterGoblet.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemAttrMeasure.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemBasicBinary.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemBasicGua.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemKinshipSword.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemNanoMender.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemPackage.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemSpaceAnchor.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemSummon.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemSummonEternal.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/ItemYiJianMei.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorUnderfootGeta.java create mode 100644 src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorXieGeta.java create mode 100644 src/main/java/com/somebody/idlframewok/item/potions/PotionBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemCreatureRadar.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemHateDetector.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemMirrorWork.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAquireItems.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAttackBoost.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBlessedArmor.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBulletStrike.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneBlock.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneEgg.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillDecodeItem.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceDamageAbsorption.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperiencePrideShield.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceStrike.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBall.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBlast.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillGambit.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillModListStrike.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillRepairArmor.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSacrifce2020.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSheepTransform.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearby.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearbyToGiven.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillThunderFall.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutFixed.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutPercent.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillVanquishWeak.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/ItemSkillWindWalk.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemArknightsSkillBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemSkillTrueSL.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/arrowrain/ItemSkillArrowRainBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/martial/BuffTuple.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillGuaPalm.java create mode 100644 src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillMartialAttack.java create mode 100644 src/main/java/com/somebody/idlframewok/item/weapon/ItemEtherealSword.java create mode 100644 src/main/java/com/somebody/idlframewok/item/weapon/ItemHealingGun.java create mode 100644 src/main/java/com/somebody/idlframewok/item/weapon/ItemPistolBase.java create mode 100644 src/main/java/com/somebody/idlframewok/item/weapon/ItemSmashShield.java create mode 100644 src/main/java/com/somebody/idlframewok/keys/KeyboardManager.java create mode 100644 src/main/java/com/somebody/idlframewok/keys/ModKeyBinding.java create mode 100644 src/main/java/com/somebody/idlframewok/meta/MetaUtil.java create mode 100644 src/main/java/com/somebody/idlframewok/network/NetworkHandler.java create mode 100644 src/main/java/com/somebody/idlframewok/network/protocols/PacketTest.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/EffectTuple.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/ModPotions.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/PotionEventHandler.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/BasePotion.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/BaseSimplePotion.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionBlastResist.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionDeadly.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionErosion.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionInsidiousDisease.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionMagicResist.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionUndying.java create mode 100644 src/main/java/com/somebody/idlframewok/potion/buff/PotionZenHeart.java create mode 100644 src/main/java/com/somebody/idlframewok/proxy/ClientProxy.java create mode 100644 src/main/java/com/somebody/idlframewok/proxy/ProxyBase.java create mode 100644 src/main/java/com/somebody/idlframewok/proxy/ServerProxy.java create mode 100644 src/main/java/com/somebody/idlframewok/recipe/special/BasicGua8.java create mode 100644 src/main/java/com/somebody/idlframewok/recipe/special/GobletDigBlockAssign.java create mode 100644 src/main/java/com/somebody/idlframewok/recipe/special/GobletFill.java create mode 100644 src/main/java/com/somebody/idlframewok/recipe/special/GuaEnhanceByCrafting.java create mode 100644 src/main/java/com/somebody/idlframewok/recipe/special/SkillUpgrade.java create mode 100644 src/main/java/com/somebody/idlframewok/util/AchvDef.java create mode 100644 src/main/java/com/somebody/idlframewok/util/CommonDef.java create mode 100644 src/main/java/com/somebody/idlframewok/util/CommonFunctions.java create mode 100644 src/main/java/com/somebody/idlframewok/util/EntityUtil.java create mode 100644 src/main/java/com/somebody/idlframewok/util/IDLGeneral.java create mode 100644 src/main/java/com/somebody/idlframewok/util/IDLNBT.java create mode 100644 src/main/java/com/somebody/idlframewok/util/IDLSkillNBT.java create mode 100644 src/main/java/com/somebody/idlframewok/util/IHasModel.java create mode 100644 src/main/java/com/somebody/idlframewok/util/MessageDef.java create mode 100644 src/main/java/com/somebody/idlframewok/util/ModSoundHandler.java create mode 100644 src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTDef.java create mode 100644 src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTUtil.java create mode 100644 src/main/java/com/somebody/idlframewok/util/PlayerUtil.java create mode 100644 src/main/java/com/somebody/idlframewok/util/Reference.java create mode 100644 src/main/java/com/somebody/idlframewok/util/StringUtil.java create mode 100644 src/main/java/com/somebody/idlframewok/util/Teleport.java create mode 100644 src/main/java/com/somebody/idlframewok/util/sound/ModSoundEvent.java create mode 100644 src/main/java/com/somebody/idlframewok/world/biome/BiomeForDimOne.java create mode 100644 src/main/java/com/somebody/idlframewok/world/biome/BiomeOne.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/DimensionOne.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/ChunkGeneratorHexCube16.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/HexCubeHelper.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeBase.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeSoilRoom.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTorchRoom.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTreasure.java create mode 100644 src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeWoodRoom.java create mode 100644 src/main/java/com/somebody/idlframewok/world/structure/ModGenStructure.java create mode 100644 src/main/java/com/somebody/idlframewok/world/structure/TestStructurePieces.java create mode 100644 src/main/java/com/somebody/idlframewok/world/tree/WorldGenTestTree.java create mode 100644 src/main/java/com/somebody/idlframewok/world/types/WorldTypeCustom.java create mode 100644 src/main/java/com/somebody/idlframewok/world/types/WorldTypeOne.java create mode 100644 src/main/java/com/somebody/idlframewok/world/types/layer/GenLayerCustom.java create mode 100644 src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenNew.java create mode 100644 src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenOld.java delete mode 100644 src/main/java/mods/somebody/example/Example.java create mode 100644 src/main/resources/assets/idlframework/blockstates/backup.json create mode 100644 src/main/resources/assets/idlframework/blockstates/block_fence.json create mode 100644 src/main/resources/assets/idlframework/blockstates/builder_farm.json create mode 100644 src/main/resources/assets/idlframework/blockstates/builder_farm_sin.json create mode 100644 src/main/resources/assets/idlframework/blockstates/builder_house.json create mode 100644 src/main/resources/assets/idlframework/blockstates/builder_one.json create mode 100644 src/main/resources/assets/idlframework/blockstates/building_zabeen_site.json create mode 100644 src/main/resources/assets/idlframework/blockstates/construction_site.json create mode 100644 src/main/resources/assets/idlframework/blockstates/de_arrow_orb.json create mode 100644 src/main/resources/assets/idlframework/blockstates/de_boom_orb.json create mode 100644 src/main/resources/assets/idlframework/blockstates/de_water_orb.json create mode 100644 src/main/resources/assets/idlframework/blockstates/divine_ore.json create mode 100644 src/main/resources/assets/idlframework/blockstates/earth_mender_basic.json create mode 100644 src/main/resources/assets/idlframework/blockstates/fence_brick.json create mode 100644 src/main/resources/assets/idlframework/blockstates/grid_dark_2.json create mode 100644 src/main/resources/assets/idlframework/blockstates/grid_lamp.json create mode 100644 src/main/resources/assets/idlframework/blockstates/grid_normal.json create mode 100644 src/main/resources/assets/idlframework/blockstates/idealland_extraction_door.json create mode 100644 src/main/resources/assets/idlframework/blockstates/idealland_light_basic.json create mode 100644 src/main/resources/assets/idlframework/blockstates/idl_glass.json create mode 100644 src/main/resources/assets/idlframework/blockstates/moroon_block.json create mode 100644 src/main/resources/assets/idlframework/blockstates/nullify_orb.json create mode 100644 src/main/resources/assets/idlframework/blockstates/nullify_orb_mor.json create mode 100644 src/main/resources/assets/idlframework/blockstates/pure_ore.json create mode 100644 src/main/resources/assets/idlframework/blockstates/test.json create mode 100644 src/main/resources/assets/idlframework/lang/en_us.lang create mode 100644 src/main/resources/assets/idlframework/lang/zh_cn.lang create mode 100644 src/main/resources/assets/idlframework/loot_table/chests/abandoned_mineshaft.json create mode 100644 src/main/resources/assets/idlframework/loot_table/empty.json create mode 100644 src/main/resources/assets/idlframework/loot_table/entities/mor_orbital_beacon.json create mode 100644 src/main/resources/assets/idlframework/models/block/construction_site.json create mode 100644 src/main/resources/assets/idlframework/models/item/skill_base.json create mode 100644 src/main/resources/assets/idlframework/recipes/emp_site.json create mode 100644 src/main/resources/assets/idlframework/recipes/matter_original.json create mode 100644 src/main/resources/assets/idlframework/sounds.json create mode 100644 src/main/resources/assets/idlframework/sounds/entity/moroon/ambient.ogg create mode 100644 src/main/resources/assets/idlframework/sounds/entity/moroon/hurt.ogg create mode 100644 src/main/resources/assets/idlframework/textures/blocks/builder_farm.png create mode 100644 src/main/resources/assets/idlframework/textures/blocks/test.png create mode 100644 src/main/resources/assets/idlframework/textures/entity/centaur.png create mode 100644 src/main/resources/assets/idlframework/textures/entity/moroon_humanoid.png create mode 100644 src/main/resources/assets/idlframework/textures/entity/projectiles/bullet_mor.png create mode 100644 src/main/resources/assets/idlframework/textures/entity/projectiles/bullet_norm.png create mode 100644 src/main/resources/assets/idlframework/textures/gui/container/gui_demo.png create mode 100644 src/main/resources/assets/idlframework/textures/gui/container/gui_research.png create mode 100644 src/main/resources/assets/idlframework/textures/gui/container/test_gui.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_0.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_1.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_2.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_3.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_4.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_5.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_6.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/gua_7.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/matter_original.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/yang_sign.png create mode 100644 src/main/resources/assets/idlframework/textures/items/basic/yin_sign.png create mode 100644 src/main/resources/assets/idlframework/textures/items/builder/build_blank.png create mode 100644 src/main/resources/assets/idlframework/textures/items/misc/blood_iron_ingot.png create mode 100644 src/main/resources/assets/idlframework/textures/items/misc/war_bread.png create mode 100644 src/main/resources/assets/idlframework/textures/items/misc/water_caster.png create mode 100644 src/main/resources/assets/idlframework/textures/items/skill/skill_base.png create mode 100644 src/main/resources/assets/idlframework/textures/items/weapon/healing_gun.png create mode 100644 src/main/resources/assets/idlframework/textures/misc/potions.png create mode 100644 src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_1.png create mode 100644 src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_2.png diff --git a/gradle.properties b/gradle.properties index 7979536..3fb1c11 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,17 +5,17 @@ cleanroom_version=15.24.0.3029 # Mod Information # HIGHLY RECOMMEND complying with SemVer for mod_version: https://semver.org/ mod_version=1.0.0 -root_package=com.example -mod_id=modid +root_package=com.somebody.idlframewok +mod_id=idlframewok mod_name=Mod Name # Mod Metadata (Optional) mod_description= -mod_url= +mod_url=https://www.mcmod.cn/class/2421.html mod_update_json= # Delimit authors with commas -mod_authors= -mod_credits= +mod_authors=somebody +mod_credits=Idealland - they provided this framework. mod_logo_path= # Mapping Properties diff --git a/src/main/java/com/somebody/idlframewok/IdlFramework.java b/src/main/java/com/somebody/idlframewok/IdlFramework.java new file mode 100644 index 0000000..b824ae8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/IdlFramework.java @@ -0,0 +1,150 @@ +package com.somebody.idlframewok; + +import com.somebody.idlframewok.gui.ModGuiElementLoader; +import com.somebody.idlframewok.init.ModConfig; +import com.somebody.idlframewok.init.ModRecipes; +import com.somebody.idlframewok.init.ModSpawn; +import com.somebody.idlframewok.init.RegistryHandler; +import com.somebody.idlframewok.keys.KeyboardManager; +import com.somebody.idlframewok.meta.MetaUtil; +import com.somebody.idlframewok.network.NetworkHandler; +import com.somebody.idlframewok.proxy.ProxyBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.Reference; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import org.apache.logging.log4j.Logger; + +//To let the player be a traveling god who plays yin-yang magic. + +@Mod(modid = IdlFramework.MODID, name = IdlFramework.NAME, version = IdlFramework.VERSION)//dependencies = "required-after:Forge@[14.23.5.2705,)" +public class IdlFramework { + public static final String MODID = "untitled"; + public static final String NAME = "IdlFramework"; + public static final String VERSION = "0.1.101"; + + public static Logger logger; + + public static final boolean SHOW_WARN = true; + + @Mod.Instance + public static IdlFramework instance; + + @SidedProxy(clientSide = Reference.CLIENT_PROXY_CLASS, serverSide = Reference.SERVER_PROXY_CLASS) + public static ProxyBase proxy; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) { + logger = event.getModLog(); + + if (MODID.equals("untitled")) + { + logger.error("Please change your mod id in the main class."); + + } + + if (Reference.CLIENT_PROXY_CLASS.indexOf("somebody.idlframewok.proxy.ClientProxy") > 0) + { + logger.warn("Have you changed your package name to author and modname?"); + + } + + RegistryHandler.preInitRegistries(event); + + } + + @EventHandler + public static void Init(FMLInitializationEvent event) { + ModRecipes.Init(); + RegisterTileEntity(); + RegistryHandler.initRegistries(event); + new ModGuiElementLoader(); + if (!proxy.isServer()) + { + KeyboardManager.init(); + } + NetworkHandler.init(); + + LogWarning("%s has finished its initializations", MODID); + + } + + @EventHandler + public void postInit(FMLPostInitializationEvent event) { + // Moved Spawning registry to last since forge doesn't auto-generate sub + // "M' biomes until late + if (ModConfig.SPAWN_CONF.SPAWN) { + ModSpawn.registerSpawnList(); + } + + MetaUtil.isIDLLoaded = Loader.isModLoaded("idealland"); + MetaUtil.isIRRLoaded = Loader.isModLoaded("itemrender"); + MetaUtil.isLoaded_TiC = Loader.isModLoaded("tconstruct"); + MetaUtil.isLoaded_Slashblade = Loader.isModLoaded("flammpfeil.slashblade"); + MetaUtil.isLoaded_Botania = Loader.isModLoaded("botania"); + MetaUtil.isLoaded_DWeapon = Loader.isModLoaded("dweapon"); + MetaUtil.isLoaded_AOA3 = Loader.isModLoaded(CommonDef.MOD_NAME_AOA3); + MetaUtil.isLoaded_GC = Loader.isModLoaded("galacticraftcore"); + MetaUtil.isLoaded_Taoism = Loader.isModLoaded("taoism"); + MetaUtil.isLoaded_GOG = Loader.isModLoaded(CommonDef.MOD_NAME_GOG); + + TrashTalking(); + + RegistryHandler.postInitReg(); + } + + @EventHandler + public static void serverInit(FMLServerStartingEvent event) { + RegistryHandler.serverRegistries(event); + } + + + private void TrashTalking() { + if (MetaUtil.isIDLLoaded) + { + IdlFramework.Log("[Idealland Framework] Bow to Idealland."); + } + else { + IdlFramework.Log("[Idealland Framework] Made with Idealland Framework."); + } + } + + private static void RegisterTileEntity() { +// GameRegistry.registerTileEntity(TileEntityDeBoomOrb.class, new ResourceLocation(MODID, "deboom_orb_basic")); + + //GameRegistry.registerTileEntity(TileEntityBuilderFarm.class, new ResourceLocation(MODID, "builder_farm_basic")); + //GameRegistry.registerTileEntity(TileEntityBuilderOne.class, new ResourceLocation(MODID, "builder.builder_one")); + } + + public static void LogWarning(String str, Object... args) { + if (SHOW_WARN) { + logger.warn(String.format(str, args)); + } + } + + public static void LogWarning(String str) { + if (SHOW_WARN) { + logger.warn(str); + } + } + + public static void Log(String str) { +// if (ModConfig.GeneralConf.LOG_ON) +// { + logger.info(str); +// } + } + + public static void Log(String str, Object... args) { +// if (ModConfig.GeneralConf.LOG_ON) +// { + logger.info(String.format(str, args)); +// } + } +} \ No newline at end of file diff --git a/src/main/java/com/somebody/idlframewok/TODO.txt b/src/main/java/com/somebody/idlframewok/TODO.txt new file mode 100644 index 0000000..f930f04 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/TODO.txt @@ -0,0 +1,15 @@ +plans: +buff: +[shield A]: absorbs damage. for each damage absorbed, -1s. +[shield B]: (Darker Protection) absorbs damage, revenges attacker, try create explosion +[Explosion Proof] +[Arrow Proof]* only arrows, or other bullets +[melee proof] +[nullified/phased]deal and receive no melee damage + +[void touch]all damage is void damage. + +[Berserk]Damage dealt and receive is increaed by Lv * 10% +--crtical +[Crit% Up/Down] +[Crit% Dmg Up/Down] \ No newline at end of file diff --git a/src/main/java/com/somebody/idlframewok/blocks/BlockBase.java b/src/main/java/com/somebody/idlframewok/blocks/BlockBase.java new file mode 100644 index 0000000..b6491a6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/BlockBase.java @@ -0,0 +1,49 @@ +package com.somebody.idlframewok.blocks; + +import java.util.Random; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.item.ModItems; +import com.somebody.idlframewok.util.IHasModel; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; + +public class BlockBase extends Block implements IHasModel +{ + public BlockBase(String name, Material material) + { + super(material); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC);; + + ModBlocks.BLOCKS.add(this); + ModItems.ITEMS.add(new ItemBlock(this).setRegistryName(this.getRegistryName())); + + setHardness(5.0F); + //setResistance(1000.0F); + //setHarvestLevel("pickaxe", 1); + //setLightLevel(1f); + setLightOpacity(1); + } + + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { + return super.quantityDropped(rand); + } + + @Override + public void registerModels() { + IdlFramework.proxy.registerItemRenderer(Item.getItemFromBlock(this), 0, "inventory"); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/BlockTeleporter.java b/src/main/java/com/somebody/idlframewok/blocks/BlockTeleporter.java new file mode 100644 index 0000000..cb8b127 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/BlockTeleporter.java @@ -0,0 +1,26 @@ +package com.somebody.idlframewok.blocks; + +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BlockTeleporter extends BlockBase { + public BlockTeleporter(String name, Material material) { + super(name, material); + } + + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + if (!worldIn.isRemote) { +// Teleport.teleportToDim(playerIn, ModConfig.DEBUG_CONF.DIM_ONE_ID, playerIn.getPosition().getX(), +// playerIn.posY + 5, playerIn.posZ); + return true; + } + + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/Furnitures/BlockExtractionDoorTest.java b/src/main/java/com/somebody/idlframewok/blocks/Furnitures/BlockExtractionDoorTest.java new file mode 100644 index 0000000..95bbc64 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/Furnitures/BlockExtractionDoorTest.java @@ -0,0 +1,514 @@ +package com.somebody.idlframewok.blocks.Furnitures; + +import java.util.Random; +import javax.annotation.Nullable; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockExtractionDoorTest extends BlockBase { + public BlockExtractionDoorTest(String name, Material material) + { + super(name, material); + setSoundType(SoundType.STONE); + setHardness(5.0F); + setResistance(35.0F); + setLightOpacity(1); + + this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.NORTH).withProperty(POWERED, Boolean.valueOf(false))); + this.setCreativeTab(ModCreativeTab.IDL_MISC); + } + + public static final PropertyEnum FACING = PropertyEnum.create("facing", BlockExtractionDoorTest.EnumOrientation.class); + public static final PropertyBool POWERED = PropertyBool.create("powered"); + protected static final AxisAlignedBB LEVER_NORTH_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB LEVER_SOUTH_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB LEVER_WEST_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB LEVER_EAST_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB LEVER_UP_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB LEVER_DOWN_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + + protected static final AxisAlignedBB OPENED_LEVER_NORTH_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB OPENED_LEVER_SOUTH_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB OPENED_LEVER_WEST_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB OPENED_LEVER_EAST_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB OPENED_LEVER_UP_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + protected static final AxisAlignedBB OPENED_LEVER_DOWN_AABB = new AxisAlignedBB(0D,0D,0D,1D,1D,1D); + + + @Deprecated + @Nullable + public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) + { + if (blockState.getValue(POWERED)) { + return null; + } + else + { + return blockState.getBoundingBox(worldIn, pos); + } + } + + /** + * Used to determine ambient occlusion and culling when rebuilding chunks for render + */ + public boolean isOpaqueCube(IBlockState state) + { + return !state.getValue(POWERED); + } + + public boolean isFullCube(IBlockState state) + { + return !state.getValue(POWERED); + } + + public boolean causesSuffocation(IBlockState state) + { + return false; + } + + /** + * Check whether this Block can be placed at pos, while aiming at the specified side of an adjacent block + */ + public boolean canPlaceBlockOnSide(World worldIn, BlockPos pos, EnumFacing side) + { + return canAttachTo(worldIn, pos, side); + } + + /** + * Checks if this block can be placed exactly at the given position. + */ + public boolean canPlaceBlockAt(World worldIn, BlockPos pos) + { + for (EnumFacing enumfacing : EnumFacing.values()) + { + if (canAttachTo(worldIn, pos, enumfacing)) + { + return true; + } + } + + return false; + } + + protected static boolean canAttachTo(World worldIn, BlockPos p_181090_1_, EnumFacing p_181090_2_) + { + return true; + } + + /** + * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the + * IBlockstate + */ + public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) + { + IBlockState iblockstate = this.getDefaultState().withProperty(POWERED, Boolean.valueOf(false)); + + if (canAttachTo(worldIn, pos, facing)) + { + return iblockstate.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.forFacings(facing, placer.getHorizontalFacing())); + } + else + { + for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) + { + if (enumfacing != facing && canAttachTo(worldIn, pos, enumfacing)) + { + return iblockstate.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.forFacings(enumfacing, placer.getHorizontalFacing())); + } + } + + if (worldIn.getBlockState(pos.down()).isTopSolid()) + { + return iblockstate.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.forFacings(EnumFacing.UP, placer.getHorizontalFacing())); + } + else + { + return iblockstate; + } + } + } + + /** + * Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor + * change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid + * block, etc. + */ + public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) + { + if (this.checkCanSurvive(worldIn, pos, state) && !canAttachTo(worldIn, pos, state.getValue(FACING).getFacing())) + { + this.dropBlockAsItem(worldIn, pos, state, 0); + worldIn.setBlockToAir(pos); + } + } + + private boolean checkCanSurvive(World worldIn, BlockPos pos, IBlockState state) + { + if (this.canPlaceBlockAt(worldIn, pos)) + { + return true; + } + else + { + this.dropBlockAsItem(worldIn, pos, state, 0); + worldIn.setBlockToAir(pos); + return false; + } + } + + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) + { + switch (state.getValue(FACING)) + { + case EAST: + default: + return LEVER_EAST_AABB; + case WEST: + return LEVER_WEST_AABB; + case SOUTH: + return LEVER_SOUTH_AABB; + case NORTH: + return LEVER_NORTH_AABB; + case UP_Z: + case UP_X: + return LEVER_UP_AABB; + case DOWN_X: + case DOWN_Z: + return LEVER_DOWN_AABB; + } + } + + /** + * Called when the block is right clicked by a player. + */ + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) + { + if (worldIn.isRemote) + { + return true; + } + else + { + Toggle(worldIn, state, pos); + float f = state.getValue(POWERED) ? 0.6F : 0.5F; + worldIn.playSound(null, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 0.3F, f); + + OnNotifySync(worldIn, pos.add(1,0,0), !state.getValue(POWERED)); + OnNotifySync(worldIn, pos.add(-1,0,0), !state.getValue(POWERED)); + OnNotifySync(worldIn, pos.add(0,1,0), !state.getValue(POWERED)); + OnNotifySync(worldIn, pos.add(0,-1,0), !state.getValue(POWERED)); + OnNotifySync(worldIn, pos.add(0,0,1), !state.getValue(POWERED)); + OnNotifySync(worldIn, pos.add(0,0,-1), !state.getValue(POWERED)); + return true; + } + } + + public void Toggle(World worldIn, IBlockState state,BlockPos pos) + { + state = state.cycleProperty(POWERED); + worldIn.setBlockState(pos, state, 3); + worldIn.notifyNeighborsOfStateChange(pos, this, false); + EnumFacing enumfacing = state.getValue(FACING).getFacing(); + worldIn.notifyNeighborsOfStateChange(pos.offset(enumfacing.getOpposite()), this, false); + } + + public static void OnNotifySync(World world, BlockPos pos, boolean toOpen) { + IBlockState block = world.getBlockState(pos); + + if (block.getBlock() instanceof BlockExtractionDoorTest) { + BlockExtractionDoorTest door = (BlockExtractionDoorTest)(block.getBlock()); + if (isOpened(block) != toOpen){ + door.Toggle(world, block, pos); + OnNotifySync(world, pos.add(1,0,0), !block.getValue(POWERED)); + OnNotifySync(world, pos.add(-1,0,0), !block.getValue(POWERED)); + OnNotifySync(world, pos.add(0,1,0), !block.getValue(POWERED)); + OnNotifySync(world, pos.add(0,-1,0), !block.getValue(POWERED)); + OnNotifySync(world, pos.add(0,0,1), !block.getValue(POWERED)); + OnNotifySync(world, pos.add(0,0,-1), !block.getValue(POWERED)); + } + } + } + + /** + * Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated + */ + public void breakBlock(World worldIn, BlockPos pos, IBlockState state) + { + if (state.getValue(POWERED).booleanValue()) + { + worldIn.notifyNeighborsOfStateChange(pos, this, false); + EnumFacing enumfacing = state.getValue(FACING).getFacing(); + worldIn.notifyNeighborsOfStateChange(pos.offset(enumfacing.getOpposite()), this, false); + } + + super.breakBlock(worldIn, pos, state); + } + + /** + * Get the Item that this Block should drop when harvested. + */ + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return Item.getItemFromBlock(this); + } + + /** + * Can this block provide power. Only wire currently seems to have this change based on its state. + */ + public boolean canProvidePower(IBlockState state) + { + return true; + } + + /** + * Convert the given metadata into a BlockState for this Block + */ + public IBlockState getStateFromMeta(int meta) + { + return this.getDefaultState().withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.byMetadata(meta & 7)).withProperty(POWERED, Boolean.valueOf((meta & 8) > 0)); + } + + /** + * Convert the BlockState into the correct metadata value + */ + public int getMetaFromState(IBlockState state) + { + int i = 0; + i = i | state.getValue(FACING).getMetadata(); + + if (state.getValue(POWERED)) + { + i |= 8; + } + + return i; + } + + /** + * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed + * blockstate. + */ + public IBlockState withRotation(IBlockState state, Rotation rot) + { + switch (rot) + { + case CLOCKWISE_180: + + switch (state.getValue(FACING)) + { + case EAST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.WEST); + case WEST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.EAST); + case SOUTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.NORTH); + case NORTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.SOUTH); + default: + return state; + } + + case COUNTERCLOCKWISE_90: + + switch (state.getValue(FACING)) + { + case EAST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.NORTH); + case WEST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.SOUTH); + case SOUTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.EAST); + case NORTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.WEST); + case UP_Z: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.UP_X); + case UP_X: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.UP_Z); + case DOWN_X: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.DOWN_Z); + case DOWN_Z: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.DOWN_X); + } + + case CLOCKWISE_90: + + switch (state.getValue(FACING)) + { + case EAST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.SOUTH); + case WEST: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.NORTH); + case SOUTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.WEST); + case NORTH: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.EAST); + case UP_Z: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.UP_X); + case UP_X: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.UP_Z); + case DOWN_X: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.DOWN_Z); + case DOWN_Z: + return state.withProperty(FACING, BlockExtractionDoorTest.EnumOrientation.DOWN_X); + } + + default: + return state; + } + } + + /** + * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed + * blockstate. + */ + public IBlockState withMirror(IBlockState state, Mirror mirrorIn) + { + return state.withRotation(mirrorIn.toRotation(state.getValue(FACING).getFacing())); + } + + protected BlockStateContainer createBlockState() + { + return new BlockStateContainer(this, FACING, POWERED); + } + + public boolean isPassable(IBlockAccess worldIn, BlockPos pos) + { + return isOpened(worldIn, pos); + } + + public static boolean isOpened(IBlockAccess worldIn, BlockPos pos) + { + return worldIn.getBlockState(pos).getValue(POWERED); + } + + public static boolean isOpened(IBlockState state) + { + return state.getValue(POWERED); + } + + public enum EnumOrientation implements IStringSerializable + { + DOWN_X(0, "down_x", EnumFacing.DOWN), + EAST(1, "east", EnumFacing.EAST), + WEST(2, "west", EnumFacing.WEST), + SOUTH(3, "south", EnumFacing.SOUTH), + NORTH(4, "north", EnumFacing.NORTH), + UP_Z(5, "up_z", EnumFacing.UP), + UP_X(6, "up_x", EnumFacing.UP), + DOWN_Z(7, "down_z", EnumFacing.DOWN); + + private static final BlockExtractionDoorTest.EnumOrientation[] META_LOOKUP = new BlockExtractionDoorTest.EnumOrientation[values().length]; + private final int meta; + private final String name; + private final EnumFacing facing; + + EnumOrientation(int meta, String name, EnumFacing facing) + { + this.meta = meta; + this.name = name; + this.facing = facing; + } + + public int getMetadata() + { + return this.meta; + } + + public EnumFacing getFacing() + { + return this.facing; + } + + public String toString() + { + return this.name; + } + + public static BlockExtractionDoorTest.EnumOrientation byMetadata(int meta) + { + if (meta < 0 || meta >= META_LOOKUP.length) + { + meta = 0; + } + + return META_LOOKUP[meta]; + } + + public static BlockExtractionDoorTest.EnumOrientation forFacings(EnumFacing clickedSide, EnumFacing entityFacing) + { + switch (clickedSide) + { + case DOWN: + + switch (entityFacing.getAxis()) + { + case X: + return DOWN_X; + case Z: + return DOWN_Z; + default: + throw new IllegalArgumentException("Invalid entityFacing " + entityFacing + " for facing " + clickedSide); + } + + case UP: + + switch (entityFacing.getAxis()) + { + case X: + return UP_X; + case Z: + return UP_Z; + default: + throw new IllegalArgumentException("Invalid entityFacing " + entityFacing + " for facing " + clickedSide); + } + + case NORTH: + return NORTH; + case SOUTH: + return SOUTH; + case WEST: + return WEST; + case EAST: + return EAST; + default: + throw new IllegalArgumentException("Invalid facing: " + clickedSide); + } + } + + public String getName() + { + return this.name; + } + + static + { + for (BlockExtractionDoorTest.EnumOrientation blocklever$enumorientation : values()) + { + META_LOOKUP[blocklever$enumorientation.getMetadata()] = blocklever$enumorientation; + } + } + } + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/ModBlocks.java b/src/main/java/com/somebody/idlframewok/blocks/ModBlocks.java new file mode 100644 index 0000000..7e52fb2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/ModBlocks.java @@ -0,0 +1,20 @@ +package com.somebody.idlframewok.blocks; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; + +public class ModBlocks { + public static final List BLOCKS = new ArrayList(); + + /* + * To add a block, put a line here, + * -Create a json at assets.eo.blockstates + * -Create a json at assets.eo.models.block + * -Create a json at assets.eo.models.item + * -Add corresponding texture png + */ + + //public static final Block GRID_BLOCK_1 = new BlockBase("test", Material.CLAY).setCreativeTab(ModCreativeTab.IDL_MISC).setHardness(15f); +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockDeboomOrb.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockDeboomOrb.java new file mode 100644 index 0000000..180ce33 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockDeboomOrb.java @@ -0,0 +1,56 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.blocks.tileEntity.orbs.TileEntityDeBoomOrb; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class BlockDeboomOrb extends BlockBase implements ITileEntityProvider { + + public static final int NULLIFY_DISTANCE = 7; + + public BlockDeboomOrb(String name, Material material) { + super(name, material); + this.hasTileEntity = true; + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(1500.0F); + setHarvestLevel("pickaxe", 3); + setLightOpacity(1); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { +// int max = 4; +// int min = 1; +// return rand.nextInt(max) + min; + + return super.quantityDropped(rand); + } + + /** + * Returns a new instance of a block's tile entity class. Called on placing the block. + */ + public TileEntity createNewTileEntity(World worldIn, int meta) + { + return new TileEntityDeBoomOrb(); + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockGeneralOrb.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockGeneralOrb.java new file mode 100644 index 0000000..26f885b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockGeneralOrb.java @@ -0,0 +1,64 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class BlockGeneralOrb extends BlockBase implements ITileEntityProvider { + + public Class tileEntity; + + public BlockGeneralOrb(String name, Material material, Class classEntity) { + super(name, material); + this.hasTileEntity = true; + this.tileEntity = classEntity; + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(1500.0F); + setHarvestLevel("pickaxe", 3); + setLightOpacity(1); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { +// int max = 4; +// int min = 1; +// return rand.nextInt(max) + min; + + return super.quantityDropped(rand); + } + + /** + * Returns a new instance of a block's tile entity class. Called on placing the block. + */ + public TileEntity createNewTileEntity(World worldIn, int meta) + { + try { + return tileEntity.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + return null; + } catch (IllegalAccessException e) { + e.printStackTrace(); + return null; + } + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockNullifyOrb.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockNullifyOrb.java new file mode 100644 index 0000000..68866d1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/BlockNullifyOrb.java @@ -0,0 +1,64 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.blocks.tileEntity.orbs.TileEntityNullifyOrb; +import com.somebody.idlframewok.blocks.tileEntity.orbs.TileEntityNullifyOrbMor; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class BlockNullifyOrb extends BlockBase implements ITileEntityProvider { + + public boolean isMoroonProof = false; + public BlockNullifyOrb(String name, Material material) { + super(name, material); + this.hasTileEntity = true; + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(15.0F); + setHarvestLevel("pickaxe", 3); + setLightOpacity(1); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + public BlockNullifyOrb setAdvanced(boolean val) + { + isMoroonProof = val; + return this; + } + + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { + return super.quantityDropped(rand); + } + + /** + * Returns a new instance of a block's tile entity class. Called on placing the block. + */ + public TileEntity createNewTileEntity(World worldIn, int meta) + { + if (isMoroonProof) + { + return new TileEntityNullifyOrbMor(); + }else { + return new TileEntityNullifyOrb(); + } + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/DivineOre.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/DivineOre.java new file mode 100644 index 0000000..a4abb98 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/DivineOre.java @@ -0,0 +1,40 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; + +public class DivineOre extends BlockBase { + + public DivineOre(String name, Material material) { + super(name, material); + + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(15.0F); + setHarvestLevel("pickaxe", 3); + setLightLevel(1f); + setLightOpacity(1); + + } + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { +// int max = 4; +// int min = 1; +// return rand.nextInt(max) + min; + + return super.quantityDropped(rand); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/IdeallandLight.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/IdeallandLight.java new file mode 100644 index 0000000..a8cc3da --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/IdeallandLight.java @@ -0,0 +1,41 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; + +public class IdeallandLight extends BlockBase { + + public IdeallandLight(String name, Material material) { + super(name, material); + + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(1000.0F); + setHarvestLevel("pickaxe", 1); + setLightLevel(1f); + setLightOpacity(1); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { +// int max = 4; +// int min = 1; +// return rand.nextInt(max) + min; + + return super.quantityDropped(rand); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/ModBlockGlassBase.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/ModBlockGlassBase.java new file mode 100644 index 0000000..5e66432 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/ModBlockGlassBase.java @@ -0,0 +1,61 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import com.somebody.idlframewok.blocks.BlockBase; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ModBlockGlassBase extends BlockBase { + public ModBlockGlassBase(String name, Material material) { + super(name, material); + } + + @SideOnly(Side.CLIENT) + public BlockRenderLayer getBlockLayer() + { + return BlockRenderLayer.TRANSLUCENT; + } + + public boolean isFullCube(IBlockState state) + { + return false; + } + + protected boolean canSilkHarvest() + { + return true; + } + + /** + * Used to determine ambient occlusion and culling when rebuilding chunks for render + */ + public boolean isOpaqueCube(IBlockState state) + { + return false; + } + + @SideOnly(Side.CLIENT) + public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) + { + IBlockState iblockstate = blockAccess.getBlockState(pos.offset(side)); + Block block = iblockstate.getBlock(); + + if (blockState != iblockstate) + { + return true; + } + + if (block == this) + { + return false; + } + + return super.shouldSideBeRendered(blockState, blockAccess, pos, side); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockBasic/PureOre.java b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/PureOre.java new file mode 100644 index 0000000..8e8b64c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockBasic/PureOre.java @@ -0,0 +1,33 @@ +package com.somebody.idlframewok.blocks.blockBasic; + +import java.util.Random; + +import com.somebody.idlframewok.blocks.BlockBase; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; + +public class PureOre extends BlockBase { + + public PureOre(String name, Material material) { + super(name, material); + + setSoundType(SoundType.METAL); + setHardness(15.0F); + setResistance(15.0F); + setHarvestLevel("pickaxe", 1); + } + + //optional + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return super.getItemDropped(state, rand, fortune); + } + + @Override + public int quantityDropped(Random rand) { + return super.quantityDropped(rand); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockMisc/BlockArtifactHead.java b/src/main/java/com/somebody/idlframewok/blocks/blockMisc/BlockArtifactHead.java new file mode 100644 index 0000000..3cd9cdc --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockMisc/BlockArtifactHead.java @@ -0,0 +1,237 @@ +package com.somebody.idlframewok.blocks.blockMisc; + +import javax.annotation.Nullable; + +import com.google.common.base.Predicate; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.block.material.MapColor; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.BlockWorldState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.block.state.pattern.BlockMaterialMatcher; +import net.minecraft.block.state.pattern.BlockPattern; +import net.minecraft.block.state.pattern.BlockStateMatcher; +import net.minecraft.block.state.pattern.FactoryBlockPattern; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.monster.EntityIronGolem; +import net.minecraft.entity.monster.EntitySnowman; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BlockArtifactHead extends BlockHorizontal +{ + private BlockPattern snowmanBasePattern; + private BlockPattern snowmanPattern; + private BlockPattern golemBasePattern; + private BlockPattern golemPattern; + private static final Predicate IS_PUMPKIN = new Predicate() + { + public boolean apply(@Nullable IBlockState p_apply_1_) + { + return p_apply_1_ != null && (p_apply_1_.getBlock() == Blocks.PUMPKIN || p_apply_1_.getBlock() == Blocks.LIT_PUMPKIN); + } + }; + + protected BlockArtifactHead() + { + super(Material.GOURD, MapColor.ADOBE); + this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH)); + this.setTickRandomly(true); + this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS); + } + + /** + * Called after the block is set in the Chunk data, but before the Tile Entity is set + */ + public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) + { + super.onBlockAdded(worldIn, pos, state); + this.trySpawnGolem(worldIn, pos); + } + + public boolean canDispenserPlace(World worldIn, BlockPos pos) + { + return this.getSnowmanBasePattern().match(worldIn, pos) != null || this.getGolemBasePattern().match(worldIn, pos) != null; + } + + private void trySpawnGolem(World worldIn, BlockPos pos) + { + BlockPattern.PatternHelper blockpattern$patternhelper = this.getSnowmanPattern().match(worldIn, pos); + + if (blockpattern$patternhelper != null) + { + for (int i = 0; i < this.getSnowmanPattern().getThumbLength(); ++i) + { + BlockWorldState blockworldstate = blockpattern$patternhelper.translateOffset(0, i, 0); + worldIn.setBlockState(blockworldstate.getPos(), Blocks.AIR.getDefaultState(), 2); + } + + EntitySnowman entitysnowman = new EntitySnowman(worldIn); + BlockPos blockpos1 = blockpattern$patternhelper.translateOffset(0, 2, 0).getPos(); + entitysnowman.setLocationAndAngles((double)blockpos1.getX() + 0.5D, (double)blockpos1.getY() + 0.05D, (double)blockpos1.getZ() + 0.5D, 0.0F, 0.0F); + worldIn.spawnEntity(entitysnowman); + + for (EntityPlayerMP entityplayermp : worldIn.getEntitiesWithinAABB(EntityPlayerMP.class, entitysnowman.getEntityBoundingBox().grow(5.0D))) + { + CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayermp, entitysnowman); + } + + for (int l = 0; l < 120; ++l) + { + worldIn.spawnParticle(EnumParticleTypes.SNOW_SHOVEL, (double)blockpos1.getX() + worldIn.rand.nextDouble(), (double)blockpos1.getY() + worldIn.rand.nextDouble() * 2.5D, (double)blockpos1.getZ() + worldIn.rand.nextDouble(), 0.0D, 0.0D, 0.0D); + } + + for (int i1 = 0; i1 < this.getSnowmanPattern().getThumbLength(); ++i1) + { + BlockWorldState blockworldstate2 = blockpattern$patternhelper.translateOffset(0, i1, 0); + worldIn.notifyNeighborsRespectDebug(blockworldstate2.getPos(), Blocks.AIR, false); + } + } + else + { + blockpattern$patternhelper = this.getGolemPattern().match(worldIn, pos); + + if (blockpattern$patternhelper != null) + { + for (int j = 0; j < this.getGolemPattern().getPalmLength(); ++j) + { + for (int k = 0; k < this.getGolemPattern().getThumbLength(); ++k) + { + worldIn.setBlockState(blockpattern$patternhelper.translateOffset(j, k, 0).getPos(), Blocks.AIR.getDefaultState(), 2); + } + } + + BlockPos blockpos = blockpattern$patternhelper.translateOffset(1, 2, 0).getPos(); + EntityIronGolem entityirongolem = new EntityIronGolem(worldIn); + entityirongolem.setPlayerCreated(true); + entityirongolem.setLocationAndAngles((double)blockpos.getX() + 0.5D, (double)blockpos.getY() + 0.05D, (double)blockpos.getZ() + 0.5D, 0.0F, 0.0F); + worldIn.spawnEntity(entityirongolem); + + for (EntityPlayerMP entityplayermp1 : worldIn.getEntitiesWithinAABB(EntityPlayerMP.class, entityirongolem.getEntityBoundingBox().grow(5.0D))) + { + CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayermp1, entityirongolem); + } + + for (int j1 = 0; j1 < 120; ++j1) + { + worldIn.spawnParticle(EnumParticleTypes.SNOWBALL, (double)blockpos.getX() + worldIn.rand.nextDouble(), (double)blockpos.getY() + worldIn.rand.nextDouble() * 3.9D, (double)blockpos.getZ() + worldIn.rand.nextDouble(), 0.0D, 0.0D, 0.0D); + } + + for (int k1 = 0; k1 < this.getGolemPattern().getPalmLength(); ++k1) + { + for (int l1 = 0; l1 < this.getGolemPattern().getThumbLength(); ++l1) + { + BlockWorldState blockworldstate1 = blockpattern$patternhelper.translateOffset(k1, l1, 0); + worldIn.notifyNeighborsRespectDebug(blockworldstate1.getPos(), Blocks.AIR, false); + } + } + } + } + } + + /** + * Checks if this block can be placed exactly at the given position. + */ + public boolean canPlaceBlockAt(World worldIn, BlockPos pos) + { + return worldIn.getBlockState(pos).getBlock().isReplaceable(worldIn, pos) && worldIn.isSideSolid(pos.down(), EnumFacing.UP); + } + + /** + * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed + * blockstate. + */ + public IBlockState withRotation(IBlockState state, Rotation rot) + { + return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); + } + + /** + * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed + * blockstate. + */ + public IBlockState withMirror(IBlockState state, Mirror mirrorIn) + { + return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); + } + + /** + * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the + * IBlockstate + */ + public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) + { + return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()); + } + + /** + * Convert the given metadata into a BlockState for this Block + */ + public IBlockState getStateFromMeta(int meta) + { + return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta)); + } + + /** + * Convert the BlockState into the correct metadata value + */ + public int getMetaFromState(IBlockState state) + { + return ((EnumFacing)state.getValue(FACING)).getHorizontalIndex(); + } + + protected BlockStateContainer createBlockState() + { + return new BlockStateContainer(this, new IProperty[] {FACING}); + } + + protected BlockPattern getSnowmanBasePattern() + { + if (this.snowmanBasePattern == null) + { + this.snowmanBasePattern = FactoryBlockPattern.start().aisle(" ", "#", "#").where('#', BlockWorldState.hasState(BlockStateMatcher.forBlock(Blocks.SNOW))).build(); + } + + return this.snowmanBasePattern; + } + + protected BlockPattern getSnowmanPattern() + { + if (this.snowmanPattern == null) + { + this.snowmanPattern = FactoryBlockPattern.start().aisle("^", "#", "#").where('^', BlockWorldState.hasState(IS_PUMPKIN)).where('#', BlockWorldState.hasState(BlockStateMatcher.forBlock(Blocks.SNOW))).build(); + } + + return this.snowmanPattern; + } + + protected BlockPattern getGolemBasePattern() + { + if (this.golemBasePattern == null) + { + this.golemBasePattern = FactoryBlockPattern.start().aisle("~ ~", "###", "~#~").where('#', BlockWorldState.hasState(BlockStateMatcher.forBlock(Blocks.IRON_BLOCK))).where('~', BlockWorldState.hasState(BlockMaterialMatcher.forMaterial(Material.AIR))).build(); + } + + return this.golemBasePattern; + } + + protected BlockPattern getGolemPattern() + { + if (this.golemPattern == null) + { + this.golemPattern = FactoryBlockPattern.start().aisle("~^~", "###", "~#~").where('^', BlockWorldState.hasState(IS_PUMPKIN)).where('#', BlockWorldState.hasState(BlockStateMatcher.forBlock(Blocks.IRON_BLOCK))).where('~', BlockWorldState.hasState(BlockMaterialMatcher.forMaterial(Material.AIR))).build(); + } + + return this.golemPattern; + } +} \ No newline at end of file diff --git a/src/main/java/com/somebody/idlframewok/blocks/blockMoroon/BlockMoroonBase.java b/src/main/java/com/somebody/idlframewok/blocks/blockMoroon/BlockMoroonBase.java new file mode 100644 index 0000000..4c60bd8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/blockMoroon/BlockMoroonBase.java @@ -0,0 +1,11 @@ +package com.somebody.idlframewok.blocks.blockMoroon; + +import com.somebody.idlframewok.blocks.BlockBase; +import net.minecraft.block.material.Material; + +public class BlockMoroonBase extends BlockBase { + public BlockMoroonBase(String name, Material material) { + super(name, material); + setResistance(1.0F); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderBase.java b/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderBase.java new file mode 100644 index 0000000..60faba9 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderBase.java @@ -0,0 +1,42 @@ +package com.somebody.idlframewok.blocks.builder; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.blocks.tileEntity.builder.TileEntityBuilderBase; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.world.World; + +public class BlockBuilderBase extends BlockBase implements ITileEntityProvider { + + Class tileEntity; + + public BlockBuilderBase(String name, Material material, Class tileEntity) { + super(name, material); + this.tileEntity = tileEntity; + setCreativeTab(ModCreativeTab.IDL_MISC); + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(15.0F); + setHarvestLevel("pickaxe", 3); + setLightOpacity(1); + } + + /** + * Returns a new instance of a block's tile entity class. Called on placing the block. + */ + public TileEntityBuilderBase createNewTileEntity(World worldIn, int meta) { + TileEntityBuilderBase t = null; + try { + t = tileEntity.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + IdlFramework.Log("Instantiate failed"); + } + return t; + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderOne.java b/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderOne.java new file mode 100644 index 0000000..9409ab3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/builder/BlockBuilderOne.java @@ -0,0 +1,32 @@ +package com.somebody.idlframewok.blocks.builder; + +import com.somebody.idlframewok.blocks.BlockBase; +import com.somebody.idlframewok.blocks.tileEntity.builder.TileEntityBuilderOne; +import com.somebody.idlframewok.init.ModCreativeTab; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class BlockBuilderOne extends BlockBase implements ITileEntityProvider { + + public BlockBuilderOne(String name, Material material) { + super(name, material); + setCreativeTab(ModCreativeTab.IDL_MISC); + setSoundType(SoundType.METAL); + setHardness(5.0F); + setResistance(15.0F); + setHarvestLevel("pickaxe", 3); + setLightOpacity(1); + } + + /** + * Returns a new instance of a block's tile entity class. Called on placing the block. + */ + public TileEntity createNewTileEntity(World worldIn, int meta) { + TileEntityBuilderOne t = new TileEntityBuilderOne(); + t.buildRatePerTick = 1f; + return t; + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderBase.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderBase.java new file mode 100644 index 0000000..f814647 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderBase.java @@ -0,0 +1,208 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder; + +import java.util.Vector; + +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBase; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlock; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlockSafe; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; + +public class TileEntityBuilderBase extends TileEntity implements ITickable { + private SoundEvent onLoadSound = SoundEvents.BLOCK_NOTE_CHIME; + + protected SoundEvent buildSound = SoundEvents.BLOCK_NOTE_CHIME; + protected SoundEvent finishSound = SoundEvents.BLOCK_NOTE_XYLOPHONE; + protected SoundEvent failSound = SoundEvents.BLOCK_LEVER_CLICK; + + protected Vector list; + + protected int reserved_first_tasks_count = 0;//some has to be done before anything else, like clearing + + @Override + public void onLoad() + { + super.onLoad(); + Init(); + } + + void Init() + { + InitTaskQueue(); + } + + public void PlaySound(SoundEvent ev) + { + world.playSound(null, this.pos, ev, SoundCategory.BLOCKS, 0.3F, 1f); + } + + + public void CreateParticles() + { +// if (world.isRemote && isReady) +// { +// Random random = new Random(); +// Vec3d myPos = GetPosInFloat(); +// float range = 2f; +// float x = (random.nextFloat() - 0.5f) * range; +// float y = (random.nextFloat() - 0.5f) * range; +// float z = (random.nextFloat() - 0.5f) * range; +// float vFactor = -1f; +// +// world.spawnParticle(particleType, myPos.x + x, myPos.y + y, myPos.z + z, x * vFactor, y * vFactor, z * vFactor); +// } + } + + //building + + public float buildRatePerTick = 1f; + public float curBuildCounter = - CommonDef.TICK_PER_SECOND * 3; + + private int curBuildActionIndex = 0; + private boolean finished = false; + + public void readFromNBT(NBTTagCompound compound) { + super.readFromNBT(compound); + this.curBuildActionIndex = compound.getInteger(IDLNBTDef.CUR_TASK_INDEX); + this.buildRatePerTick = compound.getFloat(IDLNBTDef.BUILD_SPEED); + if (list == null){ + InitTaskQueue(); + } + + if (curBuildActionIndex >= list.size()) { + finished = true; + return; + } + } + + public NBTTagCompound getUpdateTag() + { + return this.writeToNBT(new NBTTagCompound()); + } + + public NBTTagCompound writeToNBT(NBTTagCompound compound) + { + super.writeToNBT(compound); + compound.setInteger(IDLNBTDef.CUR_TASK_INDEX, this.curBuildActionIndex); + compound.setFloat(IDLNBTDef.BUILD_SPEED, this.buildRatePerTick); + return compound; + } + + protected void OnFinished(){ + world.setBlockState(pos, Blocks.AIR.getDefaultState()); + invalidate(); + } + + @Override + public void update() { + if (finished || world.isRemote) { + return; + } + + curBuildCounter += buildRatePerTick; + while (curBuildCounter > 1){ + curBuildCounter -= 1; + + BuilderActionBase action = list.get(curBuildActionIndex); + if (action != null){ + boolean success = action.Execute(world, this.pos); + if (success) { + curBuildActionIndex++; + if (curBuildActionIndex >= list.size()) { + finished = true; + PlaySound(finishSound); + OnFinished(); + return; + } + + if (world.getTotalWorldTime() % CommonDef.TICK_PER_SECOND == 0) { + PlaySound(buildSound); + } + } + else { + if (world.getTotalWorldTime() % CommonDef.TICK_PER_SECOND == 0) { + PlaySound(failSound); + } + return; + } + } + } + } + + public float GetProgress() { + return MathHelper.clamp(curBuildActionIndex / list.size(), 0f, 1f) ; + } + + public void InitTaskQueue(){ +// int radius = 10; +// list = new Vector(); +// for (int x = -radius; x <= radius; x++) +// for (int z = -radius; z <= radius; z++) { +// list.add(new BuilderActionBlock(ModBlocks.CONSTRUCTION_SITE, x,-1,z)); +// } + } + + //some helper + public void AddTaskFillWithBlockCentered(BlockPos origin, int rangeX, int rangeY, int rangeZ, IBlockState newState) { + AddTaskFillWithBlockCentered(origin, rangeX, rangeY, rangeZ, newState, true); + } + + public void AddTaskFillWithBlockCentered(BlockPos origin, int rangeX, int rangeY, int rangeZ, IBlockState newState, boolean isSafe) { + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = -rangeY; y <= rangeY; y++) { + for (int z = -rangeZ; z <= rangeZ; z++) { + AddTaskBuild(origin.add(x, y, z), newState, isSafe); + } + } + } + } + + public void AddTaskBuildWallWithBlockCentered(BlockPos origin, int rangeX, int height, int rangeZ, IBlockState newState) { + AddTaskBuildWallWithBlockCentered(origin, rangeX, height, rangeZ, newState, true); + } + + public void AddTaskBuildWallWithBlockCentered(BlockPos origin, int rangeX, int height, int rangeZ, IBlockState newState, boolean isSafe) { + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = 0; y < height; y++) { + for (int z = -rangeZ; z <= rangeZ; z++) { + AddTaskBuild(origin.add(x, y, z), newState, isSafe); + } + } + } + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState) { + AddTaskBuild(pos, newState, true); + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState, boolean isSafe){ + if (isSafe) { + if (newState.getBlock() == Blocks.AIR) { + list.add(reserved_first_tasks_count, new BuilderActionBlock(newState, pos)); + reserved_first_tasks_count++; + }else { + list.add(reserved_first_tasks_count, new BuilderActionBlock(Blocks.BRICK_BLOCK, pos)); + list.add(new BuilderActionBlockSafe(newState, pos)); + } + } else { + list.add(new BuilderActionBlock(newState, pos)); + } + } + +// static +// { +// registerSpawnList("idlframewok:builder.builder_one", TileEntityBuilderBase.class); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderOne.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderOne.java new file mode 100644 index 0000000..d90a588 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/TileEntityBuilderOne.java @@ -0,0 +1,24 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder; + +import java.util.Vector; + +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBase; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlock; +import net.minecraft.init.Blocks; + +public class TileEntityBuilderOne extends TileEntityBuilderBase { + + public void InitTaskQueue(){ + int radius = 10; + list = new Vector(); + for (int x = -radius; x <= radius; x++) + for (int z = -radius; z <= radius; z++) { + list.add(new BuilderActionBlock(Blocks.BRICK_BLOCK, x,-1,z)); + } + } + + static + { + register("idlframewok:builder.builder_one", TileEntityBuilderOne.class); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBase.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBase.java new file mode 100644 index 0000000..1b6abcb --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBase.java @@ -0,0 +1,37 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder.builderAction; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class BuilderActionBase { + + Vec3d relativePos; + public boolean complete = false; + + BuilderActionBase(float x, float y, float z){ + SetRelativePos(x,y,z); + } + + BuilderActionBase(BlockPos blockPos){ + SetRelativePos(blockPos.getX(),blockPos.getY(),blockPos.getZ()); + } + + public boolean IsComplete(){ + return complete; + } + + public boolean Execute(World world, BlockPos ori_pos){ + complete = true; + return true; + } + + public void SetRelativePos(float x, float y, float z){ + relativePos = new Vec3d(x,y,z); + } + + public Vec3d getRelativePos() + { + return relativePos; + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlock.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlock.java new file mode 100644 index 0000000..a001433 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlock.java @@ -0,0 +1,73 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder.builderAction; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class BuilderActionBlock extends BuilderActionBase { + + private Block block; + protected IBlockState blockState; + + public BuilderActionBlock(Block _block, int x, int y, int z){ + super((float) x,(float) y,(float) z); + block = _block; + blockState = _block.getDefaultState(); + } + + public BuilderActionBlock(IBlockState _block_state, int x, int y, int z){ + super((float) x,(float) y,(float) z); + block = _block_state.getBlock(); + blockState = _block_state; + } + + public BuilderActionBlock(Block _block, BlockPos blockPos){ + super(blockPos); + block = _block; + blockState = _block.getDefaultState(); + } + + public BuilderActionBlock(IBlockState _block_state, BlockPos blockPos){ + super(blockPos); + block = _block_state.getBlock(); + blockState = _block_state; + } + + @Override + public boolean Execute(World world, BlockPos ori_pos){ + if (relativePos.lengthSquared() < 1) { + IdlFramework.LogWarning("Trying to build a block at self-pos."); + return true; + } + + BlockPos pos = ori_pos.add(relativePos.x, relativePos.y, relativePos.z); + if (!world.isBlockLoaded(pos)) { + return false; + } + float range = 0.5f; + Vec3d posInFloat = new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + AxisAlignedBB aabb = new AxisAlignedBB(posInFloat.x - range, posInFloat.y - range, posInFloat.z - range, posInFloat.x + range, posInFloat.y + range, posInFloat.z + range); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, aabb); + if (entities.size() > 0) { + //building stuck because of entity + return false; + } + + if (!world.isRemote) { + //should drop the original blocks + //dig time should be considered + if (world.getBlockState(pos) != blockState) { + world.setBlockState(pos, blockState); + } + } + return super.Execute(world, ori_pos); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockBrutal.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockBrutal.java new file mode 100644 index 0000000..4970db4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockBrutal.java @@ -0,0 +1,68 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder.builderAction; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BuilderActionBlockBrutal extends BuilderActionBase { + + private Block block; + protected IBlockState blockState; + + public BuilderActionBlockBrutal(Block _block, int x, int y, int z){ + super((float) x,(float) y,(float) z); + block = _block; + blockState = _block.getDefaultState(); + } + + public BuilderActionBlockBrutal(IBlockState _block_state, int x, int y, int z){ + super((float) x,(float) y,(float) z); + block = _block_state.getBlock(); + blockState = _block_state; + } + + public BuilderActionBlockBrutal(Block _block, BlockPos blockPos){ + super(blockPos); + block = _block; + blockState = _block.getDefaultState(); + } + + public BuilderActionBlockBrutal(IBlockState _block_state, BlockPos blockPos){ + super(blockPos); + block = _block_state.getBlock(); + blockState = _block_state; + } + + @Override + public boolean Execute(World world, BlockPos ori_pos){ +// if (relativePos.lengthSquared() < 1) { +// //IdlFramework.LogWarning("Trying to build a block at self-pos."); +// //return true; +// } + + BlockPos pos = ori_pos.add(relativePos.x, relativePos.y, relativePos.z); + if (!world.isBlockLoaded(pos)) { + return false; + } + float range = 0.5f; +// Vec3d posInFloat = new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); +// AxisAlignedBB aabb = new AxisAlignedBB(posInFloat.x - range, posInFloat.y - range, posInFloat.z - range, posInFloat.x + range, posInFloat.y + range, posInFloat.z + range); +// List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, aabb); +// if (entities.size() > 0) { +// //building stuck because of entity +// return false; +// } + + if (!world.isRemote) { + //should drop the original blocks + //dig time should be considered + IBlockState original = world.getBlockState(pos); + if (original != blockState && original != Blocks.BEDROCK.getDefaultState()) { + world.setBlockState(pos, blockState); + } + } + return super.Execute(world, ori_pos); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockSafe.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockSafe.java new file mode 100644 index 0000000..3622d8c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionBlockSafe.java @@ -0,0 +1,69 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder.builderAction; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class BuilderActionBlockSafe extends BuilderActionBlock { + + public static Block block_req = Blocks.BRICK_BLOCK; + + public BuilderActionBlockSafe(Block _block, Block _req , int x, int y, int z) { + super(_block, x, y, z); + block_req = _req; + } + + public BuilderActionBlockSafe(Block _block, int x, int y, int z) { + super(_block, x, y, z); + } + + public BuilderActionBlockSafe(Block _block, BlockPos blockPos) { + super(_block, blockPos); + } + + public BuilderActionBlockSafe(IBlockState _block_state, int x, int y, int z) { + super(_block_state, x, y, z); + } + + public BuilderActionBlockSafe(IBlockState _block_state, BlockPos blockPos) { + super(_block_state, blockPos); + } + + @Override + public boolean Execute(World world, BlockPos ori_pos){ + if (relativePos.lengthSquared() < 1) { + //IdlFramework.LogWarning("Trying to build a block at self-pos."); + return true; + } + + BlockPos pos = ori_pos.add(relativePos.x, relativePos.y, relativePos.z); + if (!world.isBlockLoaded(pos)) { + return false; + } + + if (!world.isRemote) { + if (world.getBlockState(pos).getBlock() == block_req) { + return super.Execute(world, ori_pos); + } else { + float range = 0.5f; + Vec3d posInFloat = new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); + AxisAlignedBB aabb = new AxisAlignedBB(posInFloat.x - range, posInFloat.y - range, posInFloat.z - range, posInFloat.x + range, posInFloat.y + range, posInFloat.z + range); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, aabb); + if (entities.size() > 0) { + //building stuck because of entity + return false; + } + world.setBlockState(pos, block_req.getDefaultState()); + } + } + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionSummonEntity.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionSummonEntity.java new file mode 100644 index 0000000..9b9820d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/builder/builderAction/BuilderActionSummonEntity.java @@ -0,0 +1,55 @@ +package com.somebody.idlframewok.blocks.tileEntity.builder.builderAction; + +import java.lang.reflect.InvocationTargetException; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class BuilderActionSummonEntity extends BuilderActionBase { + + Vec3d relative_pos; + public boolean complete = false; + + protected Class toSummon; + +// BuilderActionSummonEntity(float x, float y, float z){ +// SetRelativePos(x,y,z); +// } +// +// BuilderActionSummonEntity(BlockPos blockPos){ +// SetRelativePos(blockPos.getX(),blockPos.getY(),blockPos.getZ()); +// } + + public BuilderActionSummonEntity(BlockPos blockPos, Class toSummon){ + super(blockPos); + SetRelativePos(blockPos.getX(),blockPos.getY(),blockPos.getZ()); + this.toSummon = toSummon; + } + + public boolean Execute(World world, BlockPos ori_pos){ + if (world.isRemote) + { + return true; + } + + try { + Entity summoned = toSummon.getConstructor(World.class).newInstance(world); + summoned.setPosition(ori_pos.getX() + relative_pos.x + 0.5f, + ori_pos.getY() + relative_pos.y + 0.5f, + ori_pos.getZ() + relative_pos.z + 0.5f); + world.spawnEntity(summoned); + + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + IdlFramework.LogWarning("A building process failed to summon creature"); + } + return super.Execute(world, ori_pos); + } + + public void SetRelativePos(float x, float y, float z){ + relative_pos = new Vec3d(x,y,z); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeArrowOrb.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeArrowOrb.java new file mode 100644 index 0000000..e8eeecd --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeArrowOrb.java @@ -0,0 +1,90 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.entity.projectile.EntityShulkerBullet; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ITickable; + +//"Tonation Orb" de-detonation orb +public class TileEntityDeArrowOrb extends TileEntityOrbBase implements ITickable { + + @Override + public void update() { + super.update(); + disarmProjectiles(); + } + + private void disarmProjectiles() + { + if (world.isRemote) { + return; + } + + List entities = world.getEntitiesWithinAABB(Entity.class, + aabb); + for (Entity entity : entities) { + HandleProjectile(entity); + } + } + + private void HandleProjectile(Entity projectile) + { + if (projectile.isDead) + { + return; + } + + if (projectile instanceof IProjectile || + projectile instanceof EntityFireball || + projectile instanceof EntityShulkerBullet) { + ItemStack result = GetCorrespondingStack(projectile); + if (result != null) { + projectile.entityDropItem(result, 0.1F); + + } + projectile.setDead(); + } + } + + //Tried to get the arrow from the entity. + //there is an implemented method, but it's protected. + //The only way I can think of to support light arrow and tipped arrows are rewriting them from nbt. + private ItemStack GetArrowStack(EntityArrow arrow) { + return new ItemStack(Items.ARROW); + } + + private ItemStack GetCorrespondingStack(Entity projectile) + { + if (projectile instanceof IProjectile) { + if (projectile instanceof EntityArrow) { + EntityArrow arrow = (EntityArrow) projectile; + if (arrow.pickupStatus == EntityArrow.PickupStatus.ALLOWED) + { + return GetArrowStack(arrow); + } + else { + return null; + } + } + } else if (projectile instanceof EntityFireball) + { + return new ItemStack(Items.FIRE_CHARGE); + }else if (projectile instanceof EntityTNTPrimed) { + return new ItemStack(Blocks.TNT.getItemDropped(Blocks.TNT.getDefaultState(), null, 0)); + } + return ItemStack.EMPTY; + } + + static + { + register("idlframewok:de_arrow_orb", TileEntityDeArrowOrb.class); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeBoomOrb.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeBoomOrb.java new file mode 100644 index 0000000..58e56c8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityDeBoomOrb.java @@ -0,0 +1,30 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.world.ExplosionEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +//"Tonation Orb" de-detonation orb +public class TileEntityDeBoomOrb extends TileEntityOrbBase implements ITickable { + + @SubscribeEvent + public void onExplode(ExplosionEvent.Start event) { + Vec3d pos = event.getExplosion().getPosition(); + //IdlFramework.Log(String.format("onExplode:(%s,%s,%s)", pos.x, pos.y, pos.z)); + //can use some optimization here. each orb will make it worse. + + if (!event.isCanceled() && aabb.contains(pos)) + { + event.setCanceled(true); + PlaySoundHere(); + IdlFramework.Log("Stopped an explosion"); + } + } + + static + { + register("idlframewok:deboom_orb_basic", TileEntityDeBoomOrb.class); + } +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityEarthMender.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityEarthMender.java new file mode 100644 index 0000000..de9c47f --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityEarthMender.java @@ -0,0 +1,112 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class TileEntityEarthMender extends TileEntityOrbBase implements ITickable { + + int depth = 4; + int range = 5;//0 is self. this is radius + + @Override + public void update() { + super.update(); + + World worldIn = this.world; + if (worldIn.isRemote) { + return; + } + if (worldIn.getTotalWorldTime() % 3L == 0L) + { + IBlockState block = Blocks.DIRT.getDefaultState(); + + int diameter = 2 * range + 1; + int zFactor = diameter; + int slowDownFactor = 5; + + long worldTime = worldIn.getTotalWorldTime() / slowDownFactor; + + int dx = (int) (worldTime % diameter) - range; + int dz = (int) (worldTime / zFactor % (diameter)) - range; + + BlockPos targetPos = pos.add(dx, -depth, dz); + + boolean isDownEmpty = IsBlockPosEmpty(worldIn, targetPos.down()); + boolean isCenterEmpty = IsBlockPosEmpty(worldIn, targetPos); + + for(int y = 1; y <= depth; y++) + { + boolean[] nearbyOccupied = new boolean[4]; + nearbyOccupied[0] = !IsBlockPosEmpty(worldIn, targetPos.east()); + nearbyOccupied[1] = !IsBlockPosEmpty(worldIn, targetPos.south()); + nearbyOccupied[2] = !IsBlockPosEmpty(worldIn, targetPos.west()); + nearbyOccupied[3] = !IsBlockPosEmpty(worldIn, targetPos.north()); + + boolean putDown = false; + + if (!isDownEmpty && isCenterEmpty) + { + //check the four directions + for (int i = 0; i <= 3; i++) + { + if (nearbyOccupied[i] && nearbyOccupied[(i + 1)%4]) + { + // At first I want to make the block imitate a nearby block + //but soon I found this will allow players to get ores indefinitely. + worldIn.setBlockState(targetPos, Blocks.DIRT.getDefaultState()); + putDown = true; + break; + } + } + } + + targetPos = targetPos.up(); + isDownEmpty = isCenterEmpty && !putDown ; + isCenterEmpty = IsBlockPosEmpty(worldIn, targetPos); + } + } + } + + private boolean IsBlockStateEmpty(World worldIn, IBlockState blockState) { + boolean result = blockState.getBlock() == Blocks.AIR; + return result; + } + + private boolean IsBlockPosEmpty(World worldIn, BlockPos targetPos) { + IBlockState block = worldIn.getBlockState(targetPos); + boolean result = (block.getBlock() == Blocks.AIR) || + (block.getBlock().isReplaceable(worldIn, targetPos)); + //&& block.isOpaqueCube(); + return result; + } + +// @Override +// public boolean receiveClientEvent(int event, int param) { +// return true; +// } + +// //No Use +// @SubscribeEvent +// public void onSpawn(LivingSpawnEvent.CheckSpawn event) { +// IdlFramework.Log("Spawning:"+event.getEntityLiving().getName()); +// int range = NULLIFY_DISTANCE; +// if(event.getResult() != Event.Result.ALLOW && event.getEntityLiving() instanceof IMob) { +// AxisAlignedBB aabb = new AxisAlignedBB(event.getX() - NULLIFY_DISTANCE, event.getY() - NULLIFY_DISTANCE, event.getZ() - NULLIFY_DISTANCE, event.getX() + NULLIFY_DISTANCE, event.getY() + NULLIFY_DISTANCE, event.getZ() + NULLIFY_DISTANCE); +// if (aabb.contains(new Vec3d(this.pos.getX(), this.pos.getY(), this.pos.getZ()))) +// { +// event.setResult(Event.Result.DENY); +// IdlFramework.Log("Stopped spawning:"+event.getEntityLiving().getName()); +// return; +// } +// } +// } + + static + { + register("idlframewok:earth_mender_basic", TileEntityEarthMender.class); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrb.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrb.java new file mode 100644 index 0000000..1707101 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrb.java @@ -0,0 +1,44 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.entity.monster.IMob; +import net.minecraft.init.Blocks; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.entity.living.LivingSpawnEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class TileEntityNullifyOrb extends TileEntityOrbBase implements ITickable { + + @SubscribeEvent + public void onSpawn(LivingSpawnEvent.CheckSpawn event) { + if (world.isRemote) + { + return; + } + + if (aabb == null) + { + world.setBlockState(pos, Blocks.AIR.getDefaultState()); + IdlFramework.LogWarning("A Nullify Orb @%s is not working correctly. Removing it.", pos); + invalidate(); + return; + } + + if(event.getResult() != Event.Result.DENY && event.getEntityLiving() instanceof IMob) { + if (aabb.contains(new Vec3d(event.getX(), event.getY(), event.getZ()))) + { + event.setResult(Event.Result.DENY); + //IdlFramework.Log("Stopped spawning:"+event.getEntityLiving().getName()); + return; + } + } + } + + static + { + register("idlframewok:nullify_orb_basic", TileEntityNullifyOrb.class); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrbMor.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrbMor.java new file mode 100644 index 0000000..fee5bd2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityNullifyOrbMor.java @@ -0,0 +1,40 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import com.somebody.idlframewok.util.EntityUtil; +import net.minecraft.entity.monster.IMob; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.entity.living.LivingSpawnEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class TileEntityNullifyOrbMor extends TileEntityNullifyOrb implements ITickable { + + protected int range = 15; + + void Init() + { + super.Init(); + SetRange(range); + } + + @SubscribeEvent + public void onSpawn(LivingSpawnEvent.CheckSpawn event) { + if(event.getResult() != Event.Result.DENY && + (event.getEntityLiving() instanceof IMob || EntityUtil.isMoroonTeam(event.getEntityLiving())) + ) { + if (aabb.contains(new Vec3d(event.getX(), event.getY(), event.getZ()))) + { + event.setResult(Event.Result.DENY); + //IdlFramework.Log("Stopped spawning:"+event.getEntityLiving().getName()); + return; + } + } + } + + static + { + register("idlframewok:nullify_orb_mor", TileEntityNullifyOrbMor.class); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityOrbBase.java b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityOrbBase.java new file mode 100644 index 0000000..efbd9ff --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/blocks/tileEntity/orbs/TileEntityOrbBase.java @@ -0,0 +1,148 @@ +package com.somebody.idlframewok.blocks.tileEntity.orbs; + +import java.util.Random; + +import net.minecraft.init.SoundEvents; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.common.MinecraftForge; + +public class TileEntityOrbBase extends TileEntity implements ITickable { + + public AxisAlignedBB aabb; + private int range = 7; + public boolean isReady = false; + public SoundEvent onLoadSound = SoundEvents.BLOCK_NOTE_CHIME; + public EnumParticleTypes particleType = EnumParticleTypes.CRIT_MAGIC; + + public void SetRange(int newRange){ + range = newRange; + Vec3d posInFloat = GetPosInFloat(); + //IdlFramework.Log(String.format("SetRange:(%s,%s,%s) +- %s", posInFloat.x, posInFloat.y, posInFloat.z, newRange)); + aabb = new AxisAlignedBB(posInFloat.x - range, posInFloat.y - range, posInFloat.z - range, posInFloat.x + range, posInFloat.y + range, posInFloat.z + range); + + } + + public int getRange() + { + return range; + } + + public void onLoad() + { + Init(); + } + + @Override + public void invalidate() { + MinecraftForge.EVENT_BUS.unregister(this); + super.invalidate(); + } + + public Vec3d GetPosInFloat() + { + BlockPos myPos = this.pos; + Vec3d posInFloat = new Vec3d(myPos.getX() + 0.5, myPos.getY() + 0.5, myPos.getZ() + 0.5); + return posInFloat; + } + + void Init() + { + MinecraftForge.EVENT_BUS.register(this); + isReady = true; + SetRange(range); + if (!world.isRemote) + { + //Init Success + PlaySoundHere(); + } + } + + public void PlaySoundHere() + { + world.playSound(null, this.pos, onLoadSound, SoundCategory.BLOCKS, 0.3F, 1f); + } + + public void CreateParticles() + { + if (world.isRemote && isReady) + { + Random random = new Random(); + Vec3d myPos = GetPosInFloat(); + float range = 2f; + float x = (random.nextFloat() - 0.5f) * range; + float y = (random.nextFloat() - 0.5f) * range; + float z = (random.nextFloat() - 0.5f) * range; + float vFactor = -1f; + + world.spawnParticle(particleType, myPos.x + x, myPos.y + y, myPos.z + z, x * vFactor, y * vFactor, z * vFactor); + } + } + + @Override + public void update() { + //create particles + + CreateParticles(); + } + + //failed attempt +// @SubscribeEvent +// public void onWorldRenderLast(RenderWorldLastEvent event) { +// GlStateManager.pushMatrix(); +// GL11.glPushAttrib(GL11.GL_LIGHTING_BIT); +// GlStateManager.disableDepth(); +// GlStateManager.disableTexture2D(); +// GlStateManager.enableBlend(); +// +// //Minecraft.getMinecraft().getRenderManager().setRenderPosition(pos.getX(), pos.getY(), pos.getZ()); +// +// //Add drawing here +// int color = Color.HSBtoRGB(0F, 0.6F, 1F); +// Vec3d posInFloat = GetPosInFloat(); +// +// GlStateManager.scale(1F, 1F, 1F); +// +// GlStateManager.glLineWidth(1f); +// +// //draw a cube +// //for () +// DrawLine(posInFloat.x - range, posInFloat.y, posInFloat.z - range, +// posInFloat.x + range, posInFloat.y, posInFloat.z + range); +// +// DrawLine(posInFloat.x - range, posInFloat.y, posInFloat.z - range, +// posInFloat.x + range, posInFloat.y, posInFloat.z - range); +// +// DrawLine(posInFloat.x - range, posInFloat.y, posInFloat.z - range, +// posInFloat.x - range, posInFloat.y, posInFloat.z + range); +// +// DrawLine(posInFloat.x - range, posInFloat.y, posInFloat.z - range, +// posInFloat.x - range, posInFloat.y, posInFloat.z - range); +// +// DrawLine(posInFloat.x + range, posInFloat.y, posInFloat.z + range, +// posInFloat.x + range, posInFloat.y, posInFloat.z - range); +// +// DrawLine(posInFloat.x + range, posInFloat.y, posInFloat.z - range, +// posInFloat.x - range, posInFloat.y, posInFloat.z + range); +// +// GlStateManager.enableDepth(); +// GlStateManager.enableTexture2D(); +// GlStateManager.disableBlend(); +// GL11.glPopAttrib(); +// GlStateManager.popMatrix(); +// } +// +// public static void DrawLine(double x1, double y1, double z1, double x2, double y2, double z2){ +// Tessellator tessellator = Tessellator.getInstance(); +// tessellator.getBuffer().begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); +// tessellator.getBuffer().pos(x1, y1, z1).endVertex(); +// tessellator.getBuffer().pos(x2, y2, z2).endVertex(); +// tessellator.draw(); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/command/CommandDimTeleport.java b/src/main/java/com/somebody/idlframewok/command/CommandDimTeleport.java new file mode 100644 index 0000000..7458349 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/command/CommandDimTeleport.java @@ -0,0 +1,73 @@ +package com.somebody.idlframewok.command; + +import java.util.List; + +import com.google.common.collect.Lists; +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.Teleport; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.text.TextFormatting; + +public class CommandDimTeleport extends CommandBase { + + private final List aliases = Lists.newArrayList(IdlFramework.MODID, "tp", "tpdim", "tpdimension", "chuansong"); + + @Override + public String getName() { + return "tpdimension"; + } + + @Override + public String getUsage(ICommandSender sender) { + return "tpdimension "; + } + + @Override + public List getAliases() { + return aliases; + } + + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) { + return true; + } + + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + if (args.length < 1) { + return; + } + + String s = args[0]; + int dimensionID; + + try{ + dimensionID = Integer.parseInt(s); + }catch (NumberFormatException e) + { + if (sender instanceof EntityPlayerMP) + { + CommonFunctions.SendMsgToPlayerStyled((EntityPlayerMP) sender, "idlframewok.msg.dim_id_invalid", TextFormatting.RED, s); + } + return; + } + + if (sender instanceof EntityPlayer) + { + try{ + Teleport.teleportToDim((EntityPlayer) sender, dimensionID, ((EntityPlayer) sender).posX, ((EntityPlayer) sender).posY, ((EntityPlayer) sender).posZ); + } + catch (IllegalArgumentException e) + { + CommonFunctions.SendMsgToPlayerStyled((EntityPlayerMP) sender, "idlframewok.msg.dim_id_invalid", TextFormatting.RED, s); + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/command/ModCommands.java b/src/main/java/com/somebody/idlframewok/command/ModCommands.java new file mode 100644 index 0000000..6a17c9b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/command/ModCommands.java @@ -0,0 +1,4 @@ +package com.somebody.idlframewok.command; + +public class ModCommands { +} diff --git a/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentBase.java b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentBase.java new file mode 100644 index 0000000..0858950 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentBase.java @@ -0,0 +1,288 @@ +package com.somebody.idlframewok.enchantments; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.EnumEnchantmentType; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.item.ItemTool; +import net.minecraft.util.DamageSource; + +public class ModEnchantmentBase extends Enchantment { + private boolean isTreasure = false; + + private int maxLevel = 1; + + private float base_val = 0f; + private float per_level = 0f; + + private float rarityBaseMultiplier = 1f; + private float rarityDeltaMultiplier = 1f; + + private Enchantment[] conflicts = new Enchantment[]{}; + + private boolean isHidden = false; + + private boolean isCurseEnch = false; + + //make this accessible + protected final EntityEquipmentSlot[] applicableEquipmentTypesOpen; + + //failed attempt to inter-mod compatible + //private Enchantment shareConflicts = null; + + //values get set +// public void setSimulateConflictForVanilla(Enchantment ench) +// {//doesn't work since canApplyTogether is protected +// shareConflicts = ench; +// } + + public ModEnchantmentBase setHidden(boolean val) + { + isHidden = val; + return this; + } + + public ModEnchantmentBase setMaxLevel(int maxLevel) + { + this.maxLevel = maxLevel; + return this; + } + + public ModEnchantmentBase setAsTreasure() + { + this.isTreasure = true; + return this; + } + public ModEnchantmentBase setAsCurse() + { + this.isCurseEnch = true; + return this; + } + + public ModEnchantmentBase setConflicts(Enchantment[] conflicts) + { + this.conflicts = conflicts; + return this; + } + + public ModEnchantmentBase setRarityModifier(float baseFactor, float deltaFactor) + { + this.rarityBaseMultiplier = baseFactor; + this.rarityDeltaMultiplier = deltaFactor; + return this; + } + + public ModEnchantmentBase setValue(float base_val, float per_level) + { + this.base_val = base_val; + this.per_level = per_level; + return this; + } + + @Override + public boolean isCurse() { + return isCurseEnch; + } + + public float getValue(int level) + { + if (level <= 0) + { + return 0; + } + return base_val + (level - 1) * per_level; + } + + public float getValue(EntityLivingBase creature) + { + return getValue(getLevelOnCreature(creature)); + } + + public int getLevelOnCreature(EntityLivingBase creature) + { + if (creature == null) + { + return 0; + } + return EnchantmentHelper.getMaxEnchantmentLevel(this, creature); + } + + public boolean appliedOnCreature(EntityLivingBase creature) + { + if (creature == null) + { + return false; + } + return EnchantmentHelper.getMaxEnchantmentLevel(this, creature) > 0; + } + + //Constructors + public ModEnchantmentBase(String name, Rarity rarityIn, EnumEnchantmentType typeIn, EntityEquipmentSlot[] slots) + { + super(rarityIn, typeIn, slots); + setRegistryName(IdlFramework.MODID, name); + setName(name); + ModEnchantmentInit.ENCHANTMENT_LIST.add(this); + applicableEquipmentTypesOpen = slots; + //note this slots arguments. Only enchantments in those slots will be counted! + + //additional enchantments: (modified level + 1) / 50, after applying, + //modified level /= 2. This don't change the list, but only changes the chance of going on. + + //rarity: +// COMMON(10), +// UNCOMMON(5), +// RARE(2), +// VERY_RARE(1); + } + + // // Generate a random number between 1 and 1+(enchantability/2), with a triangular distribution +// int rand_enchantability = 1 + randomInt(enchantability / 4 + 1) + randomInt(enchantability / 4 + 1); +// +// // Choose the enchantment level +// int k = chosen_enchantment_level + rand_enchantability; +// +// // A random bonus, between .85 and 1.15 +// float rand_bonus_percent = 1 + (randomFloat() + randomFloat() - 1) * 0.15; +// +// // Finally, we calculate the level +// int final_level = round(k * rand_bonus_percent); +//if ( final_level < 1 ) final_level = 1 + + // max: (30 + MaterialEnchantability/2) * 1.15 = 34.5 + 0.575 * ench + //diamond: + + //B = 1~30, depending on slots and bookshelves + //L = B + R1 + R2 + 1 + //R = randomInteger(0, E / 4) + //L *= 1 + random(-0.15,0.15) + @Override + public int getMinEnchantability(int enchantmentLevel) { + return (int) (super.getMinEnchantability(enchantmentLevel) * rarityBaseMultiplier); + } + + @Override + public int getMaxEnchantability(int enchantmentLevel) { + return (int) (getMinEnchantability(enchantmentLevel) * rarityBaseMultiplier + 50 * rarityDeltaMultiplier); + } + + @Override + public int getMaxLevel() { + return maxLevel; + } + + @Override + public int getMinLevel() { + return super.getMinLevel(); + } + + @Override + protected boolean canApplyTogether(Enchantment ench) { + for (Enchantment iter: + conflicts) { + if (ench == iter) + { + return false; + } + } + + return super.canApplyTogether(ench); + } + +// @Override +// public boolean isCompatibleWith(Enchantment en) +// { +// //this won't work +// } + + //Normally you won't care for this + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack) { + //special requirement: tool or sword + if (applicableEquipmentTypesOpen == ModEnchantmentInit.mainHand) + { + Item itemType = stack.getItem(); + if (!(itemType instanceof ItemSword) && !(itemType instanceof ItemTool)) { + return false; + } + } + return !isHidden && super.canApplyAtEnchantingTable(stack); + } + + //if it's treasure, it can NOT be applied at enchant table + //villager will sell it for double price + public boolean isTreasureEnchantment() + { + return this.isTreasure; + } + + // @Override +// public float calcDamageByCreature(int level, EnumCreatureAttribute creatureType) { +// return super.calcDamageByCreature(level, creatureType); +// } + + //other shorthands + public int getEnchantmentLevel(ItemStack stack) { + return EnchantmentHelper.getEnchantmentLevel(this, stack); + } + + /** + * Called whenever a mob is damaged with an item that has this enchantment on it. + */ + public void onEntityDamaged(EntityLivingBase user, Entity target, int level) + { + } + + /** + * Whenever an entity that has this enchantment on one of its associated items is damaged this method will be + * called. + */ + public void onUserHurt(EntityLivingBase user, Entity attacker, int level) + { + } + + /** + * Calculates the damage protection of the enchantment based on level and damage source passed. + */ + public int calcModifierDamage(int level, DamageSource source) + { + //Note that this can't judge the victim's attributes as it does not contain the ref of that living base. + //it returns an int, but at last it calculates as a float. + //1 = 8% Damage. 10 = 80% (max reduction) + //note it's not Enchantment.calcDamageByCreature(int level, EnumCreatureAttribute creatureType) + + return super.calcModifierDamage(level, source); + + //EnchantmentProtection: +// if (source.canHarmInCreative()) +// { +// return 0; +// } +// else if (this.protectionType == EnchantmentProtection.Type.ALL) +// { +// return level; +// } +// else if (this.protectionType == EnchantmentProtection.Type.FIRE && source.isFireDamage()) +// { +// return level * 2; +// } +// else if (this.protectionType == EnchantmentProtection.Type.FALL && source == DamageSource.FALL) +// { +// return level * 3; +// } +// else if (this.protectionType == EnchantmentProtection.Type.EXPLOSION && source.isExplosion()) +// { +// return level * 2; +// } +// else +// { +// return this.protectionType == EnchantmentProtection.Type.PROJECTILE && source.isProjectile() ? level * 2 : 0; +// } + } +} diff --git a/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentInit.java b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentInit.java new file mode 100644 index 0000000..19799fb --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentInit.java @@ -0,0 +1,119 @@ +package com.somebody.idlframewok.enchantments; + +import java.util.ArrayList; +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Enchantments; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.RegistryNamespaced; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = IdlFramework.MODID) +public class ModEnchantmentInit { + + public static final EntityEquipmentSlot[] armorSlots = new EntityEquipmentSlot[] {EntityEquipmentSlot.HEAD, EntityEquipmentSlot.CHEST, EntityEquipmentSlot.LEGS, EntityEquipmentSlot.FEET}; + public static final EntityEquipmentSlot[] allSlots = EntityEquipmentSlot.values(); + public static final EntityEquipmentSlot[] handSlots = new EntityEquipmentSlot[] {EntityEquipmentSlot.MAINHAND, EntityEquipmentSlot.OFFHAND}; + public static final EntityEquipmentSlot[] mainHand = new EntityEquipmentSlot[] {EntityEquipmentSlot.MAINHAND}; + + public static final RegistryNamespaced REGISTRY = net.minecraftforge.registries.GameData.getWrapper(Enchantment.class); + public static final List ENCHANTMENT_LIST = new ArrayList(); + + //Example Enchant +// public static final ModEnchantmentBase ANTI_VANILLA = new ModEnchantmentBase("idlframewok.anti_vanilla", Enchantment.Rarity.UNCOMMON, EnumEnchantmentType.WEAPON, mainHand) +// .setMaxLevel(10).setValue(0.3f, 0.3f); + + //Conflict groups + public static final Enchantment[] WEAPON_DAMAGE_CONFLICT_GROUP = new Enchantment[] + { + Enchantments.SHARPNESS, + Enchantments.SMITE, + Enchantments.BANE_OF_ARTHROPODS, + //ANTI_VANILLA, + }; + + + public static void BeforeRegister() + { + //ANTI_AOA.setHidden(!MetaUtil.isLoaded_AOA3); + + ApplyConflictGroup(WEAPON_DAMAGE_CONFLICT_GROUP); + } + + private static void ApplyConflictGroup(Enchantment[] group) + { + for (Enchantment ench: + group + ) { + //is my enchants + if (ench instanceof ModEnchantmentBase) + { + ((ModEnchantmentBase) ench).setConflicts(group); + } + } + } + + + @SubscribeEvent + public static void onCreatureHurt(LivingHurtEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + + if (evt.isCanceled() || world.isRemote) + { + return; + } + + float dmgModifier = 1f; + + Entity trueSource = evt.getSource().getTrueSource(); + if (trueSource instanceof EntityLivingBase) { + + EntityLivingBase attacker = (EntityLivingBase) trueSource; + + } + + evt.setAmount(evt.getAmount() * dmgModifier); + } + + @SubscribeEvent + public static void onLivingUpdateEvent(LivingEvent.LivingUpdateEvent event) + { + EntityLivingBase livingBase = event.getEntityLiving(); + + for (EntityEquipmentSlot slot: + EntityEquipmentSlot.values()) { + checkItemForTicking(livingBase, slot); + } + } + + public static void checkItemForTicking(EntityLivingBase living, EntityEquipmentSlot slot) + { + World world = living.world; + + ItemStack stack = living.getItemStackFromSlot(slot); + if (!stack.isEmpty()) + { + if (world.getWorldTime() % CommonDef.TICK_PER_SECOND == 0) + { + + } + } + } + + void OnJump(LivingEvent.LivingJumpEvent event) + { + + } +} diff --git a/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentProtection.java b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentProtection.java new file mode 100644 index 0000000..52c49a4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/enchantments/ModEnchantmentProtection.java @@ -0,0 +1,16 @@ +package com.somebody.idlframewok.enchantments; + +import net.minecraft.enchantment.EnumEnchantmentType; +import net.minecraft.inventory.EntityEquipmentSlot; + +public class ModEnchantmentProtection extends ModEnchantmentBase { + public ModEnchantmentProtection(String name, Rarity rarityIn, EnumEnchantmentType typeIn, EntityEquipmentSlot[] slots) { + super(name, rarityIn, typeIn, slots); + } + + //damage *= this + @Override + public float getValue(int level) { + return 1f / (1 + (float)level / 2f); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/BuildingCore.java b/src/main/java/com/somebody/idlframewok/entity/BuildingCore.java new file mode 100644 index 0000000..0a4eee2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/BuildingCore.java @@ -0,0 +1,179 @@ +package com.somebody.idlframewok.entity; + +import java.util.Vector; + +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBase; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlock; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlockBrutal; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBlockSafe; +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionSummonEntity; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class BuildingCore { + + private World world; + protected Vector list; + + protected int reserved_first_tasks_count = 0;//some has to be done before anything else, like clearing + + public float buildRatePerTick = 60f; + public float curBuildCounter = - CommonDef.TICK_PER_SECOND * 3f * buildRatePerTick; + + private int curBuildActionIndex = 0; + private boolean finished = false; + + private BuildingCore() { + } + + public void ResetTasks() + { + reserved_first_tasks_count = 0; + list.clear(); + } + + public void setSpeed(float buildSpeed) + { + buildRatePerTick = buildSpeed; + curBuildCounter = - CommonDef.TICK_PER_SECOND * 3f * buildRatePerTick; + } + + public BuildingCore(World world) { + this.world = world; + list = new Vector<>(); + } + + public void AddTaskSummon(BlockPos pos, Class creature) + { + list.add(new BuilderActionSummonEntity(pos, creature)); + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState) { + AddTaskBuild(pos, newState, false); + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState, boolean isSafe){ + if (isSafe) { + if (newState.getBlock() == Blocks.AIR) { + list.add(reserved_first_tasks_count, new BuilderActionBlock(newState, pos)); + reserved_first_tasks_count++; + }else { + list.add(reserved_first_tasks_count, new BuilderActionBlock(Blocks.BRICK_BLOCK, pos)); + list.add(new BuilderActionBlockSafe(newState, pos)); + } + } else { + list.add(new BuilderActionBlockBrutal(newState, pos)); + } + } + + public void readFromNBT(NBTTagCompound compound) { + //super.readFromNBT(compound); + this.curBuildActionIndex = compound.getInteger(IDLNBTDef.CUR_TASK_INDEX); + this.buildRatePerTick = compound.getFloat(IDLNBTDef.BUILD_SPEED); + + if (curBuildActionIndex >= list.size()) { + finished = true; + } + } + +// public NBTTagCompound getUpdateTag() +// { +// return this.writeToNBT(new NBTTagCompound()); +// } + + public NBTTagCompound writeToNBT(NBTTagCompound compound) + { + //super.writeToNBT(compound); + compound.setInteger(IDLNBTDef.CUR_TASK_INDEX, this.curBuildActionIndex); + compound.setFloat(IDLNBTDef.BUILD_SPEED, this.buildRatePerTick); + return compound; + } + + public BuilderActionBase getCurAction() + { + if (curBuildActionIndex >= list.size()) + { + return list.get(list.size() - 1); + } + else { + return list.get(curBuildActionIndex); + } + } + + public void update(BlockPos basePos) { + boolean remote = world.isRemote; + + if (finished || remote) { + return; + } + + curBuildCounter += buildRatePerTick; + while (curBuildCounter > 1){ + curBuildCounter--; + + BuilderActionBase action = list.get(curBuildActionIndex); + if (action != null){ + boolean success = action.Execute(world, basePos); + if (success) { + curBuildActionIndex++; + if (curBuildActionIndex >= list.size()) { + finished = true; + OnFinished(basePos); + return; + } + } + else { + return; + } + } + } + } + + public float GetProgress() { + return MathHelper.clamp((float) curBuildActionIndex / list.size(), 0f, 1f) ; + } + + public void OnFinished(BlockPos basePos) + { + world.playSound(basePos.getX(), basePos.getY(), basePos.getZ(), SoundEvents.BLOCK_PISTON_EXTEND, null, 1f, 1f, true); + } + + //some helper + public void AddTaskFillWithBlockCentered(BlockPos origin, int rangeX, int rangeY, int rangeZ, IBlockState newState) { + AddTaskFillWithBlockCentered(origin, rangeX, rangeY, rangeZ, newState, false); + } + + public void AddTaskFillWithBlockCentered(BlockPos origin, int rangeX, int rangeY, int rangeZ, IBlockState newState, boolean isSafe) { + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = -rangeY; y <= rangeY; y++) { + for (int z = -rangeZ; z <= rangeZ; z++) { + AddTaskBuild(origin.add(x, y, z), newState, isSafe); + } + } + } + } + + public void AddTaskBuildWallWithBlockCentered(BlockPos origin, int rangeX, int height, int rangeZ, IBlockState newState) { + AddTaskBuildWallWithBlockCentered(origin, rangeX, height, rangeZ, newState, false); + } + + public void AddTaskBuildWallWithBlockCentered(BlockPos origin, int rangeX, int height, int rangeZ, IBlockState newState, boolean isSafe) { + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = height - 1; y >= 0; y--) { + for (int z = -rangeZ; z <= rangeZ; z++) { + AddTaskBuild(origin.add(x, y, z), newState, isSafe); + } + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/ModEntityInit.java b/src/main/java/com/somebody/idlframewok/entity/ModEntityInit.java new file mode 100644 index 0000000..ef28941 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/ModEntityInit.java @@ -0,0 +1,51 @@ +package com.somebody.idlframewok.entity; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.datafix.DataFixer; +import net.minecraftforge.fml.common.registry.EntityRegistry; + +public class ModEntityInit { + private static int ENTITY_NEXT_ID = 1; + public static void registerEntities() + { + //Examples +// registerEntity("moroon_orbital_beacon", EntityMoroonBombBeacon.class); +// registerEntity("moroon_tainter", EntityMoroonTainter.class,0xff00ff, 0x000033); +// registerEntity("idealland_whitetower_core", EntityIDLWhiteTowerCore.class, ENTITY_NEXT_ID, 128, 0xeeee00, 0xffffff); + + //the bullet + //registerEntity("bullet", EntityIdlProjectile.class); + + //Assign Dungeons + //DungeonHooks.addDungeonMob(EntityList.getKey(EntityMoroonTainter.class), STANDARD_DUNGEON_MOB_RARITY); + + DataFixer datafixer = new DataFixer(1343); + } + + private static void registerEntity(String name, Class entity) + { + registerEntity(name, entity, ENTITY_NEXT_ID, 50, 0xff00ff, 0x000000); + } + + private static void registerEntity(String name, Class entity, int color1, int color2) + { + registerEntity(name, entity, ENTITY_NEXT_ID, 50, color1, color2); + } + + private static void registerEntity(String name, Class entity, int id, int range, int color1, int color2){ + EntityRegistry.registerModEntity(new ResourceLocation(Reference.MOD_ID + ":" + name), + entity, + name, + id, + IdlFramework.instance, + range, + 1, + true, + color1, color2 + ); + ENTITY_NEXT_ID++; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/RenderHandler.java b/src/main/java/com/somebody/idlframewok/entity/RenderHandler.java new file mode 100644 index 0000000..1d96f15 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/RenderHandler.java @@ -0,0 +1,19 @@ +package com.somebody.idlframewok.entity; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.entity.creatures.moroon.EntityMoroonUnitBase; +import com.somebody.idlframewok.entity.creatures.render.RenderBullet; +import com.somebody.idlframewok.entity.creatures.render.RenderMoroonHumanoid; +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.client.registry.RenderingRegistry; + +public class RenderHandler { + + public static void registerEntityRenders() { + RenderingRegistry.registerEntityRenderingHandler(EntityMoroonUnitBase.class, RenderMoroonHumanoid::new); + + RenderingRegistry.registerEntityRenderingHandler(EntityIdlProjectile.class, renderManager -> new RenderBullet<>(renderManager, new ResourceLocation(IdlFramework.MODID, + "textures/entity/projectiles/bullet_norm.png"))); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/EntityModUnit.java b/src/main/java/com/somebody/idlframewok/entity/creatures/EntityModUnit.java new file mode 100644 index 0000000..2662feb --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/EntityModUnit.java @@ -0,0 +1,473 @@ +package com.somebody.idlframewok.entity.creatures; + +import java.util.UUID; +import javax.annotation.Nullable; + +import com.google.common.base.Predicate; +import com.somebody.idlframewok.blocks.blockMoroon.BlockMoroonBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import net.minecraft.block.material.EnumPushReaction; +import net.minecraft.block.state.IBlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityCreature; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.World; + +public class EntityModUnit extends EntityCreature { + + private int level = 1; + + public boolean is_pinned_on_ground = false; + public boolean is_mechanic = false; + public boolean is_god = false; + public boolean is_building = false; + public boolean is_cubix = false; + + public boolean spawn_without_darkness = false; + public boolean spawn_without_moroon_ground = false; + + public boolean isMoroon = false; + public boolean isIdealland = false; + protected boolean applyLevelBoost = false; + + public boolean dontDespawn = false; + + public float MP = 0; + public float MPMax = 0; + public float MPRegen = 1 / CommonDef.TICK_PER_SECOND; + + protected static final DataParameter SWINGING_ARMS = EntityDataManager.createKey(EntityModUnit.class, DataSerializers.BOOLEAN); + + public EntityModUnit(World worldIn) { + super(worldIn); + //this.entityCollisionReduction = 0.9f;//not much use for fixed ones + } + + public EntityModUnit setBuilding() + { + is_mechanic = true; + is_building = true; + is_pinned_on_ground = true; + dontDespawn = true; + return this; + } + + + protected void entityInit() + { + this.dataManager.register(SWINGING_ARMS, Boolean.FALSE); + + super.entityInit(); + } + + @Override + public void writeEntityToNBT(NBTTagCompound compound) { + super.writeEntityToNBT(compound); + compound.setInteger(IDLNBTDef.LEVEL, level); + } + + @Override + public void readEntityFromNBT(NBTTagCompound compound) { + super.readEntityFromNBT(compound); + level = compound.getInteger(IDLNBTDef.LEVEL); + } + + public void setLevel(int newLevel) + { + if (newLevel > 0) + { + level = newLevel; + ApplyLevelModifier(); + } + } + + public int getLevel() + { + return level; + } + + protected int maxEasyLevel = 3; + protected int maxNormLevel = 5; + protected int maxHardLevel = 10; + + public int getMaxLevel() { + return 10; + } + + public int getRank() + { + int level = getLevel(); + if (level>=maxHardLevel) + { + return 4; + } + else if (level>=maxNormLevel) + { + return 3; + } + else if (level>=maxEasyLevel) + { + return 2; + } + return 1; + } + + public void ApplyGeneralLevelBoost(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) + { + //with localDiff / 10 chance to lv up recursively + int level = getLevel(); + int maxLv = getMaxLevel(); + float localDifficulty = difficulty.getAdditionalDifficulty(); + while (level < maxLv && ((getRNG().nextFloat()* 10f) <= localDifficulty)) + { + level++; + } + setLevel(level); + } + + @Override + public void onUpdate() { + super.onUpdate(); + + if (EntityUtil.getAttitude(EntityUtil.Faction.PLAYER, this) == EntityUtil.ATTITUDE.HATE) + { + if (!this.world.isRemote && this.world.getDifficulty() == EnumDifficulty.PEACEFUL) + { + this.setDead(); + } + } + + if (is_pinned_on_ground) + { + motionX = 0; + motionZ = 0; + } + + if (MP < MPMax) + { + MP += MPRegen; + if (MP > MPMax) + { + MP = MPMax; + } + } + } + + public boolean trySpendMana(float val) + { + if (val <= MP) + { + MP -= val; + return true; + } + return false; + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); + } + + //KB:1.0 = total defend + public void setAttr(double sight, double speed, double attack, double armor, double hp) + { + //float modifier = getLevelModifier(); + float modifier = 1f; + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(sight * modifier); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(speed * modifier); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(attack * modifier); + this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(armor * modifier); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(hp * modifier); + if (is_pinned_on_ground) + { + this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(2.0f); + } + } + + protected static final UUID LEVEL_BONUS_UUID = UUID.fromString("CEE0E5FE-3E5C-4515-AD0C-66483EAC7B9B"); + + public void ApplyLevelModifier() + { + AttributeModifier LEVEL_BONUS_MODIFIER = (new AttributeModifier(LEVEL_BONUS_UUID, "level bonus", getLevelModifier(), 1)); + + //prevent crashing + if (this.getEntityAttribute(SharedMonsterAttributes.ARMOR).hasModifier(LEVEL_BONUS_MODIFIER)) { + this.getEntityAttribute(SharedMonsterAttributes.ARMOR).removeModifier(LEVEL_BONUS_UUID); + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).removeModifier(LEVEL_BONUS_UUID); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).removeModifier(LEVEL_BONUS_UUID); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).removeModifier(LEVEL_BONUS_UUID); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).removeModifier(LEVEL_BONUS_UUID); + } + + this.getEntityAttribute(SharedMonsterAttributes.ARMOR).applyModifier(LEVEL_BONUS_MODIFIER); + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).applyModifier(LEVEL_BONUS_MODIFIER); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).applyModifier(LEVEL_BONUS_MODIFIER); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).applyModifier(LEVEL_BONUS_MODIFIER); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier(LEVEL_BONUS_MODIFIER); + this.setHealth(this.getMaxHealth()); + } + + public float getLevelModifier() + { + return (level - 1f) * 0.2f; + } + + //Simulate EntityMob, use enchantments, knockback, etc. + //this is attacking other + public boolean attackEntityAsMob(Entity target) + { + float f = (float)this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); + int i = 0; + + if (target instanceof EntityLivingBase) + { + f += EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((EntityLivingBase)target).getCreatureAttribute()); + i += EnchantmentHelper.getKnockbackModifier(this); + } + + boolean flag = target.attackEntityFrom(DamageSource.causeMobDamage(this), f); + + if (flag) + { + if (i > 0) + { + ((EntityLivingBase)target).knockBack(this, (float)i * 0.5F, (double) MathHelper.sin(this.rotationYaw * 0.017453292F), (double)(-MathHelper.cos(this.rotationYaw * 0.017453292F))); + this.motionX *= 0.6D; + this.motionZ *= 0.6D; + } + + int j = EnchantmentHelper.getFireAspectModifier(this); + + if (j > 0) + { + target.setFire(j * 4); + } + + if (target instanceof EntityPlayer) + { + EntityPlayer entityplayer = (EntityPlayer)target; + ItemStack itemstack = this.getHeldItemMainhand(); + ItemStack itemstack1 = entityplayer.isHandActive() ? entityplayer.getActiveItemStack() : ItemStack.EMPTY; + + if (!itemstack.isEmpty() && !itemstack1.isEmpty() && itemstack.getItem().canDisableShield(itemstack, itemstack1, entityplayer, this) && itemstack1.getItem().isShield(itemstack1, entityplayer)) + { + float f1 = 0.25F + (float)EnchantmentHelper.getEfficiencyModifier(this) * 0.05F; + + if (this.rand.nextFloat() < f1) + { + entityplayer.getCooldownTracker().setCooldown(itemstack1.getItem(), 100); + this.world.setEntityState(entityplayer, (byte)30); + } + } + } + + this.applyEnchantments(this, target); + } + + return flag; + } + + + + public EnumPushReaction getPushReaction() + { + if (is_pinned_on_ground) + { + return EnumPushReaction.IGNORE; + } + else { + return EnumPushReaction.NORMAL; + } + } + /** + * Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called + * when entity is reloaded from nbt. Mainly used for initializing attributes and inventory + */ + @Nullable + public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) + { + livingdata = super.onInitialSpawn(difficulty, livingdata); + return livingdata; + } + + @Override + public void addVelocity(double x, double y, double z) { + if (is_pinned_on_ground) { + super.addVelocity(0, y, 0); + } else { + super.addVelocity(x, y, z); + } + } + + //being knocked by others + @Override + public void knockBack(Entity source, float strength, double xRatio, double zRatio) { + if (!is_pinned_on_ground) { + super.knockBack(source, strength, xRatio, zRatio); + } + } + + //sound + @Override + protected SoundEvent getAmbientSound() { + return super.getAmbientSound(); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damageSourceIn) { + return super.getHurtSound(damageSourceIn); + } + + @Override + protected SoundEvent getDeathSound() { + return super.getDeathSound(); + } + + + //Spawn------------------------------------------------------ + + public boolean getCanSpawnHere() + { + IBlockState iblockstate = this.world.getBlockState((new BlockPos(this)).down()); + + return iblockstate.canEntitySpawn(this) + && this.getBlockPathWeight(new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ)) >= 0.0F + && (spawn_without_darkness || isValidLightLevel()) + && (spawn_without_moroon_ground || iblockstate.getBlock() instanceof BlockMoroonBase); + } + + /** + * Checks to make sure the light is not too bright where the mob is spawning + */ + protected boolean isValidLightLevel() + { + BlockPos blockpos = new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ); + + if (this.world.getLightFor(EnumSkyBlock.SKY, blockpos) > this.rand.nextInt(32)) + { + return false; + } + else + { + int i = this.world.getLightFromNeighbors(blockpos); + + if (this.world.isThundering()) + { + int j = this.world.getSkylightSubtracted(); + this.world.setSkylightSubtracted(10); + i = this.world.getLightFromNeighbors(blockpos); + this.world.setSkylightSubtracted(j); + } + + return i <= this.rand.nextInt(8); + } + } + +// /** +// * Get this Entity's EnumCreatureAttribute +// */ +// public EnumCreatureAttribute getCreatureAttribute() +// { +// return EnumCreatureAttribute.UNDEAD; +// } + +// @Nullable +// protected ResourceLocation getLootTable() +// { +// return ModLootList.EMPTY; +// } + + //AI.................................. + public class ModAIAttackNearest extends EntityAINearestAttackableTarget + { + public ModAIAttackNearest(EntityCreature creature, Class classTarget, boolean checkSight) { + super(creature, classTarget, checkSight); + } + + public ModAIAttackNearest(EntityCreature creature, Class classTarget, boolean checkSight, boolean onlyNearby) { + super(creature, classTarget, checkSight, onlyNearby); + } + + public ModAIAttackNearest(EntityCreature creature, Class classTarget, int chance, boolean checkSight, boolean onlyNearby, @Nullable Predicate targetSelector) { + super(creature, classTarget, chance, checkSight, onlyNearby, targetSelector); + } + + protected AxisAlignedBB getTargetableArea(double targetDistance) + { + return this.taskOwner.getEntityBoundingBox().grow(targetDistance, targetDistance, targetDistance); + } + } + + public class ModAIAttackNearestAntiAir extends EntityAINearestAttackableTarget + { + public ModAIAttackNearestAntiAir(EntityCreature creature, Class classTarget, boolean checkSight) { + super(creature, classTarget, checkSight); + } + + public ModAIAttackNearestAntiAir(EntityCreature creature, Class classTarget, boolean checkSight, boolean onlyNearby) { + super(creature, classTarget, checkSight, onlyNearby); + } + + public ModAIAttackNearestAntiAir(EntityCreature creature, Class classTarget, int chance, boolean checkSight, boolean onlyNearby, @Nullable Predicate targetSelector) { + super(creature, classTarget, chance, checkSight, onlyNearby, targetSelector); + } + + protected AxisAlignedBB getTargetableArea(double targetDistance) + { + return this.taskOwner.getEntityBoundingBox().grow(targetDistance, 255, targetDistance); + } + } + + @Override + public boolean attackEntityFrom(DamageSource source, float amount) { + if (is_building){ + if (source == DamageSource.IN_WALL) { + return false; + } + + if (source.isExplosion() || source.isFireDamage()) + { + amount *= 2; + } + + if (source.isProjectile()) + { + amount *= 0.5f; + } + } + + return super.attackEntityFrom(source, amount); + } + + @Override + public boolean isNoDespawnRequired() { + return dontDespawn; + } + + protected boolean canDespawn() + { + return !dontDespawn; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/BulletMode.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/BulletMode.java new file mode 100644 index 0000000..c5d649d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/BulletMode.java @@ -0,0 +1,7 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +//Imitate TF +public enum BulletMode{ + SmallFireball, + BigFireball +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIAttackRangedSniper.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIAttackRangedSniper.java new file mode 100644 index 0000000..7ea259e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIAttackRangedSniper.java @@ -0,0 +1,14 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.ai.EntityAIAttackRanged; + +public class EntityAIAttackRangedSniper extends EntityAIAttackRanged { + public EntityAIAttackRangedSniper(IRangedAttackMob attacker, double movespeed, int maxAttackTime, float maxAttackDistanceIn) { + super(attacker, movespeed, maxAttackTime, maxAttackDistanceIn); + } + + public EntityAIAttackRangedSniper(IRangedAttackMob attacker, double movespeed, int p_i1650_4_, int maxAttackTime, float maxAttackDistanceIn) { + super(attacker, movespeed, p_i1650_4_, maxAttackTime, maxAttackDistanceIn); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIBulletAttack.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIBulletAttack.java new file mode 100644 index 0000000..dfcaec4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIBulletAttack.java @@ -0,0 +1,161 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.entity.projectile.EntitySmallFireball; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class EntityAIBulletAttack extends EntityAIBase +{ + public RangedAttackArguments attackArguments = new RangedAttackArguments(); + public static float hostRadius = 0.5f; + private World worldObj; + /** The entity the AI instance has been applied to */ + private EntityLiving entityHost; + private EntityLivingBase attackTarget; + private float sqRange = 100f; + /** + * A decrementing tick that spawns a ranged attack once this value reaches 0. It is then set back to the + * maxRangedAttackTime. + */ + private int rangedAttackTime = 0; + private int ticksLookingAtTarget = 0; + + public EntityAIBulletAttack(EntityLiving par1EntityLiving, RangedAttackArguments args){ + this.attackArguments = args; + sqRange = args.range * args.range; + this.entityHost = par1EntityLiving; + this.worldObj = par1EntityLiving.world; + this.setMutexBits(3); + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() + { + EntityLivingBase var1 = this.entityHost.getAttackTarget(); + + if (var1 == null || this.entityHost.getRNG().nextFloat() > attackArguments.attack_chance) + { + return false; + } + else + { + this.attackTarget = var1; + return true; + } + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + @Override + public boolean shouldContinueExecuting() + { +// if (attackArguments.isTurret) { +// return this.shouldExecute(); +// } else { + return this.shouldExecute() || !this.entityHost.getNavigator().noPath(); +// } + } + + /** + * Resets the task + */ + @Override + public void resetTask() + { + this.attackTarget = null; + } + + /** + * Updates the task + */ + @Override + public void updateTask() + { + double maxRange = sqRange; + double targetDistance = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.posY, this.attackTarget.posZ); + boolean canSee = this.entityHost.getEntitySenses().canSee(this.attackTarget); + + if (canSee) + { + ++this.ticksLookingAtTarget; + } + else + { +// IdlFramework.LogWarning("cant see"); + this.ticksLookingAtTarget = 0; + } + +// IdlFramework.Log(String.format("Looking ticks = %d", ticksLookingAtTarget )); +// IdlFramework.Log(String.format("dist = %.2f/%.2f", targetDistance, maxRange)); + if (targetDistance <= maxRange && this.ticksLookingAtTarget >= 20) + { + this.entityHost.getNavigator().clearPath(); + } + else + { + this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, attackArguments.bullet_speed); +// if (!attackArguments.isTurret) { +// this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, attackArguments.bullet_speed); +// } +// else if (this.ticksLookingAtTarget >= 100) { +// resetTask(); +// return; +// } + } + + this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F); + this.rangedAttackTime = Math.max(this.rangedAttackTime - 1, 0); + + if (this.rangedAttackTime <= 0) + { + if (targetDistance <= maxRange && canSee) + { + this.doRangedAttack(); + this.rangedAttackTime = attackArguments.cool_down; + } + } + } + + /** + * Performs a ranged attack according to the AI's rangedAttackID. + */ + protected void doRangedAttack() + { + double d1 = hostRadius; + Vec3d vec3d = this.entityHost.getLook(1.0F); + double d2 = attackTarget.posX - (this.entityHost.posX + vec3d.x * d1); + double d3 = attackTarget.getEntityBoundingBox().minY + (double)(attackTarget.height / 2.0F) - (0.5D + this.entityHost.posY + (double)(this.entityHost.height / 2.0F)); + double d4 = attackTarget.posZ - (this.entityHost.posZ + vec3d.z * d1); + worldObj.playEvent(null, 1016, new BlockPos(this.entityHost), 0); + + //this swing is not working for turrets, reason unknown. + //will probably work on other things. + this.entityHost.swingArm(EnumHand.MAIN_HAND); + this.entityHost.swingArm(EnumHand.OFF_HAND); + this.entityHost.limbSwingAmount = 1.5f; + + EntityFireball entityBullet; + if (attackArguments.attack_mode == BulletMode.SmallFireball) { + entityBullet = new EntitySmallFireball(worldObj, this.entityHost, d2, d3, d4); + } else { + entityBullet = new EntityLargeFireball(worldObj, this.entityHost, d2, d3, d4); + ((EntityLargeFireball)entityBullet).explosionPower = (int)attackArguments.power; + } + + entityBullet.posX = this.entityHost.posX + vec3d.x * d1; + entityBullet.posY = this.entityHost.posY + (double)(this.entityHost.height / 2.0F); + entityBullet.posZ = this.entityHost.posZ + vec3d.z * d1; + worldObj.spawnEntity(entityBullet); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIStrafeRangedAttack.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIStrafeRangedAttack.java new file mode 100644 index 0000000..823afc3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAIStrafeRangedAttack.java @@ -0,0 +1,197 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.util.EnumHand; + +public class EntityAIStrafeRangedAttack extends EntityAIBase +{ + private final T entity; + private final double moveSpeedAmp; + private int attackCooldown; + private final float maxAttackDistanceSq; + private int attackTime = -1; + private int seeTime; + private boolean strafingClockwise; + private boolean strafingBackwards; + private int strafingTime = -1; + float targetLostThreshold = 3f; + + float aimingCooldownTimeMin = 0.3f; + float aimingCooldownTimeDelta = 0.7f; + + int curAimingCooldownThreshold = 0; + void randomAimingCooldown() + { + curAimingCooldownThreshold = (int) (CommonDef.TICK_PER_SECOND *( aimingCooldownTimeMin + this.entity.getRNG().nextFloat() * aimingCooldownTimeDelta)); + } + + public EntityAIStrafeRangedAttack(T self, double moveSpeedAmp, int attackCd, float maxAttackDistance) + { + this.entity = self; + this.moveSpeedAmp = moveSpeedAmp; + this.attackCooldown = attackCd; + this.maxAttackDistanceSq = maxAttackDistance * maxAttackDistance; + this.setMutexBits(3); + } + + //This is the time between two attacking-aiming sequence + public void setAttackCooldown(int attackCooldown) + { + this.attackCooldown = attackCooldown; + } + + //aiming can be interruppted by sight lost + public void setAimingCooldown(float minVal, float range) + { + aimingCooldownTimeMin = minVal; + aimingCooldownTimeDelta = range; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + return this.entity.getAttackTarget() != null && this.isRangedWeaponInMainhand(); + } + + protected boolean isRangedWeaponInMainhand() + { + return CommonFunctions.isItemRangedWeapon(this.entity.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND)); + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean shouldContinueExecuting() + { + return (this.shouldExecute() || !this.entity.getNavigator().noPath()) && this.isRangedWeaponInMainhand(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + super.startExecuting(); + this.entity.setSwingingArms(true); + } + + /** + * Reset the task's internal state. Called when this task is interrupted by another one + */ + public void resetTask() + { + super.resetTask(); + this.entity.setSwingingArms(false); + this.seeTime = 0; + this.attackTime = -1; + this.entity.resetActiveHand(); + } + + /** + * Keep ticking a continuous task that has already been started + */ + public void updateTask() + { + EntityLivingBase entitylivingbase = this.entity.getAttackTarget(); + + if (entitylivingbase != null) + { + double d0 = this.entity.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ); + boolean canSee = this.entity.getEntitySenses().canSee(entitylivingbase); + boolean flag1 = this.seeTime > 0; + + if (canSee != flag1) + { + this.seeTime = 0; + } + + if (canSee) + { + ++this.seeTime; + } + else + { + --this.seeTime; + } + + if (d0 <= (double)this.maxAttackDistanceSq && this.seeTime >= CommonDef.TICK_PER_SECOND) + { + this.entity.getNavigator().clearPath(); + ++this.strafingTime; + } + else + { + this.entity.getNavigator().tryMoveToEntityLiving(entitylivingbase, this.moveSpeedAmp); + this.strafingTime = -1; + } + + if (this.strafingTime >= CommonDef.TICK_PER_SECOND) + { + if ((double)this.entity.getRNG().nextFloat() < 0.3D) + { + this.strafingClockwise = !this.strafingClockwise; + } + + if ((double)this.entity.getRNG().nextFloat() < 0.3D) + { + this.strafingBackwards = !this.strafingBackwards; + } + + this.strafingTime = 0; + } + + if (this.strafingTime > -1) + { + if (d0 > (double)(this.maxAttackDistanceSq * 0.75F)) + { + this.strafingBackwards = false; + } + else if (d0 < (double)(this.maxAttackDistanceSq * 0.25F)) + { + this.strafingBackwards = true; + } + + this.entity.getMoveHelper().strafe(this.strafingBackwards ? -0.5F : 0.5F, this.strafingClockwise ? 0.5F : -0.5F); + this.entity.faceEntity(entitylivingbase, 30.0F, 30.0F); + } + else + { + this.entity.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F); + } + + //IdlFramework.Log("isHandActive = %s, uuid=%s", this.entity.isHandActive(), this.entity.getUniqueID()); + if (this.entity.isHandActive()) + { + if (!canSee && this.seeTime < -targetLostThreshold * CommonDef.TICK_PER_SECOND) + { + this.entity.resetActiveHand(); + } + else if (canSee) + { + int aimingTicks = this.entity.getItemInUseMaxCount(); + + if (aimingTicks >= curAimingCooldownThreshold) + { + this.entity.resetActiveHand(); + this.entity.attackEntityWithRangedAttack(entitylivingbase, (float) d0); + this.attackTime = this.attackCooldown; + + randomAimingCooldown(); + } + } + } + else if (--this.attackTime <= 0 && this.seeTime >= -targetLostThreshold * CommonDef.TICK_PER_SECOND) + { + this.entity.setActiveHand(EnumHand.MAIN_HAND); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAITurretAttack.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAITurretAttack.java new file mode 100644 index 0000000..814d806 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/EntityAITurretAttack.java @@ -0,0 +1,126 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import com.somebody.idlframewok.entity.projectiles.ProjectileArgs; +import com.somebody.idlframewok.util.EntityUtil; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.EnumDifficulty; + +public class EntityAITurretAttack extends EntityAIBase { + + protected final EntityLiving self; + protected int curCoolDown; + protected float rangeSquare = 400f; + float errorModifier; + float bulletAccel = 0.1f; + + public int coolDownMin = 20;//ticks + public int coolDownDelta = 20;//ticks + + public EntityAITurretAttack(EntityLiving self, float errorModifier) + { + this.self = self; + this.errorModifier = errorModifier; + } + + public EntityAITurretAttack(EntityLiving self, float errorModifier, int coolDownMin, int coolDownDelta) { + this.self = self; + this.errorModifier = errorModifier; + this.coolDownMin = coolDownMin; + this.coolDownDelta = coolDownDelta; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() { + EntityLivingBase entitylivingbase = self.getAttackTarget(); + return entitylivingbase != null && entitylivingbase.isEntityAlive(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.curCoolDown = coolDownMin; + } + + /** + * Reset the task's internal state. Called when this task is interrupted by another one + */ + public void resetTask() + { + + } + + /** + * Keep ticking a continuous task that has already been started + */ + public void updateTask() + { + if (self.world.getDifficulty() != EnumDifficulty.PEACEFUL) + { + --this.curCoolDown; + EntityLivingBase attackTarget = self.getAttackTarget(); + + if (attackTarget != null) + { + double d0 = self.getDistanceSq(attackTarget); + self.getLookHelper().setLookPosition(attackTarget.posX, + attackTarget.posY + (double)attackTarget.getEyeHeight(), + attackTarget.posZ, + (float)self.getHorizontalFaceSpeed(), + (float)self.getVerticalFaceSpeed()); + + rangeSquare = (float) (EntityUtil.getSight(self) * EntityUtil.getSight(self)); + + if (d0 < rangeSquare) + { + if (this.curCoolDown <= 0) + { + IAttributeInstance attribute = self.getEntityAttribute(SharedMonsterAttributes.ATTACK_SPEED); + double speedFactor = ((attribute == null) || (attribute.getAttributeValue() == 0)) ? 1 : attribute.getBaseValue() / attribute.getAttributeValue(); + + this.curCoolDown = (int) ((coolDownMin + self.getRNG().nextInt(coolDownDelta)) * speedFactor); + onAttackTriggered(attackTarget); + + } + } + else + { + self.setAttackTarget(null); + } + } + super.updateTask(); + } + } + + public void onAttackTriggered(EntityLivingBase target) + { + double d0 = self.getDistanceSq(target); + double d1 = target.posX - self.posX; + double d2 = target.getEntityBoundingBox().minY + (double)(target.height / 2.0F) - (self.posY + (double)(self.height / 2.0F)); + double d3 = target.posZ - self.posZ; + + float dist = MathHelper.sqrt(MathHelper.sqrt(d0)); + float estimateHitTime = MathHelper.sqrt(2 * bulletAccel * dist); + + //float halfDist = MathHelper.sqrt(MathHelper.sqrt(d0)) * 0.5F; + + EntityIdlProjectile entityIdlProjectile = new EntityIdlProjectile(self.world, new ProjectileArgs((float) EntityUtil.getAttack(self)), self, + d1 + self.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionX, + d2 + self.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionY, + d3 + self.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionZ, + bulletAccel); + + //entityIdlProjectile.posY += self.posY + (double)(self.height / 2.0F); + self.world.spawnEntity(entityIdlProjectile); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ai/RangedAttackArguments.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/RangedAttackArguments.java new file mode 100644 index 0000000..ccf8299 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ai/RangedAttackArguments.java @@ -0,0 +1,11 @@ +package com.somebody.idlframewok.entity.creatures.ai; + +public class RangedAttackArguments { + public float range = 100f; + public int cool_down = 20;//ticks + public float power = 1f; + public float bullet_speed = 2f; + public float attack_chance = 1f; + public BulletMode attack_mode = BulletMode.SmallFireball; + public boolean isTurret = false; +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingBase.java b/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingBase.java new file mode 100644 index 0000000..01477ec --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingBase.java @@ -0,0 +1,96 @@ +package com.somebody.idlframewok.entity.creatures.buildings; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.blocks.tileEntity.builder.builderAction.BuilderActionBase; +import com.somebody.idlframewok.entity.BuildingCore; +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.World; + +public class EntityIdlBuildingBase extends EntityModUnit { + BuildingCore buildingCore; + protected boolean suicide_after_finish = true; + public EntityIdlBuildingBase(World worldIn) { + super(worldIn); + + buildingCore = new BuildingCore(worldIn); + InitTaskQueue(); + setAttr(1, 0, 0, 8, 10); + this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(1.0); + setBuilding(); + } + + @Nullable + @Override + public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) { + + + return super.onInitialSpawn(difficulty, livingdata); + } + + public Vec3d getCurBuildingVector() + { + BuilderActionBase action = buildingCore.getCurAction(); + if (action == null) + { + return Vec3d.ZERO; + }else { + Vec3d result = action.getRelativePos(); + return result==null ? Vec3d.ZERO : result; + } + } + + void InitTaskQueue() + { + AddTaskBuild(getPosition().add(0,-1,0), Blocks.BRICK_BLOCK.getDefaultState()); + //AddTaskBuildWallWithBlockCentered(origin.add(-floorReach,2,0), 0, windowHeight, 1, windowMaterial); + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState) { + buildingCore.AddTaskBuild(pos, newState, true); + } + + public void AddTaskBuild(BlockPos pos, IBlockState newState, boolean isSafe) { + buildingCore.AddTaskBuild(pos, newState, isSafe); + } + + @Override + public void onUpdate() { + super.onUpdate(); + buildingCore.update(this.getPosition()); + + if (!world.isRemote && suicide_after_finish && buildingCore.GetProgress() >= 1f) + { + attackEntityFrom(DamageSource.OUT_OF_WORLD, getMaxHealth() * 100f); + } + } + + @Override + public void readFromNBT(NBTTagCompound compound) { + super.readFromNBT(compound); + buildingCore.readFromNBT(compound); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound) { + NBTTagCompound result = super.writeToNBT(compound); + result = buildingCore.writeToNBT(result); + return result; + } + + @Override + protected boolean canDespawn() { + return false; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingRoom.java b/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingRoom.java new file mode 100644 index 0000000..900061a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/buildings/EntityIdlBuildingRoom.java @@ -0,0 +1,52 @@ +package com.somebody.idlframewok.entity.creatures.buildings; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EntityIdlBuildingRoom extends EntityIdlBuildingBase { + + private int size = 3; + + public EntityIdlBuildingRoom(World worldIn) { + super(worldIn); + setAttr(1, 0, 0, 8, 5); + size = 3;//ModConfig.DEBUG_CONF.ROOM_SIZE; + buildingCore.ResetTasks(); + InitTaskQueue(); + buildingCore.setSpeed(40f / CommonDef.TICK_PER_SECOND); + IdlFramework.LogWarning("Summon. Size = " + size); + } + + void InitTaskQueue() + { + BlockPos origin = new BlockPos(0,0,0); + + if (buildingCore == null) + { + IdlFramework.LogWarning("Core is null"); + } + + int bottomRange = size; + int wallHeight = 2 * size + 1; + + IdlFramework.LogWarning("Size = " + size); + + IBlockState blockState = Blocks.IRON_BLOCK.getDefaultState(); + + //floor + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(0, -1, 0), bottomRange, 1, bottomRange, blockState); + + //ceiling + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(0, wallHeight, 0), bottomRange, 1, bottomRange, blockState); + + //surrounding + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(0, 0, bottomRange + 1), bottomRange + 1, wallHeight, 0, blockState); + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(0, 0, -bottomRange - 1), bottomRange + 1, wallHeight, 0, blockState); + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(bottomRange + 1, 0, 0), 0, wallHeight, bottomRange, blockState); + buildingCore.AddTaskBuildWallWithBlockCentered(origin.add(-bottomRange - 1, 0, 0), 0, wallHeight, bottomRange, blockState); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/ideallandTeam/EntityIdeallandUnitBase.java b/src/main/java/com/somebody/idlframewok/entity/creatures/ideallandTeam/EntityIdeallandUnitBase.java new file mode 100644 index 0000000..ece708a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/ideallandTeam/EntityIdeallandUnitBase.java @@ -0,0 +1,72 @@ +package com.somebody.idlframewok.entity.creatures.ideallandTeam; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.pathfinding.PathNavigateGround; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.World; + +public class EntityIdeallandUnitBase extends EntityModUnit { + public EntityIdeallandUnitBase(World worldIn) { + super(worldIn); + setCanPickUpLoot(false);//prevent pick up player things. keep until gui done + isMoroon = false; + isIdealland = true; + dontDespawn = true; + } + + public int getRank() + { + int level = getLevel(); + if (level>=maxHardLevel) + { + return 4; + } + else if (level>=maxNormLevel) + { + return 3; + } + else if (level>=maxEasyLevel) + { + return 2; + } + return 1; + } + + public void ApplyGeneralLevelBoost(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) + { + //with localDiff / 10 chance to lv up recursively + int level = getLevel(); + int maxLv = getMaxLevel(); + float localDifficulty = difficulty.getAdditionalDifficulty(); + while (level < maxLv && ((getRNG().nextFloat()* 10f) <= localDifficulty)) + { + level++; + } + setLevel(level); + } + +// @Nullable +// @Override +// public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) { +// livingdata = super.onInitialSpawn(difficulty, livingdata); +// ApplyGeneralLevelBoost(difficulty, livingdata); +// return super.onInitialSpawn(difficulty, livingdata); +// } + + protected void applyGeneralAI() + { + +// this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, false, true, new Predicate() +// { +// public boolean apply(@Nullable EntityLiving p_apply_1_) +// { +// return p_apply_1_ != null && IMob.VISIBLE_MOB_SELECTOR.apply(p_apply_1_) && !(p_apply_1_ instanceof EntityCreeper); +// } +// })); + + ((PathNavigateGround)this.getNavigator()).setEnterDoors(true); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityEternalZombie.java b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityEternalZombie.java new file mode 100644 index 0000000..170fcfa --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityEternalZombie.java @@ -0,0 +1,35 @@ +package com.somebody.idlframewok.entity.creatures.misc; + +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class EntityEternalZombie extends EntityZombie { + + public EntityEternalZombie(World worldIn) { + super(worldIn); + setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.DIAMOND_HELMET)); + setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(Items.DIAMOND_CHESTPLATE)); + setItemStackToSlot(EntityEquipmentSlot.LEGS, new ItemStack(Items.DIAMOND_LEGGINGS)); + setItemStackToSlot(EntityEquipmentSlot.FEET, new ItemStack(Items.DIAMOND_BOOTS)); + + setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.DIAMOND_SWORD)); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(35.0D); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(3.0D); + this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(2.0D); + } + + protected boolean shouldBurnInDay() + { + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityHiredSkeleton.java b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityHiredSkeleton.java new file mode 100644 index 0000000..afec696 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityHiredSkeleton.java @@ -0,0 +1,49 @@ +package com.somebody.idlframewok.entity.creatures.misc; + +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.monster.EntitySkeleton; +import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class EntityHiredSkeleton extends EntitySkeleton { + + boolean canDespawnNatural = true; + + public void SetDespawnable(boolean val) + { + canDespawnNatural = val; + } + + public EntityHiredSkeleton(World worldIn) { + super(worldIn); + setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.LEATHER_HELMET)); + setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(Items.LEATHER_CHESTPLATE)); + setItemStackToSlot(EntityEquipmentSlot.LEGS, new ItemStack(Items.LEATHER_LEGGINGS)); + setItemStackToSlot(EntityEquipmentSlot.FEET, new ItemStack(Items.LEATHER_BOOTS)); + + setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(35.0D); + } + + @Override + public void onEntityUpdate() { + super.onEntityUpdate(); + //IdlFramework.Log(getPositionVector() + " " + getUniqueID().toString()); + } + + protected boolean shouldBurnInDay() + { + return false; + } + protected boolean canDespawn() + { + return canDespawnNatural; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype.java b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype.java new file mode 100644 index 0000000..0544d56 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype.java @@ -0,0 +1,205 @@ +package com.somebody.idlframewok.entity.creatures.misc; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.entity.ai.EntityAIFindEntityNearestPlayer; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.monster.EntityGhast; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class EntityTurretPrototype extends EntityGhast { + public EntityTurretPrototype(World worldIn) { + super(worldIn); + this.setSize(0.9F,1F); + } + + @Override + protected void initEntityAI() { + //super.initEntityAI(); + //this.tasks.addTask(7, new EntityTurretPrototype.AILookAround(this)); + this.tasks.addTask(7, new EntityTurretPrototype.AIFireballAttack(this)); + this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); + this.tasks.addTask(7, new EntityAILookIdle(this)); + + this.targetTasks.addTask(1, new EntityAIFindEntityNearestPlayer(this)); + //this.targetTasks.addTask(1, new EntityAIFindEntityNearestPlayer(this)); + //this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); + //this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); + //this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityCow.class, true)); + } + + @Override + protected void applyEntityAttributes() { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(40.0D); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0D); + this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(1.0D); + } + + @Override + public float getEyeHeight() { + return 0.5F; + } + + @Override + protected SoundEvent getAmbientSound() { + return super.getAmbientSound(); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damageSourceIn) { + return super.getHurtSound(damageSourceIn); + } + + @Override + protected SoundEvent getDeathSound() { + return super.getDeathSound(); + } + + //attacking + /** The explosion radius of spawned fireballs. */ + private int explosionStrength = 1; + public int getFireballStrength() + { + return this.explosionStrength; + } + +// private static final DataParameter ATTACKING = EntityDataManager.createKey(EntityTurretPrototype.class, DataSerializers.BOOLEAN); + +// public void setAttacking(boolean attacking) +// { +// this.dataManager.set(ATTACKING, attacking); +// } + + //AI + public static class AIFireballAttack extends EntityAIBase + { + private final EntityTurretPrototype parentEntity; + public int attackTimer; + + public AIFireballAttack(EntityTurretPrototype ghast) + { + this.parentEntity = ghast; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + return this.parentEntity.getAttackTarget() != null; + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.attackTimer = 0; + } + + /** + * Reset the task's internal state. Called when this task is interrupted by another one + */ + public void resetTask() + { + this.parentEntity.setAttacking(false); + } + + /** + * Keep ticking a continuous task that has already been started + */ + public void updateTask() + { + EntityLivingBase entitylivingbase = this.parentEntity.getAttackTarget(); + double d0 = 64.0D; + + if (entitylivingbase.getDistanceSq(this.parentEntity) < 4096.0D && this.parentEntity.canEntityBeSeen(entitylivingbase)) + { + World world = this.parentEntity.world; + ++this.attackTimer; + + if (this.attackTimer == 10) + { + world.playEvent((EntityPlayer)null, 1015, new BlockPos(this.parentEntity), 0); + } + + if (this.attackTimer == 20) + { + double d1 = 4.0D; + Vec3d vec3d = this.parentEntity.getLook(1.0F); + double d2 = entitylivingbase.posX - (this.parentEntity.posX + vec3d.x * 4.0D); + double d3 = entitylivingbase.getEntityBoundingBox().minY + (double)(entitylivingbase.height / 2.0F) - (0.5D + this.parentEntity.posY + (double)(this.parentEntity.height / 2.0F)); + double d4 = entitylivingbase.posZ - (this.parentEntity.posZ + vec3d.z * 4.0D); + world.playEvent((EntityPlayer)null, 1016, new BlockPos(this.parentEntity), 0); + EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.parentEntity, d2, d3, d4); + entitylargefireball.explosionPower = this.parentEntity.getFireballStrength(); + entitylargefireball.posX = this.parentEntity.posX + vec3d.x * 4.0D; + entitylargefireball.posY = this.parentEntity.posY + (double)(this.parentEntity.height / 2.0F) + 0.5D; + entitylargefireball.posZ = this.parentEntity.posZ + vec3d.z * 4.0D; + world.spawnEntity(entitylargefireball); + this.attackTimer = -40; + } + } + else if (this.attackTimer > 0) + { + --this.attackTimer; + } + + this.parentEntity.setAttacking(this.attackTimer > 10); + } + } + + public static class AILookAround extends EntityAIBase + { + private final EntityTurretPrototype parentEntity; + + public AILookAround(EntityTurretPrototype ghast) + { + this.parentEntity = ghast; + this.setMutexBits(2); + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + return true; + } + + /** + * Keep ticking a continuous task that has already been started + */ + public void updateTask() + { + if (this.parentEntity.getAttackTarget() == null) + { + this.parentEntity.rotationYaw = -((float) MathHelper.atan2(this.parentEntity.motionX, this.parentEntity.motionZ)) * (180F / (float)Math.PI); + this.parentEntity.renderYawOffset = this.parentEntity.rotationYaw; + } + else + { + EntityLivingBase entitylivingbase = this.parentEntity.getAttackTarget(); + double d0 = 64.0D; + + if (entitylivingbase.getDistanceSq(this.parentEntity) < 4096.0D) + { + double d1 = entitylivingbase.posX - this.parentEntity.posX; + double d2 = entitylivingbase.posZ - this.parentEntity.posZ; + this.parentEntity.rotationYaw = -((float)MathHelper.atan2(d1, d2)) * (180F / (float)Math.PI); + this.parentEntity.renderYawOffset = this.parentEntity.rotationYaw; + } + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype2.java b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype2.java new file mode 100644 index 0000000..383b46c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/misc/EntityTurretPrototype2.java @@ -0,0 +1,63 @@ +package com.somebody.idlframewok.entity.creatures.misc; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.entity.creatures.ai.BulletMode; +import com.somebody.idlframewok.entity.creatures.ai.EntityAIBulletAttack; +import com.somebody.idlframewok.entity.creatures.ai.RangedAttackArguments; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.monster.EntityIronGolem; +import net.minecraft.entity.passive.EntityCow; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +public class EntityTurretPrototype2 extends EntityModUnit { +//public class EntityTurretPrototype2 extends EntityMob implements IRangedAttackMob { + + public static float lookRange = 10f; + public static boolean fixed_on_ground = true; + + + public EntityTurretPrototype2(World worldIn) { + super(worldIn); + setSize(0.9F,1F); + entityCollisionReduction = 0.9f;//not much use for fixed ones + is_mechanic = true; + } + + @Override + public float getEyeHeight() { + return 0.5F; + } + + @Override + protected void initEntityAI() { + this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, lookRange)); + this.tasks.addTask(6, new EntityAILookIdle(this)); + + RangedAttackArguments args = new RangedAttackArguments(); + args.attack_mode = BulletMode.SmallFireball; + args.range = (float) this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).getBaseValue(); + args.isTurret = true; + + this.tasks.addTask(5, new EntityAIBulletAttack(this, args)); + + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0])); + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true)); + this.targetTasks.addTask(4, new EntityAINearestAttackableTarget(this, EntityCow.class, true)); + + } + + @Override + protected void applyEntityAttributes() { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(40.0D); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0D); + this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(1.0D); + this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(32.0D); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelCentaur.java b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelCentaur.java new file mode 100644 index 0000000..09ecb65 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelCentaur.java @@ -0,0 +1,114 @@ +package com.somebody.idlframewok.entity.creatures.model; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; + +/** + * ModelCow - Either Mojang or a mod author + * Created using Tabula 7.1.0 + */ +public class ModelCentaur extends ModelBase { + public ModelRenderer cow_body; + public ModelRenderer cow_belly; + public ModelRenderer cow_leg_2_L; + public ModelRenderer cow_leg_1_L; + public ModelRenderer cow_leg_2_R; + public ModelRenderer cow_leg_1_R; + public ModelRenderer VillagerHead; + public ModelRenderer VillagerRHand; + public ModelRenderer VillagerLHand; + public ModelRenderer VillagerCenterHand; + public ModelRenderer VillagerChest; + public ModelRenderer VillagerCoat; + public ModelRenderer VillagerNose; + + public ModelCentaur() { + this.textureWidth = 64; + this.textureHeight = 32; + this.VillagerLHand = new ModelRenderer(this, 44, 22); + this.VillagerLHand.setRotationPoint(0.20000000000000004F, -12.0F, -5.799999999999996F); + this.VillagerLHand.addBox(4.0F, -2.0F, -2.0F, 4, 8, 4, 0.0F); + this.setRotateAngle(VillagerLHand, -0.7499679795819634F, 0.0F, 0.0F); + this.VillagerCoat = new ModelRenderer(this, 0, 38); + this.VillagerCoat.setRotationPoint(0.20000000000000004F, -15.0F, -4.799999999999999F); + this.VillagerCoat.addBox(-4.0F, 0.0F, -3.0F, 8, 18, 6, 0.5F); + this.VillagerNose = new ModelRenderer(this, 24, 0); + this.VillagerNose.setRotationPoint(0.0F, -2.0F, 0.0F); + this.VillagerNose.addBox(-1.0F, -1.0F, -6.0F, 2, 4, 2, 0.0F); + this.VillagerRHand = new ModelRenderer(this, 44, 22); + this.VillagerRHand.setRotationPoint(0.20000000000000004F, -12.0F, -5.799999999999996F); + this.VillagerRHand.addBox(-8.0F, -2.0F, -2.0F, 4, 8, 4, 0.0F); + this.setRotateAngle(VillagerRHand, -0.7499679795819634F, 0.0F, 0.0F); + this.cow_belly = new ModelRenderer(this, 52, 0); + this.cow_belly.setRotationPoint(0.0F, 5.0F, 2.0F); + this.cow_belly.addBox(-2.0F, 2.0F, -8.0F, 4, 6, 1, 0.0F); + this.setRotateAngle(cow_belly, 1.5707963267948966F, 0.0F, 0.0F); + this.VillagerCenterHand = new ModelRenderer(this, 40, 38); + this.VillagerCenterHand.setRotationPoint(0.20000000000000004F, -12.0F, -5.799999999999996F); + this.VillagerCenterHand.addBox(-4.0F, 2.0F, -2.0F, 8, 4, 4, 0.0F); + this.setRotateAngle(VillagerCenterHand, -0.7499679795819634F, 0.0F, 0.0F); + this.VillagerHead = new ModelRenderer(this, 0, 0); + this.VillagerHead.setRotationPoint(0.20000000000000004F, -15.0F, -4.799999999999999F); + this.VillagerHead.addBox(-4.0F, -10.0F, -4.0F, 8, 10, 8, 0.0F); + this.cow_body = new ModelRenderer(this, 18, 4); + this.cow_body.setRotationPoint(0.0F, 5.0F, 2.0F); + this.cow_body.addBox(-6.0F, -10.0F, -7.0F, 12, 18, 10, 0.0F); + this.setRotateAngle(cow_body, 1.5707963267948966F, 0.0F, 0.0F); + this.cow_leg_2_L = new ModelRenderer(this, 0, 16); + this.cow_leg_2_L.setRotationPoint(4.0F, 12.0F, 7.0F); + this.cow_leg_2_L.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F); + this.VillagerChest = new ModelRenderer(this, 16, 20); + this.VillagerChest.setRotationPoint(0.20000000000000004F, -15.0F, -4.799999999999999F); + this.VillagerChest.addBox(-4.0F, 0.0F, -3.0F, 8, 12, 6, 0.0F); + this.cow_leg_1_L = new ModelRenderer(this, 0, 16); + this.cow_leg_1_L.setRotationPoint(4.0F, 12.0F, -6.0F); + this.cow_leg_1_L.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F); + this.cow_leg_2_R = new ModelRenderer(this, 0, 16); + this.cow_leg_2_R.setRotationPoint(-4.0F, 12.0F, 7.0F); + this.cow_leg_2_R.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F); + this.cow_leg_1_R = new ModelRenderer(this, 0, 16); + this.cow_leg_1_R.setRotationPoint(-4.0F, 12.0F, -6.0F); + this.cow_leg_1_R.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F); + this.VillagerHead.addChild(this.VillagerNose); + } + + @Override + public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) { + this.VillagerLHand.render(f5); + this.VillagerCoat.render(f5); + this.VillagerRHand.render(f5); + this.cow_belly.render(f5); + this.VillagerCenterHand.render(f5); + this.VillagerHead.render(f5); + this.cow_body.render(f5); + this.cow_leg_2_L.render(f5); + this.VillagerChest.render(f5); + this.cow_leg_1_L.render(f5); + this.cow_leg_2_R.render(f5); + this.cow_leg_1_R.render(f5); + } + + /** + * This is a helper function from Tabula to set the rotation of model parts + */ + public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) { + modelRenderer.rotateAngleX = x; + modelRenderer.rotateAngleY = y; + modelRenderer.rotateAngleZ = z; + } + + @Override + public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) { + this.cow_leg_1_L.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + this.cow_leg_2_L.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + + this.cow_leg_1_R.rotateAngleX = - MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + this.cow_leg_2_R.rotateAngleX = - MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + + this.VillagerHead.rotateAngleY = netHeadYaw * 0.017453292F; + this.VillagerHead.rotateAngleX = headPitch * 0.017453292F; + //super.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor, entityIn); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelIDLConstruction.java b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelIDLConstruction.java new file mode 100644 index 0000000..c0d40d7 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelIDLConstruction.java @@ -0,0 +1,162 @@ +package com.somebody.idlframewok.entity.creatures.model; + +import com.somebody.idlframewok.entity.creatures.buildings.EntityIdlBuildingBase; +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.Vec3d; + +/** + * ModelIDLConstruction - TaoismDeepLake + * Created using Tabula 7.1.0 + */ +public class ModelIDLConstruction extends ModelBase { + public ModelRenderer Pillar; + public ModelRenderer Floor; + public ModelRenderer Target; + public ModelRenderer CornerBoard; + public ModelRenderer CornerBoard_1; + public ModelRenderer CornerBoard_2; + public ModelRenderer CornerBoard_3; + + public ModelIDLConstruction() { + this.textureWidth = 64; + this.textureHeight = 64; + this.Pillar = new ModelRenderer(this, 0, 0); + this.Pillar.setRotationPoint(0.0F, 24.0F, 0.0F); + this.Pillar.addBox(-2.0F, -4.0F, -2.0F, 4, 4, 4, 0.0F); + this.CornerBoard = new ModelRenderer(this, 44, 0); + this.CornerBoard.setRotationPoint(8.0F, 23.5F, -8.0F); + this.CornerBoard.addBox(0.0F, 0.0F, -1.0F, 4, 1, 2, 0.0F); + this.setRotateAngle(CornerBoard, 0.0F, 0.7853981633974483F, 0.0F); + this.Target = new ModelRenderer(this, 32, 0); + this.Target.setRotationPoint(0.0F, 0.0F, 0.0F); + this.Target.addBox(-2.0F, -2.0F, -2.0F, 4, 4, 4, 0.0F); + this.CornerBoard_2 = new ModelRenderer(this, 46, 6); + this.CornerBoard_2.setRotationPoint(-8.0F, 23.5F, 8.0F); + this.CornerBoard_2.addBox(0.0F, 0.0F, -1.0F, 4, 1, 2, 0.0F); + this.setRotateAngle(CornerBoard_2, 0.0F, -2.356194490192345F, 0.0F); + this.Floor = new ModelRenderer(this, 8, 0); + this.Floor.setRotationPoint(0.0F, 23.5F, 0.0F); + this.Floor.addBox(-4.0F, 0.0F, -4.0F, 8, 1, 8, 0.0F); + this.CornerBoard_1 = new ModelRenderer(this, 48, 3); + this.CornerBoard_1.setRotationPoint(8.0F, 23.5F, 8.0F); + this.CornerBoard_1.addBox(0.0F, 0.0F, -1.0F, 4, 1, 2, 0.0F); + this.setRotateAngle(CornerBoard_1, 0.0F, -0.7853981633974483F, 0.0F); + this.CornerBoard_3 = new ModelRenderer(this, 0, 9); + this.CornerBoard_3.setRotationPoint(-8.0F, 23.5F, -8.0F); + this.CornerBoard_3.addBox(0.0F, 0.0F, -1.0F, 4, 1, 2, 0.0F); + this.setRotateAngle(CornerBoard_3, 0.0F, 2.356194490192345F, 0.0F); + } + + @Override + public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) { + GlStateManager.pushMatrix(); + GlStateManager.translate(this.Pillar.offsetX, this.Pillar.offsetY, this.Pillar.offsetZ); + GlStateManager.translate(this.Pillar.rotationPointX * f5, this.Pillar.rotationPointY * f5, this.Pillar.rotationPointZ * f5); + GlStateManager.scale(1.0D, 4.0D, 1.0D); + GlStateManager.translate(-this.Pillar.offsetX, -this.Pillar.offsetY, -this.Pillar.offsetZ); + GlStateManager.translate(-this.Pillar.rotationPointX * f5, -this.Pillar.rotationPointY * f5, -this.Pillar.rotationPointZ * f5); + this.Pillar.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.CornerBoard.offsetX, this.CornerBoard.offsetY, this.CornerBoard.offsetZ); + GlStateManager.translate(this.CornerBoard.rotationPointX * f5, this.CornerBoard.rotationPointY * f5, this.CornerBoard.rotationPointZ * f5); + GlStateManager.scale(4.0D, 1.0D, 4.0D); + GlStateManager.translate(-this.CornerBoard.offsetX, -this.CornerBoard.offsetY, -this.CornerBoard.offsetZ); + GlStateManager.translate(-this.CornerBoard.rotationPointX * f5, -this.CornerBoard.rotationPointY * f5, -this.CornerBoard.rotationPointZ * f5); + this.CornerBoard.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.Target.offsetX, this.Target.offsetY, this.Target.offsetZ); + GlStateManager.translate(this.Target.rotationPointX * f5, this.Target.rotationPointY * f5, this.Target.rotationPointZ * f5); + GlStateManager.scale(5.0D, 5.0D, 5.0D); + GlStateManager.translate(-this.Target.offsetX, -this.Target.offsetY, -this.Target.offsetZ); + GlStateManager.translate(-this.Target.rotationPointX * f5, -this.Target.rotationPointY * f5, -this.Target.rotationPointZ * f5); + this.Target.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.CornerBoard_2.offsetX, this.CornerBoard_2.offsetY, this.CornerBoard_2.offsetZ); + GlStateManager.translate(this.CornerBoard_2.rotationPointX * f5, this.CornerBoard_2.rotationPointY * f5, this.CornerBoard_2.rotationPointZ * f5); + GlStateManager.scale(4.0D, 1.0D, 4.0D); + GlStateManager.translate(-this.CornerBoard_2.offsetX, -this.CornerBoard_2.offsetY, -this.CornerBoard_2.offsetZ); + GlStateManager.translate(-this.CornerBoard_2.rotationPointX * f5, -this.CornerBoard_2.rotationPointY * f5, -this.CornerBoard_2.rotationPointZ * f5); + this.CornerBoard_2.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.Floor.offsetX, this.Floor.offsetY, this.Floor.offsetZ); + GlStateManager.translate(this.Floor.rotationPointX * f5, this.Floor.rotationPointY * f5, this.Floor.rotationPointZ * f5); + GlStateManager.scale(2.5D, 1.0D, 2.5D); + GlStateManager.translate(-this.Floor.offsetX, -this.Floor.offsetY, -this.Floor.offsetZ); + GlStateManager.translate(-this.Floor.rotationPointX * f5, -this.Floor.rotationPointY * f5, -this.Floor.rotationPointZ * f5); + this.Floor.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.CornerBoard_1.offsetX, this.CornerBoard_1.offsetY, this.CornerBoard_1.offsetZ); + GlStateManager.translate(this.CornerBoard_1.rotationPointX * f5, this.CornerBoard_1.rotationPointY * f5, this.CornerBoard_1.rotationPointZ * f5); + GlStateManager.scale(4.0D, 1.0D, 4.0D); + GlStateManager.translate(-this.CornerBoard_1.offsetX, -this.CornerBoard_1.offsetY, -this.CornerBoard_1.offsetZ); + GlStateManager.translate(-this.CornerBoard_1.rotationPointX * f5, -this.CornerBoard_1.rotationPointY * f5, -this.CornerBoard_1.rotationPointZ * f5); + this.CornerBoard_1.render(f5); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(this.CornerBoard_3.offsetX, this.CornerBoard_3.offsetY, this.CornerBoard_3.offsetZ); + GlStateManager.translate(this.CornerBoard_3.rotationPointX * f5, this.CornerBoard_3.rotationPointY * f5, this.CornerBoard_3.rotationPointZ * f5); + GlStateManager.scale(4.0D, 1.0D, 4.0D); + GlStateManager.translate(-this.CornerBoard_3.offsetX, -this.CornerBoard_3.offsetY, -this.CornerBoard_3.offsetZ); + GlStateManager.translate(-this.CornerBoard_3.rotationPointX * f5, -this.CornerBoard_3.rotationPointY * f5, -this.CornerBoard_3.rotationPointZ * f5); + this.CornerBoard_3.render(f5); + GlStateManager.popMatrix(); + } + + /** + * This is a helper function from Tabula to set the rotation of model parts + */ + public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) { + modelRenderer.rotateAngleX = x; + modelRenderer.rotateAngleY = y; + modelRenderer.rotateAngleZ = z; + } + + int timeToReady = CommonDef.TICK_PER_SECOND; + float maxAngle = 3.14159f/2f; + + @Override + public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) { + this.Target.rotateAngleY = ageInTicks * 5f; + if (entityIn instanceof EntityIdlBuildingBase) + { + EntityIdlBuildingBase buildingBase = (EntityIdlBuildingBase) entityIn; + Vec3d vec = buildingBase.getCurBuildingVector().rotateYaw(entityIn.rotationYaw); + float offset = 0f; + this.Target.offsetX = (float) (vec.x + offset); + this.Target.offsetY = (float) (-vec.y + offset); + this.Target.offsetZ = (float) (vec.z + offset); + +// if (ageInTicks <= timeToReady) { +// CornerBoard.rotateAngleZ = -maxAngle * (ageInTicks / timeToReady); +// CornerBoard_1.rotateAngleZ = maxAngle * (ageInTicks / timeToReady); +// CornerBoard_2.rotateAngleZ = -maxAngle * (ageInTicks / timeToReady); +// CornerBoard_3.rotateAngleZ = maxAngle * (ageInTicks / timeToReady); +// +// CornerBoard.rotateAngleX = -maxAngle * (ageInTicks / timeToReady); +// CornerBoard_1.rotateAngleX = maxAngle * (ageInTicks / timeToReady); +// CornerBoard_2.rotateAngleX = -maxAngle * (ageInTicks / timeToReady); +// CornerBoard_3.rotateAngleX = maxAngle * (ageInTicks / timeToReady); +// } +// else { +// CornerBoard.rotateAngleZ = maxAngle; +// CornerBoard_1.rotateAngleZ = maxAngle; +// CornerBoard_2.rotateAngleZ = maxAngle; +// CornerBoard_3.rotateAngleZ = maxAngle; +// CornerBoard.rotateAngleX = maxAngle; +// CornerBoard_1.rotateAngleX = maxAngle; +// CornerBoard_2.rotateAngleX = maxAngle; +// CornerBoard_3.rotateAngleX = maxAngle; +// } + } + //this.Target.offsetX = + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelMoroonBeacon.java b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelMoroonBeacon.java new file mode 100644 index 0000000..d2cec6e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelMoroonBeacon.java @@ -0,0 +1,88 @@ +package com.somebody.idlframewok.entity.creatures.model; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.entity.Entity; + +/** + * MoroonBeacon - TaoismDeeplake + * Created using Tabula 7.1.0 + */ +public class ModelMoroonBeacon extends ModelBase { + public ModelRenderer CenterPillar; + public ModelRenderer BuildBase; + public ModelRenderer RotationBase; + public ModelRenderer RotationBase_1; + public ModelRenderer SidePillar; + public ModelRenderer SidePillar_1; + public ModelRenderer SidePillar_2; + public ModelRenderer SidePillar_3; + public ModelRenderer SidePillar_4; + public ModelRenderer SidePillar_5; + + public ModelMoroonBeacon() { + this.textureWidth = 64; + this.textureHeight = 32; + this.SidePillar = new ModelRenderer(this, 0, 0); + this.SidePillar.setRotationPoint(0.0F, 0.0F, -8.0F); + this.SidePillar.addBox(-1.0F, 1.0F, -1.0F, 2, 8, 2, 0.0F); + this.SidePillar_5 = new ModelRenderer(this, 0, 0); + this.SidePillar_5.setRotationPoint(0.0F, 8.0F, 0.0F); + this.SidePillar_5.addBox(-1.0F, -1.0F, -7.0F, 2, 2, 14, 0.0F); + this.SidePillar_1 = new ModelRenderer(this, 0, 0); + this.SidePillar_1.setRotationPoint(0.0F, 0.0F, 8.0F); + this.SidePillar_1.addBox(-1.0F, 1.0F, -1.0F, 2, 8, 2, 0.0F); + this.RotationBase_1 = new ModelRenderer(this, 0, 0); + this.RotationBase_1.setRotationPoint(0.0F, 0.0F, 0.0F); + this.RotationBase_1.addBox(0.0F, 0.0F, 0.0F, 0, 0, 0, 0.0F); + this.SidePillar_3 = new ModelRenderer(this, 0, 0); + this.SidePillar_3.setRotationPoint(0.0F, 0.0F, -8.0F); + this.SidePillar_3.addBox(-1.0F, 1.0F, -1.0F, 2, 8, 2, 0.0F); + this.RotationBase = new ModelRenderer(this, 0, 0); + this.RotationBase.setRotationPoint(0.0F, 9.0F, 0.0F); + this.RotationBase.addBox(0.0F, 0.0F, 0.0F, 0, 0, 0, 0.0F); + this.SidePillar_2 = new ModelRenderer(this, 0, 0); + this.SidePillar_2.setRotationPoint(0.0F, 8.0F, 0.0F); + this.SidePillar_2.addBox(-1.0F, -1.0F, -7.0F, 2, 2, 14, 0.0F); + this.SidePillar_4 = new ModelRenderer(this, 0, 0); + this.SidePillar_4.setRotationPoint(0.0F, 0.0F, 8.0F); + this.SidePillar_4.addBox(-1.0F, 1.0F, -1.0F, 2, 8, 2, 0.0F); + this.CenterPillar = new ModelRenderer(this, 0, 0); + this.CenterPillar.setRotationPoint(0.0F, 0.0F, 0.0F); + this.CenterPillar.addBox(-2.0F, -8.0F, -2.0F, 4, 32, 4, 0.0F); + this.BuildBase = new ModelRenderer(this, 0, 0); + this.BuildBase.setRotationPoint(0.0F, 24.0F, 0.0F); + this.BuildBase.addBox(-4.0F, -0.5F, -4.0F, 8, 1, 8, 0.0F); + this.RotationBase.addChild(this.SidePillar); + this.RotationBase_1.addChild(this.SidePillar_5); + this.RotationBase.addChild(this.SidePillar_1); + this.RotationBase_1.addChild(this.SidePillar_3); + this.RotationBase.addChild(this.SidePillar_2); + this.RotationBase_1.addChild(this.SidePillar_4); + } + + @Override + public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) { + this.RotationBase_1.render(f5); + this.RotationBase.render(f5); + this.CenterPillar.render(f5); + this.BuildBase.render(f5); + } + + + @Override + public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) { + + this.RotationBase.rotateAngleY = (float) (Math.sin(ageInTicks * 0.017453292F) * 5f); + this.RotationBase_1.rotateAngleY = ageInTicks * 0.017453292F * -10.1f; + } + + /** + * This is a helper function from Tabula to set the rotation of model parts + */ + public void setRotationAngles(ModelRenderer modelRenderer, float x, float y, float z) { + modelRenderer.rotateAngleX = x; + modelRenderer.rotateAngleY = y; + modelRenderer.rotateAngleZ = z; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelTurretPrototype.java b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelTurretPrototype.java new file mode 100644 index 0000000..32ad691 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/model/ModelTurretPrototype.java @@ -0,0 +1,72 @@ +package com.somebody.idlframewok.entity.creatures.model; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; + +/** + * TurrentPrototype - TaoismDeepLake + * Created using Tabula 7.1.0 + */ +public class ModelTurretPrototype extends ModelBase { + public ModelRenderer BaseHead; + public ModelRenderer BaseRoot; + public ModelRenderer BarrelLookBase; + public ModelRenderer BodyL; + public ModelRenderer HeadR; + public ModelRenderer Barrel; + + public ModelTurretPrototype() { + this.textureWidth = 128; + this.textureHeight = 64; + this.Barrel = new ModelRenderer(this, 10, 17); + this.Barrel.mirror = true; + this.Barrel.setRotationPoint(0.0F, 0.0F, 0.0F); + this.Barrel.addBox(-1.0F, -1.0F, 0.0F, 2, 2, 32, 0.0F); + this.BarrelLookBase = new ModelRenderer(this, 45, 0); + this.BarrelLookBase.setRotationPoint(0.0F, 0.0F, 0.0F); + this.BarrelLookBase.addBox(-4.0F, -2.0F, -2.0F, 8, 4, 4, 0.0F); + this.HeadR = new ModelRenderer(this, 0, 17); + this.HeadR.setRotationPoint(0.0F, 0.0F, 0.0F); + this.HeadR.addBox(3.0F, -8.0F, -8.0F, 5, 16, 16, 0.0F); + this.BaseHead = new ModelRenderer(this, 0, 0); + this.BaseHead.setRotationPoint(0.0F, 16.0F, 0.0F); + this.BaseHead.addBox(-1.0F, 0.0F, -1.0F, 2, 2, 2, 0.0F); + this.BodyL = new ModelRenderer(this, 60, 0); + this.BodyL.setRotationPoint(0.0F, 0.0F, 0.0F); + this.BodyL.addBox(-8.0F, -8.0F, -8.0F, 5, 16, 16, 0.0F); + this.BaseRoot = new ModelRenderer(this, 0, 0); + this.BaseRoot.setRotationPoint(0.0F, 16.0F, 0.0F); + this.BaseRoot.addBox(-2.0F, 0.0F, -2.0F, 4, 10, 4, 0.0F); + this.BarrelLookBase.addChild(this.Barrel); + this.BaseHead.addChild(this.BarrelLookBase); + this.BaseHead.addChild(this.HeadR); + this.BaseHead.addChild(this.BodyL); + } + + @Override + public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale) { + this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn); + this.BaseHead.render(scale); + this.BaseRoot.render(scale); +// this.BaseHead.renderWithRotation(scale); +// this.BaseRoot.renderWithRotation(scale); + } + + /** + * This is a helper function from Tabula to set the rotation of model parts + */ + public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) { + modelRenderer.rotateAngleX = x; + modelRenderer.rotateAngleY = y; + modelRenderer.rotateAngleZ = z; + } + + @Override + public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) { + this.BarrelLookBase.offsetZ = MathHelper.cos(limbSwing * 0.6662F) * 0.5F * limbSwingAmount; + this.BaseHead.rotateAngleY = netHeadYaw * 0.017453292F; + this.BarrelLookBase.rotateAngleX = 3.14F + headPitch * 0.017453292F; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMorBlindingAssassin.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMorBlindingAssassin.java new file mode 100644 index 0000000..61aeb17 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMorBlindingAssassin.java @@ -0,0 +1,173 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.EntityUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + +public class EntityMorBlindingAssassin extends EntityMoroonUnitBase { + int stealthNeedTick = CommonDef.TICK_PER_SECOND * 10; + int stealthCounter = 0; + //A creatures that teleports whenever its hit + public EntityMorBlindingAssassin(World worldIn) { + super(worldIn); + spawn_without_darkness = false; + spawn_without_moroon_ground = false; + + inflictBerserkBuff =false; + + experienceValue = 30; + //MinecraftForge.EVENT_BUS.register(this); + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Items.FLINT_AND_STEEL)); + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 8.0F, 0.6D, 0.6D)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + //wont move through village + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonUnitBase.class})); + applyGeneralAI(); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + + setAttr(64, 0.4, 7, 2, 16); + } + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + if (stealthCounter >= stealthNeedTick || this.world.isRainingAt(getPosition())) + { + if (world.getWorldTime() % CommonDef.TICK_PER_SECOND == 3) { + addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, CommonDef.TICK_PER_SECOND * 2, 0)); + + } + stealthCounter++; + } + } + } + +// @SubscribeEvent +// public void onHit(LivingHurtEvent evt) +// { +// Entity attacker = evt.getSource().getTrueSource(); +// if (attacker == this) +// { +// +// +// } +// } + + @Override + public boolean attackEntityAsMob(Entity entityIn) { + boolean result = super.attackEntityAsMob(entityIn); + stealthCounter = 0; + EntityUtil.TryRemoveGivenBuff(this, MobEffects.INVISIBILITY); + if (result) + { + if (entityIn instanceof EntityLivingBase) + { + EntityLivingBase target = (EntityLivingBase) entityIn; + target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, + (int) (CommonDef.TICK_PER_SECOND * this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue()), + 0)); + fiveRandomTeleport(); + } + } + + return result; + } + + private void fiveRandomTeleport() + { + int trial = 5; + while(trial > 0) + { + if (teleportRandomly()) + { + break; + } + trial--; + } + } + + /** + * Teleport the enderman to a random nearby position + */ + protected boolean teleportRandomly() + { + double d0 = this.posX + (this.rand.nextDouble() - 0.5D) * 64.0D; + double d1 = this.posY + (double)(this.rand.nextInt(64) - 32); + double d2 = this.posZ + (this.rand.nextDouble() - 0.5D) * 64.0D; + return this.teleportTo(d0, d1, d2); + } + + /** + * Teleport the enderman to another entity + */ + protected boolean teleportToEntity(Entity p_70816_1_) + { + Vec3d vec3d = new Vec3d(this.posX - p_70816_1_.posX, this.getEntityBoundingBox().minY + (double)(this.height / 2.0F) - p_70816_1_.posY + (double)p_70816_1_.getEyeHeight(), this.posZ - p_70816_1_.posZ); + vec3d = vec3d.normalize(); + double d0 = 16.0D; + double d1 = this.posX + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D; + double d2 = this.posY + (double)(this.rand.nextInt(16) - 8) - vec3d.y * 16.0D; + double d3 = this.posZ + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D; + return this.teleportTo(d1, d2, d3); + } + + /** + * Teleport the enderman + */ + private boolean teleportTo(double x, double y, double z) + { + net.minecraftforge.event.entity.living.EnderTeleportEvent event = new net.minecraftforge.event.entity.living.EnderTeleportEvent(this, x, y, z, 0); + if (MinecraftForge.EVENT_BUS.post(event)) return false; + boolean flag = this.attemptTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ()); + + if (flag) + { + this.world.playSound((EntityPlayer)null, this.prevPosX, this.prevPosY, this.prevPosZ, SoundEvents.ENTITY_ENDERMEN_TELEPORT, this.getSoundCategory(), 1.0F, 1.0F); + this.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0F); + } + + return flag; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonFlickFighter.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonFlickFighter.java new file mode 100644 index 0000000..35f7826 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonFlickFighter.java @@ -0,0 +1,161 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class EntityMoroonFlickFighter extends EntityMoroonUnitBase { + //A creatures that teleports whenever its hit + public EntityMoroonFlickFighter(World worldIn) { + super(worldIn); + spawn_without_darkness = true; + spawn_without_moroon_ground = false; + MinecraftForge.EVENT_BUS.register(this); + experienceValue = 15; + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Items.ENDER_PEARL)); + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); + + if (wasRecentlyHit) { +// if (getRNG().nextFloat() <= (1 + lootingModifier) * 0.3f +// ) { +// dropItem(ModItems.ITEM_ETHREAL_SWORD, rand.nextInt(1 + lootingModifier)); +// } + + dropItem(Items.ENDER_PEARL, rand.nextInt(1 + lootingModifier)); + } + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 8.0F, 0.6D, 0.6D)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonUnitBase.class})); + applyGeneralAI(); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + + setAttr(32, 0.4, 6.0, 2, 16); + } + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + if (world.getWorldTime() % CommonDef.TICK_PER_SECOND == 0) { + + } + } + } + + @SubscribeEvent + public void onHurt(LivingHurtEvent evt) + { + if (evt.getEntity() == this) + { + Entity attacker = evt.getSource().getTrueSource(); + if (attacker instanceof EntityLivingBase) + { + this.setAttackTarget((EntityLivingBase) attacker); + fiveRandomTeleport(); + } + else { + fiveRandomTeleport(); + } + } + } + + private void fiveRandomTeleport() + { + int trial = 5; + while(trial > 0) + { + if (teleportRandomly()) + { + break; + } + trial--; + } + } + + /** + * Teleport the enderman to a random nearby position + */ + protected boolean teleportRandomly() + { + double d0 = this.posX + (this.rand.nextDouble() - 0.5D) * 64.0D; + double d1 = this.posY + (double)(this.rand.nextInt(64) - 32); + double d2 = this.posZ + (this.rand.nextDouble() - 0.5D) * 64.0D; + return this.teleportTo(d0, d1, d2); + } + + /** + * Teleport the enderman to another entity + */ + protected boolean teleportToEntity(Entity p_70816_1_) + { + Vec3d vec3d = new Vec3d(this.posX - p_70816_1_.posX, this.getEntityBoundingBox().minY + (double)(this.height / 2.0F) - p_70816_1_.posY + (double)p_70816_1_.getEyeHeight(), this.posZ - p_70816_1_.posZ); + vec3d = vec3d.normalize(); + double d0 = 16.0D; + double d1 = this.posX + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D; + double d2 = this.posY + (double)(this.rand.nextInt(16) - 8) - vec3d.y * 16.0D; + double d3 = this.posZ + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D; + return this.teleportTo(d1, d2, d3); + } + + /** + * Teleport the enderman + */ + private boolean teleportTo(double x, double y, double z) + { + net.minecraftforge.event.entity.living.EnderTeleportEvent event = new net.minecraftforge.event.entity.living.EnderTeleportEvent(this, x, y, z, 0); + if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event)) return false; + boolean flag = this.attemptTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ()); + + if (flag) + { + this.world.playSound((EntityPlayer)null, this.prevPosX, this.prevPosY, this.prevPosZ, SoundEvents.ENTITY_ENDERMEN_TELEPORT, this.getSoundCategory(), 1.0F, 1.0F); + this.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0F); + } + + return flag; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonGhostArcher.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonGhostArcher.java new file mode 100644 index 0000000..97ebb17 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonGhostArcher.java @@ -0,0 +1,209 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIAttackRanged; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityTippedArrow; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class EntityMoroonGhostArcher extends EntityMoroonUnitBase implements IRangedAttackMob { + private int stationaryCounter = 0; + private int stationaryToInvisible = CommonDef.TICK_PER_SECOND * 5; + + //A creatures that does ranged attack and becomes invisible + public EntityMoroonGhostArcher(World worldIn) { + super(worldIn); + spawn_without_darkness = true; + spawn_without_moroon_ground = false; + MinecraftForge.EVENT_BUS.register(this); + experienceValue = 15; + setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + //setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(ModItems.helmetSniper)); + setSneaking(true); + inflictBerserkBuff = false; + } + + public void updateAITasks() + { + setSneaking(true); + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); + + if (wasRecentlyHit) { + //if (lootingModifier >= rand.nextInt(10)) +// { +// dropItem(ModItems.skill_hate_detect_sniper, 1); +// } +// +// if (lootingModifier >= rand.nextInt(10)) +// { +// dropItem(ModItems.helmetSniper, 1); +// } + + //dropItem(ModItems.skillFireBall, rand.nextInt(1 + lootingModifier)); + } + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(1, new EntityAIAttackRanged(this, 0.3f, CommonDef.TICK_PER_SECOND * 2, 32.0F)); + //this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 16.0F, 0.6D, 1D)); +// this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); +// this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); +// this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, EntityMoroonUnitBase.class)); + applyGeneralAI(); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + setAttr(32, 0.3, 20, 2, 20); + } + + @Override + public void onUpdate() { + super.onUpdate(); + if (!this.world.isRemote) + { + //if (this.getMoveHelper().isUpdating()) { + //double d0 = this.getMoveHelper().getSpeed(); + + // if ((getAttackTarget() != null) || (this.getActivePotionEffect(ModPotions.INTERFERENCE) != null)) +// { +// stationaryCounter=0; +// if (this.getActivePotionEffect(MobEffects.INVISIBILITY) != null) +// { +// EntityUtil.TryRemoveGivenBuff(this, MobEffects.INVISIBILITY); +// } +// +// }else { +// stationaryCounter++; +// if (stationaryCounter > stationaryToInvisible) { +// stationaryCounter = stationaryToInvisible; +// if (world.getWorldTime() % TICK_PER_SECOND == 0) { +// addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, TICK_PER_SECOND * 2, 0)); +// } +// } +// } + //} + } + } + + /** + * sets this entity's combat AI. + */ +// public void setCombatTask() +// { +// if (this.world != null && !this.world.isRemote) +// { +// this.tasks.removeTask(this.aiAttackOnCollide); +// this.tasks.removeTask(this.aiArrowAttack); +// ItemStack itemstack = this.getHeldItemMainhand(); +// +// if (itemstack.getItem() == Items.BOW) +// { +// int i = 20; +// +// if (this.world.getDifficulty() != EnumDifficulty.HARD) +// { +// i = 40; +// } +// +// this.aiArrowAttack.setAttackCooldown(i); +// this.tasks.addTask(4, this.aiArrowAttack); +// } +// else +// { +// this.tasks.addTask(4, this.aiAttackOnCollide); +// } +// } +// } + +// @SubscribeEvent +// public void onHurt(LivingHurtEvent evt) +// { +// if (evt.getEntity() == this) +// { +// Entity attacker = evt.getSource().getTrueSource(); +// if (attacker instanceof EntityLivingBase) +// { +// this.setAttackTarget((EntityLivingBase) attacker); +// } +// else { +// +// } +// } +// } + + protected EntityArrow getArrow(float p_190726_1_) + { + EntityTippedArrow entitytippedarrow = new EntityTippedArrow(this.world, this); + entitytippedarrow.setEnchantmentEffectsFromEntity(this, p_190726_1_); + return entitytippedarrow; + } + + @Override + public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor) { + //EntityMoroonBullet entityArrow = new EntityMoroonBullet(world, new ProjectileArgs((float) this.getEntityAttribute(ATTACK_DAMAGE).getAttributeValue())); + EntityArrow entityArrow = getArrow(distanceFactor); + double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D; + double d1 = target.posX - this.posX; + double d2 = d0 - entityArrow.posY; + double d3 = target.posZ - this.posZ; + float f = MathHelper.sqrt(d1 * d1 + d3 * d3) * 0.1F; + entityArrow.shoot(d1, d2 + (double)f, d3, 2F, (float)(f + 7 - this.world.getDifficulty().getDifficultyId() * 2)); + double damage = this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); + if (target.isSneaking()) + { + damage /= 5f; + } + entityArrow.setDamage(damage); + this.playSound(SoundEvents.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F)); + this.world.spawnEntity(entityArrow); + } + + private static final DataParameter SWINGING_ARMS = EntityDataManager.createKey(EntityMoroonGhostArcher.class, DataSerializers.BOOLEAN); + @SideOnly(Side.CLIENT) + public boolean isSwingingArms() + { + return ((Boolean)this.dataManager.get(SWINGING_ARMS)).booleanValue(); + } + + @Override + public void setSwingingArms(boolean swingingArms) { + this.dataManager.set(SWINGING_ARMS, Boolean.valueOf(swingingArms)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonMindMage.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonMindMage.java new file mode 100644 index 0000000..f8a9e27 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonMindMage.java @@ -0,0 +1,284 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import java.util.List; + +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAIPanic; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.pathfinding.Path; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; + +public class EntityMoroonMindMage extends EntityMoroonUnitBase implements IRangedAttackMob { + + public EntityMoroonMindMage(World worldIn) { + super(worldIn); + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Blocks.LIT_PUMPKIN)); + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(1, new EntityAIPanic(this, 1.4D)); + //this.tasks.addTask(2, new EntityAIAttackRanged((IRangedAttackMob) this, 1.0D, 60, 10.0F)); + // this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 16.0F, 0.6D, 1.0D)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonUnitBase.class})); + applyGeneralAI(); + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); +// if (rand.nextFloat() < 0.1f * getLevel()) +// { +// dropItem(ModItems.ITEM_HELM_SANITY, 1 + rand.nextInt(2 + lootingModifier)); +// } +// +// if (rand.nextFloat() < 0.01f * getLevel() * (1+lootingModifier)) +// { +// dropItem(ModItems.ITEM_EL_PSY_CONGROO, 1); +// } + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + setAttr(32.0D, 0.33000000417232513D, 3.0D, 0.0D, 14.0D); + } + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + //if (world.getWorldTime() % TICK_PER_SECOND == 1 && getActivePotionEffect(ModPotions.INTERFERENCE) == null) + { + float range = (float) getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).getAttributeValue(); + + if (getRank() > 1) + { + //strong mind mages resists mind magic, won't attack allies + if (EntityUtil.getAttitude(this, getAttackTarget()) == EntityUtil.ATTITUDE.FRIEND) + { + setAttackTarget(null); + } + } + + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + IDLGeneral.ServerAABB(getPositionEyes(0f), range)); + + for (EntityLivingBase living: + entities + ) { + if (living == this) + continue; + + if (living instanceof EntityPlayer) + { + //ignore creative players + if (((EntityPlayer)living).capabilities.isCreativeMode) + { + continue; + } + } + + EntityUtil.ATTITUDE attitude = EntityUtil.getAttitude(this, living); + if (attitude == EntityUtil.ATTITUDE.FRIEND) { + ApplyMindControlToFriend(living); + } + else if (attitude == EntityUtil.ATTITUDE.HATE || living == getAttackTarget()) + { + ApplyMindControlToEnemy(living); + } + else if (living instanceof EntityLiving) + { + EntityLivingBase theirTarget = ((EntityLiving) living).getAttackTarget(); + if (EntityUtil.getAttitude(this, theirTarget) == EntityUtil.ATTITUDE.FRIEND) + { + ApplyMindControlToEnemy(living); + } + } + } + } + } + else { + //remote + } + } + + public float getSeconds() + { + return getLevel(); + } + + public int getBuffLevel() + { + return getRank() - 1; + } + + + public void ApplyMindControlToEnemy(EntityLivingBase livingBase) + { +// if (livingBase.getItemStackFromSlot(EntityEquipmentSlot.HEAD).getItem() instanceof ItemHelmSanity) +// { +// return; +// } + + if (getAttackTarget() == null) + { + Path path = getNavigator().getPathToEntityLiving(livingBase); + if (path != null) + { + setAttackTarget(livingBase); + } + else { + getLookHelper().setLookPosition(livingBase.posX, livingBase.posY, livingBase.posZ, 0.1f, 0.1f); + } + } + + int rank = getRank(); + + EntityUtil.TryRemoveGivenBuff(livingBase, MobEffects.INVISIBILITY); + EntityUtil.TryRemoveGivenBuff(livingBase, MobEffects.NIGHT_VISION); + + //EntityUtil.ApplyBuff(livingBase, ModPotions.CRIT_CHANCE_MINUS, getBuffLevel(), getSeconds()); + EntityUtil.ApplyBuff(livingBase, MobEffects.GLOWING, 0, getLevel()); + if (rank >= 2) + { + EntityUtil.ApplyBuff(livingBase, MobEffects.NAUSEA, getBuffLevel(), getSeconds()); + EntityUtil.ApplyBuff(livingBase, MobEffects.WEAKNESS, getBuffLevel(), getSeconds()); + if (rank >= 3) + { + EntityUtil.ApplyBuff(livingBase, MobEffects.BLINDNESS,0, getSeconds()); + EntityUtil.ApplyBuff(livingBase, MobEffects.SLOWNESS, getBuffLevel(), getSeconds()); + } + } + + TryChangeTargetToEnemy(livingBase); + } + + public void ApplyMindControlToFriend(EntityLivingBase livingBase) + { +// if (livingBase.getItemStackFromSlot(EntityEquipmentSlot.HEAD).getItem() instanceof ItemHelmSanity) +// { +// return; +// } + + int level = getLevel(); + int rank = getRank(); + + EntityUtil.ApplyBuff(livingBase, MobEffects.INVISIBILITY, getBuffLevel(), getSeconds()); + EntityUtil.TryRemoveGivenBuff(livingBase, MobEffects.GLOWING); + EntityUtil.TryRemoveGivenBuff(livingBase, MobEffects.BLINDNESS); + EntityUtil.TryRemoveGivenBuff(livingBase, MobEffects.NAUSEA); + + if (rank >= 2) + { + //EntityUtil.ApplyBuff(livingBase, ModPotions.CRIT_CHANCE_PLUS, getBuffLevel(), getSeconds()); + if (rank >= 3) + { + EntityUtil.ApplyBuff(livingBase, MobEffects.HASTE, getBuffLevel(), getSeconds()); + } + } + + TryChangeTargetToEnemy(livingBase); + } + + public void TryChangeTargetToEnemy(EntityLivingBase livingBase) + { + if (livingBase instanceof EntityLiving) + { + //change their targets + EntityLiving entityLiving = (EntityLiving) livingBase; + EntityLivingBase theirTarget = ((EntityLiving) livingBase).getAttackTarget(); + if (EntityUtil.getAttitude(this, theirTarget) != EntityUtil.ATTITUDE.HATE) + { + //try to make them attack only if the path ready + EntityLivingBase myTarget = getAttackTarget(); + if (myTarget != null) + { + Path path = entityLiving.getNavigator().getPathToEntityLiving(myTarget); + if (path != null) + { + setAttackTarget(myTarget); + } + else { + // target not available for mind-control subject, just cancel their current friendly fire + //and warn them of the target. Note this will weaken the disruption to enemy, too. + getLookHelper().setLookPosition(livingBase.posX, livingBase.posY, livingBase.posZ, 0.1f, 0.1f); + setAttackTarget(null); + } + } + else { + setAttackTarget(null); + } + } + } + } + + /** + * Attack the specified entity using a ranged attack. + */ + public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor) + { +// if (getRank() <= 2) +// { +// return; +// } +// +// double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D; +// double d1 = target.posX + target.motionX - this.posX; +// double d2 = d0 - this.posY; +// double d3 = target.posZ + target.motionZ - this.posZ; +// float f = MathHelper.sqrt(d1 * d1 + d3 * d3); +// PotionType potiontype = PotionTypes.HARMING; +// +// if (f >= 8.0F && !target.isPotionActive(MobEffects.SLOWNESS)) +// { +// potiontype = PotionTypes.SLOWNESS; +// } +// else if (f <= 3.0F && !target.isPotionActive(MobEffects.WEAKNESS) && this.rand.nextFloat() < 0.25F) +// { +// potiontype = PotionTypes.WEAKNESS; +// } +// +// EntityPotion entitypotion = new EntityPotion(this.world, this, PotionUtils.addPotionToItemStack(new ItemStack(Items.SPLASH_POTION), potiontype)); +// entitypotion.rotationPitch -= -20.0F; +// entitypotion.shoot(d1, d2 + (double)(f * 0.2F), d3, 0.75F, 8.0F); +// this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_WITCH_THROW, this.getSoundCategory(), 1.0F, 0.8F + this.rand.nextFloat() * 0.4F); +// this.world.spawnEntity(entitypotion); + + } + + @Override + public void setSwingingArms(boolean swingingArms) { + + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonStandardInfantry.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonStandardInfantry.java new file mode 100644 index 0000000..635fe26 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonStandardInfantry.java @@ -0,0 +1,184 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.ai.EntityAIStrafeRangedAttack; +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIAvoidEntity; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; + +public class EntityMoroonStandardInfantry extends EntityMoroonUnitBase implements IRangedAttackMob { + private float bulletAccel = 0.1f; + private float errorModifier = 0.2f; + + public EntityMoroonStandardInfantry(World worldIn) { + super(worldIn); + this.setCombatTask(); + autoArmor = true; + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); + + if (wasRecentlyHit) { + if (getRNG().nextFloat() < 0.1f * (1 + lootingModifier)) + { + //dropItem (ModItems.MOROON_RIFLE, 1); + } + } + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + setAttr(32.0D, 0.33000000417232513D, 8.0D, 5.0D, 20.0D); + } + + @Override + public void readEntityFromNBT(NBTTagCompound compound) { + super.readEntityFromNBT(compound); + this.setCombatTask(); + } + + protected final EntityAIStrafeRangedAttack aiArrowAttack = new EntityAIStrafeRangedAttack<>(this, 1.0D, 5, 16.0F); + protected final EntityAIAttackMelee aiAttackOnCollide = new EntityAIAttackMelee(this, 1.2D, false) + { + /** + * Reset the task's internal state. Called when this task is interrupted by another one + */ + public void resetTask() + { + super.resetTask(); + EntityMoroonStandardInfantry.this.setSwingingArms(false); + } + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + super.startExecuting(); + EntityMoroonStandardInfantry.this.setSwingingArms(true); + } + }; + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + // this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 8.0F, 0.6D, 0.6D)); + this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityTNTPrimed.class, 8.0F, 0.6D, 0.6D)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 0.5D, false)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonTainter.class})); + applyGeneralAI(); + } + + @Nullable + @Override + public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) { + this.setEquipmentBasedOnDifficulty(difficulty); + this.setEnchantmentBasedOnDifficulty(difficulty); + this.setCombatTask(); + return super.onInitialSpawn(difficulty, livingdata); + } + + protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty) + { + super.setEquipmentBasedOnDifficulty(difficulty); + //this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(ModItems.MOROON_RIFLE)); + } + + public void setItemStackToSlot(EntityEquipmentSlot slotIn, ItemStack stack) + { + super.setItemStackToSlot(slotIn, stack); + + if (!this.world.isRemote && slotIn == EntityEquipmentSlot.MAINHAND) + { + this.setCombatTask(); + } + } + + /** + * sets this entity's combat AI. + */ + public void setCombatTask() + { + if (this.world != null && !this.world.isRemote) + { + this.tasks.removeTask(this.aiAttackOnCollide); + this.tasks.removeTask(this.aiArrowAttack); + ItemStack itemstack = this.getHeldItemMainhand(); + + if (CommonFunctions.isItemRangedWeapon(itemstack)) + { + int i = 20; + + if (this.world.getDifficulty() != EnumDifficulty.HARD) + { + i = 40; + } + + this.aiArrowAttack.setAttackCooldown(i); + this.tasks.addTask(4, this.aiArrowAttack); + } + else + { + this.tasks.addTask(4, this.aiAttackOnCollide); + } + } + } + + @Override + public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor) { + double d0 = this.getDistanceSq(target); + double d1 = target.posX - this.posX; + double d2 = target.getEntityBoundingBox().minY + (double)(target.height / 2.0F) - (this.posY + (double)(this.height / 2.0F)); + double d3 = target.posZ - this.posZ; + + float dist = MathHelper.sqrt(MathHelper.sqrt(d0)); + float estimateHitTime = MathHelper.sqrt(2 * bulletAccel * dist); + +// EntityMoroonBullet entityIdlProjectile = new EntityMoroonBullet(this.world, new ProjectileArgs((float) EntityUtil.getAttack(this)), this, +// d1 + this.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionX, +// d2 + this.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionY, +// d3 + this.getRNG().nextGaussian() * (double)errorModifier + estimateHitTime * target.motionZ, +// bulletAccel); +// +// playSound(SoundEvents.BLOCK_PISTON_EXTEND, 1f, 2f); +// world.spawnEntity(entityIdlProjectile); + } + + @Override + public void setSwingingArms(boolean swingingArms) { + this.dataManager.set(SWINGING_ARMS, swingingArms); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTainter.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTainter.java new file mode 100644 index 0000000..8514778 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTainter.java @@ -0,0 +1,100 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class EntityMoroonTainter extends EntityMoroonUnitBase { + + public float taintChance = 0.03f;//per tick + + public EntityMoroonTainter(World worldIn) { + super(worldIn); + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Blocks.PUMPKIN)); + spawn_without_moroon_ground = true; + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonTainter.class})); + applyGeneralAI(); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + setAttr(35.0D, 0.33000000417232513D, 3.0D, 0.0D, 14.0D); + } + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + int i = MathHelper.floor(this.posX); + int j = MathHelper.floor(this.posY); + int k = MathHelper.floor(this.posZ); + + if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this)) + { + return; + } + //Creates MoronBase block under foot + for (int l = 0; l < 4; ++l) + { + i = MathHelper.floor(this.posX + (double)((float)(l % 2 * 2 - 1) * 0.25F)); + j = MathHelper.floor(this.posY) - 1; + k = MathHelper.floor(this.posZ + (double)((float)(l / 2 % 2 * 2 - 1) * 0.25F)); + BlockPos blockpos = new BlockPos(i, j, k); + + if (rand.nextFloat() < taintChance * (2 - getHealth() / getMaxHealth()) && + legalTransformBlockstate(this.world.getBlockState(blockpos))) + { + this.world.setBlockState(blockpos, Blocks.PUMPKIN.getDefaultState()); + } + } + } + } + + public boolean legalTransformBlockstate(IBlockState state) + { + return state.getMaterial() != Material.AIR && state.getBlock() != Blocks.MOB_SPAWNER; + } + + public void onLivingUpdate() + { + super.onLivingUpdate(); + } + + public boolean getCanSpawnHere() + { + return super.getCanSpawnHere(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTideMaker.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTideMaker.java new file mode 100644 index 0000000..b6bd6a6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonTideMaker.java @@ -0,0 +1,116 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class EntityMoroonTideMaker extends EntityMoroonUnitBase { + + public EntityMoroonTideMaker(World worldIn) { + super(worldIn); + experienceValue = 10; + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Items.WATER_BUCKET)); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + + setAttr(16.0D, 0.5D, 5.0D, 0.0D, 64.0D); + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + + //this.tasks.addTask(1, new EntityAIAvoidEntity(this, EntityGolem.class, 8.0F, 0.6D, 0.6D)); + + this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 8.0F, 0.6D, 0.6D)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[0])); + applyGeneralAI(); + } + + //wont be affected by water flow + @Override + public boolean isPushedByWater() { + return false; + } + + @SubscribeEvent + public static void onCreatureDied(final LivingDeathEvent ev) { + World world = ev.getEntityLiving().world; + EntityLivingBase diedOne = ev.getEntityLiving(); + } + + + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + int i = MathHelper.floor(this.posX); + int j = MathHelper.floor(this.posY); + int k = MathHelper.floor(this.posZ); + + if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this)) + { + return; + } + //Creates water alongside + for (int l = 0; l < 4; ++l) + { + i = MathHelper.floor(this.posX + (double)((float)(l % 2 * 2 - 1) * 0.25F)); + j = MathHelper.floor(this.posY); + k = MathHelper.floor(this.posZ + (double)((float)(l / 2 % 2 * 2 - 1) * 0.25F)); + BlockPos blockpos = new BlockPos(i, j, k); + + if ((this.world.getBlockState(blockpos).getMaterial() == Material.AIR || + this.world.getBlockState(blockpos).getBlock() == Blocks.FLOWING_WATER) + && + this.world.getBlockState(blockpos.add(0, -1 ,0)).getMaterial() != Material.AIR) + { + this.world.setBlockState(blockpos, Blocks.WATER.getDefaultState()); + } + } + } + } + + public void onLivingUpdate() + { + super.onLivingUpdate(); + + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonUnitBase.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonUnitBase.java new file mode 100644 index 0000000..6cf3181 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonUnitBase.java @@ -0,0 +1,183 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.entity.creatures.ideallandTeam.EntityIdeallandUnitBase; +import net.minecraft.entity.IEntityLivingData; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.passive.EntityVillager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.pathfinding.PathNavigateGround; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundEvent; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; + +public class EntityMoroonUnitBase extends EntityModUnit { + + int berserkGazeLv = 0; + protected boolean inflictBerserkBuff = true; + protected boolean autoArmor = false; + +// protected float[] inventoryHandsDropChances = new float[2]; +// /** Chances for armor dropping when this entity dies. */ +// protected float[] inventoryArmorDropChances = new float[4]; + + + + // (Base + Op0) × (1 + SUM(Op1)) × PRODUCT(1+Op2) + //Note that ops are 1 + + //https://minecraft-zh.gamepedia.com/%E5%B1%9E%E6%80%A7 + public EntityMoroonUnitBase(World worldIn) { + super(worldIn); + setCanPickUpLoot(true); + spawn_without_darkness = false; + spawn_without_moroon_ground = false; + experienceValue = 10; + isMoroon = true; + isIdealland = false; + applyLevelBoost = true; + } + + public int getMaxLevel() { + switch (world.getDifficulty()) + { + case PEACEFUL: + return 1; + case EASY: + return 3; + case NORMAL: + return 5; + case HARD: + return maxHardLevel; + } + return 1; + } + + public int getRank() + { + int level = getLevel(); + if (level>=maxHardLevel) + { + return 4; + } + else if (level>=maxNormLevel) + { + return 3; + } + else if (level>=maxEasyLevel) + { + return 2; + } + return 1; + } + + public void ApplyGeneralLevelBoost(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) + { + //with localDiff / 10 chance to lv up recursively + int level = getLevel(); + int maxLv = getMaxLevel(); + float localDifficulty = difficulty.getAdditionalDifficulty(); + while (level < maxLv && ((getRNG().nextFloat()* 10f) <= localDifficulty)) + { + level++; + } + setLevel(level); + } + + @Nullable + @Override + public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) { + livingdata = super.onInitialSpawn(difficulty, livingdata); + ApplyGeneralLevelBoost(difficulty, livingdata); + + if (autoArmor) + { + this.setEquipmentBasedOnDifficulty(difficulty); + this.setEnchantmentBasedOnDifficulty(difficulty); + } + + return super.onInitialSpawn(difficulty, livingdata); + } + + protected void applyGeneralAI() + { + + + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIdeallandUnitBase.class, true)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityZombie.class, false)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false)); + + ((PathNavigateGround)this.getNavigator()).setEnterDoors(true); + } + + @Override + public void onUpdate() { + super.onUpdate(); +// EntityLivingBase target = getAttackTarget(); +// if (inflictBerserkBuff && target != null && berserkGazeLv >= 0 && (world.getWorldTime() % TICK_PER_SECOND == 7) ) +// { +// target.addPotionEffect(new PotionEffect(ModPotions.BERSERK, TICK_PER_SECOND + 1, berserkGazeLv)); +// } + } + + /** + * Checks if the entity's current position is a valid location to spawn this entity. + */ + public boolean getCanSpawnHere() + { + return this.world.getDifficulty() != EnumDifficulty.PEACEFUL && super.getCanSpawnHere(); + } + + public boolean isPreventingPlayerRest(EntityPlayer playerIn) + { + return true; + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); + //IdlFramework.Log("dropLoot Called"); +// dropItem(ModItems.MOR_FRAG, 2 + rand.nextInt(2 + lootingModifier)); +// if (rand.nextFloat() < 0.01f * getLevel()) +// { +// dropItem(ModItems.RANDOM_SKILL, 1); +// } +// +// if (rand.nextFloat() < 0.1f * getLevel()) +// { +// dropItem(ModItems.itemNanoMender_16, 1 + rand.nextInt(2 + lootingModifier)); +// } +// +// if (rand.nextFloat() < 0.1f * getLevel()) +// { +// dropItem(ModItems.itemNanoMender_16, 1 + rand.nextInt(2 + lootingModifier)); +// } +// +// if (rand.nextFloat() < 0.2f * getLevel()) +// { +// dropItem(ModItems.FIGHT_BREAD, 1 + rand.nextInt(2 + lootingModifier)); +// } +// +// if (rand.nextFloat() < ModConfig.GeneralConf.SKILL_RATE * getLevel()) +// { +// dropItem(ModItems.itemNanoMender_128, 1); +// } + + } + + @Override + protected SoundEvent getHurtSound(DamageSource damageSourceIn) { + return SoundEvents.ENTITY_PLAYER_HURT; + } + + // @Override +// protected SoundEvent getAmbientSound() { +// return ModSoundHandler.SOUND_1; +// } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonVampire.java b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonVampire.java new file mode 100644 index 0000000..835124d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/moroon/EntityMoroonVampire.java @@ -0,0 +1,202 @@ +package com.somebody.idlframewok.entity.creatures.moroon; + +import java.util.List; + +import com.somebody.idlframewok.entity.creatures.ideallandTeam.EntityIdeallandUnitBase; +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveThroughVillage; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWanderAvoidWater; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.entity.passive.EntityCow; +import net.minecraft.entity.passive.EntitySheep; +import net.minecraft.entity.passive.EntityVillager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.pathfinding.PathNavigateGround; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import static com.somebody.idlframewok.util.CommonDef.TICK_PER_SECOND; + +public class EntityMoroonVampire extends EntityMoroonUnitBase { + //Summons bats + //Attacking summons bats + //Consume bats to revive + //Become bats when killed (can be used for other vampires) + int summonBatCount = 4; + float summonReqMP = 60f; + + + float reviveConsumeRange = 16; + int reviveConsumeCount = 2; + + + @Override + public boolean isEntityUndead() { + return true; + } + + public EntityMoroonVampire(World worldIn) { + super(worldIn); + + spawn_without_darkness = false; + spawn_without_moroon_ground = true; + MinecraftForge.EVENT_BUS.register(this); + experienceValue = 40; + + MPMax = 100f; + MP = MPMax; + + setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(Items.MUTTON)); + } + + @Override + protected void dropLoot(boolean wasRecentlyHit, int lootingModifier, DamageSource source) { + super.dropLoot(wasRecentlyHit, lootingModifier, source); + +// if (wasRecentlyHit) { +// dropItem(ModItems.skillAttack1, rand.nextInt(1 + lootingModifier)); +// } + } + + protected void initEntityAI() + { + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false)); + //this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityMoroonBombBeacon.class, 8.0F, 0.6D, 1d)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); + this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); + this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.applyEntityAI(); + } + + protected void applyEntityAI() + { + //this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityMoroonVampire.class})); + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, false)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIdeallandUnitBase.class, false)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityZombie.class, false)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false)); + + ((PathNavigateGround)this.getNavigator()).setEnterDoors(true); + this.targetTasks.addTask(4, new EntityAINearestAttackableTarget(this, EntitySheep.class, false)); + this.targetTasks.addTask(4, new EntityAINearestAttackableTarget(this, EntityCow.class, false)); + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + + setAttr(32, 0.4, 6.0, 2, 24); + } + + @Override + public void onUpdate() { + super.onUpdate(); + //IdlFramework.Log("Tick"); + if (!this.world.isRemote) + { + if (world.getWorldTime() % TICK_PER_SECOND == 0) { + if (getAttackTarget() != null && trySpendMana(summonReqMP)) + { + float angle = getRNG().nextFloat() * 6.28f; + for (int i = 1; i <= summonBatCount; i++) + { + EntityBat bat = new EntityBat(world); + angle += 6.28f / summonBatCount; + bat.setPosition(posX + Math.cos(angle), posY, posZ + Math.sin(angle)); + bat.spawnExplosionParticle(); + world.spawnEntity(bat); + } + setHealth(0.8f * getHealth()); + + } + } + } + } + + public boolean attackEntityAsMob(Entity target) { + boolean result = super.attackEntityAsMob(target); + if (result) + { + this.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 3*TICK_PER_SECOND, 0)); + heal(1f); + } + return result; + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void OnDeath(LivingDeathEvent ev) + { + if (!world.isRemote) + { + EntityLivingBase diedOne = ev.getEntityLiving(); + if (diedOne == this) + { + List entities = world.getEntitiesWithinAABB(EntityBat.class, + IDLGeneral.ServerAABB(getPositionEyes(0f), reviveConsumeRange)); + + if (entities.size() >= reviveConsumeCount) + { + ev.setCanceled(true); + for (int i = 0; i < reviveConsumeCount; i++) + { + EntityBat entityBat = entities.get(i); + this.heal(entityBat.getHealth() / 2); + entityBat.setDead(); + this.spawnRunningParticles(); + this.playSound(SoundEvents.ENTITY_WITCH_AMBIENT, 1f, 1f); + } + } + else { + float angle = getRNG().nextFloat() * 6.28f; + for (int i = 1; i <= summonBatCount; i++) + { + EntityBat bat = new EntityBat(world); + angle += 6.28f / summonBatCount; + bat.setPosition(posX + Math.cos(angle), posY, posZ + Math.sin(angle)); + bat.spawnExplosionParticle(); + world.spawnEntity(bat); + } + } + } + + DamageSource source = ev.getSource(); + if (source != null) + { + Entity killer = source.getTrueSource(); + if (killer == this) + { + EntityBat bat = new EntityBat(world); + bat.setPosition(diedOne.posX , diedOne.posY, diedOne.posZ); + bat.spawnExplosionParticle(); + world.spawnEntity(bat); + heal(diedOne.getMaxHealth() / 10f); + } + } + } + + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderBullet.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderBullet.java new file mode 100644 index 0000000..4b9cec9 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderBullet.java @@ -0,0 +1,67 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +public class RenderBullet extends Render { + + private final ResourceLocation texture; + + public RenderBullet(final RenderManager manager, final ResourceLocation textureResource) { + super(manager); + texture = textureResource; + } + + public void doRender(T entity, double x, double y, double z, float entityYaw, float partialTicks) + { + GlStateManager.pushMatrix(); + bindEntityTexture(entity); + GlStateManager.translate((float)x, (float)y,(float)z); + GlStateManager.enableRescaleNormal(); + GlStateManager.scale(0.5f, 0.5f, 0.5f); + + Tessellator tess = Tessellator.getInstance(); + BufferBuilder buffer = tess.getBuffer(); + + GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F); + + if (renderOutlines) { + GlStateManager.enableColorMaterial(); + GlStateManager.enableOutlineMode(getTeamColor(entity)); + } + + buffer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL); + buffer.pos(-0.5D, -0.25D, 0.0D).tex(0.0D, 1.0D).normal(0.0F, 1.0F, 0.0F).endVertex(); + buffer.pos(0.5D, -0.25D, 0.0D).tex(1.0D, 1.0D).normal(0.0F, 1.0F, 0.0F).endVertex(); + buffer.pos(0.5D, 0.75D, 0.0D).tex(1.0D, 0.0D).normal(0.0F, 1.0F, 0.0F).endVertex(); + buffer.pos(-0.5D, 0.75D, 0.0D).tex(0.0D, 0.0D).normal(0.0F, 1.0F, 0.0F).endVertex(); + tess.draw(); + + if (renderOutlines) { + GlStateManager.disableOutlineMode(); + GlStateManager.disableColorMaterial(); + } + + GlStateManager.disableRescaleNormal(); + GlStateManager.popMatrix(); + } + + /** + * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. + */ + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityIdlProjectile entity) + { + return texture; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderConstruction.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderConstruction.java new file mode 100644 index 0000000..23a32c3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderConstruction.java @@ -0,0 +1,29 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.entity.creatures.model.ModelIDLConstruction; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.renderer.entity.RenderLiving; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; + +public class RenderConstruction extends RenderLiving { + public static final ResourceLocation TEXTURES = new ResourceLocation(Reference.MOD_ID + ":textures/entity/idl_construction.png"); + public RenderConstruction(RenderManager manager){ + super(manager, new ModelIDLConstruction(), 0.5F); + } + + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityModUnit entity) { + return TEXTURES; + } + + @Override + protected void applyRotations(EntityModUnit entityLiving, float p_77043_2_, float rotationYaw, float partialTicks) { + super.applyRotations(entityLiving, p_77043_2_, rotationYaw, partialTicks); + + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderModUnit.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderModUnit.java new file mode 100644 index 0000000..53c54f4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderModUnit.java @@ -0,0 +1,42 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.model.ModelZombie; +import net.minecraft.client.renderer.entity.RenderBiped; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class RenderModUnit extends RenderBiped { + private static final ResourceLocation DEFAULT_RES_LOC = new ResourceLocation("textures/entity/steve.png"); + + public RenderModUnit(RenderManager renderManagerIn) + { + super(renderManagerIn, new ModelZombie(), 0.5F); + } + + + public RenderModUnit(RenderManager renderManagerIn, ModelBiped modelBipedIn, float shadowSize) { + super(renderManagerIn, modelBipedIn, shadowSize); +// LayerBipedArmor layerbipedarmor = new LayerBipedArmor(this) +// { +// protected void initArmor() +// { +// this.modelLeggings = new ModelZombie(0.5F, true); +// this.modelArmor = new ModelZombie(1.0F, true); +// } +// }; +// this.addLayer(layerbipedarmor); + } + + /** + * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. + */ + protected ResourceLocation getEntityTexture(EntityModUnit entity) + { + return DEFAULT_RES_LOC; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderMoroonHumanoid.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderMoroonHumanoid.java new file mode 100644 index 0000000..a39c38e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderMoroonHumanoid.java @@ -0,0 +1,52 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.model.ModelPlayer; +import net.minecraft.client.renderer.entity.RenderBiped; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.layers.LayerBipedArmor; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class RenderMoroonHumanoid extends RenderBiped { + private static final ResourceLocation DEFAULT_RES_LOC = new ResourceLocation(Reference.MOD_ID + ":textures/entity/moroon_humanoid.png"); + + public RenderMoroonHumanoid(RenderManager renderManagerIn) + { + super(renderManagerIn, new ModelPlayer(1f, false), 0.5F); + this.addLayer(new LayerBipedArmor(this)); + //this.addLayer(new LayerHeldItem(this)); + //this.addLayer(new LayerArrow(this)); +// this.addLayer(new LayerDeadmau5Head(this)); +// this.addLayer(new LayerCape(this)); +// this.addLayer(new LayerCustomHead(this.getMainModel().bipedHead)); + //this.addLayer(new LayerElytra(this)); + //this.addLayer(new LayerEntityOnShoulder(renderManager)); + } + + + public RenderMoroonHumanoid(RenderManager renderManagerIn, ModelBiped modelBipedIn, float shadowSize) { + super(renderManagerIn, modelBipedIn, shadowSize); +// LayerBipedArmor layerbipedarmor = new LayerBipedArmor(this) +// { +// protected void initArmor() +// { +// this.modelLeggings = new ModelZombie(0.5F, true); +// this.modelArmor = new ModelZombie(1.0F, true); +// } +// }; +// this.addLayer(layerbipedarmor); + } + + /** + * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. + */ + protected ResourceLocation getEntityTexture(EntityModUnit entity) + { + return DEFAULT_RES_LOC; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret.java new file mode 100644 index 0000000..f4eba98 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret.java @@ -0,0 +1,29 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.entity.creatures.model.ModelTurretPrototype; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.renderer.entity.RenderLiving; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; + +public class RenderTurret extends RenderLiving { + public static final ResourceLocation TEXTURES = new ResourceLocation(Reference.MOD_ID + ":textures/entity/turret_one.png"); + public RenderTurret(RenderManager manager){ + super(manager, new ModelTurretPrototype(), 0.5F); + } + + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityModUnit entity) { + return TEXTURES; + } + + @Override + protected void applyRotations(EntityModUnit entityLiving, float p_77043_2_, float rotationYaw, float partialTicks) { + super.applyRotations(entityLiving, p_77043_2_, rotationYaw, partialTicks); + + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret2.java b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret2.java new file mode 100644 index 0000000..7f5061e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/creatures/render/RenderTurret2.java @@ -0,0 +1,28 @@ +package com.somebody.idlframewok.entity.creatures.render; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.entity.creatures.misc.EntityTurretPrototype2; +import com.somebody.idlframewok.entity.creatures.model.ModelTurretPrototype; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.renderer.entity.RenderLiving; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; + +public class RenderTurret2 extends RenderLiving { + public static final ResourceLocation TEXTURES = new ResourceLocation(Reference.MOD_ID + ":textures/entity/turret_one.png"); + public RenderTurret2(RenderManager manager){ + super(manager, new ModelTurretPrototype(), 0.5F); + } + + @Nullable + @Override + protected ResourceLocation getEntityTexture(EntityTurretPrototype2 entity) { + return TEXTURES; + } + + @Override + protected void applyRotations(EntityTurretPrototype2 entityLiving, float p_77043_2_, float rotationYaw, float partialTicks) { + super.applyRotations(entityLiving, p_77043_2_, rotationYaw, partialTicks); + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/projectiles/EntityIdlProjectile.java b/src/main/java/com/somebody/idlframewok/entity/projectiles/EntityIdlProjectile.java new file mode 100644 index 0000000..9f3a9f6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/projectiles/EntityIdlProjectile.java @@ -0,0 +1,354 @@ +package com.somebody.idlframewok.entity.projectiles; + +import java.util.Random; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.projectile.ProjectileHelper; +import net.minecraft.init.SoundEvents; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +//modified from fireballs +public class EntityIdlProjectile extends Entity implements IProjectile { + public EntityLivingBase shootingEntity; + private int ticksAlive; + protected int ticksInAir; + public double accelerationX; + public double accelerationY; + public double accelerationZ; + public ProjectileArgs args; + boolean hitToDeflect = false; + + public float acceleration = 0.1f; + + protected EntityIdlProjectile(World worldIn) + { + super(worldIn); + args = new ProjectileArgs(1f); + } + + @Override + protected void entityInit() { + + } + + protected EntityIdlProjectile(World worldIn, ProjectileArgs args) { + super(worldIn); + this.args = args; + //IdlFramework.Log("bullet created %s, args = %s", getUniqueID(), this.args); + } + + /** + * Checks if the entity is in range to render. + */ + @SideOnly(Side.CLIENT) + public boolean isInRangeToRenderDist(double distance) + { + double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 4.0D; + + if (Double.isNaN(d0)) + { + d0 = 4.0D; + } + + d0 = d0 * 64.0D; + return distance < d0 * d0; + } + +// public EntityIdlProjectile(World worldIn, ProjectileArgs args, double x, double y, double z, double accelX, double accelY, double accelZ) +// { +// this(worldIn, args); +// this.setSize(0.3125F, 0.3125F); +// this.setLocationAndAngles(x, y, z, this.rotationYaw, this.rotationPitch); +// this.setPosition(x, y, z); +// double d0 = (double) MathHelper.sqrt(accelX * accelX + accelY * accelY + accelZ * accelZ); +// this.accelerationX = accelX / d0 * 0.1D; +// this.accelerationY = accelY / d0 * 0.1D; +// this.accelerationZ = accelZ / d0 * 0.1D; +// } + + public EntityIdlProjectile(World worldIn, ProjectileArgs args, EntityLivingBase shooter, double accelX, double accelY, double accelZ, float acceleration) + { + this(worldIn, args); + this.shootingEntity = shooter; + this.setSize(0.3125F, 0.3125F); + + Vec3d shooterFacing = shooter.getLook(0f); + + this.setLocationAndAngles(shooter.posX + shooterFacing.x, + shooter.posY + shooter.getEyeHeight() + shooterFacing.y, + shooter.posZ + shooterFacing.z, + shooter.rotationYaw, shooter.rotationPitch); + this.setPosition(this.posX, this.posY, this.posZ); + this.motionX = 0.0D; + this.motionY = 0.0D; + this.motionZ = 0.0D; + //accelX = accelX + this.rand.nextGaussian() * 0.4D; + //accelY = accelY + this.rand.nextGaussian() * 0.4D; + //accelZ = accelZ + this.rand.nextGaussian() * 0.4D; + double accelLength = (double)MathHelper.sqrt(accelX * accelX + accelY * accelY + accelZ * accelZ); + this.accelerationX = accelX / accelLength * acceleration; + this.accelerationY = accelY / accelLength * acceleration; + this.accelerationZ = accelZ / accelLength * acceleration; + } + + public EntityIdlProjectile(World worldIn, ProjectileArgs args, EntityLivingBase shooter, double accelX, double accelY, double accelZ) + { + this(worldIn, args, shooter, accelX, accelY, accelZ, 0.1f); + } + + /** + * Called to update the entity's position/logic. + */ + public void onUpdate() + { + //IdlFramework.Log("Bullet pos update:%s", getPositionEyes(0)); + + if (this.world.isRemote || (this.shootingEntity == null || !this.shootingEntity.isDead) && this.world.isBlockLoaded(new BlockPos(this))) + { + super.onUpdate(); + + if (this.isFireballFiery()) + { + this.setFire(1); + } + + ++this.ticksInAir; + RayTraceResult raytraceresult = ProjectileHelper.forwardsRaycast(this, true, this.ticksInAir >= 25, this.shootingEntity); + + if (raytraceresult != null && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, raytraceresult)) + { + this.onImpact(raytraceresult); + } + + this.posX += this.motionX; + this.posY += this.motionY; + this.posZ += this.motionZ; + ProjectileHelper.rotateTowardsMovement(this, 0.2F); + float f = 0.99f; + + if (this.isInWater()) + { + for (int i = 0; i < 4; ++i) + { + float f1 = 0.25F; + this.world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX - this.motionX * 0.25D, this.posY - this.motionY * 0.25D, this.posZ - this.motionZ * 0.25D, this.motionX, this.motionY, this.motionZ); + } + + f = 0.8F; + } + + this.motionX += this.accelerationX; + this.motionY += this.accelerationY; + this.motionZ += this.accelerationZ; + this.motionX *= (double)f; + this.motionY *= (double)f; + this.motionZ *= (double)f; + //this.world.spawnParticle(this.getParticleType(), this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D); + this.setPosition(this.posX, this.posY, this.posZ); + } + else + { + this.setDead(); + } + } + + protected boolean isFireballFiery() + { + if (args == null) + { + //IdlFramework.LogWarning("Args not found for bullet"); + return false; + } + return args.burning; + } + +// protected EnumParticleTypes getParticleType() +// { +// return EnumParticleTypes.SMOKE_NORMAL; +// } + + /** + * Called when this EntityIdlProjectile hits a block or entity. + */ + protected void onImpact(RayTraceResult result) + { + //IdlFramework.Log("bullet impact %s", getUniqueID()); + if (!this.world.isRemote) + { + if (result.entityHit != null) + { + result.entityHit.attackEntityFrom(DamageSource.causeIndirectDamage(this, this.shootingEntity).setProjectile(), args.damage); + this.applyEnchantments(this.shootingEntity, result.entityHit); + } + + boolean flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.shootingEntity); + if (args.explosion_power > 0) { + this.world.newExplosion(null, posX, posY, posZ, args.explosion_power, flag, flag); + } + world.playSound(posX, posY, posZ, SoundEvents.BLOCK_LAVA_EXTINGUISH, + SoundCategory.NEUTRAL, 1f, 1f, false); + + this.setDead(); + } + else { + world.spawnParticle(EnumParticleTypes.CLOUD, posX, posY, posZ, motionX, motionY, motionZ); + if (result.entityHit == null) + { + Random random = new Random(); + float vx = (float) (motionX * 0.3f); + float vy = (float) (motionY * 0.3f); + float vz = (float) (motionZ * 0.3f); + + world.spawnParticle(EnumParticleTypes.FLAME, posX, posY, posZ, vx * random.nextFloat(), vy * random.nextFloat(), vz * random.nextFloat()); + world.spawnParticle(EnumParticleTypes.FLAME, posX, posY, posZ, -vx * random.nextFloat(), -vy * random.nextFloat(), -vz * random.nextFloat()); + world.spawnParticle(EnumParticleTypes.FLAME, posX, posY, posZ, -vx * random.nextFloat(), -vy * random.nextFloat(), -vz * random.nextFloat()); + } + } + } + + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + public void writeEntityToNBT(NBTTagCompound compound) + { + compound.setTag("direction", this.newDoubleNBTList(this.motionX, this.motionY, this.motionZ)); + compound.setTag("power", this.newDoubleNBTList(this.accelerationX, this.accelerationY, this.accelerationZ)); + compound.setInteger("life", this.ticksAlive); + + this.args.writeEntityToNBT(compound); + } + + /** + * (abstract) Protected helper method to read subclass entity data from NBT. + */ + public void readEntityFromNBT(NBTTagCompound compound) + { + if (compound.hasKey("power", 9)) + { + NBTTagList nbttaglist = compound.getTagList("power", 6); + + if (nbttaglist.tagCount() == 3) + { + this.accelerationX = nbttaglist.getDoubleAt(0); + this.accelerationY = nbttaglist.getDoubleAt(1); + this.accelerationZ = nbttaglist.getDoubleAt(2); + } + } + + this.ticksAlive = compound.getInteger("life"); + + if (compound.hasKey("direction", 9) && compound.getTagList("direction", 6).tagCount() == 3) + { + NBTTagList nbttaglist1 = compound.getTagList("direction", 6); + this.motionX = nbttaglist1.getDoubleAt(0); + this.motionY = nbttaglist1.getDoubleAt(1); + this.motionZ = nbttaglist1.getDoubleAt(2); + } + else + { + this.setDead(); + } + + if (this.args == null) + { + this.args = new ProjectileArgs(1f); + } + this.args.readEntityFromNBT(compound); + } + + /** + * Returns true if other Entities should be prevented from moving through this Entity. + */ + public boolean canBeCollidedWith() + { + return true; + } + + public float getCollisionBorderSize() + { + return 1.0F; + } + + /** + * Called when the entity is attacked. + */ + public boolean attackEntityFrom(DamageSource source, float amount) + { + if (this.isEntityInvulnerable(source) || !hitToDeflect) + { + return false; + } + else + { + this.markVelocityChanged(); + + if (source.getTrueSource() != null) + { + Vec3d vec3d = source.getTrueSource().getLookVec(); + + this.motionX = vec3d.x; + this.motionY = vec3d.y; + this.motionZ = vec3d.z; + this.accelerationX = this.motionX * 0.1D; + this.accelerationY = this.motionY * 0.1D; + this.accelerationZ = this.motionZ * 0.1D; + + if (source.getTrueSource() instanceof EntityLivingBase) + { + this.shootingEntity = (EntityLivingBase)source.getTrueSource(); + } + + return true; + } + else + { + return false; + } + } + } + + @SideOnly(Side.CLIENT) + public int getBrightnessForRender() + { + return 15728880; + } + + /** + * Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction. + */ + public void shoot(double x, double y, double z, float velocity, float inaccuracy) + { + float f = MathHelper.sqrt(x * x + y * y + z * z); + x = x / (double)f; + y = y / (double)f; + z = z / (double)f; + x = x + this.rand.nextGaussian() * 0.007499999832361937D * (double)inaccuracy; + y = y + this.rand.nextGaussian() * 0.007499999832361937D * (double)inaccuracy; + z = z + this.rand.nextGaussian() * 0.007499999832361937D * (double)inaccuracy; + x = x * (double)velocity; + y = y * (double)velocity; + z = z * (double)velocity; + this.motionX = x; + this.motionY = y; + this.motionZ = z; + float f1 = MathHelper.sqrt(x * x + z * z); + this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI)); + this.rotationPitch = (float)(MathHelper.atan2(y, (double)f1) * (180D / Math.PI)); + this.prevRotationYaw = this.rotationYaw; + this.prevRotationPitch = this.rotationPitch; + //this.ticksInGround = 0; + } +} diff --git a/src/main/java/com/somebody/idlframewok/entity/projectiles/ProjectileArgs.java b/src/main/java/com/somebody/idlframewok/entity/projectiles/ProjectileArgs.java new file mode 100644 index 0000000..18bf332 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/entity/projectiles/ProjectileArgs.java @@ -0,0 +1,38 @@ +package com.somebody.idlframewok.entity.projectiles; + +import net.minecraft.nbt.NBTTagCompound; + +public class ProjectileArgs { + public float damage = 1f; + public float explosion_power = 0f; + public float speed = 1f; + public boolean burning = false; + + public ProjectileArgs(float damage, float explosion_power, float speed, boolean burning) { + this.damage = damage; + this.explosion_power = explosion_power; + this.speed = speed; + this.burning = burning; + } + + public ProjectileArgs(float damage) { + this.damage = damage; + } + + public void writeEntityToNBT(NBTTagCompound compound) + { + compound.setFloat("damage", damage); + compound.setFloat("explosion_power", explosion_power); + compound.setBoolean("burning", this.burning); + compound.setFloat("explosion_power", this.explosion_power); + } + + public void readEntityFromNBT(NBTTagCompound compound) + { + this.damage = compound.getFloat("damage"); + this.explosion_power = compound.getFloat("explosion_power"); + this.burning = compound.getBoolean("burning"); + this.explosion_power = compound.getFloat("explosion_power"); + + } +} diff --git a/src/main/java/com/somebody/idlframewok/events/ModStarterEvents.java b/src/main/java/com/somebody/idlframewok/events/ModStarterEvents.java new file mode 100644 index 0000000..693d888 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/events/ModStarterEvents.java @@ -0,0 +1,31 @@ +package com.somebody.idlframewok.events; + +import com.somebody.idlframewok.util.IDLNBT; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ModStarterEvents { + @SubscribeEvent + public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { + EntityPlayer player = event.player; + //IdlFramework.Log(getPlyrIdlTagSafe(player).toString()); + int lastStarterVer = IDLNBT.getPlayerIdeallandIntSafe(player, IDLNBTDef.STARTER_KIT_VERSION_TAG); + if(lastStarterVer < IDLNBTDef.CUR_STARTER_KIT_VERSION) { +// IDLNBT.setPlayerIdeallandTagSafe(player, STARTER_KIT_VERSION_TAG, CUR_STARTER_KIT_VERSION); +// +// ItemStack scry = new ItemStack(Items.QUARTZ); +// player.addItemStackToInventory(scry); +// +// if (player instanceof EntityPlayerMP) { +// CommonFunctions.SendMsgToPlayerStyled((EntityPlayerMP)player, "idlframework.msg.starter_kit_given", TextFormatting.AQUA); +// } +// IdlFramework.Log(String.format("Given starter items to player %s, ver %d", player.getDisplayNameString(), CUR_STARTER_KIT_VERSION)); + } + } + +} diff --git a/src/main/java/com/somebody/idlframewok/gui/ModGuiElementLoader.java b/src/main/java/com/somebody/idlframewok/gui/ModGuiElementLoader.java new file mode 100644 index 0000000..4983104 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/gui/ModGuiElementLoader.java @@ -0,0 +1,48 @@ +package com.somebody.idlframewok.gui; + +import javax.annotation.Nullable; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.gui.expOne.ContainerDemo; +import com.somebody.idlframewok.gui.expOne.GuiContainerDemo; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.IGuiHandler; +import net.minecraftforge.fml.common.network.NetworkRegistry; + +//todo +//https://fmltutor.ustc-zzzz.net/3.4.3-GUI%E7%95%8C%E9%9D%A2%E4%B8%AD%E7%9A%84%E4%BA%A4%E4%BA%92.html +public class ModGuiElementLoader implements IGuiHandler { + + public static final int GUI_DEMO = 1; + public static final int GUI_RESEARCH = 2; + + public ModGuiElementLoader() + { + NetworkRegistry.INSTANCE.registerGuiHandler(IdlFramework.instance, this); + } + + @Nullable + @Override + public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + switch (ID) + { + case GUI_DEMO: + return new ContainerDemo(player); + default: + return null; + } + } + + @Nullable + @Override + public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + switch (ID) + { + case GUI_DEMO: + return new GuiContainerDemo(new ContainerDemo(player)); + default: + return null; + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/gui/expOne/ContainerDemo.java b/src/main/java/com/somebody/idlframewok/gui/expOne/ContainerDemo.java new file mode 100644 index 0000000..f43b5a0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/gui/expOne/ContainerDemo.java @@ -0,0 +1,193 @@ +package com.somebody.idlframewok.gui.expOne; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +//https://fmltutor.ustc-zzzz.net/3.4.2-GUI%E7%95%8C%E9%9D%A2%E7%9A%84%E4%B8%AA%E6%80%A7%E5%8C%96%E4%B8%8E%E7%89%A9%E5%93%81%E6%A7%BD%E7%9A%84%E6%B7%BB%E5%8A%A0.html +public class ContainerDemo extends Container { + private ItemStackHandler items = new ItemStackHandler(4); + + protected Slot goldSlot; + protected Slot diamondSlot; + protected Slot emeraldSlot; + protected Slot ironSlot; + + public ContainerDemo(EntityPlayer player) + { + super(); + + this.addSlotToContainer(this.goldSlot = new SlotItemHandler(items, 0, 38 + 0 * 32, 20) + { + @Override + public boolean isItemValid(ItemStack stack) + { + return stack != null && stack.getItem() == Items.GOLD_INGOT && super.isItemValid(stack); + } + + @Override + public int getItemStackLimit(ItemStack stack) + { + return 16; + } + }); + + //2nd + this.addSlotToContainer(this.diamondSlot = new SlotItemHandler(items, 1, 38 + 1 * 32, 20) + { + { + this.putStack(new ItemStack(Items.DIAMOND, 64)); + } + + @Override + public boolean canTakeStack(EntityPlayer playerIn) + { + return false; + } + }); + + //3rd + this.addSlotToContainer(this.emeraldSlot = new SlotItemHandler(items, 2, 38 + 2 * 32, 20) + { + @Override + public boolean isItemValid(ItemStack stack) + { + return stack != null && stack.getItem() == Items.EMERALD && super.isItemValid(stack); + } + + @Override + public void onSlotChanged() + { + ItemStack stack = this.getStack(); + int amount = stack.isEmpty() ? 64 : 64 - stack.getCount(); + ContainerDemo.this.diamondSlot.putStack(amount == 0 ? ItemStack.EMPTY : new ItemStack(Items.DIAMOND, amount)); + super.onSlotChanged(); + } + }); + + //4th + this.addSlotToContainer(this.ironSlot = new SlotItemHandler(items, 3, 38 + 3 * 32, 20) + { + { + this.putStack(new ItemStack(Items.IRON_INGOT, 64)); + } + + @Override + public boolean canTakeStack(EntityPlayer playerIn) + { + return false; + } + }); + + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 9; ++j) + { + this.addSlotToContainer(new Slot(player.inventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18)); + } + } + + for (int i = 0; i < 9; ++i) + { + this.addSlotToContainer(new Slot(player.inventory, i, 8 + i * 18, 109)); + } + + + } + + public Slot getIronSlot() + { + return this.ironSlot; + } + + @Override + public boolean canInteractWith(EntityPlayer playerIn) { + return true; + //return playerIn.getHeldItemOffhand().getItem() == ModItems.DEBUG_ITEM_3; + } + + @Override + public void onContainerClosed(EntityPlayer playerIn) + { + //if the gui does not connects a tile entity, this must be manually rewritten + super.onContainerClosed(playerIn); + + if (playerIn.isServerWorld()) + { + ItemStack goldStack = this.goldSlot.getStack(); + if (goldStack != ItemStack.EMPTY) + { + playerIn.addItemStackToInventory(goldStack); + this.goldSlot.putStack(ItemStack.EMPTY); + } + ItemStack emeraldStack = this.emeraldSlot.getStack(); + if (emeraldStack != ItemStack.EMPTY) + { + playerIn.addItemStackToInventory(emeraldStack); + this.emeraldSlot.putStack(ItemStack.EMPTY); + } + } + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) + { + Slot slot = inventorySlots.get(index); + + if (slot == null || !slot.getHasStack()) + { + return null; + } + + ItemStack newStack = slot.getStack(), oldStack = newStack.copy(); + + //--------------------- + boolean isMerged = false; + + if (index == 0 || index == 2) + { + isMerged = mergeItemStack(newStack, 4, 40, true); + } + else if (index >= 4 && index < 31) + { + isMerged = !goldSlot.getHasStack() && newStack.getCount() <= 16 && mergeItemStack(newStack, 0, 1, false) + || !emeraldSlot.getHasStack() && mergeItemStack(newStack, 2, 3, false) + || mergeItemStack(newStack, 31, 40, false); + } + else if (index >= 31 && index < 40) + { + isMerged = !goldSlot.getHasStack() && newStack.getCount() <= 16 && mergeItemStack(newStack, 0, 1, false) + || !emeraldSlot.getHasStack() && mergeItemStack(newStack, 2, 3, false) + || mergeItemStack(newStack, 4, 31, false); + } + + if (!isMerged) + { + return ItemStack.EMPTY; + } + + //--------------------- + + if (!isMerged) + { + return ItemStack.EMPTY; + } + + if (newStack.getCount() == 0) + { + slot.putStack(ItemStack.EMPTY); + } + else + { + slot.onSlotChanged(); + } + + slot.onTake(playerIn, newStack); + + return oldStack; + } +} diff --git a/src/main/java/com/somebody/idlframewok/gui/expOne/GuiContainerDemo.java b/src/main/java/com/somebody/idlframewok/gui/expOne/GuiContainerDemo.java new file mode 100644 index 0000000..d2fd987 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/gui/expOne/GuiContainerDemo.java @@ -0,0 +1,134 @@ +package com.somebody.idlframewok.gui.expOne; + +import java.io.IOException; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiContainerDemo extends GuiContainer { + private static final String TEXTURE_PATH = IdlFramework.MODID + ":" + "textures/gui/container/gui_demo.png"; + private static final ResourceLocation TEXTURE = new ResourceLocation(TEXTURE_PATH); + + private static final int BUTTON_UP = 0; + private static final int BUTTON_DOWN = 1; + + private Slot ironSlot; + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + GlStateManager.color(1.0F, 1.0F, 1.0F); + + this.mc.getTextureManager().bindTexture(TEXTURE); + int offsetX = (this.width - this.xSize) / 2, offsetY = (this.height - this.ySize) / 2; + + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + } + + public GuiContainerDemo(ContainerDemo inventorySlotsIn) + { + super(inventorySlotsIn); + this.xSize = 176; + this.ySize = 133; + this.ironSlot = inventorySlotsIn.getIronSlot(); + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) + { + this.drawVerticalLine(30, 19, 36, 0xFF000000); + this.drawHorizontalLine(8, 167, 43, 0xFF000000); + + String title = I18n.format("container.fmltutor.demo"); + this.fontRenderer.drawString(title, (this.xSize - this.fontRenderer.getStringWidth(title)) / 2, 6, 0x404040); + + ItemStack item = new ItemStack(Items.QUARTZ); + this.itemRender.renderItemAndEffectIntoGUI(item, 8, 20); + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException + { + ItemStack stack = this.ironSlot.getStack(); + int amount = stack == ItemStack.EMPTY ? 0 : stack.getCount(); + + switch (button.id) + { + case BUTTON_DOWN: + amount = (amount + 64) % 65; + break; + case BUTTON_UP: + amount = (amount + 1) % 65; + break; + default: + super.actionPerformed(button); + return; + } + + this.ironSlot.putStack(amount == 0 ? ItemStack.EMPTY : new ItemStack(Items.IRON_INGOT, amount)); + } + + @Override + public void initGui() + { + super.initGui(); + int offsetX = (this.width - this.xSize) / 2, offsetY = (this.height - this.ySize) / 2; + this.buttonList.add(new GuiButton(BUTTON_UP, offsetX + 153, offsetY + 17, 15, 10, "") + { + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) + { + if (this.visible) + { + GlStateManager.color(1.0F, 1.0F, 1.0F); + + mc.getTextureManager().bindTexture(TEXTURE); + int x = mouseX - this.x, y = mouseY - this.y; + + if (x >= 0 && y >= 0 && x < this.width && y < this.height) + { + this.drawTexturedModalRect(this.x, this.y, 1, 146, this.width, this.height); + } + else + { + this.drawTexturedModalRect(this.x, this.y, 1, 134, this.width, this.height); + } + } + } + }); + this.buttonList.add(new GuiButton(BUTTON_DOWN, offsetX + 153, offsetY + 29, 15, 10, "") + { + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) + { + if (this.visible) + { + GlStateManager.color(1.0F, 1.0F, 1.0F); + + mc.getTextureManager().bindTexture(TEXTURE); + int x = mouseX - this.x, y = mouseY - this.y; + + if (x >= 0 && y >= 0 && x < this.width && y < this.height) + { + this.drawTexturedModalRect(this.x, this.y, 20, 146, this.width, this.height); + } + else + { + this.drawTexturedModalRect(this.x, this.y, 20, 134, this.width, this.height); + } + } + } + }); + } +} + diff --git a/src/main/java/com/somebody/idlframewok/init/InitBiome.java b/src/main/java/com/somebody/idlframewok/init/InitBiome.java new file mode 100644 index 0000000..8ed778e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/InitBiome.java @@ -0,0 +1,29 @@ +package com.somebody.idlframewok.init; + +import com.somebody.idlframewok.IdlFramework; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.BiomeDictionary.Type; +import net.minecraftforge.common.BiomeManager; +import net.minecraftforge.common.BiomeManager.BiomeEntry; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +public class InitBiome { + //public static final Biome BIOME_ONE = new BiomeOne(); + public static void registerBiomes() + { + //initBiome(BIOME_ONE, "biome_one", BiomeManager.BiomeType.WARM, Type.HILLS, Type.DENSE); + } + + public static Biome initBiome(Biome biome, String name, BiomeManager.BiomeType biomeType, Type... type) + { + biome.setRegistryName(name); + ForgeRegistries.BIOMES.register(biome); + IdlFramework.LogWarning("Biome registered:%s", name); + BiomeDictionary.addTypes(biome, type); + BiomeManager.addBiome(biomeType, new BiomeEntry(biome, 10)); + BiomeManager.addSpawnBiome(biome); + return biome; + } + +} diff --git a/src/main/java/com/somebody/idlframewok/init/InitDimension.java b/src/main/java/com/somebody/idlframewok/init/InitDimension.java new file mode 100644 index 0000000..bd677ff --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/InitDimension.java @@ -0,0 +1,10 @@ +package com.somebody.idlframewok.init; + +public class InitDimension { + //public static final DimensionType DIM_ONE = DimensionType.register("Dim_one", "_testdim", ModConfig.DEBUG_CONF.DIM_ONE_ID, DimensionOne.class, false); + + public static void registerDimensions() + { + //DimensionManager.registerDimension(ModConfig.DEBUG_CONF.DIM_ONE_ID, DIM_ONE); + } +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModAchivements.java b/src/main/java/com/somebody/idlframewok/init/ModAchivements.java new file mode 100644 index 0000000..990ee80 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModAchivements.java @@ -0,0 +1,7 @@ +package com.somebody.idlframewok.init; + +public class ModAchivements { + + //Todo: achivements + +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModAnvilEvents.java b/src/main/java/com/somebody/idlframewok/init/ModAnvilEvents.java new file mode 100644 index 0000000..45fb98a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModAnvilEvents.java @@ -0,0 +1,64 @@ +package com.somebody.idlframewok.init; + +import com.somebody.idlframewok.util.Reference; +import net.minecraftforge.event.AnvilUpdateEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ModAnvilEvents { +// @Cancelable +// public class AnvilUpdateEvent extends Event +// { +// @Nonnull +// private final ItemStack left; // The left side of the input +// @Nonnull +// private final ItemStack right; // The right side of the input +// private final String name; // The name to set the item, if the user specified one. +// @Nonnull +// private ItemStack output; // Set this to set the output stack +// private int cost; // The base cost, set this to change it if output != null +// private int materialCost; // The number of items from the right slot to be consumed during the repair. Leave as 0 to consume the entire stack. +// +// public AnvilUpdateEvent(@Nonnull ItemStack left, @Nonnull ItemStack right, String name, int cost) +// { +// this.left = left; +// this.right = right; +// this.output = ItemStack.EMPTY; +// this.name = name; +// this.setCost(cost); +// this.setMaterialCost(0); +// } +// +// @Nonnull +// public ItemStack getLeft() { return left; } +// @Nonnull +// public ItemStack getRight() { return right; } +// public String getName() { return name; } +// @Nonnull +// public ItemStack getOutput() { return output; } +// public void setOutput(@Nonnull ItemStack output) { this.output = output; } +// public int getCost() { return cost; } +// public void setCost(int cost) { this.cost = cost; } +// public int getMaterialCost() { return materialCost; } +// public void setMaterialCost(int materialCost) { this.materialCost = materialCost; } +// } + + @SubscribeEvent + public static void checkEdictCraft(AnvilUpdateEvent event) + { +// if (event.getLeft() != ItemStack.EMPTY && event.getRight() != ItemStack.EMPTY ) { +// ItemStack left = event.getLeft(); +// ItemStack right = event.getRight(); +// +// if (left.getItem() == Items.PAPER && right.getItem() == Item.getItemFromBlock(Blocks.GOLD_BLOCK)) +// { +// event.setMaterialCost(1); +// event.setCost(30); +// +// ItemStack result = new ItemStack(ModItems.RANDOM_EDICT); +// event.setOutput(result); +// } +// } + } +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModConfig.java b/src/main/java/com/somebody/idlframewok/init/ModConfig.java new file mode 100644 index 0000000..92c6b6a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModConfig.java @@ -0,0 +1,59 @@ +package com.somebody.idlframewok.init; + +import com.somebody.idlframewok.util.Reference; +import net.minecraftforge.common.config.Config; +import net.minecraftforge.common.config.ConfigManager; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Config(modid = Reference.MOD_ID, category = "") +public class ModConfig { + @Mod.EventBusSubscriber(modid = Reference.MOD_ID) + private static class EventHandler { + + private EventHandler() { + } + + @SubscribeEvent + public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event) { + if (event.getModID().equals(Reference.MOD_ID)) { + ConfigManager.sync(Reference.MOD_ID, Config.Type.INSTANCE); + } + } + } + + @Config.LangKey("configgui.idlframewok.category.Menu0.GeneralConf") + @Config.Comment("IdlFramework general config.") + public static final GeneralConf GeneralConf = new GeneralConf(); + + public static class GeneralConf { +// @Config.LangKey("idlframewok.conf.general.welcome") +// @Config.Comment("The text shown when a player logs in. Can be a key or a string.") +// public String WELCOME_MSG = "idlframewok.msg.welcome"; + } + + @Config.LangKey("configgui.idlframewok.category.Menu0.DebugConf") + @Config.Comment("Config for developers") + public static final DebugConf DEBUG_CONF = new DebugConf(); + + public static class DebugConf { + + } + + @Config.LangKey("configgui.idlframewok.category.Menu0.SpawnConf") + @Config.Comment("Spawning") + public static final SpawnConf SPAWN_CONF = new SpawnConf(); + + public static class SpawnConf { + @Config.LangKey("conf.spawn.enabled") + @Config.Comment("Spawn mod creatures") + @Config.RequiresMcRestart + public boolean SPAWN = true; + +// @Config.LangKey("entity.moroon_tainter.name") +// @Config.Comment("Spawn Moroon Tainter") +// @Config.RequiresMcRestart +// public int SPAWN_TAINTER = 100; + } +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModCreativeTab.java b/src/main/java/com/somebody/idlframewok/init/ModCreativeTab.java new file mode 100644 index 0000000..da14f2e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModCreativeTab.java @@ -0,0 +1,18 @@ +package com.somebody.idlframewok.init; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ModCreativeTab { + public static final CreativeTabs IDL_MISC = new CreativeTabs(CreativeTabs.getNextID(), "ideallandMiscTab") + { + @SideOnly(Side.CLIENT) + public ItemStack getTabIconItem() + { + return new ItemStack(Items.QUARTZ); + } + }; +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModLootList.java b/src/main/java/com/somebody/idlframewok/init/ModLootList.java new file mode 100644 index 0000000..4f0ea77 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModLootList.java @@ -0,0 +1,61 @@ +package com.somebody.idlframewok.init; + +import java.io.File; +import java.util.Collections; +import java.util.Set; + +import com.google.common.collect.Sets; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.loot.LootTable; +import net.minecraft.world.storage.loot.LootTableManager; + +public class ModLootList { + + private static final Set LOOT_TABLES = Sets.newHashSet(); + private static final Set READ_ONLY_LOOT_TABLES = Collections.unmodifiableSet(LOOT_TABLES); + public static final ResourceLocation EMPTY = register("empty"); + //public static final ResourceLocation M_O_B = register("entities/mor_orbital_beacon"); + + + private static ResourceLocation register(String id) + { + return register(new ResourceLocation(Reference.MOD_ID, "loot_table/" + id)); + } + + public static ResourceLocation register(ResourceLocation id) + { + if (LOOT_TABLES.add(id)) + { + return id; + } + else + { + throw new IllegalArgumentException(id + " is already a registered modded loot table"); + } + } + + /** + * An unmodifiable set is returned + */ + public static Set getAll() + { + return READ_ONLY_LOOT_TABLES; + } + + public static boolean test() + { + LootTableManager loottablemanager = new LootTableManager((File)null); + + for (ResourceLocation resourcelocation : READ_ONLY_LOOT_TABLES) + { + if (loottablemanager.getLootTableFromLocation(resourcelocation) == LootTable.EMPTY_LOOT_TABLE) + { + return false; + } + } + + return true; + } + +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModRecipes.java b/src/main/java/com/somebody/idlframewok/init/ModRecipes.java new file mode 100644 index 0000000..02fdbc1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModRecipes.java @@ -0,0 +1,28 @@ +package com.somebody.idlframewok.init; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.item.crafting.IRecipe; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.registries.IForgeRegistry; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ModRecipes { + + + public static void Init() { + //Only smelting recipes +// GameRegistry.addSmelting(ModItems.PURE_INGOT, +// new ItemStack(ModItems.WEAPON_PEARL), +// 0.1f); + + } + + @SubscribeEvent + public static void registerRecipes(RegistryEvent.Register evt) { + IForgeRegistry r = evt.getRegistry(); + //Example + //r.register(new GobletFill().setRegistryName(new ResourceLocation(Reference.MOD_ID, "goblet_fill"))); + } +} diff --git a/src/main/java/com/somebody/idlframewok/init/ModSpawn.java b/src/main/java/com/somebody/idlframewok/init/ModSpawn.java new file mode 100644 index 0000000..a4ca6e3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/ModSpawn.java @@ -0,0 +1,103 @@ +package com.somebody.idlframewok.init; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.BiomeDictionary.Type; + +public class ModSpawn { + + /** + * Register Mobs based on Biome sub Types + */ + public static void registerSpawnList() { + Map> biomeMap = buildBiomeListByType(); + + addNormalSpawn(biomeMap); + addHumidSpawn(biomeMap); + addOpenGroundSpawn(biomeMap); + } + + //Mob + public static void add(Biome biome, int weight, Class entityclassIn, int groupCountMin, int groupCountMax) { + if (weight > 0) { + biome.getSpawnableList(EnumCreatureType.MONSTER).add(new Biome.SpawnListEntry(entityclassIn, weight, groupCountMin, groupCountMax)); + } + } + + public static void add_friendly(Biome biome, int weight, Class entityclassIn, int groupCountMin, int groupCountMax) { + if (weight > 0) { + biome.getSpawnableList(EnumCreatureType.CREATURE).add(new Biome.SpawnListEntry(entityclassIn, weight, groupCountMin, groupCountMax)); + } + } + + private static Map> buildBiomeListByType() { + Map> biomesAndTypes = new HashMap<>(); + + for (Biome biome : Biome.REGISTRY) { + Set types = BiomeDictionary.getTypes(biome); + for (BiomeDictionary.Type type : types) { + if (!biomesAndTypes.containsKey(type)) { + biomesAndTypes.put(type, new HashSet<>()); + } + + biomesAndTypes.get(type).add(biome); + } + } + + return biomesAndTypes; + } + + private static void addNormalSpawn(Map> biomeMap) { + for (Biome biome : Biome.REGISTRY) { + //Example Spawn + //add(biome, ModConfig.SPAWN_CONF.SPAWN_TAINTER, EntityMoroonTainter.class, 1, 4); + } + } + + private static void addOpenGroundSpawn(Map> biomeMap) { + for (Biome biome : Biome.REGISTRY) { + //if (!BiomeDictionary.hasType(biome, Type.DENSE)) + // add(biome, ModConfig.SPAWN_CONF.SPAWN_SKELETON_TOWER, EntitySpawnTower.class, 1, 1); + } + } + + private static void addHumidSpawn(Map> biomeMap) { + for (Biome biome : Biome.REGISTRY) { + if (BiomeDictionary.hasType(biome, Type.WET) || (BiomeDictionary.hasType(biome, Type.WATER))) + { + //add(biome, ModConfig.SPAWN_CONF.SPAWN_TIDE_MAKER, EntityMoroonTideMaker.class, 1, 1); + } + } + } + + private static void addNetherSPAWN(Map> biomeMap) { + /* + * NETHER + */ +// for (Biome biome : biomeMap.get(Type.NETHER)) { +// add(10, EntityMoroonTainter.class, 1, 4, biome); +// } + } + + /** + * Bridge Method for simpler spawning registry + * + * @param weight Spawn rate + * @param entityclassIn Entity + * @param groupCountMin Minimum amount (always 1) + * @param groupCountMax Maximum amount (depreciated due to chunk limits) + * @param biome Biome + */ + public static void add(int weight, Class entityclassIn, int groupCountMin, int groupCountMax, Biome biome) { + if (weight > 0) { + biome.getSpawnableList(EnumCreatureType.MONSTER).add(new Biome.SpawnListEntry(entityclassIn, weight, groupCountMin, groupCountMax)); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/init/RegistryHandler.java b/src/main/java/com/somebody/idlframewok/init/RegistryHandler.java new file mode 100644 index 0000000..6910db3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/init/RegistryHandler.java @@ -0,0 +1,95 @@ +package com.somebody.idlframewok.init; + +import com.somebody.idlframewok.blocks.ModBlocks; +import com.somebody.idlframewok.enchantments.ModEnchantmentInit; +import com.somebody.idlframewok.entity.ModEntityInit; +import com.somebody.idlframewok.entity.RenderHandler; +import com.somebody.idlframewok.item.ModItems; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.ModSoundHandler; +import net.minecraft.block.Block; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.Item; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@EventBusSubscriber +public class RegistryHandler { + @SubscribeEvent + public static void onItemRegister(RegistryEvent.Register event) + { + event.getRegistry().registerAll(ModItems.ITEMS.toArray(new Item[0])); + } + + @SubscribeEvent + public static void onBlockRegister(RegistryEvent.Register event) { + event.getRegistry().registerAll(ModBlocks.BLOCKS.toArray(new Block[0])); + } + + @SubscribeEvent + public static void onEnchantmentRegister(RegistryEvent.Register event) + { + ModEnchantmentInit.BeforeRegister(); + event.getRegistry().registerAll(ModEnchantmentInit.ENCHANTMENT_LIST.toArray(new Enchantment[0])); + +// for (Enchantment enchantment : Enchantment.REGISTRY) { +// IdlFramework.Log("registered enchantments: %s", enchantment.getName()); +// } + } + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public static void onModelRegister(ModelRegistryEvent event) + { + for(Item item : ModItems.ITEMS) + { + if (item instanceof IHasModel) + { + ((IHasModel)item).registerModels(); + } + } + + for(Block block : ModBlocks.BLOCKS) + { + if (block instanceof IHasModel) + { + ((IHasModel)block).registerModels(); + } + } + + RenderHandler.registerEntityRenders(); + } + + public static void preInitRegistries(FMLPreInitializationEvent event) + { + //GameRegistry.registerWorldGenerator(new ModWorldGenOld(), 100); + //GameRegistry.registerWorldGenerator(new ModWorldGenNew(), 120); + + InitBiome.registerBiomes(); + InitDimension.registerDimensions(); + + ModEntityInit.registerEntities(); + } + + public static void postInitReg() + { + //WorldType TYPE_ONE = new WorldTypeOne(); + } + + public static void initRegistries(FMLInitializationEvent event) + { + ModSoundHandler.soundRegister(); + } + + public static void serverRegistries(FMLServerStartingEvent event) + { + //event.registerServerCommand(new CommandDimTeleport()); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/IGuaEnhance.java b/src/main/java/com/somebody/idlframewok/item/IGuaEnhance.java new file mode 100644 index 0000000..e1c62b7 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/IGuaEnhance.java @@ -0,0 +1,7 @@ +package com.somebody.idlframewok.item; + +public interface IGuaEnhance { + //Some item accepts not every gua + public boolean acceptGuaIndex(int index); + +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemAdaptingBase.java b/src/main/java/com/somebody/idlframewok/item/ItemAdaptingBase.java new file mode 100644 index 0000000..9a8ac5b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemAdaptingBase.java @@ -0,0 +1,119 @@ +package com.somebody.idlframewok.item; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Enchantments; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemAdaptingBase extends ItemBase { + public ItemAdaptingBase(String name) { + super(name); + } + + public float base_power = 6f; + public float base_range = 3f; + public float base_cd = 10f; + + public float getPower(ItemStack stack) + { + float result = base_power; + int powerEnchant = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER, stack); + + if (powerEnchant > 0) + { + result += powerEnchant ; + } + return result; + } + + public float getRange(ItemStack stack) + { + float result = base_power; + int powerEnchant = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER, stack); + + if (powerEnchant > 0) + { + result += powerEnchant ; + } + return result; + } + + + public int getCoolDownTicks(ItemStack stack) + { + return (int) (base_cd * CommonDef.TICK_PER_SECOND); + } + + @Override + public int getMaxDamage(ItemStack stack) { + return 256; + } + + /** + * How long it takes to use or consume an item + */ + public int getMaxItemUseDuration(ItemStack stack) + { + return 72000; + } + + /** + * returns the action that specifies what animation to play when the items is being used + */ + public EnumAction getItemUseAction(ItemStack stack) + { + return EnumAction.BOW; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.PUNCH || enchantment == Enchantments.INFINITY) + { + return false; + } + + if (enchantment == Enchantments.POWER || enchantment == Enchantments.UNBREAKING) + { + return true; + } + + return super.canApplyAtEnchantingTable(stack, enchantment); + } + + /** + * Called when the player stops using an Item (stops holding the right mouse button). + */ + public void onPlayerStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) + { + if (!useable) + { + return; + } + + onCreatureStoppedUsing(stack, worldIn, entityLiving, timeLeft); + entityLiving.swingArm(entityLiving.getHeldItemMainhand() == stack ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND); + + if (!worldIn.isRemote) + { + if (entityLiving instanceof EntityPlayer) + { + EntityPlayer entityplayer = (EntityPlayer)entityLiving; + { + entityplayer.getCooldownTracker().setCooldown(this, getCoolDownTicks(stack)); + } + } + } + } + + + public void onCreatureStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) + { + + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemArmorBase.java b/src/main/java/com/somebody/idlframewok/item/ItemArmorBase.java new file mode 100644 index 0000000..2ef7a6a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemArmorBase.java @@ -0,0 +1,215 @@ +package com.somebody.idlframewok.item; + +import java.util.List; +import java.util.UUID; +import javax.annotation.Nullable; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +//try to sync with ItemBase +public class ItemArmorBase extends ItemArmor implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + protected boolean logNBT = false; + + protected boolean ignoreVanillaSystem = false; + + protected static final UUID[] ARMOR_MODIFIERS_OVERRIDE = new UUID[] {UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"), UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"), UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"), UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")}; + private String texturePath; + public ItemArmorBase(String name, ArmorMaterial materialIn, int renderIndexIn, EntityEquipmentSlot equipmentSlotIn) { + super(materialIn, renderIndexIn, equipmentSlotIn); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + + ModItems.ITEMS.add(this); + + InitItem(); + } + + public void InitItem() + { + + } + + public ItemArmorBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + +// @Override +// public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { +// //Particle; +// super.onUsingTick(stack, living, count); +// //IdlFramework.LogWarning(String.format("base onUsingTick %s",count)); +// +// if (living.world.isRemote) +// { +// clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); +// } +// else +// { +// serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); +// } +// } +// +// public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) +// { +// +// } +// +// public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) +// { +// +// } + + /** + * Called by RenderBiped and RenderPlayer to determine the armor texture that + * should be use for the currently equipped item. + * This will only be called on instances of ItemArmor. + * + * Returning null from this function will use the default value. + * + * @param stack ItemStack for the equipped armor + * @param entity The entity wearing the armor + * @param slot The slot the armor is in + * @param type The subtype, can be null or "overlay" + * @return Path of texture to bind, or null to use default + */ + @Nullable + public String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type) + { + return null; + } + + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //virtual + public void onUpdateWearing(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + EntityLivingBase living = (EntityLivingBase) entityIn; + if (living.getItemStackFromSlot(armorType) == stack) + { + onUpdateWearing(stack, worldIn, entityIn, itemSlot, isSelected); + } + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + if (ignoreVanillaSystem) + { + return HashMultimap.create(); + }else { + return super.getAttributeModifiers(equipmentSlot, stack); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemArmorLivingMetalBase.java b/src/main/java/com/somebody/idlframewok/item/ItemArmorLivingMetalBase.java new file mode 100644 index 0000000..e6ef417 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemArmorLivingMetalBase.java @@ -0,0 +1,121 @@ +package com.somebody.idlframewok.item; + +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.FoodStats; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHealEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +//try to sync with ItemBase +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemArmorLivingMetalBase extends ItemArmorBase implements IHasModel { + + public ItemArmorLivingMetalBase(String name, ArmorMaterial materialIn, int renderIndexIn, EntityEquipmentSlot equipmentSlotIn) { + super(name, materialIn, renderIndexIn, equipmentSlotIn); + ignoreVanillaSystem = false; + } + + public int getRepairAmount(ItemStack stack, Entity entityIn) + { + return 1; + } + + public double getHealthPlus(ItemStack stack) + { + return 1; + } + + @Override + public void onUpdateWearing(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdateWearing(stack, worldIn, entityIn, itemSlot, isSelected); + EntityPlayer player = (EntityPlayer) entityIn; + + if (worldIn.getWorldTime() % CommonDef.TICK_PER_SECOND == 0) + { + boolean flagRule = player.world.getGameRules().getBoolean("naturalRegeneration"); + FoodStats stats = player.getFoodStats(); + if (flagRule && stats.getFoodLevel() >= 20) + { + // && stats.getSaturationLevel() > 0.0F && + if (player.getHealth() >= player.getMaxHealth()) + { + CommonFunctions.RepairItem(stack, getRepairAmount(stack, entityIn)); + } + } + } + + if (!worldIn.isRemote) + { + if (((float)stack.getItemDamage() / stack.getMaxDamage()) >= 0.9f) + { + if (worldIn.getWorldTime() % CommonDef.TICK_PER_SECOND == 0 && !IDLNBTUtil.GetBoolean(stack, IDLNBTDef.BIOMETAL_WARNED, false)) { + IDLNBTUtil.SetBoolean(stack, IDLNBTDef.BIOMETAL_WARNED, true); + CommonFunctions.SendMsgToPlayer((EntityPlayerMP) player, "idlframewok.msg.low_dura", stack.getDisplayName()); + } + } + else { + IDLNBTUtil.SetBoolean(stack, IDLNBTDef.BIOMETAL_WARNED, false); + } + } + + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + Multimap multimap = super.getAttributeModifiers(equipmentSlot, stack); + + if (equipmentSlot == this.armorType) + { + //multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Armor modifier", (double)this.damageReduceAmount, 0)); + //multimap.put(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Armor toughness", (double)this.toughness, 0)); + multimap.put(SharedMonsterAttributes.MAX_HEALTH.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()],"Health modifier", getHealthPlus(stack), 0)); + //multimap.put(SharedMonsterAttributes.LUCK.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Luck", (double)1f, 0)); + } + + return multimap; + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void OnWearerHeal(LivingHealEvent event) + { + if (event.isCanceled()) + { + return; + } + + EntityLivingBase livingBase = event.getEntityLiving(); + for (EntityEquipmentSlot slot: + EntityEquipmentSlot.values()){ + ItemStack stack = livingBase.getItemStackFromSlot(slot); + if (stack.getItem() instanceof ItemArmorLivingMetalBase) + { + CommonFunctions.RepairItem(stack,Math.round(event.getAmount())); + } + } + } + +// @SideOnly(Side.CLIENT) +// @Override +// public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { +// super.addInformation(stack, world, tooltip, flag); +// +// //tooltip.add(I18n.format("idlframewok.gua_enhance_total.desc", IDLSkillNBT.GetGuaEnhanceTotal(stack))); +// tooltip.add(IDLNBTUtil.getNBT(stack).toString()); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemAxeBase.java b/src/main/java/com/somebody/idlframewok/item/ItemAxeBase.java new file mode 100644 index 0000000..e6a2cd3 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemAxeBase.java @@ -0,0 +1,170 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemAxeBase extends ItemAxe implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + //for accessing the private value + protected ToolMaterial toolMaterial; + + public ItemAxeBase(String name, ToolMaterial material) + { + super(material, 8.0F, -2.8F); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + toolMaterial = material; + ModItems.ITEMS.add(this); + + InitItem(); + } + + public ItemAxeBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //Idealland.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //for accessing private values + protected float getBaseAttackDamage() + { + return 3.0F + toolMaterial.getAttackDamage(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemBase.java b/src/main/java/com/somebody/idlframewok/item/ItemBase.java new file mode 100644 index 0000000..345c51b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemBase.java @@ -0,0 +1,230 @@ +package com.somebody.idlframewok.item; + +import java.util.List; +import java.util.UUID; +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemBase extends Item implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + protected static final UUID OFF_HAND_MODIFIER = UUID.fromString("9271eeea-5f74-4e12-97b6-7cf3c60ef7a0"); + protected static final UUID MAIN_HAND_MODIFIER = UUID.fromString("7d766720-0695-46c6-b320-44529f3da63f"); + + protected static final UUID POWER_UP_MODIFIER = UUID.fromString("dc8a0a25-24c4-43a9-bfc3-e31e431f4ebf"); + protected static final UUID POWER_UP_MODIFIER_PERCENT = UUID.fromString("9236a0fe-8f9b-4ede-80a3-05386216d06f"); + + public ItemBase(String name) + { + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + + ModItems.ITEMS.add(this); + + InitItem(); + } + + protected ItemBase setGlitter() + { + glitters = true; + return this; + } + + @SideOnly(Side.CLIENT) + public boolean hasEffect(ItemStack stack) + { + return stack.isItemEnchanted() || glitters; + } + + + public ItemBase setRangedWeapon() + { + isRangedWeapon = true; + return this; + } + + public ItemBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public boolean isRangedWeaponItem() + { + return isRangedWeapon; + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //IdlFramework.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + @Nonnull + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand hand) { + if (useable) + { + player.setActiveHand(hand); + ItemStack stack = player.getHeldItem(hand); + boolean result = onUseSimple(player, stack); + if (result) + { + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + else { + return ActionResult.newResult(EnumActionResult.FAIL, stack); + } + } + else { + return super.onItemRightClick(world, player, hand); + } + } + + public boolean onUseSimple(EntityPlayer player, ItemStack stack) + { + return true; + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + public void onMouseFire(EntityPlayer player) + { + + } + +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemDebug.java b/src/main/java/com/somebody/idlframewok/item/ItemDebug.java new file mode 100644 index 0000000..c81ab0d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemDebug.java @@ -0,0 +1,136 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import com.somebody.idlframewok.entity.projectiles.ProjectileArgs; +import com.somebody.idlframewok.gui.ModGuiElementLoader; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemDebug extends ItemBase{ + int index = 0; + public ItemDebug SetIndex(int index){ + this.index = index; + return this; + } + public ItemDebug(String name) { + super(name); + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + + //tooltip.add(I18n.format("idlframewok.gua_enhance_total.desc", IDLSkillNBT.GetGuaEnhanceTotal(stack))); + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + +// public boolean isEnchantable(ItemStack stack) +// { +// return true; +// } +// +// @Override +// public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { +// super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); +// if (stack.isItemEnchantable()) +// { +// stack.addEnchantment(ModEnchantmentInit.fireBurn, 0); +// } +// } + + + void TestEnchant(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + int p_185291_0_ = 30; + ItemStack testItemStack = playerIn.getHeldItemOffhand(); + boolean allowTreasure = false; + Item item = testItemStack.getItem(); + boolean flag = item == Items.BOOK; + + for (Enchantment enchantment : Enchantment.REGISTRY) + { + boolean judge1 = !enchantment.isTreasureEnchantment() || allowTreasure; + boolean judge2 = enchantment.canApplyAtEnchantingTable(testItemStack); + boolean judge3 = flag && enchantment.isAllowedOnBooks(); + + IdlFramework.Log("[%s]Lv %d to %d, canApplyAtEnchantingTable = %s, judgement[%s,%s,%s]", + enchantment.getName(), + enchantment.getMinLevel(), + enchantment.getMaxLevel(), + enchantment.canApplyAtEnchantingTable(testItemStack), + judge1, judge2, judge3 + ); + if (judge1 && judge2 || judge3) + { + for (int i = enchantment.getMaxLevel(); i >= enchantment.getMinLevel() ; --i) + { + IdlFramework.Log("[%s] Lv.%d available range = %d to %d", enchantment.getName(), i, + enchantment.getMinEnchantability(i), enchantment.getMaxEnchantability(i)); + if (p_185291_0_ >= enchantment.getMinEnchantability(i) && p_185291_0_ <= enchantment.getMaxEnchantability(i)) + { + IdlFramework.Log("[%s] successfully elected", enchantment.getName()); + break; + } + } + } + } + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + + playerIn.swingArm(handIn); + + ItemStack stack = playerIn.getHeldItem(handIn); + + if (index == 2 && !worldIn.isRemote) { + EntityIdlProjectile bullet = new EntityIdlProjectile(worldIn, new ProjectileArgs(4f), playerIn, 0, 0.05, 0); + worldIn.spawnEntity(bullet); + IdlFramework.Log("bullet pos = %s", bullet.getPosition()); + worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.ENTITY_PLAYER_LEVELUP, SoundCategory.PLAYERS, 1f, 1f); + //return + } + + if (!worldIn.isRemote) + { + //playerIn.getHeldItemOffhand().getItem() == ModItems.DEBUG_ITEM_3; + if (index == 3) + { + BlockPos pos = playerIn.getPosition(); + playerIn.openGui(IdlFramework.instance, ModGuiElementLoader.GUI_RESEARCH, worldIn, pos.getX(), pos.getY(), pos.getZ()); + } + //else + + //todo: optimize + //playerIn.openGui(IdlFramework.instance, ModGuiElementLoader.GUI_DEMO, worldIn, pos.getX(), pos.getY(), pos.getZ()); + +// for (int i = 1; i <= 1000; i++) +// { +// IDLNBTUtil.SetString(stack, "TEST", IDLNBTUtil.GetString(stack, "TEST", "") + "a"); +// } + } + //IdlFramework.Log("NBT len = %d", IDLNBTUtil.GetString(stack, "TEST", "").length()); + + //IDLSkillNBT.SetGuaEnhanceFree(playerIn.getHeldItem(handIn), 2); + return super.onItemRightClick(worldIn, playerIn, handIn); + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemHoeBase.java b/src/main/java/com/somebody/idlframewok/item/ItemHoeBase.java new file mode 100644 index 0000000..8795b81 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemHoeBase.java @@ -0,0 +1,170 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemHoe; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemHoeBase extends ItemHoe implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + //for accessing the private value + protected ToolMaterial toolMaterial; + + public ItemHoeBase(String name, ToolMaterial material) + { + super(material); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + toolMaterial = material; + ModItems.ITEMS.add(this); + + InitItem(); + } + + public ItemHoeBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //Idealland.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //for accessing private values + protected float getBaseAttackDamage() + { + return 3.0F + toolMaterial.getAttackDamage(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemPickaxeBase.java b/src/main/java/com/somebody/idlframewok/item/ItemPickaxeBase.java new file mode 100644 index 0000000..a99df2d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemPickaxeBase.java @@ -0,0 +1,170 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemPickaxeBase extends ItemPickaxe implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + //for accessing the private value + protected ToolMaterial toolMaterial; + + public ItemPickaxeBase(String name, ToolMaterial material) + { + super(material); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + toolMaterial = material; + ModItems.ITEMS.add(this); + + InitItem(); + } + + public ItemPickaxeBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //Idealland.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //for accessing private values + protected float getBaseAttackDamage() + { + return 3.0F + toolMaterial.getAttackDamage(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemSpadeBase.java b/src/main/java/com/somebody/idlframewok/item/ItemSpadeBase.java new file mode 100644 index 0000000..d7a7735 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemSpadeBase.java @@ -0,0 +1,170 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemSpade; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSpadeBase extends ItemSpade implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + //for accessing the private value + protected ToolMaterial toolMaterial; + + public ItemSpadeBase(String name, ToolMaterial material) + { + super(material); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + toolMaterial = material; + ModItems.ITEMS.add(this); + + InitItem(); + } + + public ItemSpadeBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //Idealland.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //for accessing private values + protected float getBaseAttackDamage() + { + return 3.0F + toolMaterial.getAttackDamage(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ItemSwordBase.java b/src/main/java/com/somebody/idlframewok/item/ItemSwordBase.java new file mode 100644 index 0000000..a38876d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ItemSwordBase.java @@ -0,0 +1,172 @@ +package com.somebody.idlframewok.item; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSwordBase extends ItemSword implements IHasModel { + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + private boolean isRangedWeapon = false; + protected boolean logNBT = false; + protected boolean glitters = false; + + //for accessing the private value + protected Item.ToolMaterial toolMaterial; + + public ItemSwordBase(String name, Item.ToolMaterial material) + { + super(material); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + toolMaterial = material; + ModItems.ITEMS.add(this); + + InitItem(); + } + + public ItemSwordBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public void InitItem() + { + if (this instanceof IGuaEnhance) + { + showGuaSocketDesc = true; + } + } + + public String GetStringForThisByKey(String key) + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + key); + } + + public String GetBasicDesc() + { + return CommonFunctions.GetStringLocalTranslated(getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { + //Particle; + super.onUsingTick(stack, living, count); + //IdlFramework.LogWarning(String.format("base onUsingTick %s",count)); + + if (living.world.isRemote) + { + clientUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + else + { + serverUseTick(stack, living, getMaxItemUseDuration(stack) - count); + } + } + + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + public void serverUseTick(ItemStack stack, EntityLivingBase living, int count) + { + + } + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + return ""; + } + + //for accessing private values + protected float getBaseAttackDamage() + { + return 3.0F + toolMaterial.getAttackDamage(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/ModItems.java b/src/main/java/com/somebody/idlframewok/item/ModItems.java new file mode 100644 index 0000000..d3f80e6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/ModItems.java @@ -0,0 +1,74 @@ +package com.somebody.idlframewok.item; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.item.Item; + +public class ModItems { + + public static final List ITEMS = new ArrayList(); + + //Basic + //public static final Item PAPER_BLOOD = new ItemBase("paper_blood"); + + + /* + WOOD(0, 59, 2.0F, 0.0F, 15), + STONE(1, 131, 4.0F, 1.0F, 5), + IRON(2, 250, 6.0F, 2.0F, 14), + DIAMOND(3, 1561, 8.0F, 3.0F, 10), + GOLD(0, 32, 12.0F, 0.0F, 22); + + harvestLevel, maxUses, efficiency, damage, enchantability + */ + + //Tool Material +// public static final Item BLOOD_IRON_INGOT = new ItemBase("blood_iron_ingot"); +// +// public static final Item.ToolMaterial TOOL_MATERIAL_BLOOD = +// EnumHelper.addToolMaterial("material_blood", 3, 512, 3.0F, 4F, 20).setRepairItem(new ItemStack( ModItems.BLOOD_IRON_INGOT)); +// +// public static final ItemKinshipSword KINSHIP_SWORD = new ItemKinshipSword("kinship_sword", TOOL_MATERIAL_BLOOD); + + //Armor +// LEATHER("leather", 5, new int[]{1, 2, 3, 1}, 15, SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 0.0F), +// CHAIN("chainmail", 15, new int[]{1, 4, 5, 2}, 12, SoundEvents.ITEM_ARMOR_EQUIP_CHAIN, 0.0F), +// IRON("iron", 15, new int[]{2, 5, 6, 2}, 9, SoundEvents.ITEM_ARMOR_EQUIP_IRON, 0.0F), +// GOLD("gold", 7, new int[]{1, 3, 5, 2}, 25, SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 0.0F), +// DIAMOND("diamond", 33, new int[]{3, 6, 8, 3}, 10, SoundEvents.ITEM_ARMOR_EQUIP_DIAMOND, 2.0F); + //Note that if you want to set a mod thing as repair material, define them before the material, otherwise it will be empty. + +// public static final ItemArmor.ArmorMaterial moroonArmorMaterial = EnumHelper.addArmorMaterial( +// "idlframewok:armor_moroon", "idlframewok:armor_moroon", 80, new int[] {3, 6, 8, 3}, 2, SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 2) +// .setRepairItem(new ItemStack(Items.QUARTZ)); +// + + //Food +// static PotionEffect eff = new PotionEffect(MobEffects.LEVITATION, TICK_PER_SECOND * 60, 0); +// public static final ItemFoodBase FIGHT_BREAD = (ItemFoodBase) new ItemFoodBase("war_bread", 10, 10, false). +// setPotionEffect(eff, 1.0f). +// setAlwaysEdible(); +// public static final ItemFoodBase MEMORY_BREAD = new ItemFoodBase("memory_bread", 3, 0.6f, false).SetXP(10); + + + + + + //Armor +// public static final ItemHelmSniper helmetSniper = (ItemHelmSniper) new ItemHelmSniper("helmet_sniper", moroonArmorMaterialSniper, 1, EntityEquipmentSlot.HEAD); +// +// public static final ItemArmorBase[] MOR_GENERAL_ARMOR = +// { new ItemArmorBase("mor_armor_1", moroonArmorMaterial, 1, EntityEquipmentSlot.HEAD) +// ,new ItemArmorBase("mor_armor_2", moroonArmorMaterial, 1, EntityEquipmentSlot.CHEST) +// ,new ItemArmorBase("mor_armor_3", moroonArmorMaterial, 1, EntityEquipmentSlot.LEGS) +// ,new ItemArmorBase("mor_armor_4", moroonArmorMaterial, 1, EntityEquipmentSlot.FEET) +// }; + + //public static final ItemSkillDecodeItem skillDecodeItem = (ItemSkillDecodeItem) new ItemSkillDecodeItem("skill_decode_item").setRarity(EnumRarity.RARE); + + //Package Example +// public static final ItemPackage RANDOM_SKILL = (ItemPackage) new ItemPackage("random_skill", new Item[]{ +// Items.BLAZE_ROD, Items.PAPER +// }).setMaxStackSize(1); +} diff --git a/src/main/java/com/somebody/idlframewok/item/armorMaterials/ModArmorMaterial.java b/src/main/java/com/somebody/idlframewok/item/armorMaterials/ModArmorMaterial.java new file mode 100644 index 0000000..5f89891 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/armorMaterials/ModArmorMaterial.java @@ -0,0 +1,7 @@ +//package com.somebody.idlframewok.item.armorMaterials; +// +//import net.minecraft.item.ItemArmor; +//import net.minecraft.item.ItemArmor.ArmorMaterial; +// +//public class ModArmorMaterial extends ArmorMaterial { +//} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemConsumableBase.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemConsumableBase.java new file mode 100644 index 0000000..0347afb --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemConsumableBase.java @@ -0,0 +1,42 @@ +package com.somebody.idlframewok.item.consumables; + +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.item.ItemBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemConsumableBase extends ItemBase { + boolean consumeSelf = true; + boolean consumeOther = false; + public ItemConsumableBase(String name) { + super(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + /** + * Called when the equipped item is right clicked. + */ + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + ItemStack itemstack = playerIn.getHeldItem(handIn); + itemstack.shrink(1); + return new ActionResult(EnumActionResult.SUCCESS, itemstack); +// EntityEquipmentSlot entityequipmentslot = EntityLiving.getSlotForItemStack(itemstack); +// ItemStack itemstack1 = playerIn.getItemStackFromSlot(entityequipmentslot); +// +// if (itemstack1.isEmpty()) +// { +// playerIn.setItemStackToSlot(entityequipmentslot, itemstack.copy()); +// itemstack.setCount(0); +// return new ActionResult(EnumActionResult.SUCCESS, itemstack); +// } +// else +// { +// return new ActionResult(EnumActionResult.FAIL, itemstack); +// } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemFightBread.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemFightBread.java new file mode 100644 index 0000000..81ae84f --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemFightBread.java @@ -0,0 +1,10 @@ +package com.somebody.idlframewok.item.consumables; + +import com.somebody.idlframewok.init.ModCreativeTab; + +public class ItemFightBread extends ItemConsumableBase { + public ItemFightBread(String name) { + super(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemLevelUpBadge.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemLevelUpBadge.java new file mode 100644 index 0000000..3f48e88 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemLevelUpBadge.java @@ -0,0 +1,35 @@ +package com.somebody.idlframewok.item.consumables; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.item.ItemBase; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; + +public class ItemLevelUpBadge extends ItemBase { + public ItemLevelUpBadge(String name) { + super(name); + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (target instanceof EntityModUnit) + { + EntityModUnit legalTarget = (EntityModUnit) target; + int level = legalTarget.getLevel(); + int lvMax = legalTarget.getMaxLevel(); + if (level < lvMax) + { + legalTarget.setLevel(level+1); + } + + playerIn.swingArm(handIn); + target.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1f, 1f); + stack.shrink(1); + return true; + } + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModular.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModular.java new file mode 100644 index 0000000..8e4ffd0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModular.java @@ -0,0 +1,87 @@ +package com.somebody.idlframewok.item.consumables; + +import java.util.List; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import static com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef.MARK_TOTAL_COUNT; + +public class ItemPowerUpModular extends ItemBase { + private IAttribute attrType; + private float amountFixed; + + public ItemPowerUpModular(String name, IAttribute attrType, float amountFixed) { + super(name); + this.attrType = attrType; + this.amountFixed = amountFixed; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (target instanceof EntityModUnit) + { + EntityModUnit legalTarget = (EntityModUnit) target; + if (legalTarget.is_mechanic) + { + int requireLv = (IDLNBTUtil.GetInt(target, MARK_TOTAL_COUNT, 0)); + if (requireLv > playerIn.experienceLevel) + { + CommonFunctions.SafeSendMsgToPlayer(playerIn, "idlframewok.msg.upgrade_module.req_lv", String.valueOf(requireLv)); + return false; + } + + if (!playerIn.world.isRemote) + { + double valueBefore = EntityUtil.getAttr(legalTarget, attrType); + boolean success = EntityUtil.boostAttr(legalTarget, attrType, amountFixed, POWER_UP_MODIFIER); + if (success) + { + double valueAfter = EntityUtil.getAttr(legalTarget, attrType); + CommonFunctions.SafeSendMsgToPlayer(playerIn, "idlframewok.msg.upgrade_module.ok", valueBefore, valueAfter); + playerIn.swingArm(handIn); + target.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1f, 1f); + stack.shrink(1); + IDLNBTUtil.SetInt(target,MARK_TOTAL_COUNT, requireLv + 1); + if (attrType == SharedMonsterAttributes.MAX_HEALTH) + { + target.heal(amountFixed); + } + } + else { + return false; + } + } + return true; + } + } + return false; + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + String mainDesc = I18n.format(key, amountFixed); + return mainDesc; + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModularPercent.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModularPercent.java new file mode 100644 index 0000000..bcc022c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemPowerUpModularPercent.java @@ -0,0 +1,87 @@ +package com.somebody.idlframewok.item.consumables; + +import java.util.List; + +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import static com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef.MARK_TOTAL_COUNT; + +public class ItemPowerUpModularPercent extends ItemBase { + private IAttribute attrType; + private float amountRatio; + + public ItemPowerUpModularPercent(String name, IAttribute attrType, float amountRatio) { + super(name); + this.attrType = attrType; + this.amountRatio = amountRatio; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (target instanceof EntityModUnit) + { + EntityModUnit legalTarget = (EntityModUnit) target; + if (legalTarget.is_mechanic) + { + int requireLv = (IDLNBTUtil.GetInt(target, MARK_TOTAL_COUNT, 0)); + if (requireLv > playerIn.experienceLevel) + { + CommonFunctions.SafeSendMsgToPlayer(playerIn, "idlframewok.msg.upgrade_module.req_lv", requireLv); + return false; + } + + if (!playerIn.world.isRemote) + { + double valueBefore = EntityUtil.getAttr(legalTarget, attrType); + boolean success = EntityUtil.boostAttrRatio(legalTarget, attrType, amountRatio, POWER_UP_MODIFIER_PERCENT); + if (success) + { + double valueAfter = EntityUtil.getAttr(legalTarget, attrType); + CommonFunctions.SafeSendMsgToPlayer(playerIn, "idlframewok.msg.upgrade_module.ok", valueBefore, valueAfter); + playerIn.swingArm(handIn); + target.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1f, 1f); + stack.shrink(1); + IDLNBTUtil.SetInt(target,MARK_TOTAL_COUNT, requireLv + 1); + if (attrType == SharedMonsterAttributes.MAX_HEALTH) + { + target.heal((float) (valueAfter - valueBefore)); + } + } + else { + return false; + } + } + return true; + } + } + return false; + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + String mainDesc = I18n.format(key, amountRatio * 100); + return mainDesc; + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/ItemRainCall.java b/src/main/java/com/somebody/idlframewok/item/consumables/ItemRainCall.java new file mode 100644 index 0000000..7c8aa35 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/ItemRainCall.java @@ -0,0 +1,39 @@ +package com.somebody.idlframewok.item.consumables; + +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; + +public class ItemRainCall extends ItemConsumableBase { + public ItemRainCall(String name) { + super(name); + } + + /** + * Called when the equipped item is right clicked. + */ + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + ItemStack stack = playerIn.getHeldItem(handIn); + Biome biome = worldIn.getBiome(playerIn.getPosition()); + + if (biome.canRain() && !worldIn.isRaining()) + { + worldIn.setRainStrength(100f); + return super.onItemRightClick(worldIn, playerIn, handIn); + } + else { + if (playerIn instanceof EntityPlayerMP) + { + CommonFunctions.SendMsgToPlayer((EntityPlayerMP) playerIn, "idlframewok.msg.cannot_rain"); + } + return new ActionResult(EnumActionResult.FAIL,stack); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeBase.java b/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeBase.java new file mode 100644 index 0000000..29baf52 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeBase.java @@ -0,0 +1,27 @@ +package com.somebody.idlframewok.item.consumables.autoConsume; + +import com.somebody.idlframewok.item.consumables.ItemConsumableBase; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class ItemAutoConsumeBase extends ItemConsumableBase { + public ItemAutoConsumeBase(String name) { + super(name); + } + + public void OnConsume(ItemStack stack, World worldIn, EntityLivingBase entityIn, int itemSlot, boolean isSelected) + { + //do something + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + OnConsume(stack, worldIn, (EntityLivingBase) entityIn, itemSlot, isSelected); + + stack.shrink(1); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeHeal.java b/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeHeal.java new file mode 100644 index 0000000..9d47e72 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/consumables/autoConsume/ItemAutoConsumeHeal.java @@ -0,0 +1,18 @@ +package com.somebody.idlframewok.item.consumables.autoConsume; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class ItemAutoConsumeHeal extends ItemAutoConsumeBase { + float healAmount = 2f; + public ItemAutoConsumeHeal(String name) { + super(name); + } + + @Override + public void OnConsume(ItemStack stack, World worldIn, EntityLivingBase entityIn, int itemSlot, boolean isSelected) { + super.OnConsume(stack, worldIn, entityIn, itemSlot, isSelected); + entityIn.heal(healAmount); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/food/ItemFoodBase.java b/src/main/java/com/somebody/idlframewok/item/food/ItemFoodBase.java new file mode 100644 index 0000000..ebedab1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/food/ItemFoodBase.java @@ -0,0 +1,156 @@ +package com.somebody.idlframewok.item.food; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.item.ModItems; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.IHasModel; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemFoodBase extends ItemFood implements IHasModel { + + private boolean overrideRarity = false; + private EnumRarity enumRarity = EnumRarity.COMMON; + protected boolean showGuaSocketDesc = false; + protected boolean shiftToShowDesc = false; + protected boolean use_flavor = false; + protected boolean useable = false; + protected boolean logNBT = false; + + //for creating variants + protected int value_main = 1; + public ItemFoodBase setValue(int amount) + { + this.value_main = amount; + return this; + } + + public ItemFoodBase setRarity(EnumRarity enumRarity) + { + overrideRarity = true; + this.enumRarity = enumRarity; + return this; + } + + public EnumRarity getRarity(ItemStack stack) + { + if (overrideRarity) + { + return enumRarity; + }else { + return super.getRarity(stack); + } + } + + public int addXP = 0; + + Potion potion; + int level; + int duration; + + public ItemFoodBase SetXP(int addXP) + { + this.addXP = addXP; + return this; + } + + + @Override + public void registerModels() + { + IdlFramework.proxy.registerItemRenderer(this, 0, "inventory"); + } + + public ItemFoodBase(String name, int amount, float saturation, boolean isWolfFood) { + super(amount, saturation, isWolfFood); + setUnlocalizedName(name); + setRegistryName(name); + setCreativeTab(ModCreativeTab.IDL_MISC); + + ModItems.ITEMS.add(this); + + InitItem(); + } + + protected void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player) + { + //IdlFramework.Log("%s:on Food Eaten", getUnlocalizedName()); + super.onFoodEaten(stack, worldIn, player); + if (addXP > 0) + { + player.addExperience(addXP); + } + } + + public void InitItem() + { + + } + + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + + IDLSkillNBT.addInformation(stack,world,tooltip,flag,shiftToShowDesc, showGuaSocketDesc, use_flavor, + getMainDesc(stack,world,tooltip,flag)); + + if (logNBT) + { + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } + } + + @SideOnly(Side.CLIENT) + public String descGetKey(ItemStack stack, World world, boolean showFlavor) + { + return showFlavor ? (stack.getUnlocalizedName() + IDLNBTDef.FLAVOR_KEY) + : (stack.getUnlocalizedName() + IDLNBTDef.DESC_COMMON); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + if (CommonFunctions.isShiftPressed() || !shiftToShowDesc) + { + String key = descGetKey(stack,world,false); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + if (!CommonFunctions.isShiftPressed() && use_flavor) + { + String key = descGetKey(stack,world,true); + if (I18n.hasKey(key)) + { + return I18n.format(key); + } + else + { + return ""; + } + } + + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemDigGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemDigGoblet.java new file mode 100644 index 0000000..0c847a8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemDigGoblet.java @@ -0,0 +1,93 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.google.common.primitives.Ints; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.block.Block; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import static com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef.ASSIGNED_BLOCK_NAME; + +public class ItemDigGoblet extends ItemGobletBase { + public ItemDigGoblet(String name) { + super(name); + } + + private void Test() + { + //Entity entity = AnvilChunkLoader.readWorldEntityPos(nbttagcompound, world, d0, d1, d2, false); + } + + public String GetStoredBlockName(ItemStack stack) + { + NBTTagCompound compound = stack.getTagCompound(); + return compound == null ? "" : compound.getString(ASSIGNED_BLOCK_NAME); + } + + public void SetStoredBlockName(ItemStack stack, Block block) + { + ResourceLocation resourceLocation = block.getRegistryName(); + IDLNBTUtil.SetString(stack, ASSIGNED_BLOCK_NAME, resourceLocation==null ? "" : block.getRegistryName().toString()); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (isSelected && !worldIn.isRemote) + { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + + String storedName = GetStoredBlockName(stack); + boolean hasSPBlock = !storedName.isEmpty(); + + if (level > 0) + { + int maxRange = 5; + int maxHeight = 3; + + int rangeXZ = Ints.min(maxRange, level); + int rangeY = Ints.min(maxHeight, level); + + for (int x = -rangeXZ; x <= rangeXZ; x++) + { + for (int z = -rangeXZ; z <= rangeXZ; z++) + { + for (int y = 0; y <= rangeY; y++) + { + Block block = worldIn.getBlockState(entityIn.getPosition().add(x, y, z)).getBlock(); + ResourceLocation loc = block.getRegistryName(); + if (block == Blocks.STONE + || (hasSPBlock && loc != null && loc.toString().equals(storedName))) + { + worldIn.setBlockState(entityIn.getPosition().add(x, y, z), Blocks.AIR.getDefaultState()); + } + } + } + } + } + } + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc"); + tooltip.add(mainDesc); + + String blockDesc = I18n.format( stack.getUnlocalizedName() + ".desc2", GetStoredBlockName(stack)); + tooltip.add(blockDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemFlameGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemFlameGoblet.java new file mode 100644 index 0000000..0313c17 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemFlameGoblet.java @@ -0,0 +1,60 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import static com.somebody.idlframewok.util.CommonDef.TICK_PER_SECOND; +import static net.minecraft.util.DamageSource.causePlayerDamage; + +public class ItemFlameGoblet extends ItemGobletBase { + public ItemFlameGoblet(String name) { + super(name); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (isSelected && !worldIn.isRemote) + { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + + if (level > 0 && worldIn.getWorldTime() % TICK_PER_SECOND == 0) + { + EntityPlayer playerIn = (EntityPlayer) entityIn; + Vec3d basePos = playerIn.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-level, -level, -level), basePos.addVector(level, level, level))); + for (EntityLiving living: entities + ) { + living.attackEntityFrom(causePlayerDamage(playerIn).setFireDamage().setMagicDamage(), level); + living.setFire(level); + } + + playerIn.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, TICK_PER_SECOND, 0)); + playerIn.setFire(level); + } + } + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc", GetLevelFromEXP(GetCacheEXP(stack))); + tooltip.add(mainDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemGobletBase.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemGobletBase.java new file mode 100644 index 0000000..ae75583 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemGobletBase.java @@ -0,0 +1,147 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLNBT; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemGobletBase extends ItemBase { + + public float cool_down = 1f; + public float cool_down_reduce_per_lv = 0f; + + public ItemGobletBase(String name) { + super(name); + } + + public void SetPayingEXP(ItemStack stack, int val) + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.P2W_PAYING_EXP, val); + } + + public int GetPayingEXP(ItemStack stack) + { + return IDLNBTUtil.GetInt(stack, IDLNBTDef.P2W_PAYING_EXP); + } + + public void SetCacheEXP(ItemStack stack, int val) + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.P2W_CACHE_EXP, val); + } + + public static int GetCacheEXP(ItemStack stack) + { + return IDLNBTUtil.GetInt(stack, IDLNBTDef.P2W_CACHE_EXP); + } + + public static int GetP2WExpForPlayer(EntityPlayer player) + { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = IDLNBT.getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + + return data.getInteger(IDLNBTDef.P2W_EXP); + } + + public static void SetP2WExpForPlayer(EntityPlayer player, int val) + { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = IDLNBT.getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + + data.setInteger(IDLNBTDef.P2W_EXP, val); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static int GetLevelFromEXP(int xp) + { + return (int)Math.log(xp+1); + } + + public static int GetExpForLevelFromEXP(int xp) + { + return (int)Math.pow(Math.exp(1), (int)Math.log(xp+1)+1); + } + public static int GetLevelFromItemStack(ItemStack stack) + { + return GetCacheEXP(stack); + } + + public static void activateCoolDown(EntityPlayer player, ItemStack stack) + { + Item item = stack.getItem(); + if (item instanceof ItemGobletBase) + { + player.getCooldownTracker().setCooldown(stack.getItem(), ((ItemGobletBase) item).GetMaxTick(stack)); + } + } + + private int GetMaxTick(ItemStack stack) { + return (int) (getCoolDown(stack) * CommonDef.TICK_PER_SECOND); + } + + public float getCoolDown(ItemStack stack) { + float result = -(GetLevelFromItemStack(stack) - 1) * cool_down_reduce_per_lv + cool_down; + return result > 0.1f ? result : 0.1f; } + + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + if (!worldIn.isRemote) + { + EntityPlayer player = (EntityPlayer) entityIn; + int playerXP = GetP2WExpForPlayer((EntityPlayer) entityIn); + int payingXP = GetPayingEXP(stack); + if (payingXP > 0) + { + //first, crafting charges the goblet + //when the player holds the goblet, the player absorbs the experience. + //todo; make the player drink from it to get the experience + playerXP += payingXP; + SetP2WExpForPlayer(player, playerXP); + SetPayingEXP(stack, 0); + } + + int lastCache = GetCacheEXP(stack); + if (lastCache != playerXP) + { + SetCacheEXP(stack, playerXP); + //stack.writeToNBT() + } + //IdlFramework.Log(playerXP + " " + getUnlocalizedName(stack)); + } + } + + @SideOnly(Side.CLIENT) + public void addInformationLast(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + int val = GetPayingEXP(stack); + if (val > 0) + tooltip.add(I18n.format("item.p2w_goblet.contain.desc", val)); + + val = GetCacheEXP(stack); + + if (GetCacheEXP(stack) > 0) + tooltip.add(I18n.format("item.p2w_goblet.player.desc", GetLevelFromEXP(val), val, GetExpForLevelFromEXP(val))); + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc"); + tooltip.add(mainDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemHealGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemHealGoblet.java new file mode 100644 index 0000000..0da3833 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemHealGoblet.java @@ -0,0 +1,59 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemHealGoblet extends ItemGobletBase { + public ItemHealGoblet(String name) { + super(name); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (isSelected && !worldIn.isRemote) + { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + + if (level > 0) + { + if (entityIn instanceof EntityLivingBase) + { + ((EntityLivingBase) entityIn).heal((float)level / CommonDef.TICK_PER_SECOND); + } + } + } + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + target.heal(GetLevelFromEXP(GetCacheEXP(stack))); + + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ITEM_BOTTLE_FILL, 1f, 1f); + return true; + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc", GetLevelFromEXP(GetCacheEXP(stack))); + tooltip.add(mainDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemKnockBackGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemKnockBackGoblet.java new file mode 100644 index 0000000..ff87305 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemKnockBackGoblet.java @@ -0,0 +1,81 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemKnockBackGoblet extends ItemGobletBase { + public ItemKnockBackGoblet(String name) { + super(name); + } + + public int getBuffLevel(int level) + { + int result = level / 3; + return result > 4 ? 4 : result; + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (isSelected && !worldIn.isRemote) + { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + + if (level > 0 && worldIn.getWorldTime() % (CommonDef.TICK_PER_SECOND << 1) == 0) + { + EntityPlayer playerIn = (EntityPlayer) entityIn; + Vec3d basePos = playerIn.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-level, -level, -level), basePos.addVector(level, level, level))); + for (EntityLiving living: entities + ) { + living.knockBack(playerIn, level * 0.1f + 0.5f, (playerIn.posX - living.posX), (playerIn.posZ - living.posZ)); + } + + playerIn.addPotionEffect(new PotionEffect(MobEffects.SPEED, CommonDef.TICK_PER_SECOND, getBuffLevel(level))); + if (playerIn.isSneaking()) + { + playerIn.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, CommonDef.TICK_PER_SECOND, getBuffLevel(level))); + } + } + } + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + target.addPotionEffect(new PotionEffect(MobEffects.SPEED, CommonDef.TICK_PER_SECOND * level, getBuffLevel(level))); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ITEM_BOTTLE_FILL, 1f, 1f); + return true; + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc", GetLevelFromEXP(GetCacheEXP(stack))); + tooltip.add(mainDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemP2WGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemP2WGoblet.java new file mode 100644 index 0000000..543301c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemP2WGoblet.java @@ -0,0 +1,9 @@ +package com.somebody.idlframewok.item.goblet; + +public class ItemP2WGoblet extends ItemGobletBase { + public ItemP2WGoblet(String name) { + super(name); + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/goblet/ItemWaterGoblet.java b/src/main/java/com/somebody/idlframewok/item/goblet/ItemWaterGoblet.java new file mode 100644 index 0000000..2a5dbf7 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/goblet/ItemWaterGoblet.java @@ -0,0 +1,54 @@ +package com.somebody.idlframewok.item.goblet; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemWaterGoblet extends ItemGobletBase { + public ItemWaterGoblet(String name) { + super(name); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + //todo : produce water, gives breathing and night vision buff in water; acquire those abilities one by one + + if (isSelected && !worldIn.isRemote) + { + int level = GetLevelFromEXP(GetCacheEXP(stack)); + + if (level > 0 && worldIn.getWorldTime() % CommonDef.TICK_PER_SECOND == 0) + { +// EntityPlayer playerIn = (EntityPlayer) entityIn; +// Vec3d basePos = playerIn.getPositionVector(); +// List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-level, -level, -level), basePos.addVector(level, level, level))); +// for (EntityLiving living: entities +// ) { +// living.attackEntityFrom(causePlayerDamage(playerIn).setFireDamage().setMagicDamage(), level); +// living.setFire(level * TICK_PER_SECOND); +// } +// +// playerIn.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, TICK_PER_SECOND, 0)); +// playerIn.setFire(level * TICK_PER_SECOND); + } + } + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc", GetLevelFromEXP(GetCacheEXP(stack))); + tooltip.add(mainDesc); + addInformationLast(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemAttrMeasure.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemAttrMeasure.java new file mode 100644 index 0000000..a167d58 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemAttrMeasure.java @@ -0,0 +1,36 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; + +public class ItemAttrMeasure extends ItemBase { + public ItemAttrMeasure(String name) { + super(name); + useable = true; + + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand) { + + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_ATK, EntityUtil.getAttr(target, SharedMonsterAttributes.ATTACK_DAMAGE)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_HP, EntityUtil.getAttr(target, SharedMonsterAttributes.MAX_HEALTH)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_DEF, EntityUtil.getAttr(target, SharedMonsterAttributes.ARMOR)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_ARMOR_T, EntityUtil.getAttr(target, SharedMonsterAttributes.ARMOR_TOUGHNESS)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_RANGE, EntityUtil.getAttr(target, SharedMonsterAttributes.FOLLOW_RANGE)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_KB_R, EntityUtil.getAttr(target, SharedMonsterAttributes.KNOCKBACK_RESISTANCE)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_SPEED, EntityUtil.getAttr(target, SharedMonsterAttributes.MOVEMENT_SPEED)); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.MARK_ATK_SPEED, EntityUtil.getAttr(target, SharedMonsterAttributes.ATTACK_SPEED)); + + return true; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicBinary.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicBinary.java new file mode 100644 index 0000000..8e565b0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicBinary.java @@ -0,0 +1,24 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.item.ItemBase; + +public class ItemBasicBinary extends ItemBase { + + public int getValue() { + return value; + } + + public ItemBasicBinary setValue(int value) { + this.value = value; + return this; + } + + int value = 0;//0 = yin, 1 = yang + + public ItemBasicBinary(String name) { + super(name); + } + + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicGua.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicGua.java new file mode 100644 index 0000000..3bb190d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemBasicGua.java @@ -0,0 +1,24 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.item.ItemBase; + +public class ItemBasicGua extends ItemBase { + + public int getGua() { + return gua; + } + + public ItemBasicGua setGua(int gua) { + this.gua = gua; + return this; + } + + int gua = 0; + + public ItemBasicGua(String name) { + super(name); + } + + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemKinshipSword.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemKinshipSword.java new file mode 100644 index 0000000..4f3999d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemKinshipSword.java @@ -0,0 +1,221 @@ +package com.somebody.idlframewok.item.misc; + +import java.util.List; + +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.item.ItemSwordBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.effect.EntityLightningBolt; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemKinshipSword extends ItemSwordBase implements IGuaEnhance { + + public ItemKinshipSword(String name, ToolMaterial material) { + super(name, material); + shiftToShowDesc = true; + } + +// @SubscribeEvent +// public static void onCreatureHurt(LivingHurtEvent evt) { +// if (evt.isCanceled()) +// { +// return; +// } +// +// World world = evt.getEntity().getEntityWorld(); +// if (!world.isRemote) { +// EntityLivingBase hurtOne = evt.getEntityLiving(); +// Entity trueSource = evt.getSource().getTrueSource(); +// +// if (hurtOne instanceof EntityPlayer && !(evt.getSource().getTrueSource() instanceof EntityPlayer)) { +// EntityPlayer player = (EntityPlayer) hurtOne; +// ItemStack stack = AttemptPlayerHand(player, EnumHand.MAIN_HAND); +// if (stack == ItemStack.EMPTY) { +// stack = AttemptPlayerHand(player, EnumHand.OFF_HAND); +// } +// if (stack != ItemStack.EMPTY) { +// ItemSkillCalmWalk skillThunderFall = ((ItemSkillCalmWalk) stack.getItem()); +// +// if (!player.world.isRemote) { +// //int level = skillThunderFall.getLevel(stack); +// evt.setCanceled(true); +// } +// } +// } +// +// if (trueSource instanceof EntityPlayer) { +// ItemStack stack = AttemptPlayerHand((EntityPlayer) trueSource, EnumHand.MAIN_HAND); +// if (stack == ItemStack.EMPTY) { +// stack = AttemptPlayerHand((EntityPlayer) trueSource, EnumHand.OFF_HAND); +// } +// if (stack != ItemStack.EMPTY) { +// evt.setCanceled(true); +// } +// } +// } +// } + + + public float getSplashDamage(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) + { + return (float)attacker.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); + } + + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) + { + stack.damageItem(1, attacker); + World worldIn = attacker.getEntityWorld(); + + if (!worldIn.isRemote) + { + float base_range = 16f + IDLSkillNBT.GetGuaEnhance(stack, 7); + + Vec3d basePos = attacker.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(target.getClass(), IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); + + for (EntityLivingBase living: entities + ) { + if (living != target) + { + //damage is only dealt once + OnHitBasic(stack, attacker, living, EnumHand.MAIN_HAND); + OnHitExtra(stack, attacker, living, EnumHand.MAIN_HAND); + } + else { + OnHitExtra(stack, attacker, living, EnumHand.MAIN_HAND); + } + + } + } + + return true; + } + //gua enhance + float windModifier = 0.1f; + //6 wind + public float getKBPower(ItemStack stack) + { + return 0.4f + windModifier * IDLSkillNBT.GetGuaEnhance(stack, 6); + } + + public void OnHitBasic(ItemStack stack, EntityLivingBase playerIn, EntityLivingBase target, EnumHand handIn) + { + if (!playerIn.world.isRemote) { + float dmg = getSplashDamage(stack, target, playerIn) / 2f + getExtraDamage(stack, target.isWet()); + + target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) playerIn), dmg); + } + } + + float getExtraDamage(ItemStack stack, boolean targetWet) + { + int fire = IDLSkillNBT.GetGuaEnhance(stack, 5); + int thunder = IDLSkillNBT.GetGuaEnhance(stack, 1); + return fire + (targetWet ? thunder * 2 : thunder); + } + + public void OnHitExtra(ItemStack stack, EntityLivingBase playerIn, EntityLivingBase target, EnumHand handIn) + { + int mountain = IDLSkillNBT.GetGuaEnhance(stack, 4); + int water = IDLSkillNBT.GetGuaEnhance(stack, 2); + int lake = IDLSkillNBT.GetGuaEnhance(stack, 3); + int fire = IDLSkillNBT.GetGuaEnhance(stack, 5); + int thunder = IDLSkillNBT.GetGuaEnhance(stack, 1); + + if (mountain > 0) + { + target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, CommonDef.TICK_PER_SECOND * mountain * 2, mountain / 4)); + } + + if (water > 0) + { + target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, CommonDef.TICK_PER_SECOND * water * 2, water / 4)); + target.extinguish(); + } + + if (lake > 0) + { + target.heal(lake); + playerIn.heal(lake); + } + + //wind + target.knockBack(playerIn, getKBPower(stack), (playerIn.posX - target.posX), (playerIn.posZ - target.posZ)); + + //fire + target.setFire(fire); + + //thunder + if (thunder >= 8) + { + playerIn.world.addWeatherEffect(new EntityLightningBolt(playerIn.world, target.posX, target.posY, target.posZ, false)); + } + + } + + @Override + public boolean acceptGuaIndex(int index) { + return index != 0; + } + + class BuffTuple + { + public int tick; + public int power; + + public BuffTuple(int power, int tick) { + this.tick = tick; + this.power = power; + } + } + +// public com.somebody.idlframewok.item.skills.martial.BuffTuple GetWaterBuff(ItemStack stack) +// { +// int water = GetGuaEnhance(stack, 2); +// return new com.somebody.idlframewok.item.skills.martial.BuffTuple(water / 4, TICK_PER_SECOND * water * 2); +// } +// +// public com.somebody.idlframewok.item.skills.martial.BuffTuple GetMountainBuff(ItemStack stack) +// { +// int gua = GetGuaEnhance(stack, 4); +// return new com.somebody.idlframewok.item.skills.martial.BuffTuple(gua / 4, TICK_PER_SECOND * gua * 2); +// } +// +// public DamageSource GetDamageSource(ItemStack stack, EntityLivingBase playerIn, EntityLivingBase target, EnumHand handIn) +// { +// return new EntityDamageSource("race", playerIn); +// } + + /** + * Gets a map of item attribute modifiers, used by ItemSword to increase hit damage. + */ + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) + { + Multimap multimap = super.getItemAttributeModifiers(slot); + + if (slot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", getBaseAttackDamage() + IDLSkillNBT.GetGuaEnhance(stack, 7), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", -2.4000000953674316D, 0)); + } + + return multimap; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemNanoMender.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemNanoMender.java new file mode 100644 index 0000000..2813269 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemNanoMender.java @@ -0,0 +1,42 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class ItemNanoMender extends ItemBase { + public ItemNanoMender(String name, int maxDmg) { + super(name); + setMaxDamage(maxDmg); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (!worldIn.isRemote) + { + EntityPlayer playerIn = (EntityPlayer) entityIn; + for (EntityEquipmentSlot slot: + EntityEquipmentSlot.values()) { + + ItemStack itemstack1 = playerIn.getItemStackFromSlot(slot); + if (!itemstack1.isEmpty() && itemstack1.isItemDamaged() && !(itemstack1.getItem() instanceof ItemNanoMender)) { + //Fix Dura + CommonFunctions.RepairItem(itemstack1, 1); + stack.damageItem(1, playerIn); + break; + } + } + } + } + +// public EnumRarity getRarity(ItemStack stack) +// { +// return stack.isItemEnchanted() ? EnumRarity.RARE : EnumRarity.COMMON; +// } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemPackage.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemPackage.java new file mode 100644 index 0000000..a41ee6b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemPackage.java @@ -0,0 +1,57 @@ +package com.somebody.idlframewok.item.misc; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.ItemBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemPackage extends ItemBase { + public Item[] validItems = new Item[]{}; + int pick = 1; + + public ItemPackage(String name, Item[] validItems) { + super(name); + this.validItems = validItems; + } + + public ItemPackage(String name, Item[] validItems, int pick) { + super(name); + this.validItems = validItems; + this.pick = pick; + } + + @Nonnull + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand hand) { + player.setActiveHand(hand); + ItemStack stack = player.getHeldItem(hand); + + if (!world.isRemote) { + + player.addItemStackToInventory(new ItemStack(validItems[player.getRNG().nextInt(validItems.length)])); + player.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1f, 1f); + player.addExperience(10); + + // Must do shrink AFTER addItemStackToInventory, + //or it would make the addItemStackToInventory fail if the new thing were to be in the new place. + // Try do this when helding one sealed weapon in slot 1, and something else in slot 2. + stack.shrink(1); + } + + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + + public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) + { + return EnumActionResult.PASS; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemSpaceAnchor.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemSpaceAnchor.java new file mode 100644 index 0000000..2b9ac9b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemSpaceAnchor.java @@ -0,0 +1,120 @@ +package com.somebody.idlframewok.item.misc; + +import java.util.List; +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSpaceAnchor extends ItemBase { + public int chargeTickDefault = 20; + + public ItemSpaceAnchor(String name) { + super(name); + useable = true; + } + + + public int chargeNeedTick(ItemStack stack) + { + return chargeTickDefault; + } + + /** + * How long it takes to use or consume an item + */ + @Override + public int getMaxItemUseDuration(ItemStack stack) + { + return 200; + } + + //Animation + @Nonnull + @Override + public EnumAction getItemUseAction(ItemStack stack) { + + return EnumAction.BOW; + + } + + @Override + public void clientUseTick(ItemStack stack, EntityLivingBase living, int count) { +// //Particle; + //DWeapons.LogWarning(String.format("onUsingTick %s",count)); + + if (count >= chargeNeedTick(stack)) { + CreateParticle(stack, living); + } + } + + private void CreateParticle(ItemStack stack, EntityLivingBase living) { + EntityUtil.SpawnParticleAround(living, EnumParticleTypes.PORTAL, 10); + } + + /** + * Called when the player stops using an Item (stops holding the right mouse button). + */ + @Override + public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase living, int time) { + //change mode + if (!world.isRemote) { + if (getMaxItemUseDuration(stack) - time >= chargeNeedTick(stack)) + { + if (IDLNBTUtil.GetBoolean(stack, IDLNBTDef.ANCHOR_READY, false)) + { + BlockPos pos = IDLNBTUtil.getMarkedPos(stack); + if (living.attemptTeleport(pos.getX(), pos.getY(), pos.getZ())) + { + stack.shrink(1); + } + else { + CommonFunctions.SafeSendMsgToPlayer((EntityPlayer) living, "idlframewok.msg.teleport.fail"); + } + } + else { + IDLNBTUtil.markPosToStack(stack, living.getPosition()); + } + + //DWeapons.LogWarning("Weapon mode is:" + GetWeaponMode(stack)); + } + } + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + + //tooltip.add(I18n.format("idlframewok.gua_enhance_total.desc", IDLSkillNBT.GetGuaEnhanceTotal(stack))); + tooltip.add(IDLNBTUtil.getNBT(stack).toString()); + } +// @Override +// public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) { +// return super.onItemUseFinish(stack, worldIn, entityLiving); +// } +// +// @Override +// public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { +// +// return super.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ); +// } +// +// @Override +// public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { +// return super.onItemRightClick(worldIn, playerIn, handIn); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemSummon.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemSummon.java new file mode 100644 index 0000000..da6a777 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemSummon.java @@ -0,0 +1,71 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemSummon extends ItemBase { + + ResourceLocation entityLocation; + + protected boolean doWarn = true; + + public ItemSummon(String name) { + super(name); + } + + public ItemSummon setEntity(String id) + { + useable = true; + this.entityLocation = new ResourceLocation(Reference.MOD_ID,id); + + //this.entityLocation = new ResourceLocation(layer); + return this; + } + + + @Override + public EnumActionResult onItemUse(EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand handIn, EnumFacing facing, float hitX, float hitY, float hitZ) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote) + { + stack.shrink(1); + Entity entity = EntityList.createEntityByIDFromName(entityLocation, worldIn); + if (entity instanceof EntityLivingBase) + { + EntityLivingBase entityLivingBase = (EntityLivingBase) entity; + entityLivingBase.setPosition(pos.getX() + 0.5f,pos.getY() + 1f,pos.getZ() + 0.5f); + IdlFramework.Log("Spawned: %s @ %s", entityLivingBase.getName(), entityLivingBase.getPosition()); + worldIn.spawnEntity(entityLivingBase); +// if (entityLivingBase instanceof EntityLiving) +// { +// ((EntityLiving)entityLivingBase).spawnExplosionParticle(); +// } + } + else { + if (doWarn) + IdlFramework.LogWarning("Trying to summon a non-living entity"); + } + } + + return super.onItemUse(playerIn, worldIn, pos, handIn, facing, hitX, hitY, hitZ); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemSummonEternal.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemSummonEternal.java new file mode 100644 index 0000000..a82f69e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemSummonEternal.java @@ -0,0 +1,42 @@ +package com.somebody.idlframewok.item.misc; + +import com.somebody.idlframewok.entity.creatures.misc.EntityEternalZombie; +import com.somebody.idlframewok.item.ItemBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemSummonEternal extends ItemBase { + + public ItemSummonEternal(String name) { + super(name); + } + + @Override + public EnumActionResult onItemUse(EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand handIn, EnumFacing facing, float hitX, float hitY, float hitZ) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote) + { + stack.shrink(1); + EntityEternalZombie zombie = new EntityEternalZombie(worldIn); + zombie.setPosition(pos.getX(),pos.getY()+1,pos.getZ()); + worldIn.spawnEntity(zombie); + }else { + playerIn.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1f, 1f); + } + + return super.onItemUse(playerIn, worldIn, pos, handIn, facing, hitX, hitY, hitZ); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/ItemYiJianMei.java b/src/main/java/com/somebody/idlframewok/item/misc/ItemYiJianMei.java new file mode 100644 index 0000000..06f6c48 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/ItemYiJianMei.java @@ -0,0 +1,29 @@ +package com.somebody.idlframewok.item.misc; + +import java.util.Random; + +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.EntityUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemYiJianMei extends ItemBase { + public ItemYiJianMei(String name) { + super(name); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + if (worldIn.isRemote && entityIn instanceof EntityPlayer) + { + Random random = ((EntityPlayer) entityIn).getRNG(); + Vec3d pos = EntityUtil.GetRandomAroundPos(entityIn.getPositionEyes(0f), 1f, random).addVector(0, random.nextFloat(), 0); + worldIn.spawnParticle(EnumParticleTypes.SNOW_SHOVEL, pos.x, pos.y, pos.z, 0,0, random.nextFloat());//from the north + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorUnderfootGeta.java b/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorUnderfootGeta.java new file mode 100644 index 0000000..69f2ea4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorUnderfootGeta.java @@ -0,0 +1,140 @@ +package com.somebody.idlframewok.item.misc.armor; + +import java.util.Collection; +import java.util.List; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.item.ItemArmorBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemArmorUnderfootGeta extends ItemArmorBase implements IGuaEnhance { + public ItemArmorUnderfootGeta(String name, ArmorMaterial materialIn, int renderIndexIn, EntityEquipmentSlot equipmentSlotIn) { + super(name, materialIn, renderIndexIn, equipmentSlotIn); + showGuaSocketDesc = true; + ignoreVanillaSystem = true; + } + + static final int maxEnhance = 5; + + @Override + public void onUpdateWearing(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdateWearing(stack, worldIn, entityIn, itemSlot, isSelected); + + if (!worldIn.isRemote) + { + EntityLivingBase livingBase = (EntityLivingBase) entityIn; + + if (livingBase instanceof EntityPlayer) + { + if (((EntityPlayer) livingBase).capabilities.isCreativeMode) + { + //quite annoying in creative + return; + } + } + + if (worldIn.getWorldTime() % (maxEnhance - IDLSkillNBT.GetGuaEnhance(stack, CommonDef.G_EARTH)) == 0) + { + Collection activePotionEffects = livingBase.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion().isBadEffect()){ + livingBase.removePotionEffect(buff.getPotion()); + break; + } + } + + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (!buff.getPotion().isBadEffect()){ + livingBase.removePotionEffect(buff.getPotion()); + break; + } + } + } + } + } + + static float fireRatioBase = 1.5f; + static float fireRatioPerEnhance = 0.5f; + public static float GetDamageMultiplierFire(ItemStack stack) + { + return IDLSkillNBT.GetGuaEnhance(stack, CommonDef.G_EARTH) * fireRatioPerEnhance + fireRatioBase; + } + + public static float GetDebuffPeriod(ItemStack stack) + { + return Math.max(1f - (float)IDLSkillNBT.GetGuaEnhance(stack, CommonDef.G_EARTH) / (float)maxEnhance, 1f/ CommonDef.TICK_PER_SECOND); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onCreatureHurt(LivingHurtEvent evt) { + if (evt.isCanceled() || !evt.getSource().isFireDamage()) { + return; + } + + EntityLivingBase hurtOne = evt.getEntityLiving(); + ItemStack onFoot = hurtOne.getItemStackFromSlot(EntityEquipmentSlot.FEET); + if (onFoot.getItem() instanceof ItemArmorUnderfootGeta) + { + float amplifier = ItemArmorUnderfootGeta.GetDamageMultiplierFire(onFoot); + evt.setAmount(evt.getAmount() * amplifier); + } + } + + @Override + public boolean acceptGuaIndex(int index) { + return index == 0; + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + float fireAmplify = GetDamageMultiplierFire(stack); + float buffTime = GetDebuffPeriod(stack); + + return I18n.format(key, buffTime, fireAmplify); + } + return ""; + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + + if (equipmentSlot == this.armorType) + { + multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Armor modifier", (double)this.damageReduceAmount, 0)); + multimap.put(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Armor toughness", (double)this.toughness, 0)); + multimap.put(SharedMonsterAttributes.MAX_HEALTH.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()],"Health modifier", (double)2f + IDLSkillNBT.GetGuaEnhance(stack, 0), 0)); + multimap.put(SharedMonsterAttributes.LUCK.getName(), new AttributeModifier(ARMOR_MODIFIERS_OVERRIDE[equipmentSlot.getIndex()], "Luck", (double)1f, 0)); + } + + return multimap; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorXieGeta.java b/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorXieGeta.java new file mode 100644 index 0000000..dff7420 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/misc/armor/ItemArmorXieGeta.java @@ -0,0 +1,186 @@ +package com.somebody.idlframewok.item.misc.armor; + +import java.util.List; + +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.item.ItemArmorBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemArmorXieGeta extends ItemArmorBase implements IGuaEnhance { + + static final int UP_HILL = 0; + static final int FLAT_WALK = 1; + static final int DOWN_HILL = 2; + static final int MAX_MODE = 2; + + public ItemArmorXieGeta(String name, ArmorMaterial materialIn, int renderIndexIn, EntityEquipmentSlot equipmentSlotIn) { + super(name, materialIn, renderIndexIn, equipmentSlotIn); + showGuaSocketDesc = true; + ignoreVanillaSystem = true; + } + + @Override + public void onUpdateWearing(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdateWearing(stack, worldIn, entityIn, itemSlot, isSelected); + + if (!worldIn.isRemote) + { + EntityLivingBase living = (EntityLivingBase) entityIn; + + int buffPower = getBuffPower(stack); + switch ((IDLNBTUtil.GetInt(stack, IDLNBTDef.MODE))) + { + case UP_HILL: + living.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, CommonDef.TICK_PER_SECOND, buffPower)); + break; + case FLAT_WALK: + living.addPotionEffect(new PotionEffect(MobEffects.SPEED, CommonDef.TICK_PER_SECOND, buffPower)); + break; + default: + living.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, CommonDef.TICK_PER_SECOND, 0)); + break; + } + } + } + + public int getBuffPower(ItemStack stack) + { + return IDLSkillNBT.GetGuaEnhance(stack, CommonDef.G_EARTH) / 3; + } + + static float basicReduction = 2f; + public static float GetDamageReductionFall(ItemStack stack) + { + if (IDLNBTUtil.GetInt(stack, IDLNBTDef.MODE) != DOWN_HILL) + { + return 0; + } + else { + return IDLSkillNBT.GetGuaEnhance(stack, CommonDef.G_EARTH) + basicReduction; + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onCreatureHurt(LivingHurtEvent evt) { + if (evt.isCanceled() || evt.getSource() != DamageSource.FALL) { + //IdlFramework.Log("Xie Geta wrong type"); + return; + } + + EntityLivingBase hurtOne = evt.getEntityLiving(); + ItemStack onFoot = hurtOne.getItemStackFromSlot(EntityEquipmentSlot.FEET); + if (onFoot.getItem() instanceof ItemArmorXieGeta) + { + float reduction = ItemArmorXieGeta.GetDamageReductionFall(onFoot); + //IdlFramework.Log("Xie Geta dmg reduction:%s", reduction); + if (evt.getAmount() <= reduction) + { + evt.setCanceled(true); + } + else { + evt.setAmount(evt.getAmount() - reduction); + } + } + } + + @Override + public EnumActionResult onItemUse(EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand handIn, EnumFacing facing, float hitX, float hitY, float hitZ) { + + ItemStack stack = playerIn.getHeldItem(handIn); + int mode = IDLNBTUtil.GetInt(stack, IDLNBTDef.MODE); + if (!worldIn.isRemote) + { + if (mode == MAX_MODE) + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.MODE, 0); + } + else + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.MODE, mode + 1); + } + } + else { + switch (mode) + { + case UP_HILL: + playerIn.playSound(SoundEvents.BLOCK_WOOD_BREAK, 1f, 1f); + break; + + case FLAT_WALK: + playerIn.playSound(SoundEvents.BLOCK_WOOD_BUTTON_CLICK_OFF, 1f, 1f); + break; + + case DOWN_HILL: + playerIn.playSound(SoundEvents.BLOCK_WOOD_BUTTON_CLICK_ON, 1f, 1f); + break; + + default: + break; + } + + } + + return super.onItemUse(playerIn, worldIn, pos, handIn, facing, hitX, hitY, hitZ); + } + + @Override + public boolean acceptGuaIndex(int index) { + return index == 0 || index == 7; + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = getNameKey(stack, world, tooltip, flag); + if (I18n.hasKey(key)) + { + float reduction = ItemArmorXieGeta.GetDamageReductionFall(stack); + int buffPower = getBuffPower(stack); + + int mode = IDLNBTUtil.GetInt(stack, IDLNBTDef.MODE); + if (mode == DOWN_HILL) + { + return I18n.format(key, reduction); + }else + { + return I18n.format(key, buffPower + 1); + } + + } + return ""; + } + + @SideOnly(Side.CLIENT) + public String getNameKey(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + int mode = IDLNBTUtil.GetInt(stack, IDLNBTDef.MODE); + return stack.getUnlocalizedName() + ".desc." + String.valueOf(mode); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/potions/PotionBase.java b/src/main/java/com/somebody/idlframewok/item/potions/PotionBase.java new file mode 100644 index 0000000..69f5199 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/potions/PotionBase.java @@ -0,0 +1,25 @@ +package com.somebody.idlframewok.item.potions; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.potion.Potion; + +public class PotionBase extends Potion { + + //todo: add a registerSpawnList for this + + public PotionBase(String name, boolean badEffect, int color, int iconIndex) { + super(badEffect, color); + setRegistryName(name); + setPotionName("idlframewok.potion." + name); + } + + public boolean hasEffect(EntityLivingBase entity) { + return hasEffect(entity, this); + } + + public boolean hasEffect(EntityLivingBase entity, Potion potion) { + return entity.getActivePotionEffect(potion) != null; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemCreatureRadar.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemCreatureRadar.java new file mode 100644 index 0000000..d2cefff --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemCreatureRadar.java @@ -0,0 +1,172 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemCreatureRadar extends ItemSkillBase { + + private String msgKey = "idlframewok.msg.radar_nearbycreatures"; + private SoundEvent alarm = SoundEvents.BLOCK_NOTE_BELL; + +// public ItemCreatureRadar(String name, Class targetCategory, String msgKey, SoundEvent alarm) { +// this(name); +// this.msgKey = msgKey; +// this.alarm = alarm; +// } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + + World world = playerIn.world; + if (!world.isRemote) { + ItemStack cloneResult = target.getPickedResult(null); + if (!cloneResult.isEmpty()) + { + ResourceLocation name = EntityList.getKey(target); + if (name != null && EntityList.ENTITY_EGGS.containsKey(name)) + { + //SetString(stack, "creature_id", name.toString()); + NBTTagCompound tagCompound = IDLNBTUtil.getNBT(stack); + tagCompound.setString("creature_id", name.toString()); + + //stack.writeToNBT(tagCompound); + //net.minecraft.item.ItemMonsterPlacer.applyEntityIdToItemStack(stack, name); + CommonFunctions.SafeSendMsgToPlayer(playerIn, getUnlocalizedName() + ".msg.success"); + IdlFramework.LogWarning(IDLNBTUtil.getNBT(stack).toString()); + activateCoolDown(playerIn, stack); + } + + return true; + } + } + + return false; + } + + public ItemCreatureRadar(String name) { + super(name); + showCDDesc = false; + showDamageDesc = false; + showRangeDesc = true; +// this.addPropertyOverride(new ResourceLocation(STATE), new IItemPropertyGetter() +// { +// @SideOnly(Side.CLIENT) +// public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) +// { +// if (entityIn == null)//when not in hand, world is null. +// { +// return 1.0F;//set to 0 will cause no updating when not in hand. dunno why +// } +// else +// { +//// if (worldIn == null) +//// { +//// worldIn = entityIn.world; +//// } +//// int state = GetInt(stack, STATE); +// //IdlFramework.Log("State = " + state); +// return (float)GetInt(stack, STATE); +// } +// } +// }); + } + + public Class getCreatureFromStack(ItemStack stack) + { + NBTTagCompound nbttagcompound = IDLNBTUtil.getNBT(stack); + //NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("EntityTag"); + + + if (nbttagcompound.hasKey("creature_id", 8)) + { + net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(new ResourceLocation( nbttagcompound.getString("creature_id"))); + if (entry != null) + { + return entry.getEntityClass(); + } + } + + return EntityPlayer.class; +// ResourceLocation resourcelocation = new ResourceLocation(nbt.getString("layer")); +// Entity entity = EntityList.createEntityByIDFromName(resourcelocation, worldIn); + + } + + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (!worldIn.isRemote) + { + int detection = 0; + float XZRangeRadius = getRange(stack); + float YRangeRadius = getRange(stack); + + Vec3d pos = entityIn.getPositionEyes(1.0F); + + IdlFramework.Log("update:", IDLNBTUtil.getNBT(stack).toString()); + + Class s = getCreatureFromStack(stack); + if (s == null) + { + s = EntityPlayer.class; + } + + List entities = worldIn.getEntitiesWithinAABB(EntityLivingBase.class, + IDLGeneral.ServerAABB(pos.addVector(-XZRangeRadius, -YRangeRadius, -XZRangeRadius), pos.addVector(XZRangeRadius, YRangeRadius, XZRangeRadius))); + for (EntityLivingBase entity : entities) + { + //IdlFramework.Log(String.format("[Active]Nearby %s -> %s" , entity.getName() ,entity.getAttackTarget())); + if (entity.getClass() == s && entity != entityIn) + { + detection++; + //IdlFramework.Log("[Active]Detected!"); + } + } + + IDLNBTUtil.SetInt(stack, IDLNBTDef.STATE, detection); + int detectionPre = IDLNBTUtil.GetInt(stack, IDLNBTDef.STATE); + if (detectionPre != detection)//optimize + { + IdlFramework.LogWarning("Changed to " + detection); + IDLNBTUtil.SetInt(stack, IDLNBTDef.STATE, detection); + CommonFunctions.SendMsgToPlayerStyled((EntityPlayerMP) entityIn, msgKey, TextFormatting.YELLOW, detection); + //worldIn.playSound(); + //entityIn.playSound(alarm, 0.7f, detection * 0.1f); + } + } + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".extra", getCreatureFromStack(stack).getName() ); + tooltip.add(mainDesc); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemHateDetector.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemHateDetector.java new file mode 100644 index 0000000..68b6f49 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemHateDetector.java @@ -0,0 +1,103 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; +import javax.annotation.Nullable; + +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.IItemPropertyGetter; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemHateDetector extends ItemSkillBase { + + private Class targetCategory = EntityLiving.class; + private String msgKey = "idlframewok.msg.being_targeted"; + private SoundEvent alarm = SoundEvents.BLOCK_NOTE_BELL; + + public ItemHateDetector(String name, Class targetCategory, String msgKey, SoundEvent alarm) { + this(name); + this.targetCategory = targetCategory; + this.msgKey = msgKey; + this.alarm = alarm; + } + + public ItemHateDetector(String name) { + super(name); + showCDDesc = false; + showDamageDesc = false; + showRangeDesc = true; + this.addPropertyOverride(new ResourceLocation(IDLNBTDef.STATE), new IItemPropertyGetter() + { + @SideOnly(Side.CLIENT) + public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) + { + if (entityIn == null)//when not in hand, world is null. + { + return 1.0F;//set to 0 will cause no updating when not in hand. dunno why + } + else + { +// if (worldIn == null) +// { +// worldIn = entityIn.world; +// } +// int state = GetInt(stack, STATE); + //IdlFramework.Log("State = " + state); + return (float) IDLNBTUtil.GetInt(stack, IDLNBTDef.STATE); + } + } + }); + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + + if (!worldIn.isRemote) + { + int detection = 0; + float XZRangeRadius = getRange(stack); + float YRangeRadius = getRange(stack); + + Vec3d pos = entityIn.getPositionEyes(1.0F); + + List entities = worldIn.getEntitiesWithinAABB(targetCategory, + IDLGeneral.ServerAABB(pos.addVector(-XZRangeRadius, -YRangeRadius, -XZRangeRadius), pos.addVector(XZRangeRadius, YRangeRadius, XZRangeRadius))); + for (EntityLiving entity : entities) + { + //IdlFramework.Log(String.format("[Active]Nearby %s -> %s" , entity.getName() ,entity.getAttackTarget())); + if (entity.getAttackTarget() == entityIn) + { + detection++; + //IdlFramework.Log("[Active]Detected!"); + } + } + + int detectionPre = IDLNBTUtil.GetInt(stack, IDLNBTDef.STATE); + if (detectionPre != detection)//optimize + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.STATE, detection); + if (detectionPre == 0) + { + CommonFunctions.SendMsgToPlayerStyled((EntityPlayerMP) entityIn, msgKey, TextFormatting.YELLOW); + } + //worldIn.playSound(); + //entityIn.playSound(alarm, 0.7f, detection * 0.1f); + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemMirrorWork.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemMirrorWork.java new file mode 100644 index 0000000..793529b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemMirrorWork.java @@ -0,0 +1,38 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemMirrorWork extends ItemSkillBase { + + public ItemMirrorWork(String name) { + super(name); + maxLevel = 10; + setCD(3600, 300); + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote && handIn == EnumHand.MAIN_HAND) + { + playerIn.setFire(5 * CommonDef.TICK_PER_SECOND); + playerIn.addItemStackToInventory(playerIn.getHeldItemOffhand().copy()); + activateCoolDown(playerIn, stack); + } + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + @Override + public EnumRarity getRarity(ItemStack stack) { + return EnumRarity.EPIC; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAquireItems.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAquireItems.java new file mode 100644 index 0000000..428cbd1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAquireItems.java @@ -0,0 +1,36 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSkillAquireItems extends ItemSkillBase { + public Item[] validItems = new Item[]{Items.PAPER}; + + public ItemSkillAquireItems(String name, Item[] validItems) { + super(name); + maxLevel = 1; + showDamageDesc = false; + this.validItems = validItems; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote) + { + playerIn.addItemStackToInventory(new ItemStack(validItems[validItems.length])); + playerIn.playSound(SoundEvents.BLOCK_NOTE_HARP, 1f, 3f); + activateCoolDown(playerIn, stack); + } + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAttackBoost.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAttackBoost.java new file mode 100644 index 0000000..f00b936 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillAttackBoost.java @@ -0,0 +1,54 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillAttackBoost extends ItemSkillBase { + public ItemSkillAttackBoost(String name) { + super(name); + cool_down = 50f; + maxLevel = 4; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + Vec3d basePos = playerIn.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(EntityLivingBase.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); + for (EntityLivingBase living: entities + ) { + if (EntityUtil.getAttitude(playerIn, living) == EntityUtil.ATTITUDE.FRIEND) + { + living.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 3* CommonDef.TICK_PER_TURN, IDLSkillNBT.getLevel(stack) - 1)); + } + } + playerIn.swingArm(handIn); + playerIn.playSound(SoundEvents.ENTITY_VILLAGER_YES, 1f, 1f); + activateCoolDown(playerIn, stack); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBase.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBase.java new file mode 100644 index 0000000..932ede6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBase.java @@ -0,0 +1,344 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.init.ModCreativeTab; +import com.somebody.idlframewok.item.ItemBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.MessageDef; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +enum SKILL_MSG_TYPE +{ + SUCCESS, + CD, +} + + +public class ItemSkillBase extends ItemBase { + public boolean isMartial = false; + + public float cool_down = 1f; + public float cool_down_reduce_per_lv = 0.2f; + + public float base_range = 5f; + public float range_per_level = 0f; + + public float basic_val = 0f; + public float val_per_level = 0f; + + public float dura_val = 0f; + public float dura_per_level = 0f; + + public float level_modifier = 0f; + + public int maxLevel = 5; + + public int gua_index = CommonDef.G_SKY; + + public boolean showCDDesc = true; + public boolean showDamageDesc = true; + public boolean showRangeDesc = false; + public boolean showDuraDesc = false; + + //for arknights + public boolean offHandCast = false; + public boolean mainHandCast = false; + public boolean cannotMouseCast = false; + + protected int maxDialogues = 0; + + protected int GetMaxTick(ItemStack stack) { + return (int) (getCoolDown(stack) * CommonDef.TICK_PER_SECOND); + } + + public ItemSkillBase(String name) { + super(name); + setMaxStackSize(1); + setNoRepair(); + setCreativeTab(ModCreativeTab.IDL_MISC); + } + + @Override + public EnumRarity getRarity(ItemStack stack) { + return super.getRarity(stack); + } + + public ItemSkillBase setMaxLevel(int maxLevel) + { + this.maxLevel = maxLevel; + return this; + } + + public ItemSkillBase setVal(float val, float val_per_level) + { + basic_val = val; + this.val_per_level = val_per_level; + return this; + } + + public ItemSkillBase setCD(float val, float val_per_level) + { + cool_down = val; + this.cool_down_reduce_per_lv = val_per_level; + return this; + } + + public ItemSkillBase setDura(float val, float val_per_level) + { + dura_val = val; + this.dura_per_level = val_per_level; + return this; + } + + public ItemSkillBase setRange(float val, float val_per_level) + { + base_range = val; + this.range_per_level = val_per_level; + return this; + } + + public float getRange(ItemStack stack) + { + return (IDLSkillNBT.getLevel(stack) - 1) * range_per_level + base_range; + } + + public float getDura(ItemStack stack) + { + return (IDLSkillNBT.getLevel(stack) - 1) * dura_per_level + dura_val; + } + public float getVal(ItemStack stack) + { + return (IDLSkillNBT.getLevel(stack) - 1) * val_per_level + basic_val; + } + public float getCoolDown(ItemStack stack) { + float result = -(IDLSkillNBT.getLevel(stack) - 1) * cool_down_reduce_per_lv + cool_down; + return result > 0.1f ? result : 0.1f; } + + //leveling------------------------------------- + + public int GetLevelMax(ItemStack stack) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return 0; + } + return maxLevel; + } + + public void SendDefaultMsg(EntityPlayer player, ItemStack stack, SKILL_MSG_TYPE msg_type) + { + switch (msg_type) + { + case CD: + CommonFunctions.SendMsgToPlayer((EntityPlayerMP)player, stack.getUnlocalizedName()+ IDLSkillNBT.IN_CD_DESC_KEY); + case SUCCESS: + CommonFunctions.SendMsgToPlayer((EntityPlayerMP)player, stack.getUnlocalizedName()+ IDLSkillNBT.SUCCESS_DESC_KEY); + default: + break; + } + } + + public static void activateCoolDown(EntityPlayer player, ItemStack stack) + { + Item item = stack.getItem(); + if (item instanceof ItemSkillBase) + { + player.getCooldownTracker().setCooldown(stack.getItem(), ((ItemSkillBase) item).GetMaxTick(stack)); + } + } + + public static void notifyCoolingDown(EntityPlayerMP player) + { + CommonFunctions.SendMsgToPlayer(player, "idlframewok.skill.msg.cool_down"); + } + + public static boolean isStackReady(EntityPlayer player, ItemStack stack) + { + return !player.getCooldownTracker().hasCooldown(stack.getItem()); + //return stack.getItemDamage() == 0; + } + + //-------------------------- + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + //stack.setItemDamage(stack.getItemDamage() - 1); + } + + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + if (cannotMouseCast) + { + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } + + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (canCast(worldIn, playerIn, handIn)) + { + tryCast(worldIn, playerIn, handIn); + activateCoolDown(playerIn, stack); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + else { + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + + } + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + public boolean canCast(World worldIn, EntityLivingBase livingBase, EnumHand handIn) + { + if (livingBase instanceof EntityPlayer) + { + isStackReady((EntityPlayer) livingBase, livingBase.getHeldItem(handIn)); + } + return true; + } + + public boolean tryCast(World worldIn, EntityLivingBase livingBase, EnumHand handIn) + { + if (livingBase instanceof EntityPlayer) + { + activateCoolDown((EntityPlayer) livingBase, livingBase.getHeldItem(handIn)); + } + return true; + } + + public boolean onKeyboardCast(EntityLivingBase caster, ItemStack stack, EnumHand hand) + { + World world = caster.world; + boolean casterIsPlayer = caster instanceof EntityPlayer; + if (!casterIsPlayer || isStackReady((EntityPlayer) caster, stack)) { + if (canCast(world, caster, hand)) { + if (hand == EnumHand.MAIN_HAND) { + if (mainHandCast) { + return tryCast(caster.world, caster, hand); + } else { + if (casterIsPlayer) + { + CommonFunctions.SafeSendMsgToPlayer(TextFormatting.RED, (EntityPlayer) caster, MessageDef.NOT_CASTABLE_MAINHAND); + } + else { + IdlFramework.LogWarning("Trying to do invalid cast from a creature: %s", caster.getName()); + } + } + } else if (hand == EnumHand.OFF_HAND) + if (offHandCast) { + return tryCast(caster.world, caster, hand); + }else { + if (casterIsPlayer) + { + CommonFunctions.SafeSendMsgToPlayer(TextFormatting.RED, (EntityPlayer) caster, MessageDef.NOT_CASTABLE_OFFHAND); + } + else { + IdlFramework.LogWarning("Trying to do invalid cast from a creature: %s", caster.getName()); + } + } + } + } + else { + EntityPlayer player = (EntityPlayer) caster; + CommonFunctions.SafeSendMsgToPlayer(TextFormatting.YELLOW, player, MessageDef.IN_COOLDOWN); + } + + return false; + } + + /** + * Returns true if the item can be used on the given entity, e.g. shears on sheep. + */ + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand) { + return false; + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + boolean shiftPressed = !shiftToShowDesc || CommonFunctions.isShiftPressed(); + if (shiftPressed) + { + if (showCDDesc) + tooltip.add(I18n.format("idlframewok.skill.shared.cool_down_desc", getCoolDown(stack))); + if (showDamageDesc && getVal(stack) > 0) + tooltip.add(I18n.format("idlframewok.skill.shared.power_desc", getVal(stack))); + if (showRangeDesc) + tooltip.add(I18n.format("idlframewok.skill.shared.range_desc", getRange(stack))); + if (showDuraDesc) + tooltip.add(GetDuraDescString(getDura(stack))); + + if (maxLevel != 1) + { + tooltip.add(I18n.format("idlframewok.skill.shared.level_desc", IDLSkillNBT.getLevel(stack), maxLevel)); + } + } + } + + @SideOnly(Side.CLIENT) + public String getItemStackDisplayName(ItemStack stack) + { + if (maxLevel == 1) + { + return super.getItemStackDisplayName(stack); + } + +// String strMain =""; +//// if (IsNameHidden(stack)) +//// { +//// strMain = I18n.format(getUnlocalizedName(stack) + IDLNBTDef.TOOLTIP_HIDDEN); +//// +//// } +//// else +// { +// strMain = super.getItemStackDisplayName(stack); +// } + + String strMain = super.getItemStackDisplayName(stack); + int lv = IDLSkillNBT.getLevel(stack); + String strMaxLv = lv == maxLevel ? I18n.format("idlframewok.skill.shared.lv_max") : ""; + + return I18n.format("idlframewok.skill.shared.name_format_with_lv",strMain, IDLSkillNBT.getLevel(stack), strMaxLv); + } + + public String GetDuraDescString(float val) + { + return I18n.format("idlframewok.skill.shared.duration_desc", val); + } + + public void trySayDialogue(EntityLivingBase livingBase, ItemStack stack) + { + if (maxDialogues > 0) + { + int index = livingBase.getRNG().nextInt(maxDialogues); + if (livingBase instanceof EntityPlayer) + { + CommonFunctions.SafeSendMsgToPlayer((EntityPlayer) livingBase, MessageDef.getSkillCastKey(stack, index)); + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBlessedArmor.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBlessedArmor.java new file mode 100644 index 0000000..4efb090 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBlessedArmor.java @@ -0,0 +1,87 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDamageEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemSkillBlessedArmor extends ItemSkillBase { + private float KBPower = 1f; + + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + public boolean isBookEnchantable(ItemStack stack, ItemStack book) + { + return true; + } + + public ItemSkillBlessedArmor(String name) { + super(name); + basic_val = 3f; + showDamageDesc = false; + } + + @SubscribeEvent + public static void onCreatureDamaged(LivingDamageEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + if (evt.getSource() == DamageSource.FALL && hurtOne instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer)hurtOne; + ItemStack stack = AttemptPlayerHand(player, EnumHand.MAIN_HAND); + if (stack == ItemStack.EMPTY) + { + stack = AttemptPlayerHand(player, EnumHand.OFF_HAND); + } + if (stack != ItemStack.EMPTY) + { + ItemSkillBlessedArmor skillThunderFall = ((ItemSkillBlessedArmor)stack.getItem()); + + evt.setAmount(0); + world.playSound(player, player.getPosition(), SoundEvents.BLOCK_NOTE_HARP, SoundCategory.PLAYERS, 1f, 3f); + } + } + } + + public static ItemStack AttemptPlayerHand(EntityPlayer player, EnumHand hand) + { + ItemStack stack = player.getHeldItem(hand); + if (stack.getItem() instanceof ItemSkillBlessedArmor && isStackReady(player, stack)){ + activateCoolDown(player, stack); + return stack; + } + return ItemStack.EMPTY; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { +// ItemStack stack = playerIn.getHeldItem(handIn); +// if (isStackReady(stack )) +// { +// Vec3d basePos = playerIn.getPositionVector(); +// List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); +// for (EntityLiving living: entities +// ) { +// living.setAttackTarget(playerIn); +// } +// playerIn.swingArm(handIn); +// activateCoolDown(stack); +// return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); +// } + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBulletStrike.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBulletStrike.java new file mode 100644 index 0000000..1b3f2f8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillBulletStrike.java @@ -0,0 +1,53 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import com.somebody.idlframewok.entity.projectiles.ProjectileArgs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillBulletStrike extends ItemSkillBase { + public ItemSkillBulletStrike(String name) { + super(name); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + doRangedAttack(playerIn); + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + }else { + playerIn.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1f, 1f); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + protected void doRangedAttack(EntityPlayer caster) + { + World worldObj = caster.world; + + double d1 = caster.getCollisionBorderSize(); + Vec3d vec3d = caster.getLookVec().scale(100); + + EntityIdlProjectile entityBullet = new EntityIdlProjectile(worldObj, new ProjectileArgs(4f), caster, vec3d.x, vec3d.y, vec3d.z, 0.1f); + + entityBullet.posX = caster.getPositionEyes(0f).x + vec3d.x * d1; + entityBullet.posY = caster.getPositionEyes(0f).y + vec3d.y * d1; + entityBullet.posZ = caster.getPositionEyes(0f).z + vec3d.z * d1; + worldObj.spawnEntity(entityBullet); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneBlock.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneBlock.java new file mode 100644 index 0000000..e3cf7b4 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneBlock.java @@ -0,0 +1,56 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemSkillCloneBlock extends ItemSkillBase { + + public ItemSkillCloneBlock(String name) { + super(name); + maxLevel = 12; + setCD(300, 20); + showDamageDesc = false; + } + + /** + * Called when a Block is right-clicked with this Item + */ + @Override + public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + ItemStack stack = player.getHeldItem(hand); + + if (isStackReady(player, stack)) { + World world = player.world; + if (!world.isRemote) { + IBlockState state = world.getBlockState(pos); + + if (state.getBlock().isAir(state, world, pos)) + { + return EnumActionResult.FAIL; + } +// if (isCreative && GuiScreen.isCtrlKeyDown() && state.getBlock().hasTileEntity(state)) +// te = world.getTileEntity(pos); + ItemStack cloneResult = state.getBlock().getPickBlock(state, null, world, pos, player); + if (!cloneResult.isEmpty()) + { + player.addItemStackToInventory(cloneResult); + activateCoolDown(player, stack); + return EnumActionResult.SUCCESS; + } + } + } + return EnumActionResult.FAIL; + } + + @Override + public EnumRarity getRarity(ItemStack stack) { + return EnumRarity.EPIC; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneEgg.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneEgg.java new file mode 100644 index 0000000..1692ee6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillCloneEgg.java @@ -0,0 +1,41 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSkillCloneEgg extends ItemSkillBase { + + public ItemSkillCloneEgg(String name) { + super(name); + maxLevel = 12; + setCD(60, 5); + showDamageDesc = false; + } + + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (isStackReady(playerIn, stack)) { + World world = playerIn.world; + if (!world.isRemote) { + ItemStack cloneResult = target.getPickedResult(null); + if (!cloneResult.isEmpty()) + { + playerIn.addItemStackToInventory(cloneResult); + activateCoolDown(playerIn, stack); + return true; + } + } + } + return false; + } + + @Override + public EnumRarity getRarity(ItemStack stack) { + return EnumRarity.EPIC; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillDecodeItem.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillDecodeItem.java new file mode 100644 index 0000000..029b431 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillDecodeItem.java @@ -0,0 +1,55 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSkillDecodeItem extends ItemSkillBase { + + public ItemSkillDecodeItem(String name) { + super(name); + maxLevel = 10; + setCD(12, 1); + setVal(1, 0.1f); + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote && handIn == EnumHand.MAIN_HAND) + { + //playerIn.setFire(5); + int count = playerIn.getHeldItemOffhand().getCount(); + float xp = (float)count * getVal(stack); + playerIn.addExperience((int) xp); + playerIn.setHeldItem(EnumHand.OFF_HAND, ItemStack.EMPTY); + activateCoolDown(playerIn, stack); + } + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + @Override + public EnumRarity getRarity(ItemStack stack) { + return EnumRarity.RARE; + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc.extra", getVal(stack)); + tooltip.add(mainDesc); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceDamageAbsorption.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceDamageAbsorption.java new file mode 100644 index 0000000..e169d5d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceDamageAbsorption.java @@ -0,0 +1,102 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemSkillExperienceDamageAbsorption extends ItemSkillBase { + + public ItemSkillExperienceDamageAbsorption(String name) { + super(name); + setCD(0.1f, 0); + setVal(2f, -0.5f);//how many xp point 1 damage would cost; + maxLevel = 4; + } + +// @SubscribeEvent +// public static void onCreatureDamaged(LivingDamageEvent evt) { +// if (evt.isCanceled()) +// { +// return; +// } +// +// World world = evt.getEntity().getEntityWorld(); +// EntityLivingBase hurtOne = evt.getEntityLiving(); +// //CrowFlight.Log(String.format("DMG:%s=%f",evt.getEntityLiving(), evt.getAmount())); +// if (hurtOne instanceof EntityPlayer) +// { +// EntityPlayer player = (EntityPlayer)hurtOne; +// ItemStack stack = AttemptPlayerHand(player, EnumHand.MAIN_HAND); +// if (stack == ItemStack.EMPTY) +// { +// stack = AttemptPlayerHand(player, EnumHand.OFF_HAND); +// } +// if (stack != ItemStack.EMPTY) +// { +// ItemSkillExperienceDamageAbsorption skill = ((ItemSkillExperienceDamageAbsorption)stack.getItem()); +// +// float amount = evt.getAmount(); +// float multiplier = skill.getVal(stack); +// int xpCost = (int) (amount * multiplier); +// +// //if (!player.world.isRemote) { +// if (CommonFunctions.TryConsumePlayerXP(player, xpCost)) +// { +// player.playSound(SoundEvents.BLOCK_GLASS_BREAK, 1f, 1f); +// evt.setAmount(0); +// } +// //} +// } +// } +// } + + + public static ItemStack AttemptPlayerHand(EntityPlayer player, EnumHand hand) + { + ItemStack stack = player.getHeldItem(hand); + if (stack.getItem() instanceof ItemSkillExperienceDamageAbsorption && isStackReady(player, stack)){ + activateCoolDown(player, stack); + return stack; + } + return ItemStack.EMPTY; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { +// ItemStack stack = playerIn.getHeldItem(handIn); +// if (isStackReady(stack )) +// { +// Vec3d basePos = playerIn.getPositionVector(); +// List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); +// for (EntityLiving living: entities +// ) { +// living.setAttackTarget(playerIn); +// } +// playerIn.swingArm(handIn); +// activateCoolDown(stack); +// return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); +// } + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } + + //Desc + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + String mainDesc = I18n.format(stack.getUnlocalizedName() + ".desc", getVal(stack)); + tooltip.add(mainDesc); + tooltip.add(I18n.format("idlframewok.skill.shared.cool_down_desc", getCoolDown(stack))); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperiencePrideShield.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperiencePrideShield.java new file mode 100644 index 0000000..6f99143 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperiencePrideShield.java @@ -0,0 +1,92 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDamageEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemSkillExperiencePrideShield extends ItemSkillBase { + + public ItemSkillExperiencePrideShield(String name) { + super(name); + setCD(0.1f, 0); + maxLevel = 1; + showCDDesc = false; + //setVal(2f, -0.5f);//how many xp point 1 damage would cost; + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void onCreatureDamaged(LivingDamageEvent evt) { + if (evt.isCanceled()) + { + return; + } + EntityLivingBase hurtOne = evt.getEntityLiving(); + //CrowFlight.Log(String.format("DMG:%s=%f",evt.getEntityLiving(), evt.getAmount())); + if (hurtOne instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer)hurtOne; + ItemStack stack = AttemptPlayerHand(player, EnumHand.MAIN_HAND); + if (stack == ItemStack.EMPTY) + { + stack = AttemptPlayerHand(player, EnumHand.OFF_HAND); + } + if (stack != ItemStack.EMPTY) + { + ItemSkillExperiencePrideShield skill = ((ItemSkillExperiencePrideShield)stack.getItem()); + + float amount = evt.getAmount(); + if (!player.world.isRemote) { + if (player.experienceLevel >= amount) + { + player.playSound(SoundEvents.BLOCK_GLASS_BREAK, 1f, 1f); + evt.setCanceled(true); + } + else { + evt.setAmount(amount * 2); + //player.experienceLevel -= 1; + } + } + } + } + } + + + public static ItemStack AttemptPlayerHand(EntityPlayer player, EnumHand hand) + { + ItemStack stack = player.getHeldItem(hand); + if (stack.getItem() instanceof ItemSkillExperiencePrideShield && isStackReady(player, stack)){ + activateCoolDown(player, stack); + return stack; + } + return ItemStack.EMPTY; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { +// ItemStack stack = playerIn.getHeldItem(handIn); +// if (isStackReady(stack )) +// { +// Vec3d basePos = playerIn.getPositionVector(); +// List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); +// for (EntityLiving living: entities +// ) { +// living.setAttackTarget(playerIn); +// } +// playerIn.swingArm(handIn); +// activateCoolDown(stack); +// return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); +// } + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceStrike.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceStrike.java new file mode 100644 index 0000000..c494579 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillExperienceStrike.java @@ -0,0 +1,37 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSkillExperienceStrike extends ItemSkillBase { + public ItemSkillExperienceStrike(String name) { + super(name); + setCD(2f,0.5f); + maxLevel = 3; + showDamageDesc = false; + showCDDesc = true; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + World world = playerIn.world; + if (!world.isRemote) + { + DamageSource damageSource = DamageSource.causePlayerDamage(playerIn).setMagicDamage(); + if (target.getHealth() < playerIn.experienceLevel) + { + damageSource.setDamageBypassesArmor(); + } + target.attackEntityFrom(damageSource, playerIn.experienceLevel); + } + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1f, 1f); + return true; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBall.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBall.java new file mode 100644 index 0000000..3cb2db8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBall.java @@ -0,0 +1,69 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.entity.projectile.EntitySmallFireball; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillFireBall extends ItemSkillBase { + public float KBPower = 1f; + public boolean useSmall = true; + public ItemSkillFireBall(String name) { + super(name); + } + + public ItemSkillFireBall setIsSmallFireBall(boolean val) + { + useSmall = val; + return this; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + doRangedAttack(playerIn); + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + }else { + playerIn.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1f, 1f); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + protected void doRangedAttack(EntityPlayer caster) + { + World worldObj = caster.world; + ItemStack stack = caster.getHeldItemMainhand(); + + double d1 = caster.getCollisionBorderSize(); + Vec3d vec3d = caster.getLookVec().scale(10); + + EntityFireball entityBullet; + if (useSmall) { + entityBullet = new EntitySmallFireball(worldObj, caster, vec3d.x, vec3d.y, vec3d.z); + } else { + entityBullet = new EntityLargeFireball(worldObj, caster,vec3d.x, vec3d.y, vec3d.z); + ((EntityLargeFireball)entityBullet).explosionPower = (int)getVal(stack); + } + + entityBullet.posX = caster.getPositionEyes(0f).x + vec3d.x * d1; + entityBullet.posY = caster.getPositionEyes(0f).y + vec3d.y * d1; + entityBullet.posZ = caster.getPositionEyes(0f).z + vec3d.z * d1; + worldObj.spawnEntity(entityBullet); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBlast.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBlast.java new file mode 100644 index 0000000..0c40ab6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillFireBlast.java @@ -0,0 +1,65 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillFireBlast extends ItemSkillBase { + public float KBPower = 0.01f; + public ItemSkillFireBlast(String name) { + super(name); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack))//mostly always ready + { + //IdlFramework.Log("Trigg'd:" + worldIn.getWorldTime()); + if (!worldIn.isRemote) + { + ItemSkillFireBlast skillThunderFall = ((ItemSkillFireBlast)stack.getItem()); + + Vec3d basePos = playerIn.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); + for (EntityLiving living: entities + ) { + living.attackEntityFrom(DamageSource.causePlayerDamage(playerIn).setFireDamage().setMagicDamage(), getVal(stack)); + //make sure it's not 0 0 ratio, or the target vanishes + living.knockBack(playerIn, skillThunderFall.KBPower, (playerIn.posX - living.posX), (playerIn.posZ - living.posZ)); + living.setFire((int)getVal(stack)); + } + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + }else { + playerIn.world.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, playerIn.posX, playerIn.posY, playerIn.posZ, 1.0D, 0.0D, 0.0D); + playerIn.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1f, 1f); + } + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } +// else { +// //wont run here in cool down. +// if (playerIn instanceof EntityPlayerMP) +// { +// notifyCoolingDown((EntityPlayerMP)playerIn); +// IdlFramework.Log("notified"); +// } +// else { +// IdlFramework.Log("wrong type"); +// } +// return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); +// } + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillGambit.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillGambit.java new file mode 100644 index 0000000..54cc555 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillGambit.java @@ -0,0 +1,47 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.Random; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; + +public class ItemSkillGambit extends ItemSkillBase { + + public ItemSkillGambit(String name) { + super(name); + maxLevel = 1; + setCD(1,0); + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote && handIn == EnumHand.MAIN_HAND) + { + Random rand = playerIn.getRNG(); + if (playerIn.getRNG().nextBoolean()) + { + playerIn.setHeldItem(EnumHand.OFF_HAND, ItemStack.EMPTY); + worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.BLOCK_GLASS_BREAK, SoundCategory.PLAYERS, 1f, 3f); + } + else { + playerIn.addItemStackToInventory(playerIn.getHeldItemOffhand().copy()); + worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.BLOCK_PISTON_CONTRACT, SoundCategory.PLAYERS, 1f, 3f); +// worldIn.spawnParticle(EnumParticleTypes.FIREWORKS_SPARK, playerIn.posX, playerIn.posY - 0.3D, playerIn.posZ, +// rand.nextGaussian() * 0.05D, -playerIn.motionY * 0.5D, rand.nextGaussian() * 0.05D); + } + + + activateCoolDown(playerIn, stack); + } + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillModListStrike.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillModListStrike.java new file mode 100644 index 0000000..bd14a14 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillModListStrike.java @@ -0,0 +1,55 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.meta.MetaUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSkillModListStrike extends ItemSkillBase { + public ItemSkillModListStrike(String name) { + super(name); + setCD(1f,0f); + showDamageDesc = false; + showCDDesc = true; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + World world = playerIn.world; + if (!world.isRemote) + { + DamageSource damageSource = DamageSource.causePlayerDamage(playerIn).setMagicDamage(); + + damageSource.setDamageBypassesArmor(); + + target.attackEntityFrom(damageSource, MetaUtil.GetModCount()); + } + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1f, 1f); + return true; + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + String mainDesc = I18n.format(key, Loader.instance().getActiveModList().size()); + return mainDesc; + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillRepairArmor.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillRepairArmor.java new file mode 100644 index 0000000..06580be --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillRepairArmor.java @@ -0,0 +1,86 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; + +public class ItemSkillRepairArmor extends ItemSkillBase { + public ItemSkillRepairArmor(String name) { + super(name); + } + + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + public boolean isBookEnchantable(ItemStack stack, ItemStack book) + { + return true; + } + + + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + ItemStack heldItem = playerIn.getHeldItem(handIn); + NBTTagList nbttaglist = heldItem.getEnchantmentTagList(); + + boolean used = false; + for (EntityEquipmentSlot slot: + EntityEquipmentSlot.values()){ + + if (slot == EntityEquipmentSlot.MAINHAND || slot == EntityEquipmentSlot.OFFHAND) + { + continue;//only repairs armor + } + + ItemStack itemstack1 = playerIn.getItemStackFromSlot(slot); + + //fix and enchant existing armor + if (!itemstack1.isEmpty()) + { + if (!playerIn.world.isRemote) + { + //Fix Dura + CommonFunctions.RepairItem(itemstack1, (int) getVal(heldItem)); + + //Copy Enchantment + for (int j = 0; j < nbttaglist.tagCount(); ++j) + { + NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(j); + int k = nbttagcompound.getShort("layer"); + int l = nbttagcompound.getShort("lvl"); + Enchantment enchantment = Enchantment.getEnchantmentByID(k); + + if (enchantment != null) + { + itemstack1.addEnchantment(enchantment, l); + } + } + } + used = true; + } + } + + if (used) + { + activateCoolDown(playerIn, heldItem); + worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.BLOCK_NOTE_HARP, SoundCategory.PLAYERS, 1f, 3f); + return new ActionResult(EnumActionResult.SUCCESS, heldItem); + } + else + { + return new ActionResult(EnumActionResult.FAIL, heldItem); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSacrifce2020.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSacrifce2020.java new file mode 100644 index 0000000..ef2e008 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSacrifce2020.java @@ -0,0 +1,58 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillSacrifce2020 extends ItemSkillBase { + public ItemSkillSacrifce2020(String name) { + super(name); + cool_down = 50f; + maxLevel = 1; + showDamageDesc = false; + + setRange(32, 32); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + Vec3d basePos = playerIn.getPositionVector(); + float range = getRange(stack); + List entities = worldIn.getEntitiesWithinAABB(EntityPlayer.class, IDLGeneral.ServerAABB(basePos.addVector(-range, -range, -range), basePos.addVector(range, range, range))); + for (EntityPlayer living: entities + ) { + if (living != playerIn) + { + EntityUtil.TryRemoveDebuff(living); + living.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, CommonDef.TICK_PER_SECOND * 5, 0)); + living.heal(living.getMaxHealth()); + } + } + + playerIn.addPotionEffect(new PotionEffect(MobEffects.POISON, CommonDef.TICK_PER_SECOND * 60, 0)); + playerIn.setHealth(1f); + activateCoolDown(playerIn, stack); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSheepTransform.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSheepTransform.java new file mode 100644 index 0000000..6740673 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillSheepTransform.java @@ -0,0 +1,52 @@ +package com.somebody.idlframewok.item.skills; + +import com.somebody.idlframewok.util.CommonFunctions; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.passive.EntitySheep; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; + +public class ItemSkillSheepTransform extends ItemSkillBase { + public ItemSkillSheepTransform(String name) { + super(name); + setCD(30f, 5f); + showDamageDesc = false; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (isStackReady(playerIn, stack)) + { + World world = playerIn.world; + if (!world.isRemote) + { + if ((target instanceof EntityLiving)) + { + EntitySheep elk = new EntitySheep(world); + elk.setPosition(target.posX,target.posY,target.posZ); + + CommonFunctions.CopyNormalAttr(target, elk); + + target.setDead(); + + world.spawnEntity(elk); + world.spawnParticle(EnumParticleTypes.MOB_APPEARANCE, target.posX, target.posY, target.posZ, 0,0,0); + world.playSound(null, target.getPosition(), SoundEvents.ENTITY_WITCH_AMBIENT, SoundCategory.PLAYERS,1f,1f); + //TryGrantAchv(playerIn, AchvDef.ELK_TRANSFORM); + } + } + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ENTITY_SHEEP_AMBIENT, 1f, 1f); + return true; + } + + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearby.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearby.java new file mode 100644 index 0000000..9638c3a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearby.java @@ -0,0 +1,44 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemSkillTauntNearby extends ItemSkillBase { + public ItemSkillTauntNearby(String name) { + super(name); + showRangeDesc = true; + showCDDesc = false; + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + Vec3d basePos = playerIn.getPositionVector(); + List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); + for (EntityLiving living: entities + ) { + living.setAttackTarget(playerIn); + } + worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.BLOCK_NOTE_HARP, SoundCategory.PLAYERS, 1f, 3f); + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearbyToGiven.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearbyToGiven.java new file mode 100644 index 0000000..4c659dc --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTauntNearbyToGiven.java @@ -0,0 +1,44 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; + +public class ItemSkillTauntNearbyToGiven extends ItemSkillBase { + public ItemSkillTauntNearbyToGiven(String name) { + super(name); + cool_down = 50f; + base_range = 10f; + range_per_level = 10f; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (isStackReady(playerIn, stack)) + { + Vec3d basePos = playerIn.getPositionVector(); + List entities = playerIn.world.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-getRange(stack), -getRange(stack), -getRange(stack)), + basePos.addVector(getRange(stack), getRange(stack), getRange(stack)))); + for (EntityLiving living: entities + ) { + if (living != target) + { + living.setAttackTarget(target); + } + } + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ENTITY_POLAR_BEAR_WARNING, 1f, 1f); + return true; + } + + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillThunderFall.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillThunderFall.java new file mode 100644 index 0000000..e5f4705 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillThunderFall.java @@ -0,0 +1,100 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDamageEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemSkillThunderFall extends ItemSkillBase { + private float KBPower = 1f; + + public ItemSkillThunderFall(String name) { + super(name); + maxLevel = 1; + basic_val = 3f; + showCDDesc = true; + } + + @SubscribeEvent + public static void onCreatureDamaged(LivingDamageEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + //CrowFlight.Log(String.format("DMG:%s=%f",evt.getEntityLiving(), evt.getAmount())); + if (evt.getSource() == DamageSource.FALL && hurtOne instanceof EntityPlayer) + { + //IdlFramework.Log("player Falling"); + EntityPlayer player = (EntityPlayer)hurtOne; + ItemStack stack = AttemptPlayerHand(player, EnumHand.MAIN_HAND); + if (stack == ItemStack.EMPTY) + { + stack = AttemptPlayerHand(player, EnumHand.OFF_HAND); + } + if (stack != ItemStack.EMPTY) + { + ItemSkillThunderFall skillThunderFall = ((ItemSkillThunderFall)stack.getItem()); + + float amount = evt.getAmount(); + float multiplier = skillThunderFall.getVal(stack); + float range = skillThunderFall.getRange(stack); + + if (!player.world.isRemote) { + Vec3d mypos = player.getPositionEyes(0f); + player.playSound(SoundEvents.ENTITY_LIGHTNING_IMPACT, 1f, 1f); + //Damage nearby entities + List list = player.world.getEntitiesWithinAABB(EntityLivingBase.class, IDLGeneral.ServerAABB(mypos.addVector(-range, -range - hurtOne.getEyeHeight(), -range), mypos.addVector(range, range, range))); + for (EntityLivingBase creature : list) { + if (creature != hurtOne) { + if (creature.attackEntityFrom(DamageSource.ANVIL, multiplier * amount)) { + creature.knockBack(player, skillThunderFall.KBPower, (player.posX - creature.posX), (player.posZ - creature.posZ)); + } + } + } + } + + evt.setAmount(0); + } + } + } + + public static ItemStack AttemptPlayerHand(EntityPlayer player, EnumHand hand) + { + ItemStack stack = player.getHeldItem(hand); + if (stack.getItem() instanceof ItemSkillThunderFall && isStackReady(player, stack)){ + activateCoolDown(player, stack); + return stack; + } + return ItemStack.EMPTY; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { +// ItemStack stack = playerIn.getHeldItem(handIn); +// if (isStackReady(stack )) +// { +// Vec3d basePos = playerIn.getPositionVector(); +// List entities = worldIn.getEntitiesWithinAABB(EntityLiving.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); +// for (EntityLiving living: entities +// ) { +// living.setAttackTarget(playerIn); +// } +// playerIn.swingArm(handIn); +// activateCoolDown(stack); +// return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); +// } + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutFixed.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutFixed.java new file mode 100644 index 0000000..2c10a66 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutFixed.java @@ -0,0 +1,61 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSkillTimeCutFixed extends ItemSkillBase { + + public ItemSkillTimeCutFixed(String name) { + super(name); + maxLevel = 5; + setCD(20,0); + setVal(1f, 0.5f); + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote && handIn == EnumHand.MAIN_HAND) + { + Item itemToSet = playerIn.getHeldItemOffhand().getItem(); + + float cut = getVal(stack); + if (itemToSet != Items.AIR && playerIn.getCooldownTracker().getCooldown(itemToSet, 0f) > 0) + { + float cd = playerIn.getCooldownTracker().getCooldown(itemToSet, 0f); + playerIn.getCooldownTracker().setCooldown(itemToSet, (int) (cd - cut)); + activateCoolDown(playerIn, stack); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + } + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + String mainDesc = I18n.format(key, getVal(stack)); + return mainDesc; + } + return ""; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutPercent.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutPercent.java new file mode 100644 index 0000000..32aa202 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillTimeCutPercent.java @@ -0,0 +1,60 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSkillTimeCutPercent extends ItemSkillBase { + + public ItemSkillTimeCutPercent(String name) { + super(name); + maxLevel = 9; + setCD(20,0); + setVal(0.9f, -0.1f); + showDamageDesc = false; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + + if (!worldIn.isRemote && handIn == EnumHand.MAIN_HAND) + { + Item itemToSet = playerIn.getHeldItemOffhand().getItem(); + + float factor = getVal(stack); + if (itemToSet != Items.AIR && playerIn.getCooldownTracker().getCooldown(itemToSet, 0f) > 0) + { + float cd = playerIn.getCooldownTracker().getCooldown(itemToSet, 0f); + playerIn.getCooldownTracker().setCooldown(itemToSet, (int) (cd * factor)); + activateCoolDown(playerIn, stack); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + } + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + String mainDesc = I18n.format(key, 100f - getVal(stack) * 100f); + return mainDesc; + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillVanquishWeak.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillVanquishWeak.java new file mode 100644 index 0000000..5da2cc1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillVanquishWeak.java @@ -0,0 +1,34 @@ +package com.somebody.idlframewok.item.skills; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; + +public class ItemSkillVanquishWeak extends ItemSkillBase { + public ItemSkillVanquishWeak(String name) { + super(name); + cool_down = 5f; + setVal(15,5f); + setCD(1f, 0.1f); + maxLevel = 25565; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (target.getHealth() < getVal(stack)) + { + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + target.playSound(SoundEvents.ENTITY_POLAR_BEAR_WARNING, 1f, 1f); + target.setDead(); + return true; + } + else { + return false; + } + + + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillWindWalk.java b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillWindWalk.java new file mode 100644 index 0000000..ddee1b0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/ItemSkillWindWalk.java @@ -0,0 +1,51 @@ +package com.somebody.idlframewok.item.skills; + +import java.util.List; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSkillWindWalk extends ItemSkillBase { + public ItemSkillWindWalk(String name) { + super(name); + cool_down = 50f; + maxLevel = 4; + showDamageDesc = false; + setVal(20,5); + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + playerIn.addPotionEffect(new PotionEffect(MobEffects.SPEED, (int)(getVal(stack) * CommonDef.TICK_PER_SECOND), IDLSkillNBT.getLevel(stack) - 1)); + playerIn.playSound(SoundEvents.BLOCK_NOTE_HARP, 1f, 3f); + activateCoolDown(playerIn, stack); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + + @Override + public void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + super.addInformation(stack, world, tooltip, flag); + tooltip.add(GetDuraDescString(getVal(stack))); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemArknightsSkillBase.java b/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemArknightsSkillBase.java new file mode 100644 index 0000000..ae524cb --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemArknightsSkillBase.java @@ -0,0 +1,238 @@ +package com.somebody.idlframewok.item.skills.arknights; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +public class ItemArknightsSkillBase extends ItemSkillBase { + + protected int[] dura = {10}; + //int[] cd = {90}; + protected int[] initPower = {0}; + + protected int[] max_charge = {5}; + + boolean isAutoCharge = true; + + public ItemArknightsSkillBase(String name) { + super(name); + CommonFunctions.addToEventBus(this); + } + + @Override + public int getMaxDamage(ItemStack stack) { + return 100; + } + + public float getInitPower(ItemStack stack) + { + int level = IDLSkillNBT.getLevel(stack) - 1; + + if (level < 0){ + return initPower[0]; + } + else if(level >= initPower.length) + { + return initPower[initPower.length - 1]; + } + + return initPower[level]; + } + + public float getDurationMax(ItemStack stack) + { + int level = IDLSkillNBT.getLevel(stack) - 1; + + if (level < 0){ + return dura[0]; + } + else if(level >= dura.length) + { + return dura[dura.length - 1]; + } + + return dura[level]; + } + + public float getChargeMax(ItemStack stack) + { + int level = IDLSkillNBT.getLevel(stack) - 1; + + if (level < 0){ + return max_charge[0]; + } + else if(level >= max_charge.length) + { + return max_charge[max_charge.length - 1]; + } + + return max_charge[level]; + } + + @Override + public float getCoolDown(ItemStack stack) { + return getChargeMax(stack); + } + + @Override + public float getDura(ItemStack stack) { + return getDurationMax(stack); + } + + public void upkeep(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) + { + if (worldIn.isRemote || worldIn.getWorldTime() % CommonDef.TICK_PER_SECOND != 0) + { + return; + } + + if (entityIn instanceof EntityPlayer) + { + boolean casting = IDLSkillNBT.IsCasting(stack); + EntityPlayer player = (EntityPlayer) entityIn; + player.getCooldownTracker().setCooldown(stack.getItem(), casting ? 3600 : 0); + if (casting) + { + float dura = IDLSkillNBT.GetDura(stack); + if (worldIn.getWorldTime() % CommonDef.TICK_PER_SECOND == 0) + { + dura -= 1f; + } + + if (dura <= 0) + { + dura = 0; + IDLSkillNBT.SetCasting(stack, false); + activateCoolDownArknights(stack); + IdlFramework.Log("%s casting complete.", entityIn); + } + + IDLSkillNBT.SetDura(stack, dura); + } + else { + if (isAutoCharge) + { + float charge = IDLSkillNBT.GetCharge(stack); + float curMaxCharge = getChargeMax(stack); + + if (charge >= curMaxCharge) + { + if (charge > curMaxCharge) + { + charge = curMaxCharge; + IDLSkillNBT.SetCharge(stack, curMaxCharge); + } + } + else { + charge += 1f; + IDLSkillNBT.SetCharge(stack, charge); + } + } + } + + if (casting) + { + stack.setItemDamage((int) ((1 - IDLSkillNBT.GetDura(stack) / getDurationMax(stack)) * getMaxDamage(stack))); + }else { + stack.setItemDamage((int) ((1 - IDLSkillNBT.GetCharge(stack) / getChargeMax(stack)) * getMaxDamage(stack))); + } + } + } + + public void activateCoolDownArknights(ItemStack stack) + { + Item item = stack.getItem(); + if (item instanceof ItemSkillBase) + { + IDLSkillNBT.SetCasting(stack, false); + IDLSkillNBT.SetCharge(stack, 0); + } + } + + @Override + public boolean canCast(World worldIn, EntityLivingBase livingBase, EnumHand handIn) { + ItemStack stack = livingBase.getHeldItem(handIn); + + boolean casting = IDLSkillNBT.IsCasting(stack); + if (casting) + { + return false; + } + + float charge = IDLSkillNBT.GetCharge(stack); + float curMaxCharge = getChargeMax(stack); + + if (charge >= curMaxCharge) + { + return super.canCast(worldIn, livingBase, handIn); + } + else { + return false; + } + } + + @Override + public boolean tryCast(World worldIn, EntityLivingBase livingBase, EnumHand handIn) { + + ItemStack stack = livingBase.getHeldItem(handIn); + IDLSkillNBT.SetCasting(stack, true); + IDLSkillNBT.SetCharge(stack, 0); + IDLSkillNBT.SetDura(stack, getDurationMax(stack)); + trySayDialogue(livingBase, stack); + + return true; + } + + @Override + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected); + upkeep(stack, worldIn, entityIn, itemSlot, isSelected); + } + + public void tryToInitializeCharge(EntityPlayer player) + { + for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + ItemStack itemstack = player.inventory.getStackInSlot(i); + { + if (itemstack.getItem() == this) + { + if (!IDLSkillNBT.IsCasting(itemstack)) + { + float power = getInitPower(itemstack); + IDLSkillNBT.SetCharge(itemstack, power); + } + } + } + } + } + + @SubscribeEvent + public void onLogIn(PlayerEvent.PlayerLoggedInEvent event) + { + if (!event.player.world.isRemote) + tryToInitializeCharge(event.player); + } + + @SubscribeEvent + public void onDeath(LivingDeathEvent event) + { + if (event.getEntityLiving() instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer) event.getEntityLiving(); + if (!player.world.isRemote) + tryToInitializeCharge(player); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemSkillTrueSL.java b/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemSkillTrueSL.java new file mode 100644 index 0000000..9bb697f --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/arknights/ItemSkillTrueSL.java @@ -0,0 +1,164 @@ +package com.somebody.idlframewok.item.skills.arknights; + +import java.util.List; +import java.util.UUID; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.CommonFunctions; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSkillTrueSL extends ItemArknightsSkillBase { + + private UUID uuid = UUID.fromString("a7d91a0a-3922-4467-a114-f476ca4daf3e"); + private float range = 3.5f * CommonDef.METER_PER_BLOCK; + + private double defReduce = -0.7; + double[] atkPlus = {1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.6, 1.8, 2.0}; + + private int[] atkCount = {3,3,3,4,4,4,5,5,5,6}; + + public ItemSkillTrueSL(String name) { + super(name); + setRange(range,0); + offHandCast = true; + cannotMouseCast = true; + maxDialogues = 4; + maxLevel = 10; + + dura = new int[]{20, 21, 22, 23, 24, 25, 26, 27, 28, 30}; + max_charge = new int[]{90}; + //max_charge = new int[]{3}; + initPower = new int[]{50, 50, 50, 55, 55, 55, 60, 65, 70, 75}; + showDuraDesc = true; + CommonFunctions.addToEventBus(this); + } + + + + @Override + public int getMaxDamage(ItemStack stack) { + return 100; + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + boolean isOn = IDLSkillNBT.IsCasting(stack); + + if (isOn && equipmentSlot == EntityEquipmentSlot.OFFHAND) + { + int level = IDLSkillNBT.getLevel(stack) - 1; + //in arknights, the modifier is type 1, but it makes no sense for players. + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(uuid, "Truesilver Slash Modifier", atkPlus[level], 2)); + multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(uuid, "Truesilver Slash Modifier", defReduce, 2)); + } + + return multimap; + } + + @Override + public void onMouseFire(EntityPlayer player) { + ItemStack stack = player.getHeldItemOffhand(); + if (stack.getItem() == this) + { + if (IDLSkillNBT.IsCasting(stack) && player.getCooledAttackStrength(0f) >= 0.99f) + { + playerSlash(player, IDLSkillNBT.getLevel(stack) - 1); + } + } + } + + public void playerSlash(EntityPlayer player, int level) + { + World world = player.world; + if (world.isRemote) + { + float scaleFactor = 2f; + + //create particle + Vec3d forward = player.getForward().scale(scaleFactor); + + double fx = forward.x; + double fy = forward.y; + double fz = forward.z; + + Vec3d right = forward.crossProduct(new Vec3d(0,1,0)).normalize().scale(scaleFactor); + + double rx = right.x; + double ry = right.y; + double rz = right.z; + + int max = 3; + for (int z = 0; z <= max; z++) + { + for (int x = - (max - z); x <= max - z; x++) + { + world.spawnParticle(EnumParticleTypes.SWEEP_ATTACK, + player.posX + fx * z + rx * x, + player.posY + player.getEyeHeight() + fy * z + ry * x, + player.posZ + fz * z + rz * x, + player.getForward().x, + player.getForward().y, + player.getForward().z); + } + } + + }else { + int targetLeft = atkCount[level]; + + Vec3d basePos = player.getPositionVector(); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, IDLGeneral.ServerAABB(basePos.addVector(-base_range, -base_range, -base_range), basePos.addVector(base_range, base_range, base_range))); + for (EntityLivingBase living: entities + ) { + if (EntityUtil.getAttitude(player, living) == EntityUtil.ATTITUDE.HATE) + { + boolean isForwad = player.getForward().dotProduct(living.getPositionVector().subtract(player.getPositionVector())) >= 0; + if (isForwad) + { + living.attackEntityFrom(DamageSource.causePlayerDamage(player), (float) EntityUtil.getAttack(player)); + targetLeft--; + if (targetLeft <= 0) + { + break; + } + } + else { + IdlFramework.Log("%s is not in front"); + } + } + } + } + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + int level = IDLSkillNBT.getLevel(stack) - 1; + String mainDesc = I18n.format(key, (int)(defReduce * 100f) , (int)(atkPlus[level] * 100f), atkCount[level]); + return mainDesc; + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/arrowrain/ItemSkillArrowRainBase.java b/src/main/java/com/somebody/idlframewok/item/skills/arrowrain/ItemSkillArrowRainBase.java new file mode 100644 index 0000000..114e19a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/arrowrain/ItemSkillArrowRainBase.java @@ -0,0 +1,75 @@ +package com.somebody.idlframewok.item.skills.arrowrain; + +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityTippedArrow; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class ItemSkillArrowRainBase extends ItemSkillBase { + public float KBPower = 1f; + public boolean useSmall = true; + public ItemSkillArrowRainBase(String name) { + super(name); + } + + public ItemSkillArrowRainBase setIsSmallFireBall(boolean val) + { + useSmall = val; + return this; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (isStackReady(playerIn, stack)) + { + if (!worldIn.isRemote) + { + //doRangedAttack(playerIn); + playerIn.swingArm(handIn); + activateCoolDown(playerIn, stack); + }else { + playerIn.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1f, 1f); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + return new ActionResult<>(EnumActionResult.FAIL, playerIn.getHeldItem(handIn)); + } + + protected EntityArrow getArrow(float p_190726_1_, EntityLivingBase shooter) + { + EntityTippedArrow entitytippedarrow = new EntityTippedArrow(shooter.world, shooter); + entitytippedarrow.setEnchantmentEffectsFromEntity(shooter, p_190726_1_); + return entitytippedarrow; + } + + public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor, EntityLivingBase shooter) { + //EntityMoroonBullet entityArrow = new EntityMoroonBullet(world, new ProjectileArgs((float) this.getEntityAttribute(ATTACK_DAMAGE).getAttributeValue())); + EntityArrow entityArrow = getArrow(distanceFactor, shooter); + double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D; + double d1 = target.posX - shooter.posX; + double d2 = d0 - entityArrow.posY; + double d3 = target.posZ - shooter.posZ; + float f = MathHelper.sqrt(d1 * d1 + d3 * d3) * 0.2F; + entityArrow.shoot(d1, d2 + (double)f, d3, 1.6F, 12.0F); + double damage = shooter.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); + if (target.isSneaking()) + { + damage /= 5f; + } + entityArrow.setDamage(shooter.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue()); + shooter.playSound(SoundEvents.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (shooter.getRNG().nextFloat() * 0.4F + 0.8F)); + shooter.world.spawnEntity(entityArrow); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/martial/BuffTuple.java b/src/main/java/com/somebody/idlframewok/item/skills/martial/BuffTuple.java new file mode 100644 index 0000000..122249e --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/martial/BuffTuple.java @@ -0,0 +1,12 @@ +package com.somebody.idlframewok.item.skills.martial; + +public class BuffTuple +{ + public int tick; + public int power; + + public BuffTuple(int power, int tick) { + this.tick = tick; + this.power = power; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillGuaPalm.java b/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillGuaPalm.java new file mode 100644 index 0000000..b645349 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillGuaPalm.java @@ -0,0 +1,211 @@ +package com.somebody.idlframewok.item.skills.martial; + +import java.util.List; + +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.util.IDLSkillNBT; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.effect.EntityLightningBolt; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EntityDamageSource; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ItemSkillGuaPalm extends ItemSkillMartialAttack implements IGuaEnhance { + public float earthModifier = 0.02f; + + public ItemSkillGuaPalm(String name) { + super(name); + maxLevel = 1; + setCD(2f,0); + showGuaSocketDesc = true; + shiftToShowDesc = true; + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (isStackReady(playerIn, stack)) + { + OnHit(stack, playerIn, target, handIn); + if (!playerIn.world.isRemote) + { + activateCoolDown(playerIn, stack); + } + return true; + } + return false; + } + + public DamageSource GetDamageSource(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + return new EntityDamageSource("martial", playerIn); + } + + @Override + public float getVal(ItemStack stack) { + return super.getVal(stack) + IDLSkillNBT.GetGuaEnhance(stack,5) + IDLSkillNBT.GetGuaEnhance(stack,1); + } + + //Gua + //Sky 7 + public float getCoolDown(ItemStack stack) { + float skyModifier = 0.1f; + float result = cool_down - IDLSkillNBT.GetGuaEnhance(stack, 7) * skyModifier; + return result > 0.1f ? result : 0.1f; + } + + //Earth 0 + @SubscribeEvent + public static void onCreatureHurt(LivingHurtEvent evt) { + + if (evt.isCanceled()) + { + return; + } + + World world = evt.getEntity().getEntityWorld(); + if (!world.isRemote) { + EntityLivingBase hurtOne = evt.getEntityLiving(); + + if (hurtOne instanceof EntityPlayer) { + EntityPlayer player = (EntityPlayer) hurtOne; + ItemStack stack = player.getHeldItemMainhand(); + if (stack.getItem() instanceof ItemSkillGuaPalm) + { + ItemSkillGuaPalm palm = (ItemSkillGuaPalm) stack.getItem(); + float dmg = evt.getAmount(); + //IdlFramework.Log("Damage reduct: %f -> %f", dmg, (1f - GetGuaEnhance(stack,0) * palm.earthModifier) * dmg); + evt.setAmount((1f - IDLSkillNBT.GetGuaEnhance(stack,0) * palm.earthModifier) * dmg); + } + } + } + } + + float windModifier = 0.1f; + //6 wind + public float getKBPower(ItemStack stack) + { + return 0.4f + windModifier * IDLSkillNBT.GetGuaEnhance(stack, 6); + } + + public void OnHitBasic(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + if (!playerIn.world.isRemote) { + float dmg = 0; + int fire = IDLSkillNBT.GetGuaEnhance(stack, 5); + int thunder = IDLSkillNBT.GetGuaEnhance(stack, 1); + dmg = fire + (target.isWet() ? thunder * 2 : thunder); + + if (target.attackEntityFrom(GetDamageSource(stack, playerIn, target, handIn), dmg)) + { + //wind + target.knockBack(playerIn, getKBPower(stack), (playerIn.posX - target.posX), (playerIn.posZ - target.posZ)); + + //fire + target.setFire(fire); + + //thunder + if (thunder >= 8) + { + playerIn.world.addWeatherEffect(new EntityLightningBolt(playerIn.world, target.posX, target.posY, target.posZ, false)); + } + + playerIn.swingArm(handIn); + if (interrupts) { + if (target instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer) target; + ItemStack inHand = player.getHeldItemMainhand(); + if (inHand.getItem() != null && inHand.getItem() instanceof ItemSkillBase) + { + ItemSkillBase.activateCoolDown(player, inHand); + } + } + } + } + + } + } + + public void OnHitExtra(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + int mountain = IDLSkillNBT.GetGuaEnhance(stack, 4); + int water = IDLSkillNBT.GetGuaEnhance(stack, 2); + int lake = IDLSkillNBT.GetGuaEnhance(stack, 3); + + if (mountain > 0) + { + target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, CommonDef.TICK_PER_SECOND * mountain * 2, mountain / 4)); + } + + if (water > 0) + { + target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, CommonDef.TICK_PER_SECOND * water * 2, water / 4)); + target.extinguish(); + } + + if (lake > 0) + { + target.heal(lake); + playerIn.heal(lake); + } + } + + @Override + public boolean acceptGuaIndex(int index) { + return true; + } + + public BuffTuple GetWaterBuff(ItemStack stack) + { + int water = IDLSkillNBT.GetGuaEnhance(stack, 2); + return new BuffTuple(water / 4, CommonDef.TICK_PER_SECOND * water * 2); + } + + public BuffTuple GetMountainBuff(ItemStack stack) + { + int gua = IDLSkillNBT.GetGuaEnhance(stack, 4); + return new BuffTuple(gua / 4, CommonDef.TICK_PER_SECOND * gua * 2); + } + + @SideOnly(Side.CLIENT) + public String getMainDesc(ItemStack stack, World world, List tooltip, ITooltipFlag flag) + { + //todo:highlight while upgrading + String key = stack.getUnlocalizedName() + ".desc"; + if (I18n.hasKey(key)) + { + BuffTuple mountain = GetMountainBuff(stack); + BuffTuple water = GetWaterBuff(stack); + int fire = IDLSkillNBT.GetGuaEnhance(stack, 5); + + + return I18n.format(stack.getUnlocalizedName() + ".desc", + (IDLSkillNBT.GetGuaEnhance(stack, 0) * earthModifier * 100f), + IDLSkillNBT.GetGuaEnhance(stack, 1), + water.power + 1, (water.tick / CommonDef.TICK_PER_SECOND), + IDLSkillNBT.GetGuaEnhance(stack, 3), + mountain.power + 1, (mountain.tick / CommonDef.TICK_PER_SECOND), + fire, fire, + IDLSkillNBT.GetGuaEnhance(stack, 6) + //GetGuaEnhance(stack, 7) + ); + } + return ""; + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillMartialAttack.java b/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillMartialAttack.java new file mode 100644 index 0000000..8fd4a28 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/skills/martial/ItemSkillMartialAttack.java @@ -0,0 +1,106 @@ +package com.somebody.idlframewok.item.skills.martial; + +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EntityDamageSource; +import net.minecraft.util.EnumHand; + +public class ItemSkillMartialAttack extends ItemSkillBase { + public float KBPowerBase = 0.1f; + public float KBPowerPerLevel = 0.1f; + + public boolean interrupts = true; + public boolean isSlam = false; + + public float getKBPower(ItemStack stack) + { + return (IDLSkillNBT.getLevel(stack) - 1) * KBPowerPerLevel + KBPowerBase; + } + + public ItemSkillMartialAttack setKB(float val, float val_per_level) + { + KBPowerBase = val; + this.KBPowerPerLevel = val_per_level; + return this; + } + + public ItemSkillMartialAttack setIsSlam(boolean slam) + { + this.isSlam = slam; + return this; + } + + + public ItemSkillMartialAttack(String name) { + super(name); + cool_down = 1f; + basic_val = 1f; + val_per_level = 1f; + isMartial = true; + } + + public void OnHit(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + OnHitBasic(stack, playerIn, target, handIn); + OnHitSound(stack, playerIn, target, handIn); + OnHitExtra(stack, playerIn, target, handIn); + } + + public void OnHitBasic(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + if (!playerIn.world.isRemote) { + target.attackEntityFrom(GetDamageSource(stack, playerIn, target, handIn), getVal(stack)); + target.knockBack(playerIn, getKBPower(stack), (playerIn.posX - target.posX), (playerIn.posZ - target.posZ)); + playerIn.swingArm(handIn); + if (interrupts) { + if (target instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer) target; + ItemStack inHand = player.getHeldItemMainhand(); + if (inHand.getItem() != null && inHand.getItem() instanceof ItemSkillBase) + { + ItemSkillBase.activateCoolDown(player, inHand); + } + } + } + } + } + + public void OnHitSound(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + target.playSound(SoundEvents.BLOCK_PISTON_EXTEND, 1f, 1f); + } + + public void OnHitExtra(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + + } + + @Override + public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) { + if (isStackReady(playerIn, stack)) + { + OnHit(stack, playerIn, target, handIn); + if (!playerIn.world.isRemote) + { + activateCoolDown(playerIn, stack); + } + return true; + } + return false; + } + + public DamageSource GetDamageSource(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand handIn) + { + if (isSlam) + { + return new EntityDamageSource("slam", playerIn); + } + return new EntityDamageSource("martial", playerIn); + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/weapon/ItemEtherealSword.java b/src/main/java/com/somebody/idlframewok/item/weapon/ItemEtherealSword.java new file mode 100644 index 0000000..866f580 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/weapon/ItemEtherealSword.java @@ -0,0 +1,67 @@ +package com.somebody.idlframewok.item.weapon; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.item.ItemSwordBase; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +public class ItemEtherealSword extends ItemSwordBase { + public ItemEtherealSword(String name, ToolMaterial material) { + super(name, material); + } + + @Override + public int getMaxDamage(ItemStack stack) { + return getEnchantmentTotalLevel(stack) * getDurabilityPerEnch(stack) + 100; + } + + public int getDurabilityPerEnch(ItemStack stack) + { + return 100; + } + + public float getDamagePerEnch(ItemStack stack) + { + return 1f; + } + + int getEnchantmentTotalLevel(ItemStack stack) + { + int result = 0; + NBTTagList nbttaglist = stack.getEnchantmentTagList(); + + for (int j = 0; j < nbttaglist.tagCount(); ++j) + { + NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(j); + int enchID = nbttagcompound.getShort("layer");//enchant ID + int lvl = nbttagcompound.getShort("lvl"); + Enchantment enchantment = Enchantment.getEnchantmentByID(enchID); + + if (enchantment != null) + { + result += lvl; + } + } + return result; + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + + if (equipmentSlot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", 1f + getEnchantmentTotalLevel(stack) * getDamagePerEnch(stack), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", -2.4000000953674316D, 0)); + } + + return multimap; + } + +} diff --git a/src/main/java/com/somebody/idlframewok/item/weapon/ItemHealingGun.java b/src/main/java/com/somebody/idlframewok/item/weapon/ItemHealingGun.java new file mode 100644 index 0000000..446a259 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/weapon/ItemHealingGun.java @@ -0,0 +1,92 @@ +package com.somebody.idlframewok.item.weapon; + +import java.util.List; + +import com.somebody.idlframewok.item.ItemAdaptingBase; +import com.somebody.idlframewok.util.EntityUtil; +import com.somebody.idlframewok.util.IDLGeneral; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemHealingGun extends ItemAdaptingBase { + public ItemHealingGun(String name) { + super(name); + setRangedWeapon(); + useable = true; + + base_cd = 10f; + base_power = 6f; + base_range = 3f; + } + + @Override + public int getMaxDamage(ItemStack stack) { + return 512; + } + + public void onCreatureStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) + { + //IdlFramework.Log("onCreatureStoppedUsing"); + Vec3d basePos = entityLiving.getPositionVector(); + float range = getRange(stack); + List entities = worldIn.getEntitiesWithinAABB(EntityLivingBase.class, IDLGeneral.ServerAABB(basePos.addVector(-range, -range, -range), basePos.addVector(range, range, range))); + //IdlFramework.Log("found %d targets", entities.size()); + for (EntityLivingBase target: entities + ) { + if (EntityUtil.getAttitude(entityLiving, target) == EntityUtil.ATTITUDE.FRIEND) + { + if (worldIn.isRemote) + { + EntityUtil.SpawnParticleAround(target, EnumParticleTypes.VILLAGER_HAPPY, 10); + }else { + target.heal(getPower(stack)); + } + } + } + + if (worldIn.isRemote) + { + //IdlFramework.Log("spawn particle!"); + spawnParticles(EnumParticleTypes.VILLAGER_HAPPY, worldIn, entityLiving); + } + + entityLiving.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1f, 0.8f); + } + + void spawnParticles(EnumParticleTypes particleType, World worldIn, EntityLivingBase center) + { + int count = 60; + float speedMagnitude = 1000f; + float maxAngle = 6.282f; + float deltaAngle = maxAngle/count; + + for (float angle = 0f; angle < maxAngle; angle += deltaAngle) + { + // float radius = center.getRNG().nextFloat() * speedMagnitude; + //IdlFramework.Log("spawn particle at %s, %s, %s", center.posX, center.posY, center.posZ); + center.world.spawnParticle(particleType, center.posX+Math.cos(angle), + center.getPositionEyes(0f).y, + center.posZ+Math.sin(angle), + Math.cos(angle) * speedMagnitude,0,Math.sin(angle) * speedMagnitude); + } + + +// Vec3d velocityShoot = Vec3d.ZERO; +// Vec3d velocitySide = Vec3d.ZERO; +// +// float theta = 0f; +// float accel = 0f; +// +// while(true) +// { +// //update +// Vec3d speed = velocityShoot.scale(Math.cos(theta)).add(velocitySide.scale(Math.sin(theta))); +// theta += accel; +// } + } + +} diff --git a/src/main/java/com/somebody/idlframewok/item/weapon/ItemPistolBase.java b/src/main/java/com/somebody/idlframewok/item/weapon/ItemPistolBase.java new file mode 100644 index 0000000..794ef07 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/weapon/ItemPistolBase.java @@ -0,0 +1,89 @@ +package com.somebody.idlframewok.item.weapon; + +import com.somebody.idlframewok.entity.projectiles.EntityIdlProjectile; +import com.somebody.idlframewok.entity.projectiles.ProjectileArgs; +import com.somebody.idlframewok.item.ItemAdaptingBase; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Enchantments; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class ItemPistolBase extends ItemAdaptingBase { + public ItemPistolBase(String name) { + super(name); + setRangedWeapon(); + useable = true; + base_cd = 1f; + } + + @Override + public int getMaxDamage(ItemStack stack) { + return 256; + } + + /** + * How long it takes to use or consume an item + */ + public int getMaxItemUseDuration(ItemStack stack) + { + return 72000; + } + + /** + * returns the action that specifies what animation to play when the items is being used + */ + public EnumAction getItemUseAction(ItemStack stack) + { + return EnumAction.BOW; + } + + public EntityIdlProjectile getBullet(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) { + return new EntityIdlProjectile(worldIn, new ProjectileArgs(5f), entityLiving, + entityLiving.getLookVec().x * 10, + entityLiving.getLookVec().y * 10, + entityLiving.getLookVec().z * 10); + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.PUNCH || enchantment == Enchantments.INFINITY) + { + return false; + } + + if (enchantment == Enchantments.POWER || enchantment == Enchantments.UNBREAKING) + { + return true; + } + + return super.canApplyAtEnchantingTable(stack, enchantment); + } + + /** + * Called when the player stops using an Item (stops holding the right mouse button). + */ + public void onCreatureStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) + { + if (!worldIn.isRemote) + { + EntityIdlProjectile bullet = getBullet(stack, worldIn, entityLiving, timeLeft); + + int powerEnchant = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER, stack); + + if (powerEnchant > 0) + { + bullet.args.damage += (double)powerEnchant * 0.5D + 0.5D; + } + + if (EnchantmentHelper.getEnchantmentLevel(Enchantments.FLAME, stack) > 0) + { + bullet.setFire(100); + } + + worldIn.spawnEntity(bullet); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/item/weapon/ItemSmashShield.java b/src/main/java/com/somebody/idlframewok/item/weapon/ItemSmashShield.java new file mode 100644 index 0000000..f6746f2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/item/weapon/ItemSmashShield.java @@ -0,0 +1,115 @@ +package com.somebody.idlframewok.item.weapon; + +import javax.annotation.Nullable; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.somebody.idlframewok.item.ItemAdaptingBase; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Enchantments; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.EnumAction; +import net.minecraft.item.IItemPropertyGetter; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ItemSmashShield extends ItemAdaptingBase { + public ItemSmashShield(String name) { + super(name); + setRangedWeapon(); + useable = true; + this.addPropertyOverride(new ResourceLocation("blocking"), new IItemPropertyGetter() + { + @SideOnly(Side.CLIENT) + public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) + { + return entityIn != null && entityIn.isHandActive() && entityIn.getActiveItemStack() == stack ? 1.0F : 0.0F; + } + }); + } + + public boolean isShield(ItemStack stack, @Nullable EntityLivingBase entity) + { + return true; + } + + /** + * returns the action that specifies what animation to play when the items is being used + */ + public EnumAction getItemUseAction(ItemStack stack) + { + return EnumAction.BLOCK; + } + + /** + * How long it takes to use or consume an item + */ + public int getMaxItemUseDuration(ItemStack stack) + { + return 72000; + } + + /** + * Called when the equipped item is right clicked. + */ + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + ItemStack itemstack = playerIn.getHeldItem(handIn); + playerIn.setActiveHand(handIn); + return new ActionResult<>(EnumActionResult.SUCCESS, itemstack); + } + + @Override + public void onPlayerStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) { + + } + + @Override + public int getMaxDamage(ItemStack stack) { + return 512; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.PUNCH || enchantment == Enchantments.INFINITY) + { + return false; + } + + if (enchantment == Enchantments.POWER || enchantment == Enchantments.UNBREAKING) + { + return true; + } + + return super.canApplyAtEnchantingTable(stack, enchantment); + } + + public Multimap getAttributeModifiers(EntityEquipmentSlot equipmentSlot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + + if (equipmentSlot == EntityEquipmentSlot.OFFHAND ) + { + multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(OFF_HAND_MODIFIER, "Weapon modifier", (double)getPower(stack), 0)); + } + + if (equipmentSlot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(MAIN_HAND_MODIFIER, "Weapon modifier", (double)getPower(stack), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(MAIN_HAND_MODIFIER, "Weapon modifier", (double)getPower(stack) / 2f, 0)); + } + + return multimap; + } + +} diff --git a/src/main/java/com/somebody/idlframewok/keys/KeyboardManager.java b/src/main/java/com/somebody/idlframewok/keys/KeyboardManager.java new file mode 100644 index 0000000..cd77b51 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/keys/KeyboardManager.java @@ -0,0 +1,61 @@ +package com.somebody.idlframewok.keys; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.proxy.ClientProxy; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +//@SideOnly(Side.CLIENT) +@Mod.EventBusSubscriber +public class KeyboardManager { + //ref: https://harbinger.covertdragon.team/chapter-18/keyboard.html + + public static void init() { + for (KeyBinding key: + ClientProxy.KEY_BINDINGS) { + ClientRegistry.registerKeyBinding(key); + } + IdlFramework.Log("Registered %d keys", ClientProxy.KEY_BINDINGS.size()); + } + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public static void onKeyPressed(InputEvent.KeyInputEvent event) { +// if (ClientProxy.CAST_OFFHAND.isPressed() || ClientProxy.CAST_MAINHAND.isPressed()) { +// +// Minecraft mc = Minecraft.getMinecraft(); +// EntityPlayerSP player = mc.player; +// if(player == null) return; +// if(mc.isGamePaused()) return; +// if(!mc.inGameHasFocus) return; +// if(mc.currentScreen != null) return; +// +// EnumHand hand = ClientProxy.CAST_OFFHAND.isKeyDown() ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND; +// IdlFramework.Log("pressed key cast :" + hand); +// +// ItemStack item = player.getHeldItem(hand); +// if(item.isEmpty()) +// { +// IdlFramework.LogWarning("Trying to cast an empty item"); +// } +// +// if(item.getItem() instanceof ItemSkillBase) +// { +// ItemSkillBase skill = (ItemSkillBase) item.getItem(); +// if (skill.canCast(player.world, player, hand)) +// { +// NetworkHandler.SendToServer(new PacketTest(hand.ordinal())); +// } +// +// } +// +// //mc.playerController.updateController(); +// // NetworkManager.channel.sendToServer(new C2SSpecialAction((byte) 1)); +// } + } +} diff --git a/src/main/java/com/somebody/idlframewok/keys/ModKeyBinding.java b/src/main/java/com/somebody/idlframewok/keys/ModKeyBinding.java new file mode 100644 index 0000000..b3856de --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/keys/ModKeyBinding.java @@ -0,0 +1,15 @@ +package com.somebody.idlframewok.keys; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.proxy.ClientProxy; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; + +//@SideOnly(Side.CLIENT) +public class ModKeyBinding extends KeyBinding { + public ModKeyBinding(String description, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, int keyCode, String category) { + super(String.format("key.%s.%s", IdlFramework.MODID, description), keyConflictContext, keyModifier, keyCode, category); + ClientProxy.KEY_BINDINGS.add(this); + } +} diff --git a/src/main/java/com/somebody/idlframewok/meta/MetaUtil.java b/src/main/java/com/somebody/idlframewok/meta/MetaUtil.java new file mode 100644 index 0000000..a514f42 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/meta/MetaUtil.java @@ -0,0 +1,46 @@ +package com.somebody.idlframewok.meta; + +import net.minecraftforge.fml.common.Loader; + +public class MetaUtil { + public static boolean isIDLLoaded = false; + public static boolean isIRRLoaded = false; + public static boolean isLoaded_TiC = false; + public static boolean isLoaded_Slashblade = false; + public static boolean isLoaded_Botania = false; + public static boolean isLoaded_DWeapon = false; + public static boolean isLoaded_AOA3 = false; + public static boolean isLoaded_GC = false; + public static boolean isLoaded_Taoism = false; + public static boolean isLoaded_GOG = false; + + //extra difficulty + public static int HARD_AOA3 = 5; + public static int HARD_GOG = 4; + + //static int modListDifficulty = 0; + static int modListExtraDifficulty = 0; + + public static int getModListExtraDifficulty() { + return modListExtraDifficulty; + } + + public static void CalcModListDifficulty() + { + //modListDifficulty = CommonFunctions.GetModCount(); + if (isLoaded_AOA3) + { + modListExtraDifficulty+=HARD_AOA3; + } + + if(isLoaded_GOG) + { + modListExtraDifficulty+=HARD_GOG; + } + } + + public static int GetModCount() + { + return Loader.instance().getActiveModList().size(); + } +} diff --git a/src/main/java/com/somebody/idlframewok/network/NetworkHandler.java b/src/main/java/com/somebody/idlframewok/network/NetworkHandler.java new file mode 100644 index 0000000..45fad48 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/network/NetworkHandler.java @@ -0,0 +1,32 @@ +package com.somebody.idlframewok.network; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.network.protocols.PacketTest; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; + +public class NetworkHandler { + public static final ResourceLocation MSG_RESOURCE = new ResourceLocation(IdlFramework.MODID, "msg"); + + public static final SimpleNetworkWrapper channel = NetworkRegistry.INSTANCE.newSimpleChannel(IdlFramework.MODID); + + static int id = 0; + public static void init() + { + //C2S + channel.registerMessage(PacketTest.Handler.class, PacketTest.class, id++, Side.SERVER); + //just call SendToServer + + + //S2C + //PacketUtil.network.sendTo(new PacketRevenge(cap.isRevengeActive()), (EntityPlayerMP)e.player); + } + + public static void SendToServer(IMessage packet) + { + channel.sendToServer(packet); + } +} diff --git a/src/main/java/com/somebody/idlframewok/network/protocols/PacketTest.java b/src/main/java/com/somebody/idlframewok/network/protocols/PacketTest.java new file mode 100644 index 0000000..7b45f52 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/network/protocols/PacketTest.java @@ -0,0 +1,68 @@ +package com.somebody.idlframewok.network.protocols; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketTest implements IMessage { + + int testVal; + + public PacketTest() { + } + + + public PacketTest(int testVal) { + this.testVal = testVal; + } + + @Override + public void fromBytes(ByteBuf buf) { + + testVal = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(testVal); + // these methods may also be of use for your code: + // for Itemstacks - ByteBufUtils.writeItemStack() + // for NBT tags ByteBufUtils.writeTag(); + // for Strings: ByteBufUtils.writeUTF8String(); + + } + + public static class Handler implements IMessageHandler { + public IMessage onMessage(final PacketTest msg, final MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().player; + + player.getServerWorld().addScheduledTask(() -> { + IdlFramework.Log("Packet:%d", msg.testVal); + + EnumHand hand = EnumHand.values()[msg.testVal]; + + ItemStack item = player.getHeldItem(hand); + if(item.isEmpty()) + { + IdlFramework.LogWarning("Trying to cast an empty item"); + } + + if(item.getItem() instanceof ItemSkillBase) + { + ItemSkillBase skill = (ItemSkillBase) item.getItem(); + if (skill.canCast(player.world, player, hand)) + { + skill.tryCast(player.world, player, hand); + } + } + }); + return null; + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/EffectTuple.java b/src/main/java/com/somebody/idlframewok/potion/EffectTuple.java new file mode 100644 index 0000000..3fa635d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/EffectTuple.java @@ -0,0 +1,37 @@ +package com.somebody.idlframewok.potion; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.MobEffects; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; + +public class EffectTuple +{ + public float chance = 0.1f; + public Potion potion = MobEffects.ABSORPTION; + public int length = 200; + + public EffectTuple(float chance, Potion potion) { + this(chance, potion, 200); + } + + public EffectTuple(float chance, Potion potion, int length) { + this.chance = chance; + this.potion = potion; + this.length = length; + } + + public void AttemptBuffWithLevel(EntityLivingBase livingBase, int level) + { + if (livingBase.getRNG().nextFloat() < chance) + { + ApplyBuffWithLevel(livingBase, level); + } + } + + public void ApplyBuffWithLevel(EntityLivingBase livingBase, int level) + { + livingBase.addPotionEffect(new PotionEffect(potion, length, level, false, false)); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/potion/ModPotions.java b/src/main/java/com/somebody/idlframewok/potion/ModPotions.java new file mode 100644 index 0000000..86d92c2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/ModPotions.java @@ -0,0 +1,46 @@ +package com.somebody.idlframewok.potion; + +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.potion.Potion; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class ModPotions { + + public static final List INSTANCES = new ArrayList(); + +// public static final PotionDeadly DEADLY = new PotionDeadly(false, 0x333333, "deadly", 0); +// public static final PotionZenHeart ZEN_HEART = new PotionZenHeart(false, 0xcccc00, "zen_heart", 1); + + @Nullable + private static Potion getRegisteredMobEffect(String id) + { + Potion potion = Potion.REGISTRY.getObject(new ResourceLocation(id)); + + if (potion == null) + { + throw new IllegalStateException("Invalid MobEffect requested: " + id); + } + else + { + return potion; + } + } + + @SubscribeEvent + public static void registerPotions(RegistryEvent.Register evt) + { + //VIRUS_ONE.tuples.add(new EffectTuple(0.2f, MobEffects.NAUSEA, 100)); + + evt.getRegistry().registerAll(INSTANCES.toArray(new Potion[0])); + IdlFramework.LogWarning("registered %d potion", INSTANCES.size()); + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/PotionEventHandler.java b/src/main/java/com/somebody/idlframewok/potion/PotionEventHandler.java new file mode 100644 index 0000000..d46db6d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/PotionEventHandler.java @@ -0,0 +1,245 @@ +package com.somebody.idlframewok.potion; + +import java.util.Collection; + +import com.somebody.idlframewok.potion.buff.BasePotion; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.living.LivingKnockBackEvent; +import net.minecraftforge.event.entity.player.CriticalHitEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class PotionEventHandler { + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void onCreatureHurt(LivingHurtEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + +// if (hurtOne.getActivePotionEffect(INVINCIBLE) != null) +// { +// evt.setCanceled(true); +// return; +// } + + //Base Damage Reduction + Collection activePotionEffects = hurtOne.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + if (!world.isRemote) + { + float reduceRatio = modBuff.getDamageReductionMultiplier(buff.getAmplifier()); + evt.setAmount((1 - reduceRatio) * evt.getAmount()); + } + } + } + + Entity trueSource = evt.getSource().getTrueSource(); + if (trueSource instanceof EntityLivingBase){ + EntityLivingBase sourceCreature = (EntityLivingBase)trueSource; +// if (sourceCreature.isEntityUndead()) +// { +// PotionEffect curBuff = hurtOne.getActivePotionEffect(ZEN_HEART); +// if (curBuff != null) { +// if (!world.isRemote) { +// evt.setCanceled(true); +// } +// } +// } + + //Apply damage multiplier + Collection activePotionEffectsAttacker = sourceCreature.getActivePotionEffects(); + for (int i = 0; i < activePotionEffectsAttacker.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffectsAttacker.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + if (!world.isRemote) + { + evt.setAmount((1 + modBuff.getAttackMultiplier(buff.getAmplifier())) * evt.getAmount()); + } + } + } + + //Critical Judgement + if (!(trueSource instanceof EntityPlayer)) {//Players have their own critical judgement system. Now we add the non-player system. + float critRate = 0.1f; + boolean isCritical = false; + + //Critical chance buff + activePotionEffects = ((EntityLivingBase) trueSource).getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect) activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) { + BasePotion modBuff = (BasePotion) buff.getPotion(); + + critRate += modBuff.getCritRate(buff.getAmplifier()); + } + } + + if (critRate > 0 && ((EntityLivingBase) trueSource).getRNG().nextFloat() < critRate) { + isCritical = true; + } + + //Critical damage multiplier buff + if (isCritical) { + float critDmg = 1.5f;//vanilla + + activePotionEffects = ((EntityLivingBase) trueSource).getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect) activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) { + BasePotion modBuff = (BasePotion) buff.getPotion(); + + critDmg += modBuff.getCritDmgModifier(buff.getAmplifier()); + } + } + + evt.setAmount((critDmg) * evt.getAmount()); + //IdlFramework.Log(String.format("%s:isCrit = %s, x%s =%s, ", trueSource.getName(), isCritical, critDmg, evt.getAmount())); + } + //IdlFramework.Log(String.format("%s:isCrit = %s, x1f =%s, ", trueSource.getName(), isCritical, evt.getAmount())); + } + } + + if (evt.isCanceled()) + { + return; + } + + //slime erosion +// if (trueSource instanceof EntitySlime) +// { +// if (!world.isRemote) +// { +// hurtOne.addPotionEffect(new PotionEffect(ModPotions.EROSION, (int)(TICK_PER_SECOND * (evt.getAmount() + 1f)), (int)(evt.getAmount() / 10))); +// } +// } + + //onHit effect + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + if (world.isRemote) + { + modBuff.playOnHitEffect(hurtOne, evt.getAmount()); + } + } + } + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void onCreatureKB(LivingKnockBackEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + if (!world.isRemote) { + //Handle virtue and undead + Entity trueSource = evt.getOriginalAttacker(); + if (trueSource instanceof EntityLivingBase){ + EntityLivingBase sourceCreature = (EntityLivingBase)trueSource; + if (sourceCreature.isEntityUndead()) + { +// PotionEffect curBuff = hurtOne.getActivePotionEffect(ZEN_HEART); +// if (curBuff != null) { +// PotionEffect sourceBuff = sourceCreature.getActivePotionEffect(ZEN_HEART); +// if (sourceBuff == null) {//prevent dead loop +// sourceCreature.knockBack(hurtOne, evt.getStrength(), -evt.getRatioX(), -evt.getRatioZ()); +// } +// evt.setCanceled(true); +// } + } + } + + //KB Reduction + if (evt.isCanceled()) + { + return; + } + + Collection activePotionEffects = hurtOne.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + + float reduceRatio = modBuff.getKBResistanceMultiplier(buff.getAmplifier()); + evt.setStrength((1 - reduceRatio) * evt.getStrength()); + } + } + } else { + + } + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void onPlayerCriticalJudge(CriticalHitEvent evt) { +// public class CriticalHitEvent extends PlayerEvent { +// private float damageModifier; +// private final float oldDamageModifier; +// private final Entity target; +// private final boolean vanillaCritical; +// } + EntityPlayer player = evt.getEntityPlayer(); + float critRate = 0f; + + Collection activePotionEffects = player.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + + critRate += modBuff.getCritRate(buff.getAmplifier()); + } + } + + if (evt.isVanillaCritical()) + { + if (critRate < 0 && player.getRNG().nextFloat() < (1 + critRate)) + { + evt.setResult(Event.Result.DENY); + } + }else { + if (critRate > 0 && player.getRNG().nextFloat() < (critRate)) + { + evt.setResult(Event.Result.ALLOW); + } + } + + boolean isCrit = evt.getResult() == Event.Result.ALLOW || (evt.getResult() == Event.Result.DEFAULT && evt.isVanillaCritical()); + //is critical + if (isCrit) + { + float critDmg = 0f; + + activePotionEffects = player.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof BasePotion) + { + BasePotion modBuff = (BasePotion)buff.getPotion(); + + critDmg += modBuff.getCritDmgModifier(buff.getAmplifier()); + } + } + + float originalModifier = evt.getDamageModifier(); + evt.setDamageModifier(originalModifier + critDmg); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/BasePotion.java b/src/main/java/com/somebody/idlframewok/potion/buff/BasePotion.java new file mode 100644 index 0000000..10e05a9 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/BasePotion.java @@ -0,0 +1,173 @@ +package com.somebody.idlframewok.potion.buff; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.EntityLivingBase; + +public class BasePotion extends BaseSimplePotion { +// private static final ResourceLocation resource = new ResourceLocation("idlframewok","textures/misc/potions.png"); +// private final int iconIndex; + + protected float damageReductionRatioBase = 0.0f; + protected float damageReductionRatioPerLevel = 0.0f; + + protected float attackIncreaseRatioBase = 0.0f; + protected float attackIncreaseRatioPerLevel = 0.0f; + + protected float knockbackResistanceRatio = 0f; + protected float knockbackResistanceRatioPerLevel = 0f; + + protected float hpRecoverPerTick = 0f; + protected float hpRecoverPerLevel = 0f; + + protected float critRateBase = 0f; + protected float critRatePerLevel = 0f; + + //default = 1.5x + protected float critDmgRatioBase = 0f; + protected float critDmgRatioPerLevel = 0f; + + protected float resistancePerLevel = 0f;//for any buff + + + //----------------------------------------- + public BasePotion setHPRevocer(float begin, float upgrade) + { + hpRecoverPerTick = begin; + hpRecoverPerLevel = upgrade; + return this; + } + + public BasePotion setKBResistance(float begin, float upgrade) + { + knockbackResistanceRatio = begin; + knockbackResistanceRatioPerLevel = upgrade; + return this; + } + + public BasePotion setAttackRatio(float begin, float upgrade) + { + attackIncreaseRatioBase = begin; + attackIncreaseRatioPerLevel = upgrade; + return this; + } + + public BasePotion setProtectionRatio(float begin, float upgrade) + { + damageReductionRatioBase = begin; + damageReductionRatioPerLevel = upgrade; + return this; + } + + public BasePotion setCritRateRatio(float begin, float upgrade) + { + critRateBase = begin; + critRatePerLevel = upgrade; + return this; + } + + public BasePotion setCritDamageRatio(float begin, float upgrade) + { + critDmgRatioBase = begin; + critDmgRatioPerLevel = upgrade; + return this; + } + //---------------------------------------- + + public BasePotion(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + } +// public BasePotion(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { +// super(isBadEffectIn, liquidColorIn); +// setRegistryName(new ResourceLocation(Reference.MOD_ID, name)); +// setPotionName("idlframewok.potion." + name); +// iconIndex = icon; +// } + + @Override + public boolean isReady(int duration, int amplifier) { + return true; + } + + @Override + public void performEffect(@Nonnull EntityLivingBase living, int amplified) { + if (living.getHealth() < living.getMaxHealth()) + { + living.heal(hpRecoverPerTick + amplified * hpRecoverPerLevel); + } + } + + public void playOnHitEffect(EntityLivingBase entityLivingBase, float damage) + { + + } + + //damage = (1-x)damage + public float getDamageReductionMultiplier(int level) + { + //cant deal negative damage + return Math.min(1f, damageReductionRatioBase + level * damageReductionRatioPerLevel); + } + + public float getHealPerTick(int level) + { + //can be negative + return hpRecoverPerTick + level * hpRecoverPerLevel; + } + + //damage = (1+x)damage + public float getAttackMultiplier(int level) + { + return Math.max(-1f, attackIncreaseRatioBase + level * attackIncreaseRatioPerLevel); + } + + //KB = (1+x)KB + public float getKBResistanceMultiplier(int level) + { + return Math.max(-1f, knockbackResistanceRatio + level * knockbackResistanceRatioPerLevel); + } + + public float getCritRate(int level) + { + //can be negative + return critRateBase + level * critRatePerLevel; + } + + //need to plus 1.5 + public float getCritDmgModifier(int level) + { + //can be negative + return critDmgRatioBase + level * critDmgRatioPerLevel; + } + +// @SideOnly(Side.CLIENT) +// private void render(int x, int y, float alpha) { +// Minecraft.getMinecraft().renderEngine.bindTexture(resource); +// Tessellator tessellator = Tessellator.getInstance(); +// BufferBuilder buf = tessellator.getBuffer(); +// buf.begin(7, DefaultVertexFormats.POSITION_TEX); +// GlStateManager.color(1, 1, 1, alpha); +// +// int textureX = iconIndex % 8 * 18; +// int textureY = 198 + iconIndex / 8 * 18; +// +// buf.pos(x, y + 18, 0).tex(textureX * 0.00390625, (textureY + 18) * 0.00390625).endVertex(); +// buf.pos(x + 18, y + 18, 0).tex((textureX + 18) * 0.00390625, (textureY + 18) * 0.00390625).endVertex(); +// buf.pos(x + 18, y, 0).tex((textureX + 18) * 0.00390625, textureY * 0.00390625).endVertex(); +// buf.pos(x, y, 0).tex(textureX * 0.00390625, textureY * 0.00390625).endVertex(); +// +// tessellator.draw(); +// } +// +// @Override +// @SideOnly(Side.CLIENT) +// public void renderInventoryEffect(int x, int y, PotionEffect effect, Minecraft mc) { +// render(x + 6, y + 7, 1); +// } +// +// @Override +// @SideOnly(Side.CLIENT) +// public void renderHUDEffect(int x, int y, PotionEffect effect, Minecraft mc, float alpha) { +// render(x + 3, y + 3, alpha); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/BaseSimplePotion.java b/src/main/java/com/somebody/idlframewok/potion/buff/BaseSimplePotion.java new file mode 100644 index 0000000..af3eeac --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/BaseSimplePotion.java @@ -0,0 +1,62 @@ +package com.somebody.idlframewok.potion.buff; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class BaseSimplePotion extends Potion { + protected static final ResourceLocation resource = new ResourceLocation("idlframewok","textures/misc/potions.png"); + protected final int iconIndex; + +// if (!this.world.isRemote) +// { +// layer.getPotion().applyAttributesModifiersToEntity(this, this.getAttributeMap(), layer.getAmplifier()); +// } + + + public BaseSimplePotion(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn); + setRegistryName(new ResourceLocation(Reference.MOD_ID, name)); + setPotionName("idlframewok.potion." + name); + iconIndex = icon; + } + + @SideOnly(Side.CLIENT) + protected void render(int x, int y, float alpha) { + Minecraft.getMinecraft().renderEngine.bindTexture(resource); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buf = tessellator.getBuffer(); + buf.begin(7, DefaultVertexFormats.POSITION_TEX); + GlStateManager.color(1, 1, 1, alpha); + + int textureX = iconIndex % 14 * 18; + int textureY = 198 - iconIndex / 14 * 18; + + buf.pos(x, y + 18, 0).tex(textureX * 0.00390625, (textureY + 18) * 0.00390625).endVertex(); + buf.pos(x + 18, y + 18, 0).tex((textureX + 18) * 0.00390625, (textureY + 18) * 0.00390625).endVertex(); + buf.pos(x + 18, y, 0).tex((textureX + 18) * 0.00390625, textureY * 0.00390625).endVertex(); + buf.pos(x, y, 0).tex(textureX * 0.00390625, textureY * 0.00390625).endVertex(); + + tessellator.draw(); + } + + @Override + @SideOnly(Side.CLIENT) + public void renderInventoryEffect(int x, int y, PotionEffect effect, Minecraft mc) { + render(x + 6, y + 7, 1); + } + + @Override + @SideOnly(Side.CLIENT) + public void renderHUDEffect(int x, int y, PotionEffect effect, Minecraft mc, float alpha) { + render(x + 3, y + 3, alpha); + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionBlastResist.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionBlastResist.java new file mode 100644 index 0000000..8b0003c --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionBlastResist.java @@ -0,0 +1,48 @@ +package com.somebody.idlframewok.potion.buff; + +import java.util.Collection; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class PotionBlastResist extends BasePotion { + public PotionBlastResist(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + knockbackResistanceRatio = 0.1f; + knockbackResistanceRatioPerLevel = 0.1f; + + resistancePerLevel = 0.25f; + } + + @SubscribeEvent + public static void onCreatureHurt(LivingHurtEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + + if (evt.isCanceled() || !evt.getSource().isExplosion()) + { + return; + } + + //Explosion Damage Reduction + Collection activePotionEffects = hurtOne.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof PotionBlastResist) + { + PotionBlastResist modBuff = (PotionBlastResist)buff.getPotion(); + if (!world.isRemote) + { + float reduceRatio = modBuff.resistancePerLevel * (buff.getAmplifier()); + evt.setAmount(Math.max(1 - reduceRatio, 0f) * evt.getAmount()); + } + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionDeadly.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionDeadly.java new file mode 100644 index 0000000..2e5b4ee --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionDeadly.java @@ -0,0 +1,18 @@ +package com.somebody.idlframewok.potion.buff; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.EntityLivingBase; + +public class PotionDeadly extends BasePotion { + + + public PotionDeadly(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + } + + @Override + public void performEffect(@Nonnull EntityLivingBase living, int amplified) { + //do nothing + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionErosion.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionErosion.java new file mode 100644 index 0000000..2713ba0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionErosion.java @@ -0,0 +1,34 @@ +package com.somebody.idlframewok.potion.buff; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; + +public class PotionErosion extends BaseSimplePotion { + public PotionErosion(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + } + + @Override + public boolean isReady(int duration, int amplifier) { + return duration % 20 == 0; + } + + @Override + public void performEffect(@Nonnull EntityLivingBase living, int amplified) { + amplified ++;//buff starts from lv 0 + for (EntityEquipmentSlot slot: + EntityEquipmentSlot.values()) { + DamageItemInSlot(slot, living, amplified); + } + } + + public void DamageItemInSlot(EntityEquipmentSlot slot, EntityLivingBase livingBase, int amount) + { + ItemStack stack = livingBase.getItemStackFromSlot(slot); + stack.damageItem(amount, livingBase); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionInsidiousDisease.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionInsidiousDisease.java new file mode 100644 index 0000000..2bcfa89 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionInsidiousDisease.java @@ -0,0 +1,51 @@ +package com.somebody.idlframewok.potion.buff; + +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.potion.EffectTuple; +import net.minecraft.entity.EntityLivingBase; + +public class PotionInsidiousDisease extends BasePotion { + + int baseCounter = 50; + + public List tuples = new ArrayList<>(); + public void AddTuple(EffectTuple tuple) + { + tuples.add(tuple); + } + + public PotionInsidiousDisease(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + + } + + @Override + public boolean isReady(int duration, int amplifier) { + int k = baseCounter >> amplifier; + + if (k > 0) + { + return duration % k == 0; + } + else + { + return true; + } + } + + @Override + public void performEffect(@Nonnull EntityLivingBase living, int amplified) { + IdlFramework.Log("Perform"); + for (EffectTuple t: + tuples + ) { + t.AttemptBuffWithLevel(living, amplified); + } + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionMagicResist.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionMagicResist.java new file mode 100644 index 0000000..81470c1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionMagicResist.java @@ -0,0 +1,46 @@ +package com.somebody.idlframewok.potion.buff; + +import java.util.Collection; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class PotionMagicResist extends BasePotion { + public PotionMagicResist(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + + resistancePerLevel = 0.25f; + } + + @SubscribeEvent + public static void onCreatureHurt(LivingHurtEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + + if (evt.isCanceled() || !evt.getSource().isMagicDamage()) + { + return; + } + + //Magic Damage Reduction + Collection activePotionEffects = hurtOne.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() instanceof PotionMagicResist) + { + PotionMagicResist modBuff = (PotionMagicResist)buff.getPotion(); + if (!world.isRemote) + { + float reduceRatio = modBuff.resistancePerLevel * (buff.getAmplifier()); + evt.setAmount(Math.max(1 - reduceRatio, 0f) * evt.getAmount()); + } + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionUndying.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionUndying.java new file mode 100644 index 0000000..4cfe135 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionUndying.java @@ -0,0 +1,36 @@ +package com.somebody.idlframewok.potion.buff; + +import com.somebody.idlframewok.util.Reference; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +@Mod.EventBusSubscriber(modid = Reference.MOD_ID) +public class PotionUndying extends BasePotion { + public PotionUndying(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + + resistancePerLevel = 0.25f; + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onCreatureDeath(LivingDeathEvent evt) { + World world = evt.getEntity().getEntityWorld(); + EntityLivingBase hurtOne = evt.getEntityLiving(); + + if (evt.isCanceled()) + { + return; + } + +// PotionEffect effect = hurtOne.getActivePotionEffect(ModPotions.UNDYING); +// if (effect != null) +// { +// evt.setCanceled(true); +// hurtOne.setHealth(hurtOne.getMaxHealth() / (ModPotions.UNDYING.resistancePerLevel * (effect.getAmplifier() + 1))); +// } + } +} diff --git a/src/main/java/com/somebody/idlframewok/potion/buff/PotionZenHeart.java b/src/main/java/com/somebody/idlframewok/potion/buff/PotionZenHeart.java new file mode 100644 index 0000000..1de608b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/potion/buff/PotionZenHeart.java @@ -0,0 +1,7 @@ +package com.somebody.idlframewok.potion.buff; + +public class PotionZenHeart extends BasePotion { + public PotionZenHeart(boolean isBadEffectIn, int liquidColorIn, String name, int icon) { + super(isBadEffectIn, liquidColorIn, name, icon); + } +} diff --git a/src/main/java/com/somebody/idlframewok/proxy/ClientProxy.java b/src/main/java/com/somebody/idlframewok/proxy/ClientProxy.java new file mode 100644 index 0000000..3815857 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/proxy/ClientProxy.java @@ -0,0 +1,25 @@ +package com.somebody.idlframewok.proxy; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.item.Item; +import net.minecraftforge.client.model.ModelLoader; + +public class ClientProxy extends ProxyBase { + public static final List KEY_BINDINGS = new ArrayList(); + //public static final KeyBinding CAST_MAINHAND = new ModKeyBinding("activate_skill_mainhand", KeyConflictContext.IN_GAME, KeyModifier.NONE, Keyboard.KEY_R, "key.category.idlframewok"); + //public static final KeyBinding CAST_OFFHAND = new ModKeyBinding("activate_skill_offhand", KeyConflictContext.IN_GAME, KeyModifier.NONE, Keyboard.KEY_GRAVE, "key.category.idlframewok"); + + public boolean isServer() + { + return false; + } + + public void registerItemRenderer(Item item, int meta, String id) + { + ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(item.getRegistryName(), id)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/proxy/ProxyBase.java b/src/main/java/com/somebody/idlframewok/proxy/ProxyBase.java new file mode 100644 index 0000000..0d604b8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/proxy/ProxyBase.java @@ -0,0 +1,14 @@ +package com.somebody.idlframewok.proxy; + +import net.minecraft.item.Item; + +public class ProxyBase { + public boolean isServer() + { + return false; + } + + public void registerItemRenderer(Item item, int meta, String id) { + //Ignored + } +} diff --git a/src/main/java/com/somebody/idlframewok/proxy/ServerProxy.java b/src/main/java/com/somebody/idlframewok/proxy/ServerProxy.java new file mode 100644 index 0000000..646ee1b --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/proxy/ServerProxy.java @@ -0,0 +1,8 @@ +package com.somebody.idlframewok.proxy; + +public class ServerProxy extends ProxyBase { + public boolean isServer() + { + return true; + } +} diff --git a/src/main/java/com/somebody/idlframewok/recipe/special/BasicGua8.java b/src/main/java/com/somebody/idlframewok/recipe/special/BasicGua8.java new file mode 100644 index 0000000..a39da91 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/recipe/special/BasicGua8.java @@ -0,0 +1,94 @@ +package com.somebody.idlframewok.recipe.special; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.misc.ItemBasicBinary; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +public class BasicGua8 extends IForgeRegistryEntry.Impl implements IRecipe { + + @Override + public boolean isDynamic() { + return true; + } + + @Override + public boolean matches(@Nonnull InventoryCrafting var1, @Nonnull World var2) { + //must place the first sign in first line + int width = var1.getWidth(); + int usedCol = -1; + for (int i = 0; i < width; i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + Item itemType = stack.getItem(); + if (itemType instanceof ItemBasicBinary) { + usedCol = i; + break; + }else + { + return false; + } + } + } + + if (usedCol < 0) { + return false; + } + + int itemCount = 0; + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + itemCount++; + if (i % width != usedCol) { + return false;//wrong shape + } + else { + Item itemType = stack.getItem(); + if (!(itemType instanceof ItemBasicBinary)) { + return false; + } + } + } + } + + return itemCount == 3; + } + + @Nonnull + @Override + public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) { + int guaValue = 0; + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + Item itemType = stack.getItem(); + if(!stack.isEmpty() && (itemType instanceof ItemBasicBinary)) { + guaValue <<= 1; + guaValue += ((ItemBasicBinary) itemType).getValue(); + } + } + +// if (guaValue >= 0 && guaValue <= ModItems.GUA.length) { +// return new ItemStack(ModItems.GUA[guaValue]); +// } + + return ItemStack.EMPTY; + } + + @Override + public boolean canFit(int width, int height) { + return height >= 3; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput() { + return ItemStack.EMPTY; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/recipe/special/GobletDigBlockAssign.java b/src/main/java/com/somebody/idlframewok/recipe/special/GobletDigBlockAssign.java new file mode 100644 index 0000000..0a2a764 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/recipe/special/GobletDigBlockAssign.java @@ -0,0 +1,104 @@ +package com.somebody.idlframewok.recipe.special; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.goblet.ItemDigGoblet; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +public class GobletDigBlockAssign extends IForgeRegistryEntry.Impl implements IRecipe { + @Override + public boolean isDynamic() { + return true; + } + + @Override + public boolean matches(@Nonnull InventoryCrafting var1, @Nonnull World var2) { + //before finding the weapon, we dont know whats the max pearl accepted + boolean foundGoblet = false; + boolean foundBlock = false; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemDigGoblet) + { + if (foundGoblet) { + //IdlFramework.Log("Found more than one goblet item"); + return false;//only one goblwt at a time + } + foundGoblet = true; + } + else if ((stack.getItem() instanceof ItemBlock) && !foundBlock) + {//found a block + foundBlock = true; + } + else + { + return false; //Found an other. + } + } + } + + return foundBlock && foundGoblet; + } + + @Nonnull + @Override + public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) { + ItemStack cup = ItemStack.EMPTY; + + boolean foundGoblet = false; + boolean foundBlock = false; + ItemBlock block = null; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemDigGoblet) + { + if (foundGoblet) { + //IdlFramework.Log("Found more than one goblet item"); + return ItemStack.EMPTY;//only one goblwt at a time + } + cup = stack; + foundGoblet = true; + } + else if ((stack.getItem() instanceof ItemBlock) && !foundBlock) + {//found a block + foundBlock = true; + block = (ItemBlock) stack.getItem(); + } + else + { + return ItemStack.EMPTY; //Found an other. + } + } + } + + ItemStack result = cup.copy(); + if (foundGoblet && foundBlock) + { + ItemDigGoblet goblet = (ItemDigGoblet) result.getItem(); + goblet.SetStoredBlockName(result, block.getBlock()); + } + + return result; + } + + @Override + public boolean canFit(int width, int height) { + return true; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput() { + return ItemStack.EMPTY; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/recipe/special/GobletFill.java b/src/main/java/com/somebody/idlframewok/recipe/special/GobletFill.java new file mode 100644 index 0000000..72e9cf6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/recipe/special/GobletFill.java @@ -0,0 +1,102 @@ +package com.somebody.idlframewok.recipe.special; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.goblet.ItemP2WGoblet; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +public class GobletFill extends IForgeRegistryEntry.Impl implements IRecipe { + + @Override + public boolean isDynamic() { + return true; + } + + @Override + public boolean matches(@Nonnull InventoryCrafting var1, @Nonnull World var2) { + int foundGoldXP = 0; + boolean foundCup = false; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemP2WGoblet) + { + if (foundCup) { + return false;//only one sword at a time + } + foundCup = true; + } + else if (stack.getItem() == Items.GOLD_INGOT) + {//found a xp item + foundGoldXP++; + } + else if(stack.getItem().equals(ItemBlock.getItemFromBlock(Blocks.GOLD_BLOCK))) + { + foundGoldXP+=9; + } + else + { + return false; + } + } + } + return foundGoldXP > 0 && foundCup; + } + + @Nonnull + @Override + public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) { + int payingXP = 0; + + ItemStack sword = ItemStack.EMPTY; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemP2WGoblet) + { + sword = stack; + payingXP += ((ItemP2WGoblet)(sword.getItem())).GetPayingEXP(stack); + } + else if(stack.getItem() == Items.GOLD_INGOT) + { + payingXP++; + } + else if(stack.getItem().getUnlocalizedName().equals(ItemBlock.getItemFromBlock(Blocks.GOLD_BLOCK).getUnlocalizedName())) + { + payingXP+=9; + } + //IdlFramework.Log(stack.getItem().getUnlocalizedName() + " vs " + ItemBlock.getItemFromBlock(Blocks.GOLD_BLOCK).getUnlocalizedName()); + } + } + + if(sword.isEmpty() || payingXP == 0) { + return ItemStack.EMPTY; + } + + ItemStack swordResult = sword.copy(); + ((ItemP2WGoblet)(swordResult.getItem())).SetPayingEXP(swordResult, payingXP); + + return swordResult; + } + + @Override + public boolean canFit(int width, int height) { + return true; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput() { + return ItemStack.EMPTY; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/recipe/special/GuaEnhanceByCrafting.java b/src/main/java/com/somebody/idlframewok/recipe/special/GuaEnhanceByCrafting.java new file mode 100644 index 0000000..480b45a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/recipe/special/GuaEnhanceByCrafting.java @@ -0,0 +1,122 @@ +package com.somebody.idlframewok.recipe.special; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.util.IDLGeneral; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +public class GuaEnhanceByCrafting extends IForgeRegistryEntry.Impl implements IRecipe { + @Override + public boolean isDynamic() { + return true; + } + + @Override + public boolean matches(@Nonnull InventoryCrafting var1, @Nonnull World var2) { + boolean foundMainItem = false; + boolean foundSecond = false; + IGuaEnhance guaEnhance = null; + int guaIndex = -1; + //currently only one gua at a time + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof IGuaEnhance) + { + if (foundMainItem || (IDLSkillNBT.GetGuaEnhanceFree(stack) == 0)) { + return false; + } + foundMainItem = true; + guaEnhance = (IGuaEnhance) stack.getItem(); + } + else if (!foundSecond) + {//found a gua + int index = IDLGeneral.returnGuaIndex(stack); + if (index >= 0) + { + foundSecond = true; + guaIndex = index; + }else { + return false; + } + + } + else + { + return false; //Found an other. + } + } + } + + if (guaEnhance != null) + { + return foundSecond && guaEnhance.acceptGuaIndex(guaIndex); + } + else { + return false; + } + } + + @Nonnull + @Override + public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) { + //wont check gua index here. + ItemStack goaEnhanceable = ItemStack.EMPTY; + + boolean foundMain = false; + boolean foundSecond = false; + int guaIndex = -1; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof IGuaEnhance) + { + if (foundMain) { + return ItemStack.EMPTY;//only one goblwt at a time + } + goaEnhanceable = stack; + foundMain = true; + } + else if (IDLGeneral.returnGuaIndex(stack) >= 0 && !foundSecond) + {//found a gua + foundSecond = true; + guaIndex = IDLGeneral.returnGuaIndex(stack); + } + else + { + return ItemStack.EMPTY; //Found an other. + } + } + } + + ItemStack result = goaEnhanceable.copy(); + if (foundMain && foundSecond) + { + int freeSockets = IDLSkillNBT.GetGuaEnhanceFree(goaEnhanceable); + IDLSkillNBT.AddGuaEnhance(result, guaIndex, 1); + IDLSkillNBT.SetGuaEnhanceFree(result, freeSockets - 1); + } + + return result; + } + + @Override + public boolean canFit(int width, int height) { + return true; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput() { + return ItemStack.EMPTY; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/recipe/special/SkillUpgrade.java b/src/main/java/com/somebody/idlframewok/recipe/special/SkillUpgrade.java new file mode 100644 index 0000000..2860435 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/recipe/special/SkillUpgrade.java @@ -0,0 +1,117 @@ +package com.somebody.idlframewok.recipe.special; + +import javax.annotation.Nonnull; + +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import com.somebody.idlframewok.util.IDLSkillNBT; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +public class SkillUpgrade extends IForgeRegistryEntry.Impl implements IRecipe { + + @Override + public boolean isDynamic() { + return true; + } + + @Override + public boolean matches(@Nonnull InventoryCrafting var1, @Nonnull World var2) { + ItemStack stack1 = ItemStack.EMPTY, stack2 = ItemStack.EMPTY; + int skillCount = 0; + int lv1 = 0, lv2 = 0; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemSkillBase) + { + skillCount++; + if (skillCount > 2) + { + return false; + } + + if (skillCount == 1) + { + stack1 = stack; + ItemSkillBase itemSkillBase = (ItemSkillBase)(stack.getItem()); + lv1 = IDLSkillNBT.getLevel(stack); + if (lv1 >= itemSkillBase.maxLevel) + { + return false; + } + } + else { + stack2 = stack; + lv2 = IDLSkillNBT.getLevel(stack); + } + } + else + { + //DWeapons.logger.warn("Find useless components:[{}], instanceof", stack.getItem().getUnlocalizedName()); + return false; //Found other. + } + } + } + + return skillCount == 2 && (stack1.getItem() == stack2.getItem()) && lv1 == lv2; + } + + @Nonnull + @Override + public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) { + ItemStack stack1 = ItemStack.EMPTY, stack2 = ItemStack.EMPTY; + ItemStack stackResult = ItemStack.EMPTY; + int skillCount = 0; + int lv1 = 0, lv2 = 0; + + for(int i = 0; i < var1.getSizeInventory(); i++) { + ItemStack stack = var1.getStackInSlot(i); + if(!stack.isEmpty()) { + if(stack.getItem() instanceof ItemSkillBase) + { + skillCount++; + if (skillCount > 2) + { + return stackResult; + } + + if (skillCount == 1) + { + ItemSkillBase itemSkillBase = (ItemSkillBase)(stack.getItem()); + stack1 = stack; + lv1 = IDLSkillNBT.getLevel(stack); + stackResult = stack1.copy(); + IDLSkillNBT.SetLevel(stackResult, lv1 + 1); + } + } + else + { + return stackResult; //Found other. + } + } + } + + if (skillCount == 2 && (stack1.getItem() == stack2.getItem())) + { + + } + + return stackResult; + } + + @Override + public boolean canFit(int width, int height) { + return true; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput() { + return ItemStack.EMPTY; + } +} + diff --git a/src/main/java/com/somebody/idlframewok/util/AchvDef.java b/src/main/java/com/somebody/idlframewok/util/AchvDef.java new file mode 100644 index 0000000..949f284 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/AchvDef.java @@ -0,0 +1,9 @@ +package com.somebody.idlframewok.util; + +public class AchvDef { + public final static String ELK_TRANSFORM = "elk_transform"; + public final static String GetAchvName(String key) + { + return Reference.MOD_ID + ":" + key; + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/CommonDef.java b/src/main/java/com/somebody/idlframewok/util/CommonDef.java new file mode 100644 index 0000000..e6b36ae --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/CommonDef.java @@ -0,0 +1,56 @@ +package com.somebody.idlframewok.util; + +import java.text.SimpleDateFormat; + +public class CommonDef { + public static final int STANDARD_DUNGEON_MOB_RARITY = 100; + + public static final int INT_AS_FLOAT = 10000; + + public static final int TICK_PER_SECOND = 20; + + //for fgo skills + public static final int SECOND_PER_TURN = 5; + //for arknight skills + public static final int METER_PER_BLOCK = 2; + + public static final int TICK_PER_TURN = SECOND_PER_TURN * TICK_PER_SECOND; + + public static final float DEG_TO_RAD = 0.017453292F; + public static final int CHUNK_SIZE = 16; + + public static int GUA_TYPES = 8; + + public static int G_EARTH = 0; + public static int G_THUNDER = 1; + public static int G_WATER = 2; + public static int G_MOUNTAIN = 4; + public static int G_LAKE = 3; + public static int G_FIRE = 5; + public static int G_WIND = 6; + public static int G_SKY = 7; + + public static int MAX_AIR = 300; + + public static String MOD_NAME_AOA3 = "aoa3"; + public static String MOD_NAME_GOG = "grimoreofgaia3"; + public static SimpleDateFormat formatDate = new SimpleDateFormat("yyyy-MM-dd"); + public static SimpleDateFormat formatTime = new SimpleDateFormat("HH:mm:ss"); + + /** + * Flag 1 will cause a block update. Flag 2 will send the change to clients. Flag 4 will prevent the block from + * being re-rendered, if this is a client world. Flag 8 will force any re-renders to run on the main thread instead + * of the worker pool, if this is a client world and flag 4 is clear. Flag 16 will prevent observers from seeing + * this change. Flags can be OR-ed + */ + public static class BlockFlags + { + public static int BLOCK_UPDATE = 1; + public static int TO_CLIENT = 2; + public static int CLIENT_DONT_RENDER = 4; + public static int FORCE_RENDER = 8; + public static int IGNORE_OB = 16; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/util/CommonFunctions.java b/src/main/java/com/somebody/idlframewok/util/CommonFunctions.java new file mode 100644 index 0000000..75aad97 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/CommonFunctions.java @@ -0,0 +1,342 @@ +package com.somebody.idlframewok.util; + +import java.util.Calendar; +import java.util.Random; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.item.ItemBase; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; + +public class CommonFunctions { + + public static double flunctate(double ori, double radius, Random random) + { + return ori + (random.nextFloat() * 2 - 1) * radius; + } + + public static boolean isSecondTick(World world) + { + return world.getWorldTime() % CommonDef.TICK_PER_SECOND == 0; + } + + public static void teleportToDimension(EntityPlayer player, int dimension, double x, double y, double z) + { + int oldDimension = player.getEntityWorld().provider.getDimension(); + EntityPlayerMP entityPlayerMP = (EntityPlayerMP) player; + MinecraftServer server = player.getEntityWorld().getMinecraftServer(); + WorldServer worldServer = server.getWorld(dimension); + player.addExperienceLevel(0); + + if (worldServer == null || worldServer.getMinecraftServer() == null) + { + throw new IllegalArgumentException("Dimension: "+dimension+" doesn't exist!"); + } + + //todo + //worldServer.getMinecraftServer().getPlayerList().transferPlayerToDimension(entityPlayerMP, dimension, new CustomTeleporter(worldServer, x, y, z)); + player.setPositionAndUpdate(x, y, z); + } + + public static float GetTemperatureHere(Entity creature) + { + BlockPos pos = creature.getPosition(); + World world = creature.getEntityWorld(); + Biome biome = world.getBiomeForCoordsBody(pos); + return biome.getTemperature(pos); + } + + public static float GetTemperatureHere(BlockPos pos, World world) + { + Biome biome = world.getBiomeForCoordsBody(pos); + return biome.getTemperature(pos); + } + + public static int SecondToTicks(int ticks) { + return ticks * CommonDef.TICK_PER_SECOND; + } + + public static int SecondToTicks(float ticks) { + return (int)(ticks * CommonDef.TICK_PER_SECOND); + } + + public static void TryGrantAchv(EntityPlayer player, String key) + { + String achvName = AchvDef.GetAchvName(key); + //todo + } + + public static void BroadCastByKey(String key, Object... args) { + FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().sendMessage(new TextComponentTranslation(key, args)); + } + + public static void SafeSendMsgToPlayer(EntityPlayer player, String key, Object... args) + { + //Please note that you can only put %s as arguments. If you put %d, it's not going to translate. + if (player instanceof EntityPlayerMP) + { + player.sendMessage((new TextComponentTranslation(key, args))); + } + } + + public static void SafeSendMsgToPlayer(TextFormatting style, EntityPlayer player, String key, Object... args) + { + //Please note that you can only put %s as arguments. If you put %d, it's not going to translate. + if (player instanceof EntityPlayerMP) + { + TextComponentTranslation textcomponenttranslation = new TextComponentTranslation(key, args); + textcomponenttranslation.getStyle().setColor(style); + player.sendMessage(textcomponenttranslation); + } + } + + public static void SendMsgToPlayer(EntityPlayerMP playerMP, String key) + { + playerMP.sendMessage(new TextComponentTranslation(key)); + } + + public static void SendMsgToPlayerStyled(EntityPlayerMP playerMP, String key, TextFormatting style, Object... args) + { + TextComponentTranslation textcomponenttranslation = new TextComponentTranslation(key, args); + textcomponenttranslation.getStyle().setColor(style); + playerMP.sendMessage(textcomponenttranslation); + } + + + public static void SendMsgToPlayer(EntityPlayerMP playerMP, String key, Object... args) + { + playerMP.sendMessage((new TextComponentTranslation(key, args))); + } + + @SideOnly(Side.CLIENT) + public static String GetStringLocalTranslated(String key) { + //return "WIP"; + return I18n.format(key); + + } + + public static void FillWithBlockCornered(World world, BlockPos origin, int lengthX, int lengthY, int lengthZ, IBlockState newState) { + BlockPos target; + for(int x = 0; + x < lengthX;x++) { + for (int y = 0; y < lengthY; y++) { + for (int z = 0; z < lengthZ; z++) { + target = origin.add(x, y, z); + //IBlockState targetBlock = world.getBlockState(target); + world.setBlockState(target, newState); + } + } + } + } + + public static void FillWithBlockCentered(World world, BlockPos origin, int rangeX, int rangeY, int rangeZ, IBlockState newState) { + BlockPos target; + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = -rangeY; y <= rangeY; y++) { + for (int z = -rangeZ; z <= rangeZ; z++) { + target = origin.add(x, y, z); + //IBlockState targetBlock = world.getBlockState(target); + world.setBlockState(target, newState); + } + } + } + } + + public static void BuildWallWithBlockCentered(World world, BlockPos origin, int rangeX, int height, int rangeZ, IBlockState newState) { + BlockPos target; + for(int x = -rangeX; + x <=rangeX;x++) { + for (int y = 0; y < height; y++) { + for (int z = -rangeZ; z <= rangeZ; z++) { + target = origin.add(x, y, z); + //IBlockState targetBlock = world.getBlockState(target); + world.setBlockState(target, newState); + } + } + } + } + + public static void LogPlayerAction(EntityLivingBase living, String action){ + IdlFramework.Log(String.format("%s(%s): %s",living.getName(), living.getUniqueID(), action)); + } + + public static boolean RepairItem(ItemStack stack, int amount) + { + if (!stack.isItemStackDamageable()) + { + return false; + } + else { + int newVal = stack.getItemDamage() - amount; + //if (newVal < 0) newVal = 0; + stack.setItemDamage(newVal); + return true; + } + } + + public static void CopyNormalAttr(EntityLivingBase ori, EntityLivingBase to) + { + CopyAttr(ori, to, SharedMonsterAttributes.FOLLOW_RANGE); + CopyAttr(ori, to, SharedMonsterAttributes.MAX_HEALTH); + CopyAttr(ori, to, SharedMonsterAttributes.MOVEMENT_SPEED); + } + + + public static void CopyAttr(EntityLivingBase ori, EntityLivingBase to, IAttribute attrType) + { + to.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(ori.getEntityAttribute(attrType).getAttributeValue()); + } + + public static int XPForLevel(int lv) + { + /** + * This method returns the cap amount of experience that the experience bar can hold. With each level, the + * experience cap on the player's experience bar is raised by 10. + */ + + if (lv >= 30) + { + return 112 + (lv - 30) * 9; + } + else + { + return lv >= 15 ? 37 + (lv - 15) * 5 : 7 + lv * 2; + } + + } + + + public static boolean TryConsumePlayerXP(EntityPlayer player, int XP) + { + //float curXP = player.experience; + float curLv = player.experienceLevel; + float costLeft = XP; + + int playerTotalXP = 0; + for (int i = 1; i <= curLv; i++) + { + playerTotalXP += XPForLevel(i); + } + playerTotalXP += player.experience; + + if (playerTotalXP < XP) + { + //not enough + return false; + } + + //todo not working here + while (costLeft > 0 && (player.experienceLevel > 0 || player.experience > 0)) + { + if (player.experience > costLeft) + { + player.experience -= costLeft; + costLeft = 0; + IdlFramework.Log("A"); + } + else { + costLeft -= player.experience; + IdlFramework.Log("B"); + if (player.experienceLevel > 0) + { + player.experienceLevel--; + player.experience = XPForLevel(player.experienceLevel); + IdlFramework.Log(String.format("player.experience = %d", XPForLevel(player.experienceLevel))); + } + } + } + IdlFramework.Log(String.format("Lv= %s, xp = %s", player.experienceLevel, player.experience)); + return true; + } + + public static boolean isItemRangedWeapon(ItemStack stack) + { + if (stack.isEmpty()) + { + return false; + } + + Item item = stack.getItem(); + if (item instanceof ItemBow) + { + return true; + } + + if (item instanceof ItemBase) + { + return ((ItemBase) item).isRangedWeaponItem(); + } + return false; + } + + public static void WriteGraveToSign(EntityPlayer player, World world, TileEntity tileEntity1) { + if (tileEntity1 instanceof TileEntitySign) + { + WriteGraveToSign(player.getDisplayName(), world, tileEntity1); + } + } + + private static void WriteGraveToSign(ITextComponent name, World world, TileEntity tileEntity1) { + if (tileEntity1 instanceof TileEntitySign) + { + ((TileEntitySign) tileEntity1).signText[0] = name; + ((TileEntitySign) tileEntity1).signText[1] = new TextComponentString("R.I.P."); + + Calendar calendar = world.getCurrentDate(); + ((TileEntitySign) tileEntity1).signText[2] = new TextComponentString( + CommonDef.formatDate.format(calendar.getTime()) + ); + + ((TileEntitySign) tileEntity1).signText[3] = new TextComponentString( + CommonDef.formatTime.format(calendar.getTime()) + ); + } + } + + @SideOnly(Side.CLIENT) + public static boolean isShiftPressed() + { + return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + } + + public static void sendBasicMsg(ItemStack stack, EntityPlayer player, int index) + { + if (player.world.isRemote) + { + return; + } + + SendMsgToPlayer((EntityPlayerMP) player, String.format("%s.msg.%d", stack.getUnlocalizedName(), index)); + } + + public static void addToEventBus(Object target) + { + MinecraftForge.EVENT_BUS.register(target); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/EntityUtil.java b/src/main/java/com/somebody/idlframewok/util/EntityUtil.java new file mode 100644 index 0000000..fb395f8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/EntityUtil.java @@ -0,0 +1,591 @@ +package com.somebody.idlframewok.util; + +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import javax.annotation.Nullable; + +import com.google.common.base.Predicate; +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.entity.creatures.EntityModUnit; +import com.somebody.idlframewok.meta.MetaUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.registry.EntityRegistry; + +@Mod.EventBusSubscriber(modid = IdlFramework.MODID) +public class EntityUtil { + public static void simpleKnockBack(float power, EntityLivingBase source, EntityLivingBase target) + { + target.knockBack(source, power, (source.posX - target.posX), (source.posZ - target.posZ)); + } + + public static void TryRemoveDebuff(EntityLivingBase livingBase) + { + //washes away debuff + Collection activePotionEffects = livingBase.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion().isBadEffect()){ + livingBase.removePotionEffect(buff.getPotion()); + } + } + } + + public static void TryRemoveGivenBuff(EntityLivingBase livingBase, Potion potion) + { + //washes away debuff + Collection activePotionEffects = livingBase.getActivePotionEffects(); + for (int i = 0; i < activePotionEffects.size(); i++) { + PotionEffect buff = (PotionEffect)activePotionEffects.toArray()[i]; + if (buff.getPotion() == potion){ + livingBase.removePotionEffect(buff.getPotion()); + return; + } + } + } + + public static boolean ApplyBuff(EntityLivingBase livingBase, Potion potion, int level, float seconds) + { + if (livingBase == null || potion == null) + { + IdlFramework.LogWarning("Trying to apply illegal potion"); + return false; + } + livingBase.addPotionEffect(new PotionEffect(potion, (int) (seconds * CommonDef.TICK_PER_SECOND) + 1, level)); + return true; + } + + public static String getModName(EntityLivingBase creature) + { + if (creature instanceof EntityPlayer || creature == null) + { + return "minecraft"; + } + EntityRegistry.EntityRegistration er = EntityRegistry.instance().lookupModSpawn(creature.getClass(), true); + if (er == null) + { + //Vanilla creatures don't have ER + return "minecraft"; + } + return er.getContainer().getModId(); + } + + //Player is not vanilla + public static boolean isVanillaResident(EntityLivingBase creature) + { + if (creature instanceof EntityPlayer || creature == null) + { + return false; + } + + EntityRegistry.EntityRegistration er = EntityRegistry.instance().lookupModSpawn(creature.getClass(), true); + if (er == null) + { + return true; + } + String modid = er.getContainer().getModId(); + return modid.equals("minecraft"); + } + + //Player is not otherWorld + public static boolean isOtherworldAggression(EntityLivingBase creature) + { + if (creature instanceof EntityPlayer || creature == null || isIdeallandTeam(creature)) + { + return false; + } + + EntityRegistry.EntityRegistration er = EntityRegistry.instance().lookupModSpawn(creature.getClass(), true); + if (er == null) + { + //Normally this will be enough. Vanilla creatures don't have ER + return false; + } + String modid = er.getContainer().getModId(); + //IdlFramework.Log("Atk ER.modid is %s, name is %s", modid, er.getRegistryName()); + + return !modid.equals("minecraft"); + } + + public static boolean isIdeallandTeam(EntityLivingBase creature) + { + return (creature instanceof EntityModUnit && ((EntityModUnit) creature).isIdealland); + } + + public static boolean isMoroonTeam(EntityLivingBase creature) + { + return (creature instanceof EntityModUnit && ((EntityModUnit) creature).isMoroon); + } + + public static boolean isMechanical(EntityLivingBase creature) + { + return (creature instanceof EntityModUnit && ((EntityModUnit) creature).is_mechanic); + } + + public static boolean isAOA3Creature(EntityLivingBase creature) + { + if (!MetaUtil.isLoaded_AOA3) + { + return false; + } + return getModName(creature).equals(CommonDef.MOD_NAME_AOA3); + } + + public static boolean isGOGCreature(EntityLivingBase creature) + { + if (!MetaUtil.isLoaded_GOG) + { + return false; + } + return getModName(creature).equals(CommonDef.MOD_NAME_AOA3); + } + + public static List getEntitiesWithinAABB(World world, Class clazz, AxisAlignedBB aabb, @Nullable Predicate filter) + { + return world.getEntitiesWithinAABB(clazz, aabb, filter); + } + + public static List getEntitiesWithinAABB(World world, Class clazz, Vec3d center, float range, @Nullable Predicate filter) + { + return world.getEntitiesWithinAABB(clazz, IDLGeneral.ServerAABB(center.addVector(-range, -range, -range), center.addVector(range, range, range)) , filter); + } + + public static Vec3d GetRandomAroundUnderfoot(EntityLivingBase entity, float radius) + { + float angle = entity.getRNG().nextFloat() * 6.282f; + return new Vec3d(entity.posX + Math.sin(angle), entity.posY, entity.posZ + Math.cos(angle)); + } + + public static Vec3d GetRandomAroundPos(Vec3d pos, float radius, Random rng) + { + float angle = rng.nextFloat() * 6.282f; + return new Vec3d(pos.x + Math.sin(angle), pos.y, pos.z + Math.cos(angle)); + } + + public static void SpawnParticleAround(EntityLivingBase entity, EnumParticleTypes particleTypes) + { + Vec3d pos = GetRandomAroundUnderfoot(entity,1f); + entity.world.spawnParticle(particleTypes, pos.x, pos.y, pos.z, 0,0,0); + } + + public static void SpawnParticleAround(EntityLivingBase entity, EnumParticleTypes particleTypes, int count) + { + for (int i = 0; i < count; i++) + { + SpawnParticleAround(entity, particleTypes); + } + } + + public static void createTeleportEffect(EntityLivingBase livingBase) + { + if (livingBase == null) + { + return; + } + + World worldIn = livingBase.world; + if (worldIn.isRemote) + { + Vec3d oriPos = livingBase.getPositionEyes(0); + Random random = livingBase.getRNG(); + AxisAlignedBB bb = livingBase.getRenderBoundingBox(); + double radiusX = bb.maxX - bb.minX; + double radiusY = bb.maxY - bb.minY; + double radiusZ = bb.maxZ - bb.minZ; + + for (int i = 0; i <= 10; i++) + { + worldIn.spawnParticle(EnumParticleTypes.PORTAL, + CommonFunctions.flunctate(oriPos.x, radiusX, random), + CommonFunctions.flunctate(oriPos.y, radiusY, random), + CommonFunctions.flunctate(oriPos.z, radiusZ, random), + random.nextFloat(), + random.nextFloat(), + random.nextFloat() + ); + } + + worldIn.playSound(oriPos.x, oriPos.y, oriPos.z, SoundEvents.ENTITY_ENDERMEN_TELEPORT, null, 1f, 1.3f, false); + } + } + + static float angle = 0f; + + @SubscribeEvent + static void onWorldTick(TickEvent.WorldTickEvent event) + { + if (event.type == TickEvent.Type.WORLD ) + { + angle += 1.0f;//ModConfig.DEBUG_CONF.HALO_OMEGA; + angle %= 6.282f; + } + } + + public static void spawnHaloParticleAround(EntityLivingBase entity, EnumParticleTypes particleTypes, float radius) + { + for (int i = 0; i < 10; i++) + { + float deltaOmega = 1.0f * i;//ModConfig.DEBUG_CONF.HALO_OMEGA; + Vec3d pos = new Vec3d(entity.posX + radius * Math.sin(angle + deltaOmega), entity.posY + 0.1f * entity.getRNG().nextFloat(), entity.posZ + radius * Math.cos(angle + deltaOmega)); + entity.world.spawnParticle(particleTypes, pos.x, pos.y, pos.z, 0,0,0); + } + } + + public static Faction faction(EntityLivingBase creature) + { + if (isMoroonTeam(creature)) + { + return Faction.MOROON; + } else if (isIdeallandTeam(creature)) + { + return Faction.IDEALLAND; + }else if (creature instanceof EntityZombie) + { + return Faction.MOB_VAN_ZOMBIE; + } + else if (creature instanceof IMob) + { + return Faction.MOB_VANILLA; + }else if (creature instanceof EntityPlayer) + { + return Faction.PLAYER; + }else + { + return Faction.CRITTER; + } + } + + public static ATTITUDE getAttitude(EntityLivingBase subject, EntityLivingBase object) + { + if (subject == null || object == null) + { + return ATTITUDE.IGNORE; + } + + if (subject.isOnSameTeam(object)) + { + return ATTITUDE.FRIEND; + } + return getAttitude(faction(subject), faction(object)); + } + + public static ATTITUDE getAttitude(Faction subject, EntityLivingBase object) + { + return getAttitude(subject, faction(object)); + } + + public static ATTITUDE getAttitude(Faction subject, Faction object) + { + if (subject == object) + { + return ATTITUDE.FRIEND; + } + + if (subject == Faction.CRITTER || object == Faction.CRITTER) + { + return ATTITUDE.IGNORE; + } + + switch (subject) + { + case PLAYER: + case IDEALLAND: + switch (object) + { + case IDEALLAND: + return ATTITUDE.FRIEND; + case MOB_VANILLA: + case MOB_VAN_ZOMBIE: + case MOROON: + return ATTITUDE.HATE; + default: + return ATTITUDE.IGNORE; + } + case MOB_VANILLA: + switch (object) + { + case IDEALLAND: + case PLAYER: + return ATTITUDE.HATE; + case MOB_VAN_ZOMBIE: + return ATTITUDE.FRIEND; + + default: + return ATTITUDE.IGNORE; + } + + case MOB_VAN_ZOMBIE: + switch (object) + { + case IDEALLAND: + case PLAYER: + return ATTITUDE.HATE; + + case MOB_VANILLA: + return ATTITUDE.FRIEND; + + default: + return ATTITUDE.IGNORE; + } + + case MOROON: + switch (object) + { + case IDEALLAND: + case MOB_VAN_ZOMBIE: + case PLAYER: + return ATTITUDE.HATE; + + default: + return ATTITUDE.IGNORE; + } + } + return ATTITUDE.IGNORE; + } + + public static Vec3d GetRandomAround(EntityLivingBase entity, float radius) + { + float angle = entity.getRNG().nextFloat() * 6.282f; + return new Vec3d(entity.posX + Math.sin(angle), entity.getEyeHeight() + entity.posY, entity.posZ + Math.cos(angle)); + } + + public static final Predicate InWater = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && p_apply_1_.isInWater(); + } + }; + + public static final Predicate FriendToIdl = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && (getAttitude(Faction.IDEALLAND, p_apply_1_)==ATTITUDE.FRIEND); + } + }; + + public static final Predicate HostileToIdl = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && (getAttitude(Faction.IDEALLAND, p_apply_1_)==ATTITUDE.HATE) && (p_apply_1_).attackable(); + } + }; + + public static final Predicate HostileToIdl_AIR = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && (getAttitude(Faction.IDEALLAND, p_apply_1_)==ATTITUDE.HATE) && (p_apply_1_).attackable() && !p_apply_1_.onGround; + } + }; + + public static final Predicate HostileToMor = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && (getAttitude(Faction.MOROON, p_apply_1_)==ATTITUDE.HATE) && (p_apply_1_).attackable(); + } + }; + + public static final Predicate IsVanilla = new Predicate() + { + public boolean apply(@Nullable EntityLivingBase p_apply_1_) + { + return p_apply_1_ != null && isVanillaResident((p_apply_1_)) && (p_apply_1_).attackable(); + } + }; + public static double getAttack(EntityLivingBase creature) + { + if (creature == null) + { + return 0; + } + + IAttributeInstance attribute = creature.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); + if (attribute == null) + { + return 0; + } + return attribute.getAttributeValue(); + } + + public static double getSight(EntityLivingBase creature) + { + if (creature == null) + { + return 0; + } + + IAttributeInstance attribute = creature.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE); + return attribute.getAttributeValue(); + } + + public static double getAtkSpeed(EntityLivingBase creature) + { + if (creature == null) + { + return 0; + } + + IAttributeInstance attribute = creature.getEntityAttribute(SharedMonsterAttributes.ATTACK_SPEED); + return attribute.getAttributeValue(); + } + + public static double getAttr(EntityLivingBase creature, IAttribute attr) + { + if (creature == null) + { + return 0; + } + + IAttributeInstance attribute = creature.getEntityAttribute(attr); + if (attribute == null) + { + return 0; + } + return attribute.getAttributeValue(); + } + + public static double getAttrBase(EntityLivingBase creature, IAttribute attr) + { + if (creature == null) + { + return 0; + } + + IAttributeInstance attribute = creature.getEntityAttribute(attr); + if (attribute == null) + { + return 0; + } + return attribute.getBaseValue(); + } + + public static boolean boostAttr(EntityLivingBase creature, IAttribute attrType, float amountFixed, UUID uuid) + { + float val = amountFixed; + IAttributeInstance attribute = creature.getEntityAttribute(attrType); + + if (attribute == null) + { + //this happens on creatures with no attack. + //will surely happen. + creature.playSound(SoundEvents.BLOCK_DISPENSER_FAIL, 1f, 1f); + return false; + } + + double valueBefore = attribute.getAttributeValue(); + + AttributeModifier modifier = attribute.getModifier(uuid); + if (modifier != null) + { + //stack up + val += modifier.getAmount(); + attribute.removeModifier(modifier); + } + attribute.applyModifier(new AttributeModifier(uuid, "pwr up", val, 0)); + double valueAfter = attribute.getAttributeValue(); + + if (modifier == null) + { + modifier = attribute.getModifier(uuid); + } + + //IdlFramework.Log("Value:%s: %.2f->%.2f", modifier.getName(), valueBefore, valueAfter); + return true; + } + + public static boolean boostAttrRatio(EntityLivingBase creature, IAttribute attrType, float amountRatio, UUID uuid) + { + float val = amountRatio; + IAttributeInstance attribute = creature.getEntityAttribute(attrType); + + if (attribute == null) + { + //this happens on creatures with no attack. + //will surely happen. + creature.playSound(SoundEvents.BLOCK_DISPENSER_FAIL, 1f, 1f); + return false; + } + + double valueBefore = attribute.getAttributeValue(); + + AttributeModifier modifier = attribute.getModifier(uuid); + if (modifier != null) + { + //stack up + val += modifier.getAmount(); + attribute.removeModifier(modifier); + } + attribute.applyModifier(new AttributeModifier(uuid, "pwr up percent", val, 1)); + double valueAfter = attribute.getAttributeValue(); + + if (modifier == null) + { + modifier = attribute.getModifier(uuid); + } + + //IdlFramework.Log("Value:%s: %.2f->%.2f", modifier.getName(), valueBefore, valueAfter); + return true; + } + + public enum Faction{ + PLAYER, + IDEALLAND, + MOB_VANILLA, + MOB_VAN_ZOMBIE, + MOROON, + CRITTER, + } + + public enum ATTITUDE{ + HATE, + IGNORE, + FRIEND + } + + public static Biome getBiomeForEntity(Entity entity) + { + World world = entity.getEntityWorld(); + return world.getBiomeForCoordsBody(entity.getPosition()); + } + + public static boolean isSunlit(Entity entity) + { + float f = entity.getBrightness(); + return f > 0.5F && entity.world.canSeeSky(new BlockPos(entity.posX, entity.posY + (double)entity.getEyeHeight(), entity.posZ)); + } + + public static boolean isMoonlit(Entity entity) + { + int tickInDay = (int) (entity.getEntityWorld().getWorldTime() % 24000); + if (tickInDay > 167 && tickInDay < 11834) + { + return false; + } + return entity.world.canSeeSky(new BlockPos(entity.posX, entity.posY + (double)entity.getEyeHeight(), entity.posZ)); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/IDLGeneral.java b/src/main/java/com/somebody/idlframewok/util/IDLGeneral.java new file mode 100644 index 0000000..07481e8 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/IDLGeneral.java @@ -0,0 +1,47 @@ +package com.somebody.idlframewok.util; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3d; + +public class IDLGeneral { + //server side dont have this constructor. + public static AxisAlignedBB ServerAABB(Vec3d from, Vec3d to) + { + return new AxisAlignedBB(from.x, from.y, from.z, to.x, to.y, to.z); + } + + public static AxisAlignedBB ServerAABB(Vec3d origin, float range) + { + return new AxisAlignedBB(origin.x - range, origin.y - range, origin.z - range, + origin.x + range, origin.y + range, origin.z + range); + } + + public static boolean EntityHasBuff(EntityLivingBase livingBase, Potion buff) + { + return livingBase.getActivePotionEffect(buff) != null; + } + + public static int EntityBuffCounter(EntityLivingBase livingBase, Potion buff) + { + PotionEffect effect = livingBase.getActivePotionEffect(buff); + return effect == null ? -1 : effect.getDuration(); + } + + public static int returnGuaIndex(ItemStack stack) + { + Item item = stack.getItem(); +// for (int i = 0; i < GUA_TYPES; i++) +// { +// if (item == ModItems.GUA[i]) +// { +// return i; +// } +// } + return -1; + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/IDLNBT.java b/src/main/java/com/somebody/idlframewok/util/IDLNBT.java new file mode 100644 index 0000000..d4d2df6 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/IDLNBT.java @@ -0,0 +1,164 @@ +package com.somebody.idlframewok.util; + +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; + +public class IDLNBT { + public int pearlCount; + public boolean isEarth; + public boolean isSky; + + private final NBTTagCompound basic; + + public IDLNBT() + { + pearlCount = 0; + isEarth = false; + isSky = false; + + basic = new NBTTagCompound(); + } + + public IDLNBT(NBTTagCompound srcNBT) + { + readFromBasic(srcNBT); + basic = srcNBT; + } + + public void readFromBasic(NBTTagCompound tag) + { + if (tag != null) + { + pearlCount = tag.getInteger(IDLNBTDef.LEVEL_TAG); + isEarth = tag.getBoolean(IDLNBTDef.IS_EARTH); + isSky = tag.getBoolean(IDLNBTDef.IS_SKY); + } + } + + public void writeToBasic(NBTTagCompound tag) + { + if (tag == null) + { + tag = new NBTTagCompound(); + } + + tag.setInteger(IDLNBTDef.LEVEL_TAG, pearlCount); + tag.setBoolean(IDLNBTDef.IS_EARTH, isEarth); + tag.setBoolean(IDLNBTDef.IS_SKY, isSky); + } + + public NBTTagCompound getBasic() + { + NBTTagCompound tag = basic.copy(); + writeToBasic(tag); + + return tag; + } + + public void save() + { + writeToBasic(basic); + } + + //PlayerData + //--PERSISTED_NBT_TAG + // --IDEALLAND + // --KILL_COUNT,etc + + + public static NBTTagCompound getTagSafe(NBTTagCompound tag, String key) { + if(tag == null) { + return new NBTTagCompound(); + } + + return tag.getCompoundTag(key); + } + + public static NBTTagCompound getPlyrIdlTagSafe(EntityPlayer player) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getTagSafe(data, IDLNBTDef.IDEALLAND); + + return idl_data; + } + + public static NBTTagCompound getPlayerIdeallandTagGroupSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getCompoundTag(key); + } + + public static int[] getPlayerIdeallandIntArraySafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getIntArray(key); + } + + public static int getPlayerIdeallandIntSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getInteger(key); + } + public static float getPlayerIdeallandFloatSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getFloat(key); + } + public static double getPlayerIdeallandDoubleSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getDouble(key); + } + public static boolean getPlayerIdeallandBoolSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getBoolean(key); + } + public static String getPlayerIdeallandStrSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getString(key); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, int value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setInteger(key, value); + + data.setTag(IDLNBTDef.IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, int[] value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setIntArray(key, value); + + data.setTag(IDLNBTDef.IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, double value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setDouble(key, value); + + data.setTag(IDLNBTDef.IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, boolean value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setBoolean(key, value); + + data.setTag(IDLNBTDef.IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, String value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setString(key, value); + + data.setTag(IDLNBTDef.IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/IDLSkillNBT.java b/src/main/java/com/somebody/idlframewok/util/IDLSkillNBT.java new file mode 100644 index 0000000..1dd29af --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/IDLSkillNBT.java @@ -0,0 +1,322 @@ +package com.somebody.idlframewok.util; + +import java.util.List; + +import com.somebody.idlframewok.item.IGuaEnhance; +import com.somebody.idlframewok.item.skills.ItemSkillBase; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef; +import com.somebody.idlframewok.util.NBTStrDef.IDLNBTUtil; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class IDLSkillNBT { + public static final String SUCCESS_DESC_KEY = ".on_sucess"; + public static final String IN_CD_DESC_KEY = ".on_cooldown"; + public int level; + public int range_boost = 0; + public int duration_boost = 0; + public int[] gua_boost = new int[8]; + +// private final NBTTagCompound basic; + +// public IDLSkillNBT() +// { +// level = 1; +// range_boost = 0; +// duration_boost = 0; +// +// basic = new NBTTagCompound(); +// } +// +// public IDLSkillNBT(NBTTagCompound srcNBT) +// { +// readFromBasic(srcNBT); +// basic = srcNBT; +// } +// +// public void readFromBasic(NBTTagCompound tag) +// { +// if (tag != null) +// { +// level = tag.getInteger(IDLNBTDef.LEVEL_TAG); +// range_boost = tag.getInteger(IDLNBTDef.RANGE_BOOST); +// duration_boost = tag.getInteger(IDLNBTDef.DURA_BOOST); +// } +// } + +// public void writeToBasic(NBTTagCompound tag) +// { +// if (tag == null) +// { +// tag = new NBTTagCompound(); +// } +// +// tag.setInteger(IDLNBTDef.LEVEL_TAG, level); +// tag.setInteger(IDLNBTDef.RANGE_BOOST, range_boost); +// tag.setInteger(IDLNBTDef.DURA_BOOST, duration_boost); +// } +// +// public NBTTagCompound getBasic() +// { +// NBTTagCompound tag = basic.copy(); +// writeToBasic(tag); +// +// return tag; +// } +// +// public void save() +// { +// writeToBasic(basic); +// } + //---------------------- + //Integer + public static void SetGuaEnhance(ItemStack stack, int guaIndex, int value) + { + NBTTagCompound ori = IDLNBTUtil.getNBT(stack); + + NBTTagCompound subset = new NBTTagCompound(); + subset.setInteger(IDLNBTDef.GUA_ENHANCE_8 + guaIndex, value); + + NBTTagCompound newTag = new NBTTagCompound(); + newTag.setTag(IDLNBTDef.GUA_ENHANCE, subset); + + ori.merge(newTag); +// if (!StackHasKey(stack, GUA_ENHANCE)) +// { +// getNBT(stack).setTag(GUA_ENHANCE, new NBTTagCompound()); +// }else { +// +// } +// +// NBTTagCompound guaEnhanceNBT = getNBT(stack).getCompoundTag(GUA_ENHANCE); +// +// guaEnhanceNBT.setInteger(GUA_ENHANCE_8 + guaIndex, value); + } + + public static void AddGuaEnhance(ItemStack stack, int guaIndex, int value) + { + SetGuaEnhance(stack, guaIndex, value + GetGuaEnhance(stack, guaIndex)); + } + + public static String GetGuaEnhanceString(ItemStack stack, int guaIndex) + { + Item stackItem = stack.getItem(); + if (stackItem instanceof IGuaEnhance) + { + IGuaEnhance guaEnhance = (IGuaEnhance) stackItem; + if (guaEnhance.acceptGuaIndex(guaIndex)) + { + return String.valueOf(GetGuaEnhance(stack, guaIndex, 0)); + } + else { + return I18n.format(IDLNBTDef.GUA_N_A_DESC); + } + } + else { + return ""; + } + + } + + public static int GetGuaEnhance(ItemStack stack, int guaIndex) + { + return GetGuaEnhance(stack, guaIndex, 0); + } + + public static int GetGuaEnhance(ItemStack stack, int guaIndex, int defaultVal) + { + if (IDLNBTUtil.StackHasKey(stack, IDLNBTDef.GUA_ENHANCE)) + { + NBTTagCompound nbt = IDLNBTUtil.getNBT(stack).getCompoundTag(IDLNBTDef.GUA_ENHANCE); + String str = String.valueOf(IDLNBTDef.GUA_ENHANCE_8 + guaIndex); + if (nbt.hasKey(str)) + { + return nbt.getInteger(str); + } + } + + return defaultVal; + } + + public static int GetGuaEnhanceTotal(ItemStack stack) + { + int result = 0; + if (IDLNBTUtil.StackHasKey(stack, IDLNBTDef.GUA_ENHANCE)) + { + NBTTagCompound nbt = IDLNBTUtil.getNBT(stack).getCompoundTag(IDLNBTDef.GUA_ENHANCE); + for (String key: nbt.getKeySet() + ) { + result += nbt.getInteger(key); + } + } + + return result; + } + + public static int GetGuaEnhanceFree(ItemStack stack) + { + return IDLNBTUtil.GetInt(stack, IDLNBTDef.GUA_FREE_SOCKET); + } + + public static void SetGuaEnhanceFree(ItemStack stack, int val) + { + IDLNBTUtil.SetInt(stack, IDLNBTDef.GUA_FREE_SOCKET, val); + } + + @SideOnly(Side.CLIENT) + public static void addInformation(ItemStack stack, World world, List tooltip, ITooltipFlag flag, + boolean shiftToShowDesc, boolean showGuaSocketDesc, boolean use_flavor, String mainDescOrFlavor) { + + boolean shiftPressed = !shiftToShowDesc || CommonFunctions.isShiftPressed(); + if (shiftPressed) + { + if (!mainDescOrFlavor.isEmpty()) + { + tooltip.add(mainDescOrFlavor); + } + + if (showGuaSocketDesc) + { + int guaTotal = IDLSkillNBT.GetGuaEnhanceTotal(stack); + tooltip.add(I18n.format(IDLNBTDef.GUA_TOTAL_SOCKET_DESC, IDLSkillNBT.GetGuaEnhanceTotal(stack))); + if (guaTotal > 0) + { + tooltip.add(I18n.format("idlframewok.gua_enhance_list.desc", GetGuaEnhanceString(stack, 0), + GetGuaEnhanceString(stack, 1), + GetGuaEnhanceString(stack, 2), + GetGuaEnhanceString(stack, 3), + GetGuaEnhanceString(stack, 4), + GetGuaEnhanceString(stack, 5), + GetGuaEnhanceString(stack, 6), + GetGuaEnhanceString(stack, 7))); + } + + int freeSockets = IDLSkillNBT.GetGuaEnhanceFree(stack); + if (freeSockets > 0) + { + tooltip.add(TextFormatting.AQUA + I18n.format(IDLNBTDef.GUA_FREE_SOCKET_DESC, freeSockets)); + } + else { + tooltip.add(TextFormatting.ITALIC + (TextFormatting.WHITE + I18n.format(IDLNBTDef.GUA_NO_FREE_SOCKET_DESC))); + } + } + } + else { + tooltip.add(TextFormatting.AQUA + I18n.format("idlframewok.shared.press_shift")); + if (use_flavor) + { + tooltip.add(TextFormatting.ITALIC + mainDescOrFlavor); + } + } + } + + public static int getLevel(ItemStack stack) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return 0; + } + ItemSkillBase skillBase = (ItemSkillBase) stack.getItem(); + + int level = IDLNBTUtil.GetInt(stack, IDLNBTDef.LEVEL_TAG); + + if (level <= 0) + { + return 1; + } + + int lvMax = skillBase.GetLevelMax(stack); + + if (level > lvMax) + { + return lvMax; + } + + return level; + } + + public static void SetLevel(ItemStack stack, int count) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return; + } + ItemSkillBase skillBase = (ItemSkillBase) stack.getItem(); + + if (count <= skillBase.GetLevelMax(stack)) { + IDLNBTUtil.SetInt(stack, IDLNBTDef.LEVEL_TAG, count); + } + } + + public static boolean IsCasting(ItemStack stack) + { + return IDLNBTUtil.GetBoolean(stack, IDLNBTDef.IS_CASTING); + } + + public static void SetCasting(ItemStack stack, boolean bool) + { + IDLNBTUtil.SetBoolean(stack, IDLNBTDef.IS_CASTING, bool); + } + + public static void SetDura(ItemStack stack, float count) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return; + } + ItemSkillBase skillBase = (ItemSkillBase) stack.getItem(); + + IDLNBTUtil.SetInt(stack, IDLNBTDef.CUR_TIME_LEFT, (int) (count * CommonDef.INT_AS_FLOAT)); + } + + public static void SetCharge(ItemStack stack, float count) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return; + } + ItemSkillBase skillBase = (ItemSkillBase) stack.getItem(); + + IDLNBTUtil.SetInt(stack, IDLNBTDef.CUR_CHARGE, (int) (count * CommonDef.INT_AS_FLOAT)); + } + + public static float GetCharge(ItemStack stack) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return 0; + } + + int charge = IDLNBTUtil.GetInt(stack, IDLNBTDef.CUR_CHARGE); + + return (float)charge / CommonDef.INT_AS_FLOAT; + } + + public static float GetDura(ItemStack stack) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return 0; + } + int dura = IDLNBTUtil.GetInt(stack, IDLNBTDef.CUR_TIME_LEFT); + + return (float)dura / CommonDef.INT_AS_FLOAT; + } + + public static void AddLevelByCount(ItemStack stack, int count) + { + if (!(stack.getItem() instanceof ItemSkillBase)) { + return; + } + ItemSkillBase skillBase = (ItemSkillBase) stack.getItem(); + int lvMax = skillBase.GetLevelMax(stack); + int anticipatedCount = count + getLevel(stack); + if (anticipatedCount <= lvMax ) { + IDLNBTUtil.SetInt(stack, IDLNBTDef.LEVEL_TAG, anticipatedCount); + } + else { + IDLNBTUtil.SetInt(stack, IDLNBTDef.LEVEL_TAG, lvMax); + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/IHasModel.java b/src/main/java/com/somebody/idlframewok/util/IHasModel.java new file mode 100644 index 0000000..0577184 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/IHasModel.java @@ -0,0 +1,5 @@ +package com.somebody.idlframewok.util; + +public interface IHasModel { + public void registerModels(); +} diff --git a/src/main/java/com/somebody/idlframewok/util/MessageDef.java b/src/main/java/com/somebody/idlframewok/util/MessageDef.java new file mode 100644 index 0000000..1092500 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/MessageDef.java @@ -0,0 +1,17 @@ +package com.somebody.idlframewok.util; + +import net.minecraft.item.ItemStack; + +public class MessageDef { + //GENERAL: + public static final String OUT_OF_RANGE = "idlframewok.msg.out_of_range"; + public static final String IN_COOLDOWN = "idlframewok.skill.msg.cool_down"; + public static final String NOT_CASTABLE_MAINHAND = "idlframewok.skill.msg.not_castable_mainhand"; + public static final String NOT_CASTABLE_OFFHAND = "idlframewok.skill.msg.not_castable_offhand"; + + public static String getSkillCastKey(ItemStack stack, int index) + { + //remove"item." + return String.format("msg.%s.cast.%d", stack.getUnlocalizedName().substring(5), index); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/ModSoundHandler.java b/src/main/java/com/somebody/idlframewok/util/ModSoundHandler.java new file mode 100644 index 0000000..a121809 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/ModSoundHandler.java @@ -0,0 +1,25 @@ +package com.somebody.idlframewok.util; + +import java.util.ArrayList; +import java.util.List; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.sound.ModSoundEvent; +import net.minecraft.util.SoundEvent; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +public class ModSoundHandler { + //To add a sound, remember assets.idlframewok.sounds.json + public static final List SOUNDS = new ArrayList<>(); + +// public static SoundEvent SOUND_1 = new ModSoundEvent("entity.moroon.ambient"); +// public static SoundEvent SOUND_2 = new ModSoundEvent("entity.moroon.hurt"); + + public static void soundRegister() + { + IdlFramework.Log("Registering %s sounds.", SOUNDS.size()); + ForgeRegistries.SOUND_EVENTS.registerAll(ModSoundHandler.SOUNDS.toArray(new SoundEvent[0])); + IdlFramework.Log("Registered %s sounds.", SOUNDS.size()); + } + +} diff --git a/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTDef.java b/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTDef.java new file mode 100644 index 0000000..4101c22 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTDef.java @@ -0,0 +1,164 @@ +package com.somebody.idlframewok.util.NBTStrDef; + +import com.somebody.idlframewok.IdlFramework; + +public class IDLNBTDef { + //GENERAL: + public static final String IDEALLAND = "idealland_nbt"; + + //NBT + public static final String IS_EARTH = "is_earth"; + public static final String IS_SKY = "is_sky"; + + //UNO + public static final String CARD_SUIT = "card_suit"; + + //goblet + public static final String P2W_EXP = "p2w_experience"; + public static final String P2W_PAYING_EXP = "p2w_experience_paying"; + public static final String P2W_CACHE_EXP = "p2w_experience_cache"; + + //skill + public static final String LEVEL_TAG = "level"; + public static final String RANGE_BOOST = "range_boost"; + public static final String DURA_BOOST = "dura_boost"; + public static final String IS_IDENTIFIED = "identified"; + public static final String STATE = "state"; + public static final String STATE_2 = "state2"; + + public static final String IS_NAME_HIDDEN = "name_hidden"; + public static final String IS_MANUAL_READY = "manual_ready"; + public static final String OWNER = "owner"; + public static final String IS_HEIRLOOM = "heirloom_of"; + public static final String HATE = "hate"; + + //skill arknights + public static final String IS_CASTING = "is_casting"; + public static final String CUR_CHARGE = "cur_charge";//x100 + public static final String CUR_TIME_LEFT = "time_left";//x100,please note that two may be the same + + + public static final String EDICT_REPEATABLE = "is_repeatable"; + + //upgrading + public static final String DIFFICULTY = "difficulty"; + + //TOOLTIP + public static final String TOOLTIP_SKY = ".sky_desc"; + public static final String TOOLTIP_EARTH = ".earth_desc"; + public static final String TOOLTIP_NORMAL = ".normal_desc"; + public static final String TOOLTIP_SHARED = ".shared_desc"; + public static final String TOOLTIP_HIDDEN = ".hidden"; + public static final String TOOLTIP_DAMAGE = ".damage_desc"; + + public static final String NAME_OFF= "idlframewok.shared.off"; + public static final String NAME_ON= "idlframewok.shared.on"; + + public static final String TRUENAME_TO_REVEAL = ".true_name_reveal"; + public static final String MANUAL_PAGE_COUNT = ".manual_page_count"; + public static final String MANUAL_PAGE_KEY = ".manual_page_"; + public static final String MANUAL_AUTHOR = ".manual_author"; + public static final String MANUAL_TITLE = ".manual_title"; + + //player + public static final String STARTER_BOOK_GIVEN = "starter_book_given"; + + //goblet + public static final String ASSIGNED_BLOCK_NAME = "assigned_block"; + + //IDL + public static final String DESC_COMMON = ".desc"; + public static final String KILL_COUNT = "kill_count"; + public static final String KILL_COUNT_MOR = "kill_count_mor"; + public static final String MOR_INTEREST = "mor_interest"; + + public static final String CHARGE_VALUE = "charge_value"; + + public static final String BIOMETAL_WARNED = "biometal_warned"; + + public static final String MODE = "mode"; + + public static final String STARTER_KIT_VERSION_TAG = "last_starter_kit_" + IdlFramework.MODID; + public static final int CUR_STARTER_KIT_VERSION = 2; + + //edict + public static final String EDICT_START = ".on_start"; + public static final String EDICT_END= ".on_end"; + public static final String EDICT_FAIL = ".on_fail"; + + public static final String EDICT_COMMON_START = "edict.shared.start"; + public static final String EDICT_COMMON_END = "edict.shared.end"; + public static final String EDICT_COMMON_FAIL = "edict.shared.fail"; + + + public static final String EDICT_COMMON_REPEAT = "edict.shared.repeatable"; + + //Builder + public static final String CUR_TASK_INDEX = "cur_task_index"; + public static final String BUILD_SPEED = "build_speed"; + public static final String BUILD_ARG_1 = "build_arg_1"; + public static final String BUILD_ARG_2 = "build_arg_2"; + + //gua socket + public static final String GUA_NO_FREE_SOCKET_DESC = "idlframewok.gua_enhance_no_free.desc"; + public static final String GUA_FREE_SOCKET_DESC = "idlframewok.gua_enhance_free.desc"; + public static final String GUA_TOTAL_SOCKET_DESC = "idlframewok.gua_enhance_total.desc"; + public static final String GUA_N_A_DESC = "idlframewok.gua_not_applicable.desc"; + + public static final String GUA_FREE_SOCKET = "gua_free_socket"; + public static final String GUA_ENHANCE = "gua_enhance"; + public static final String GUA_ENHANCE_8 = "gua_e_8"; + public static final String GUA_ENHANCE_64 = "gua_e_64"; + + //anchor + public static final String ANCHOR_READY = "anchor_ready"; + public static final String ANCHOR_X = "anchor_x"; + public static final String ANCHOR_Y = "anchor_y"; + public static final String ANCHOR_Z = "anchor_z"; + + public static final String ANCHOR_READY_2 = "anchor_ready_2"; + public static final String ANCHOR_X_2 = "anchor_x_2"; + public static final String ANCHOR_Y_2 = "anchor_y_2"; + public static final String ANCHOR_Z_2 = "anchor_z_2"; + + public static final String BUILDING_CHARGE = "building_charge"; + + //research + public static final String PACK_CODE = "pack_code"; + public static final String LEARNING_ID = "learning_id"; + public static final String LEARNING_PROGRESS = "learning_progress"; + public static final String LEARNING_DONE = "learning_done"; + + //temperature + public static final String BASE_TEMPERATURE = "base_temperature"; + public static final String BASE_IS_SET = "base_is_set"; + + //level + public static final String LAST_LEVEL = "last_lv"; + + public static final String LEVEL = "lv_idl"; + + public static final String INIT_DONE = "init_done"; + + + //nonsense + public static final String KILL_COUNT_ITEM = "kill_count";//marked on items, not players + public static final String KILL_COUNT_DESC = "idlframewok.kill_count.desc"; + + public static final String MARKING_POS_A = "marking_pos_a"; + public static final String MARKING_POS_B = "marking_pos_b"; + + public static final String MARK_ATK = "mark.attackDamage"; + public static final String MARK_HP = "mark.maxHealth"; + public static final String MARK_DEF = "mark.armor"; + public static final String MARK_ARMOR_T = "mark.armorToughness"; + public static final String MARK_RANGE = "mark.followRange"; + public static final String MARK_KB_R = "mark.knockbackResistance"; + public static final String MARK_SPEED = "mark.movementSpeed"; + public static final String MARK_ATK_SPEED = "mark.attackSpeed"; + + public static final String MARK_TOTAL_COUNT = "mark.count"; + + + public static final String FLAVOR_KEY = ".flvr"; +} diff --git a/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTUtil.java b/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTUtil.java new file mode 100644 index 0000000..78cf636 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/NBTStrDef/IDLNBTUtil.java @@ -0,0 +1,558 @@ +package com.somebody.idlframewok.util.NBTStrDef; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import javax.annotation.Nullable; + +import com.somebody.idlframewok.IdlFramework; +import com.somebody.idlframewok.util.IDLNBT; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; + +import static com.somebody.idlframewok.util.NBTStrDef.IDLNBTDef.*; + +//on a server, strlen 65000 is ok, but 66000 will crash +public class IDLNBTUtil { + public static NBTTagCompound getNBT(ItemStack stack) + { + NBTTagCompound nbt = stack.getTagCompound(); + if (nbt == null) + { + nbt = new NBTTagCompound(); + stack.setTagCompound(nbt); + } + return nbt; + } + + //so it won't produce empty tags + public static NBTTagCompound getNBTReadOnly(ItemStack stack) { + NBTTagCompound nbt = stack.getTagCompound(); + if (nbt == null) { + return new NBTTagCompound(); + } + return nbt; + } + + public static NBTTagCompound getNBT(Entity entity) { + NBTTagCompound nbt = entity.getEntityData(); + return nbt; + } + + //allow null + public static NBTTagCompound getNBT(NBTTagCompound tag) { + if(tag == null) { + return new NBTTagCompound(); + } + + return tag; + } + + //writeEntityToNBT + //readEntityFromNBT + + @Nullable + public static boolean StackHasKey(ItemStack stack, String key) { + return !(stack.isEmpty() || !getNBTReadOnly(stack).hasKey(key)); + } + + //Boolean + public static boolean SetBoolean(ItemStack stack, String key, boolean value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setBoolean(key, value); + return true; + } + + public static boolean GetBoolean(ItemStack stack, String key, boolean defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getBoolean(key); + } + else + { + return defaultVal; + } + } + + public static boolean GetBoolean(ItemStack stack, String key) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getBoolean(key); + } + else + { + return false; + } + } + //get with default val + public static boolean GetBooleanDF(ItemStack stack, String key, boolean defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getBoolean(key); + } + else + { + return defaultVal; + } + } + + //Double + public static boolean SetDouble(ItemStack stack, String key, double value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setDouble(key, value); + return true; + } + + public static double GetDouble(ItemStack stack, String key, double defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getDouble(key); + } + else + { + return defaultVal; + } + } + + //Integer + public static boolean SetLong(ItemStack stack, String key, long value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setLong(key, value); + return true; + } + + public static boolean SetState(ItemStack stack, int value) + { + return SetInt(stack, STATE, value); + } + public static boolean SetState2(ItemStack stack, int value) + { + return SetInt(stack, STATE_2, value); + } + + public static boolean SetInt(ItemStack stack, String key, int value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setInteger(key, value); + return true; + } + //Used for state on-off things. + public static boolean switchState(ItemStack stack) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setInteger(STATE, nbt.getInteger(STATE) > 0 ? 0 : 1); + return true; + } + + public static boolean setIntOptimized(ItemStack stack, String key, int value) + { + NBTTagCompound nbt = getNBT(stack); + if (nbt.getInteger(key) != value) + { + nbt.setInteger(key, value); + } + return true; + } + public static boolean SetInt(Entity entity, String key, int value) + { + NBTTagCompound nbt = getNBT(entity); + nbt.setInteger(key, value); + return true; + } + + public static boolean setIntAuto(Entity entity, String key, int value) + { + if (entity instanceof EntityPlayer) + { + setPlayerIdeallandTagSafe((EntityPlayer) entity, key, value); + return true; + } + NBTTagCompound nbt = getNBT(entity); + nbt.setInteger(key, value); + return true; + } + + public static boolean addIntAuto(Entity entity, String key, int value) + { + int oldVal = GetIntAuto(entity, key, 0); + setIntAuto(entity, key, value + oldVal); + return true; + } + + public static boolean addInt(ItemStack stack, String key, int value) { + int oldVal = GetInt(stack, key, 0); + SetInt(stack, key, value + oldVal); + return true; + } + + public static int GetInt(Entity entity, String key, int defaultVal) + { + if (EntityHasKey(entity, key)) + { + NBTTagCompound nbt = getNBT(entity); + return nbt.getInteger(key); + } + else + { + return defaultVal; + } + } + + public static int GetIntAuto(Entity entity, String key, int defaultVal) + { + if (entity instanceof EntityPlayer) + { + return getPlayerIdeallandIntSafe((EntityPlayer) entity, key); + } + + if (EntityHasKey(entity, key)) + { + NBTTagCompound nbt = getNBT(entity); + return nbt.getInteger(key); + } + else + { + return defaultVal; + } + } + + public static int GetState(ItemStack stack) + { + return GetInt(stack, STATE); + } + + public static int GetState2(ItemStack stack) + { + return GetInt(stack, STATE_2); + } + + public static int GetInt(ItemStack stack, String key, int defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getInteger(key); + } + else + { + return defaultVal; + } + } + + public static long GetLong(ItemStack stack, String key, int defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getLong(key); + } + else + { + return defaultVal; + } + } + + + public static int GetInt(ItemStack stack, String key) + { + return GetInt(stack, key, 0); + } + + //String + public static String GetString(ItemStack stack, String key, String defaultVal) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getString(key); + } + else + { + return defaultVal; + } + } + + public static boolean SetString(ItemStack stack, String key, String value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setString(key, value); + + return true; + } + + + //entity + @Nullable + public static boolean EntityHasKey(Entity entity, String key) + { + return getNBT(entity).hasKey(key); + } + + //Boolean + public static boolean GetBoolean(Entity entity, String key, boolean defaultVal) + { + if (EntityHasKey(entity, key)) + { + NBTTagCompound nbt = getNBT(entity); + return nbt.getBoolean(key); + } + else + { + return defaultVal; + } + } + + public static boolean SetBoolean(Entity stack, String key, boolean value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setBoolean(key, value); + return true; + } + + public static boolean SetString(Entity stack, String key, String value) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setString(key, value); + return true; + } + + public static int[] GetIntArray(ItemStack stack, String key) + { + if (StackHasKey(stack, key)) + { + NBTTagCompound nbt = getNBTReadOnly(stack); + return nbt.getIntArray(key); + } + else + { + return new int[0]; + } + } + + public static int[] GetIntArray(EntityLivingBase stack, String key) + { + if (EntityHasKey(stack, key)) + { + NBTTagCompound nbt = getNBT(stack); + return nbt.getIntArray(key); + } + else + { + return new int[0]; + } + } + + public static void SetIntArray(ItemStack stack, String key, int[] array) + { + NBTTagCompound nbt = getNBT(stack); + nbt.setIntArray(key, array); + } + + public static void SetGuaEnhanceFree(ItemStack stack, int val) + { + SetInt(stack, IDLNBTDef.GUA_FREE_SOCKET, val); + } + + public static boolean GetIsLearned(EntityPlayer player, int skillID) + { + int[] learnt = IDLNBT.getPlayerIdeallandIntArraySafe(player, IDLNBTDef.STARTER_KIT_VERSION_TAG); + if (Arrays.binarySearch(learnt, skillID) >= 0) + { + return true; + } + return false; + } + + public static void SetIsLearned(EntityPlayer player, int skillID, boolean val) + { + int[] learnt = IDLNBT.getPlayerIdeallandIntArraySafe(player, IDLNBTDef.LEARNING_DONE); + int oldIndex = Arrays.binarySearch(learnt, skillID); + if (oldIndex >= 0) + { + if (val) + { + return; + }else { + //todo: remove it + + } + }else { + if (val) + { + ArrayList list = new ArrayList(); + for (int oldID: + learnt + ) { + list.add(oldID); + } + list.add(skillID); + Collections.sort(list); + + int[] newLearnt = list.stream().mapToInt(Integer::valueOf).toArray(); + IDLNBT.setPlayerIdeallandTagSafe(player, IDLNBTDef.LEARNING_DONE, newLearnt); + }else { + return; + } + } + } + //-------------------------------------------- + + + + public static BlockPos getMarkedPos(ItemStack stack) + { + NBTTagCompound NBT = IDLNBTUtil.getNBTReadOnly(stack); + return new BlockPos(NBT.getDouble(IDLNBTDef.ANCHOR_X), NBT.getDouble(IDLNBTDef.ANCHOR_Y), NBT.getDouble(IDLNBTDef.ANCHOR_Z)); + } + + public static BlockPos getMarkedPos2(ItemStack stack) + { + NBTTagCompound NBT = IDLNBTUtil.getNBTReadOnly(stack); + return new BlockPos(NBT.getDouble(IDLNBTDef.ANCHOR_X_2), NBT.getDouble(IDLNBTDef.ANCHOR_Y_2), NBT.getDouble(IDLNBTDef.ANCHOR_Z_2)); + } + + public static void markPosToStack(ItemStack stack, BlockPos pos) + { + IDLNBTUtil.SetBoolean(stack, IDLNBTDef.ANCHOR_READY, true); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_X, pos.getX()); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_Y, pos.getY()); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_Z, pos.getZ()); + } + + public static void markPosToStack2(ItemStack stack, BlockPos pos) + { + IDLNBTUtil.SetBoolean(stack, IDLNBTDef.ANCHOR_READY_2, true); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_X_2, pos.getX()); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_Y_2, pos.getY()); + IDLNBTUtil.SetDouble(stack, IDLNBTDef.ANCHOR_Z_2, pos.getZ()); + } + + public static NBTTagCompound getTagSafe(NBTTagCompound tag, String key) { + if (tag == null) { + return new NBTTagCompound(); + } + + return tag.getCompoundTag(key); + } + + public static NBTTagCompound getPlyrIdlTagSafe(EntityPlayer player) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getTagSafe(data, IdlFramework.MODID); + + return idl_data; + } + + public static NBTTagCompound getPlayerIdeallandTagGroupSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getCompoundTag(key); + } + + public static int[] getPlayerIdeallandIntArraySafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getIntArray(key); + } + + public static long getPlayerIdeallandLongSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getLong(key); + } + + public static int getPlayerIdeallandIntSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getInteger(key); + } + + public static float getPlayerIdeallandFloatSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getFloat(key); + } + + public static double getPlayerIdeallandDoubleSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getDouble(key); + } + + public static boolean getPlayerIdeallandBoolSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getBoolean(key); + } + + public static String getPlayerIdeallandStrSafe(EntityPlayer player, String key) { + return getPlyrIdlTagSafe(player).getString(key); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, int value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setInteger(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, int[] value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setIntArray(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, double value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setDouble(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, long value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setLong(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, boolean value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setBoolean(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } + + public static void setPlayerIdeallandTagSafe(EntityPlayer player, String key, String value) { + NBTTagCompound playerData = player.getEntityData(); + NBTTagCompound data = getTagSafe(playerData, EntityPlayer.PERSISTED_NBT_TAG); + NBTTagCompound idl_data = getPlyrIdlTagSafe(player); + + idl_data.setString(key, value); + + data.setTag(IDEALLAND, idl_data); + playerData.setTag(EntityPlayer.PERSISTED_NBT_TAG, data); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/PlayerUtil.java b/src/main/java/com/somebody/idlframewok/util/PlayerUtil.java new file mode 100644 index 0000000..ff9e1e0 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/PlayerUtil.java @@ -0,0 +1,80 @@ +package com.somebody.idlframewok.util; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class PlayerUtil { + public static int FindItemInIvtrGeneralized(EntityPlayer player, Class itemClass) + { + for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + ItemStack itemstack = player.inventory.getStackInSlot(i); + { + //itemClass.getClass(); + if (itemClass.isAssignableFrom(itemstack.getItem().getClass())) + { + return i; + } + } + } + return -1; + } + + public static ItemStack FindStackInIvtrGeneralized(EntityPlayer player, Class itemClass) + { + for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + ItemStack itemstack = player.inventory.getStackInSlot(i); + { + //itemClass.getClass(); + if (itemClass.isAssignableFrom(itemstack.getItem().getClass())) + { + return itemstack; + } + } + } + return ItemStack.EMPTY; + } + + public static int FindItemInIvtr(EntityPlayer player, Item item) + { + for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + ItemStack itemstack = player.inventory.getStackInSlot(i); + { + if (itemstack.getItem() == item) + { + return i; + } + } + } + return -1; + } + + public static ItemStack FindStackInIvtr(EntityPlayer player, Item item) + { + for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + ItemStack itemstack = player.inventory.getStackInSlot(i); + { + if (itemstack.getItem() == item) + { + return itemstack; + } + } + } + return ItemStack.EMPTY; + } + + public static boolean isCreative(EntityPlayer player) + { + return player.capabilities.isCreativeMode; + } + + public static boolean giveToPlayer(EntityPlayer player, ItemStack stack) + { + boolean result = player.addItemStackToInventory(stack); + if (!result) + { + player.dropItem(stack, false); + } + return result; + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/Reference.java b/src/main/java/com/somebody/idlframewok/util/Reference.java new file mode 100644 index 0000000..493b288 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/Reference.java @@ -0,0 +1,10 @@ +package com.somebody.idlframewok.util; + +import com.somebody.idlframewok.IdlFramework; + +public class Reference { + public static final String MOD_ID = IdlFramework.MODID; + public static final String CLIENT_PROXY_CLASS = "com.somebody.idlframewok.proxy.ClientProxy"; + public static final String SERVER_PROXY_CLASS = "com.somebody.idlframewok.proxy.ServerProxy"; + +} diff --git a/src/main/java/com/somebody/idlframewok/util/StringUtil.java b/src/main/java/com/somebody/idlframewok/util/StringUtil.java new file mode 100644 index 0000000..f1ef5d2 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/StringUtil.java @@ -0,0 +1,10 @@ +package com.somebody.idlframewok.util; + +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; + +public class StringUtil { + public static ITextComponent getLocale(String key) { + return new TextComponentTranslation(key); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/Teleport.java b/src/main/java/com/somebody/idlframewok/util/Teleport.java new file mode 100644 index 0000000..d96a4ab --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/Teleport.java @@ -0,0 +1,52 @@ +package com.somebody.idlframewok.util; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Teleporter; +import net.minecraft.world.WorldServer; + +public class Teleport extends Teleporter { + private final WorldServer worldServer; + private double x,y,z; + + public Teleport(WorldServer worldServer, double x, double y, double z) { + super(worldServer); + this.worldServer = worldServer; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void placeInPortal(Entity entityIn, float rotationYaw) { + worldServer.getBlockState(new BlockPos(x,y,z)); + entityIn.setPosition(x,y,z); + entityIn.motionX = 0f; + entityIn.motionY = 0f; + entityIn.motionZ = 0f; + + } + + public static void teleportToDim(EntityPlayer player, int dimension, double x, double y, double z) + { + int oldDim = player.getEntityWorld().provider.getDimension(); + EntityPlayerMP entityPlayerMP = (EntityPlayerMP) player; + MinecraftServer server = player.getEntityWorld().getMinecraftServer(); + if (server == null) + { + throw new IllegalArgumentException("Player status incorrect"); + } + + WorldServer worldServerNew = server.getWorld(dimension); + if (worldServerNew == null) + { + throw new IllegalArgumentException(String.format("[IDL]Teleporting dimension: %d does not exist", dimension)); + } + + worldServerNew.getMinecraftServer().getPlayerList().transferPlayerToDimension(entityPlayerMP, dimension, new Teleport(worldServerNew, x,y,z)); + player.setPositionAndUpdate(x,y,z); + } +} diff --git a/src/main/java/com/somebody/idlframewok/util/sound/ModSoundEvent.java b/src/main/java/com/somebody/idlframewok/util/sound/ModSoundEvent.java new file mode 100644 index 0000000..6a35867 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/util/sound/ModSoundEvent.java @@ -0,0 +1,14 @@ +package com.somebody.idlframewok.util.sound; + +import com.somebody.idlframewok.util.ModSoundHandler; +import com.somebody.idlframewok.util.Reference; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; + +public class ModSoundEvent extends SoundEvent { + public ModSoundEvent(String path) { + super(new ResourceLocation(Reference.MOD_ID, path)); + ModSoundHandler.SOUNDS.add(this); + setRegistryName(path); + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/biome/BiomeForDimOne.java b/src/main/java/com/somebody/idlframewok/world/biome/BiomeForDimOne.java new file mode 100644 index 0000000..8ccb022 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/biome/BiomeForDimOne.java @@ -0,0 +1,43 @@ +package com.somebody.idlframewok.world.biome; + +import java.util.Random; + +import net.minecraft.init.Blocks; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.feature.WorldGenAbstractTree; +import net.minecraft.world.gen.feature.WorldGenBigTree; +import net.minecraft.world.gen.feature.WorldGenMinable; + +public class BiomeForDimOne extends Biome { + + protected static final WorldGenAbstractTree TREE = new WorldGenBigTree(false); + + public BiomeForDimOne() { + super(new BiomeProperties("biome_one").setBaseHeight(-1.5f).setHeightVariation(1.2f).setTemperature(0.5f).setWaterColor(0xff3333)); + + topBlock = Blocks.PUMPKIN.getDefaultState(); + fillerBlock = Blocks.GOLD_BLOCK.getDefaultState(); + + decorator.coalGen = new WorldGenMinable(Blocks.PLANKS.getDefaultState(), 10); + + decorator.treesPerChunk = 2; + + this.spawnableCreatureList.clear(); + this.spawnableCaveCreatureList.clear(); + this.spawnableMonsterList.clear(); + this.spawnableWaterCreatureList.clear(); + + // this.spawnableCreatureList.add(new SpawnListEntry(EntityGhast.class, 5, 1,2)); + } + + public BiomeForDimOne(BiomeProperties properties) { + super(properties); + } + + + @Override + public WorldGenAbstractTree getRandomTreeFeature(Random random) + { + return TREE; + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/biome/BiomeOne.java b/src/main/java/com/somebody/idlframewok/world/biome/BiomeOne.java new file mode 100644 index 0000000..df81ad5 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/biome/BiomeOne.java @@ -0,0 +1,44 @@ +package com.somebody.idlframewok.world.biome; + +import java.util.Random; + +import net.minecraft.entity.monster.EntityGhast; +import net.minecraft.init.Blocks; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.feature.WorldGenAbstractTree; +import net.minecraft.world.gen.feature.WorldGenBigTree; +import net.minecraft.world.gen.feature.WorldGenMinable; + +public class BiomeOne extends Biome { + + protected static final WorldGenAbstractTree TREE = new WorldGenBigTree(false); + + public BiomeOne() { + super(new BiomeProperties("biome_one").setBaseHeight(-1.5f).setHeightVariation(1.2f).setTemperature(0.5f).setWaterColor(0xff3333)); + + topBlock = Blocks.BOOKSHELF.getDefaultState(); + fillerBlock = Blocks.BRICK_BLOCK.getDefaultState(); + + decorator.coalGen = new WorldGenMinable(Blocks.PLANKS.getDefaultState(), 10); + + decorator.treesPerChunk = 2; + + this.spawnableCreatureList.clear(); + this.spawnableCaveCreatureList.clear(); + this.spawnableMonsterList.clear(); + this.spawnableWaterCreatureList.clear(); + + this.spawnableCreatureList.add(new SpawnListEntry(EntityGhast.class, 5, 1,2)); + } + + public BiomeOne(BiomeProperties properties) { + super(properties); + } + + + @Override + public WorldGenAbstractTree getRandomTreeFeature(Random random) + { + return TREE; + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/DimensionOne.java b/src/main/java/com/somebody/idlframewok/world/dimension/DimensionOne.java new file mode 100644 index 0000000..d667f02 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/DimensionOne.java @@ -0,0 +1,37 @@ +package com.somebody.idlframewok.world.dimension; + +import com.somebody.idlframewok.world.dimension.hexcube.ChunkGeneratorHexCube16; +import net.minecraft.world.DimensionType; +import net.minecraft.world.WorldProvider; +import net.minecraft.world.gen.IChunkGenerator; + +public class DimensionOne extends WorldProvider { + + public DimensionOne() { + //this.biomeProvider = new BiomeProviderSingle(InitBiome.BIOME_ONE); + hasSkyLight = false; + } + + @Override + public DimensionType getDimensionType() { + return DimensionType.NETHER; + //return InitDimension.DIM_ONE; + } + + @Override + public IChunkGenerator createChunkGenerator() { + return new ChunkGeneratorHexCube16( world, true, world.getSeed()); + } + + @Override + public boolean canRespawnHere() { + return false; + } + + @Override + public boolean isSurfaceWorld() { + return false; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/ChunkGeneratorHexCube16.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/ChunkGeneratorHexCube16.java new file mode 100644 index 0000000..8c4c170 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/ChunkGeneratorHexCube16.java @@ -0,0 +1,390 @@ +package com.somebody.idlframewok.world.dimension.hexcube; + +import java.util.List; +import java.util.Random; +import javax.annotation.Nullable; + +import com.somebody.idlframewok.util.CommonDef; +import com.somebody.idlframewok.world.dimension.hexcube.structure.GenCubeBase; +import com.somebody.idlframewok.world.dimension.hexcube.structure.GenCubeSoilRoom; +import com.somebody.idlframewok.world.dimension.hexcube.structure.GenCubeTorchRoom; +import com.somebody.idlframewok.world.dimension.hexcube.structure.GenCubeTreasure; +import com.somebody.idlframewok.world.dimension.hexcube.structure.GenCubeWoodRoom; +import net.minecraft.block.BlockColored; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.init.Biomes; +import net.minecraft.init.Blocks; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkPrimer; +import net.minecraft.world.gen.IChunkGenerator; + +public class ChunkGeneratorHexCube16 implements IChunkGenerator { + + private static final int heightLimit = 255; + //private static final int yNoGateLimit = 255; + + private final World world; + private final boolean generateStructures; + private final Random rand; + + + public ChunkGeneratorHexCube16(World world, boolean generate, long seed) { + this.world = world; + this.generateStructures = generate; + this.rand = new Random(seed); + world.setSeaLevel(63); + } + + private static final EnumDyeColor[] colorByDiff = + { + EnumDyeColor.WHITE,//0 + EnumDyeColor.LIME,//1 + EnumDyeColor.CYAN,//3 + EnumDyeColor.GRAY,//4 + EnumDyeColor.YELLOW,//5 + EnumDyeColor.PINK,//7 + EnumDyeColor.ORANGE,//6 + EnumDyeColor.RED,//8 + }; + + public IBlockState getWall(int x, int y, int z) + { + float difficulty = HexCubeHelper.getDifficulty(x,y,z); + + int diffInt = (int) difficulty; + if (diffInt <= colorByDiff.length) + { + EnumDyeColor color = getColorForPos(x, y, z); + + return Blocks.CONCRETE.getDefaultState().withProperty(BlockColored.COLOR, color); + } + + return Blocks.OBSIDIAN.getDefaultState(); + } + + EnumDyeColor getColorForPos(int x, int y, int z) + { + float difficulty = HexCubeHelper.getDifficulty(x,y,z); + + int diffInt = (int) difficulty; + + return colorByDiff[diffInt % colorByDiff.length]; + } + + + public IBlockState getWall() + { + return getWall(0,0,0); + } + + float getLightChance(int x, int y, int z) + { + return Math.max(1f - ((x+z)>>4) * 0.01f - (y>>4) * 0.1f, 0.01f); + } + + boolean chunkUsed(int x, int z) + { + return (x != 0 && z != 0); + } + + public void buildChunk(int x, int z, ChunkPrimer primer) { + + if (chunkUsed(x, z)) { + for (int y = 0; y < heightLimit; y+= CommonDef.CHUNK_SIZE) { + genCubeHalf(primer, x, y, z); + } + } + + if (this.generateStructures) + { + + } + + GenerateFloor(primer); + } + + private void GenerateFloor(ChunkPrimer primer) { + for (int dx = 0; dx < CommonDef.CHUNK_SIZE; dx++) + { + //for (int dy = 0; dy < CommonDef.CHUNK_SIZE; dy++) + { + for (int dz = 0; dz < CommonDef.CHUNK_SIZE; dz++) + { + //BlockPos curPos = new BlockPos(x+dx, y+dy, z+dz); + primer.setBlockState(dx, 0, dz, + Blocks.BEDROCK.getDefaultState()); +// primer.setBlockState(dx, heightLimit, dz, +// Blocks.BEDROCK.getDefaultState()); + + } + } + } + } + + void setSeedFor(int x, int y, int z) + { + rand.setSeed((long)x * 341873128712L + (long)z * 132897987541L + (long)y * 438951276L); + } + + public boolean hasLight(int x, int y, int z) + { + setSeedFor(x, y, z); + return rand.nextFloat() < getLightChance(x, y, z); + } + + void genCubeHalf(ChunkPrimer primer, int x, int y, int z) + { + setSeedFor(x, y, z); + boolean hasDoorX = rand.nextBoolean(); + boolean hasDoorY = y != 0 && rand.nextBoolean();//wont fall to void + boolean hasDoorZ = rand.nextBoolean(); + + //Make sure at least one door + if (!(hasDoorX || hasDoorY || hasDoorZ)) + { + if (rand.nextBoolean()) { + hasDoorX = true; + } else + { + hasDoorZ = true; + } + } + + boolean hasLight = hasLight(x, y, z); + + IBlockState wallState = getWall(x, y, z); + for (int dx = 0; dx < CommonDef.CHUNK_SIZE; dx++) + { + for (int dy = 0; dy < CommonDef.CHUNK_SIZE; dy++) + { + for (int dz = 0; dz < CommonDef.CHUNK_SIZE; dz++) + { + //BlockPos curPos = new BlockPos(x+dx, y+dy, z+dz); + + if (dx==0 || dy==0 || dz==0) + { + primer.setBlockState(dx, y+dy, dz, + wallState); + } + } + } + } + + genDoorAndLight(primer,x, y,z, hasDoorX, hasDoorY, hasDoorZ, hasLight); + +// BlockPos boxFace = new BlockPos(15,15,15); +// primer.setBlockState(2, 2, 2, +// Blocks.CHEST.correctFacing(world, boxFace, Blocks.CHEST.getDefaultState())); +// TileEntity tileentity1 = world.getTileEntity(blockpos2); +// +// if (tileentity1 instanceof TileEntityChest) +// { +// ((TileEntityChest)tileentity1).setLootTable(LootTableList.CHESTS_SIMPLE_DUNGEON, rand.nextLong()); +// } + + } + + private void genDoorAndLight(ChunkPrimer primer, int x, int y, int z, boolean hasDoorX, boolean hasDoorY, boolean hasDoorZ, boolean hasLight) { + int xL = 7; + int xR = 9; + + int y1 = 1; + int y2 = 3; + + EnumDyeColor color = getColorForPos(x, y, z); + + IBlockState doorStateXZ=Blocks.STAINED_GLASS_PANE.getDefaultState().withProperty(BlockColored.COLOR, color); + if (hasDoorX) + { + for (int dx = xL; dx<=xR; dx++) + { + for (int dy = y1; dy<=y2; dy++) + { + primer.setBlockState(dx, y+dy, 0, + doorStateXZ); + } + } + } + + if (hasDoorZ) + { + for (int dz = xL; dz<=xR; dz++) + { + for (int dy = y1; dy<=y2; dy++) + { + primer.setBlockState(0, y+dy, dz, + doorStateXZ); + } + } + } + + IBlockState doorStateY =Blocks.STAINED_GLASS.getDefaultState().withProperty(BlockColored.COLOR, color); + + if (hasDoorY) + { + for (int dz = xL; dz<=xR; dz++) + { + for (int dx = xL; dx<=xR; dx++) + { + primer.setBlockState(dx, y, dz, + doorStateY); + } + } + } + + if (hasLight) + { + int min = 1; + int max = CommonDef.CHUNK_SIZE -1; + primer.setBlockState(min, y+min, min, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(min, y+min, max, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(max, y+min, min, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(max, y+min, max, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(min, y+max, min, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(min, y+max, max, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(max, y+max, min, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + primer.setBlockState(max, y+max, max, Blocks.LIT_REDSTONE_LAMP.getDefaultState()); + } + } + + //infrastructure + + @Override + public Chunk generateChunk(int x, int z) { + this.rand.setSeed((long)x * 341873128712L + (long)z * 132897987541L); + ChunkPrimer chunkprimer = new ChunkPrimer(); + buildChunk(x,z,chunkprimer); + + Chunk chunk = new Chunk(this.world, chunkprimer, x, z); + byte[] abyte = chunk.getBiomeArray(); + + for (int i = 0; i < abyte.length; ++i) + { + abyte[i] = (byte)Biome.getIdForBiome(Biomes.EXTREME_HILLS); + //abyte[i] = (byte)Biome.getIdForBiome(InitBiome.BIOME_ONE); + } + + chunk.resetRelightChecks(); + return chunk; + } + + enum EnumRoomType{ + EMPTY, + TREASURE, + SOIL, + WOOD, + TORCH + } + + static GenCubeBase genCubeTreasure = new GenCubeTreasure(true); + static GenCubeBase genCubeSoil = new GenCubeSoilRoom(true); + static GenCubeBase genCubeWood = new GenCubeWoodRoom(true); + static GenCubeBase genCubeTorch = new GenCubeTorchRoom(true); + + EnumRoomType getRoomType(int x, int y, int z) + { + setSeedFor(x, y, z); + return EnumRoomType.values()[rand.nextInt(EnumRoomType.values().length)]; +// if (rand.nextFloat() < 0.05f) +// { +// return EnumRoomType.TREASURE; +// } +// +// if (rand.nextFloat() < 0.05f) +// { +// return EnumRoomType.SOIL; +// } + + //return EnumRoomType.EMPTY; + } + + + @Override + public void populate(int chunkX, int chunkZ) { + if (!chunkUsed(chunkX, chunkZ)) + { + return; + } + + net.minecraft.block.BlockFalling.fallInstantly = true; + int x = chunkX * 16; + int z = chunkZ * 16; + + net.minecraftforge.event.ForgeEventFactory.onChunkPopulate(true, this, this.world, this.rand, chunkX, chunkZ, false); + + for (int y = 0; y < heightLimit; y+= CommonDef.CHUNK_SIZE) { + + EnumRoomType type = getRoomType(x,y,z); + + setSeedFor(x, y, z); + boolean hasDoorX = rand.nextBoolean(); + boolean hasDoorY = y != 0 && rand.nextBoolean();//wont fall to void + boolean hasDoorZ = rand.nextBoolean(); + boolean hasLight = hasLight(x,y,z); + + GenCubeBase gen = null; + + switch (type) + { + case EMPTY: + break; + case TREASURE: + gen = genCubeTreasure; + break; + case SOIL: + gen = genCubeSoil; + break; + case WOOD: + gen = genCubeWood; + break; + case TORCH: + gen = genCubeTorch; + break; + default: + break; + } + + if (gen != null) + { + gen.setHasDoorXYZ(hasDoorX, hasDoorY, hasDoorZ); + gen.setHasLightXYZ(hasLight); + gen.generate(world, rand, new BlockPos(x, y, z)); + } + } + + net.minecraftforge.event.ForgeEventFactory.onChunkPopulate(false, this, this.world, this.rand, chunkX, chunkZ, false); + net.minecraft.block.BlockFalling.fallInstantly = false; + } + + @Override + public boolean generateStructures(Chunk chunkIn, int x, int z) { + return false; + } + + @Override + public List getPossibleCreatures(EnumCreatureType creatureType, BlockPos pos) { + Biome biome = this.world.getBiome(pos); + return biome.getSpawnableList(creatureType); + } + + @Nullable + @Override + public BlockPos getNearestStructurePos(World worldIn, String structureName, BlockPos position, boolean findUnexplored) { + return null; + } + + @Override + public void recreateStructures(Chunk chunkIn, int x, int z) { + + } + + @Override + public boolean isInsideStructure(World worldIn, String structureName, BlockPos pos) { + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/HexCubeHelper.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/HexCubeHelper.java new file mode 100644 index 0000000..dba973a --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/HexCubeHelper.java @@ -0,0 +1,48 @@ +package com.somebody.idlframewok.world.dimension.hexcube; + +import com.somebody.idlframewok.util.CommonDef; +import net.minecraft.init.Blocks; +import net.minecraft.world.chunk.ChunkPrimer; + +public class HexCubeHelper { + + private static final float CHUNK_PER_DIFF = 4f; + + public static float getDifficulty(int chunkX, int y, int chunkZ) + { + if (chunkX < 0) + { + chunkX = -chunkX; + } + if (chunkZ < 0) + { + chunkZ = -chunkZ; + } + + return chunkX / CHUNK_PER_DIFF + chunkZ / CHUNK_PER_DIFF + (y >> 4) / CHUNK_PER_DIFF; + } + + public static void genGrass(ChunkPrimer primer, int x, int y, int z) + { + for (int dx = 1; dx < CommonDef.CHUNK_SIZE; dx++) + { + //for (int dy = 0; dy < CHUNK_SIZE; dy++) + //{ + for (int dz = 1; dz < CommonDef.CHUNK_SIZE; dz++) + { + //BlockPos curPos = new BlockPos(x+dx, y+dy, z+dz); + + int min = 6; + int max = 10; + + if ((dx > min && dx < max) || + (dz > min && dz < max)) + { + continue; + } + primer.setBlockState(x, 1, z, Blocks.GRASS.getDefaultState()); + } + //} + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeBase.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeBase.java new file mode 100644 index 0000000..074e753 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeBase.java @@ -0,0 +1,58 @@ +package com.somebody.idlframewok.world.dimension.hexcube.structure; + +import java.util.Random; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.WorldGenerator; + +public class GenCubeBase extends WorldGenerator { + + protected boolean hasDoorX; + protected boolean hasDoorY; + protected boolean hasDoorZ; + + protected boolean hasLight; + + protected int xSize, ySize, zSize; + + public void setSize(int sizeX, int sizeY, int sizeZ) { + this.xSize = sizeX; + this.ySize = sizeY; + this.zSize = sizeZ; + } + + public GenCubeBase(boolean notify) { + this(notify, 16, 16, 16); + } + + public GenCubeBase(boolean notify, int xSize, int ySize, int zSize) { + super(notify); + this.xSize = xSize; + this.ySize = ySize; + this.zSize = zSize; + } + + public GenCubeBase(boolean notify, int xSize, int ySize) { + this(notify, xSize, ySize, xSize); + } + + //reuse the object to reduce GC. + public void setHasDoorXYZ(boolean hasDoorX, boolean hasDoorY, boolean hasDoorZ) { + this.hasDoorX = hasDoorX; + this.hasDoorY = hasDoorY; + this.hasDoorZ = hasDoorZ; + } + + public void setHasLightXYZ(boolean hasLight) + { + this.hasLight = hasLight; + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos positionOrigin) { + return false; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeSoilRoom.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeSoilRoom.java new file mode 100644 index 0000000..0638fc1 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeSoilRoom.java @@ -0,0 +1,54 @@ +package com.somebody.idlframewok.world.dimension.hexcube.structure; + +import java.util.Random; + +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class GenCubeSoilRoom extends GenCubeBase { + + public GenCubeSoilRoom(boolean notify) { + super(notify); + } + + public GenCubeSoilRoom(boolean notify, int xSize, int ySize, int zSize) { + super(notify, xSize, ySize, zSize); + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos positionOrigin) { + //positionOrigin is 0,0,0 of the room. the corner of walls + int min = 1; + int max = xSize - 1; + + int minZ = 1; + int maxZ = zSize - 1; + + int yMax = ySize - 1; + + //with chance the grass can grow + boolean isGrass = hasDoorX && !hasDoorY && hasDoorZ; + + for (int x = min; x <= max; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + BlockPos pos = positionOrigin.add(x, 1, z); + if ((x > min && x < max) || (z > minZ && z < maxZ)) + { + if (worldIn.getBlockState(pos).getBlock() != Blocks.AIR) { + //if there is a light placed, keep it + continue; + } + } + + worldIn.setBlockState(pos, isGrass ? Blocks.GRASS.getDefaultState() : Blocks.DIRT.getDefaultState(), 2); + } + } + + return false; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTorchRoom.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTorchRoom.java new file mode 100644 index 0000000..7adff51 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTorchRoom.java @@ -0,0 +1,57 @@ +package com.somebody.idlframewok.world.dimension.hexcube.structure; + +import java.util.Random; + +import net.minecraft.block.BlockTorch; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class GenCubeTorchRoom extends GenCubeBase { + public GenCubeTorchRoom(boolean notify) { + super(notify); + } + + public GenCubeTorchRoom(boolean notify, int xSize, int ySize, int zSize) { + super(notify, xSize, ySize, zSize); + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos positionOrigin) { + //positionOrigin is 0,0,0 of the room. the corner of walls + int minY = hasLight ? 2 : 1; + int min = 1; + int max = xSize - 1; + + int minZ = 1; + int maxZ = zSize - 1; + + int yMax = ySize - 1; + + //east +x + //south +z + for (int y = minY; y <= yMax; y++) + { + CreateLogAt(worldIn, positionOrigin.add(min, y, minZ), EnumFacing.SOUTH); + CreateLogAt(worldIn, positionOrigin.add(min, y, maxZ), EnumFacing.EAST); + CreateLogAt(worldIn, positionOrigin.add(max, y, maxZ), EnumFacing.NORTH); + CreateLogAt(worldIn, positionOrigin.add(max, y, minZ), EnumFacing.WEST); + } + + return false; + } + + void CreateLogAt(World worldIn, BlockPos pos, EnumFacing facing) + { + //todo: prevent torch from falling + if (worldIn.getBlockState(pos.offset(facing.getOpposite())).getBlock() == Blocks.AIR)//does this work? need check + { + this.setBlockAndNotifyAdequately(worldIn, pos, Blocks.TORCH.getDefaultState().withProperty(BlockTorch.FACING, facing)); + } + + + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTreasure.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTreasure.java new file mode 100644 index 0000000..9e8bc74 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeTreasure.java @@ -0,0 +1,63 @@ +package com.somebody.idlframewok.world.dimension.hexcube.structure; + +import java.util.Random; + +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.loot.LootTableList; + +public class GenCubeTreasure extends GenCubeBase { + + public GenCubeTreasure(boolean notify) { + super(notify); + } + + public GenCubeTreasure(boolean notify, int xSize, int ySize, int zSize) { + super(notify, xSize, ySize, zSize); + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos positionOrigin) { + //positionOrigin is 0,0,0 of the room. the corner of walls + int sideA = 2; + int sideB = xSize - 2; + + int minZ = 2; + int maxZ = zSize - 2; + + int yMax = ySize - 1; + + BlockPos[] posList = { + positionOrigin.add(sideA,1, minZ), + positionOrigin.add(sideA,1, maxZ), + positionOrigin.add(sideB,1, minZ), + positionOrigin.add(sideB,1, maxZ) + }; + + float hasLootChance = 0.25f; + for (BlockPos chestPos: + posList) { + worldIn.setBlockState(chestPos, Blocks.CHEST.correctFacing(worldIn, positionOrigin.add(xSize>>1, 1, zSize >> 1), Blocks.CHEST.getDefaultState()), 2); + TileEntity tileEntity1 = worldIn.getTileEntity(chestPos); + + if (tileEntity1 instanceof TileEntityChest) + { + if (rand.nextFloat() < hasLootChance) + { + ((TileEntityChest)tileEntity1).setLootTable(LootTableList.CHESTS_SIMPLE_DUNGEON, rand.nextLong()); + } + else { + hasLootChance += 0.25f; + } + + } + } + + return false; + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeWoodRoom.java b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeWoodRoom.java new file mode 100644 index 0000000..8d87a57 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/dimension/hexcube/structure/GenCubeWoodRoom.java @@ -0,0 +1,49 @@ +package com.somebody.idlframewok.world.dimension.hexcube.structure; + +import java.util.Random; + +import net.minecraft.block.BlockLog; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class GenCubeWoodRoom extends GenCubeBase { + + public GenCubeWoodRoom(boolean notify) { + super(notify); + } + + public GenCubeWoodRoom(boolean notify, int xSize, int ySize, int zSize) { + super(notify, xSize, ySize, zSize); + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos positionOrigin) { + //positionOrigin is 0,0,0 of the room. the corner of walls + int minY = hasLight ? 2 : 1; + int min = 1; + int max = xSize - 1; + + int minZ = 1; + int maxZ = zSize - 1; + + int yMax = ySize - 1; + + for (int y = minY; y <= yMax; y++) + { + CreateLogAt(worldIn, positionOrigin.add(min, y, minZ)); + CreateLogAt(worldIn, positionOrigin.add(min, y, maxZ)); + CreateLogAt(worldIn, positionOrigin.add(max, y, minZ)); + CreateLogAt(worldIn, positionOrigin.add(max, y, maxZ)); + } + + return false; + } + + void CreateLogAt(World worldIn, BlockPos pos) + { + this.setBlockAndNotifyAdequately(worldIn, pos, Blocks.LOG.getDefaultState().withProperty(BlockLog.LOG_AXIS, BlockLog.EnumAxis.Y)); + } + + +} diff --git a/src/main/java/com/somebody/idlframewok/world/structure/ModGenStructure.java b/src/main/java/com/somebody/idlframewok/world/structure/ModGenStructure.java new file mode 100644 index 0000000..3cd88f5 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/structure/ModGenStructure.java @@ -0,0 +1,215 @@ +package com.somebody.idlframewok.world.structure; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +import com.google.common.collect.Lists; +import it.unimi.dsi.fastutil.objects.ObjectIterator; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.structure.MapGenStructure; +import net.minecraft.world.gen.structure.StructureComponent; +import net.minecraft.world.gen.structure.StructureStart; +import net.minecraft.world.gen.structure.StructureStrongholdPieces; + +public class ModGenStructure extends MapGenStructure +{ + public final List allowedBiomes; + /** is spawned false and set true once the defined BiomeGenBases were compared with the present ones */ + private boolean ranBiomeCheck; + private ChunkPos[] structureCoords; + private double distance; + private int spread; + + public ModGenStructure() + { + this.structureCoords = new ChunkPos[128]; + this.distance = 32.0D; + this.spread = 3; + this.allowedBiomes = Lists.newArrayList(); + + //this.allowedBiomes.add(InitBiome.BIOME_ONE); + } + + public ModGenStructure(Map p_i2068_1_) + { + this(); + + for (Map.Entry entry : p_i2068_1_.entrySet()) + { + if (((String)entry.getKey()).equals("distance")) + { + this.distance = MathHelper.getDouble(entry.getValue(), this.distance, 1.0D); + } + else if (((String)entry.getKey()).equals("count")) + { + this.structureCoords = new ChunkPos[MathHelper.getInt(entry.getValue(), this.structureCoords.length, 1)]; + } + else if (((String)entry.getKey()).equals("spread")) + { + this.spread = MathHelper.getInt(entry.getValue(), this.spread, 1); + } + } + } + + public String getStructureName() + { + return "TestStructure"; + } + + public BlockPos getNearestStructurePos(World worldIn, BlockPos pos, boolean findUnexplored) + { + if (!this.ranBiomeCheck) + { + this.generatePositions(); + this.ranBiomeCheck = true; + } + + BlockPos blockpos = null; + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(0, 0, 0); + double d0 = Double.MAX_VALUE; + + for (ChunkPos chunkpos : this.structureCoords) + { + blockpos$mutableblockpos.setPos((chunkpos.x << 4) + 8, 32, (chunkpos.z << 4) + 8); + double d1 = blockpos$mutableblockpos.distanceSq(pos); + + if (blockpos == null) + { + blockpos = new BlockPos(blockpos$mutableblockpos); + d0 = d1; + } + else if (d1 < d0) + { + blockpos = new BlockPos(blockpos$mutableblockpos); + d0 = d1; + } + } + + return blockpos; + } + + protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ) + { + if (!this.ranBiomeCheck) + { + this.generatePositions(); + this.ranBiomeCheck = true; + } + + for (ChunkPos chunkpos : this.structureCoords) + { + if (chunkX == chunkpos.x && chunkZ == chunkpos.z) + { + return true; + } + } + + return false; + } + + private void generatePositions() + { + this.initializeStructureData(this.world); + int i = 0; + ObjectIterator lvt_2_1_ = this.structureMap.values().iterator(); + + while (lvt_2_1_.hasNext()) + { + StructureStart structurestart = (StructureStart)lvt_2_1_.next(); + + if (i < this.structureCoords.length) + { + this.structureCoords[i++] = new ChunkPos(structurestart.getChunkPosX(), structurestart.getChunkPosZ()); + } + } + + Random random = new Random(); + random.setSeed(this.world.getSeed()); + double d1 = random.nextDouble() * Math.PI * 2.0D; + int j = 0; + int k = 0; + int l = this.structureMap.size(); + + if (l < this.structureCoords.length) + { + for (int i1 = 0; i1 < this.structureCoords.length; ++i1) + { + double d0 = 4.0D * this.distance + this.distance * (double)j * 6.0D + (random.nextDouble() - 0.5D) * this.distance * 2.5D; + int j1 = (int)Math.round(Math.cos(d1) * d0); + int k1 = (int)Math.round(Math.sin(d1) * d0); + BlockPos blockpos = this.world.getBiomeProvider().findBiomePosition((j1 << 4) + 8, (k1 << 4) + 8, 112, this.allowedBiomes, random); + + if (blockpos != null) + { + j1 = blockpos.getX() >> 4; + k1 = blockpos.getZ() >> 4; + } + + if (i1 >= l) + { + this.structureCoords[i1] = new ChunkPos(j1, k1); + } + + d1 += (Math.PI * 2D) / (double)this.spread; + ++k; + + if (k == this.spread) + { + ++j; + k = 0; + this.spread += 2 * this.spread / (j + 1); + this.spread = Math.min(this.spread, this.structureCoords.length - i1); + d1 += random.nextDouble() * Math.PI * 2.0D; + } + } + } + } + + protected StructureStart getStructureStart(int chunkX, int chunkZ) + { + ModGenStructure.Start ModGenStructure$start; + + for (ModGenStructure$start = new ModGenStructure.Start(this.world, this.rand, chunkX, chunkZ); + ModGenStructure$start.getComponents().isEmpty() || + ((StructureStrongholdPieces.Stairs2)ModGenStructure$start.getComponents().get(0)).strongholdPortalRoom == null; + ModGenStructure$start = new ModGenStructure.Start(this.world, this.rand, chunkX, chunkZ)) + { + ; + } + + return ModGenStructure$start; + } + + public static class Start extends StructureStart + { + public Start() + { + } + + public Start(World worldIn, Random random, int chunkX, int chunkZ) + { + super(chunkX, chunkZ); + StructureStrongholdPieces.prepareStructurePieces(); + StructureStrongholdPieces.Stairs2 structurestrongholdpieces$stairs2 = new StructureStrongholdPieces.Stairs2(0, random, (chunkX << 4) + 2, (chunkZ << 4) + 2); + this.components.add(structurestrongholdpieces$stairs2); + structurestrongholdpieces$stairs2.buildComponent(structurestrongholdpieces$stairs2, this.components, random); + List list = structurestrongholdpieces$stairs2.pendingChildren; + + while (!list.isEmpty()) + { + int i = random.nextInt(list.size()); + StructureComponent structurecomponent = list.remove(i); + structurecomponent.buildComponent(structurestrongholdpieces$stairs2, this.components, random); + } + + this.updateBoundingBox(); + this.markAvailableHeight(worldIn, random, 10); + } + } + +} diff --git a/src/main/java/com/somebody/idlframewok/world/structure/TestStructurePieces.java b/src/main/java/com/somebody/idlframewok/world/structure/TestStructurePieces.java new file mode 100644 index 0000000..f9b958d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/structure/TestStructurePieces.java @@ -0,0 +1,989 @@ +package com.somebody.idlframewok.world.structure; + +import java.util.List; +import java.util.Random; +import javax.annotation.Nullable; + +import com.google.common.collect.Lists; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.BlockRail; +import net.minecraft.block.BlockRailBase; +import net.minecraft.block.BlockTorch; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.item.EntityMinecartChest; +import net.minecraft.entity.monster.EntityCaveSpider; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.MapGenMineshaft; +import net.minecraft.world.gen.structure.MapGenStructureIO; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.StructureComponent; +import net.minecraft.world.gen.structure.template.TemplateManager; +import net.minecraft.world.storage.loot.LootTableList; + +public class TestStructurePieces { + + //see StructureComponent + + public static void registerStructurePieces() + { + MapGenStructureIO.registerStructureComponent(TestStructurePieces.Corridor.class, "MSCorridor"); + MapGenStructureIO.registerStructureComponent(TestStructurePieces.Cross.class, "MSCrossing"); + MapGenStructureIO.registerStructureComponent(TestStructurePieces.Room.class, "MSRoom"); + MapGenStructureIO.registerStructureComponent(TestStructurePieces.Stairs.class, "MSStairs"); + } + + private static TestStructurePieces.Peice createRandomShaftPiece(List p_189940_0_, Random p_189940_1_, int p_189940_2_, int p_189940_3_, int p_189940_4_, @Nullable EnumFacing p_189940_5_, int p_189940_6_, MapGenMineshaft.Type p_189940_7_) + { + int i = p_189940_1_.nextInt(100); + + if (i >= 80) + { + StructureBoundingBox structureboundingbox = TestStructurePieces.Cross.findCrossing(p_189940_0_, p_189940_1_, p_189940_2_, p_189940_3_, p_189940_4_, p_189940_5_); + + if (structureboundingbox != null) + { + return new TestStructurePieces.Cross(p_189940_6_, p_189940_1_, structureboundingbox, p_189940_5_, p_189940_7_); + } + } + else if (i >= 70) + { + StructureBoundingBox structureboundingbox1 = TestStructurePieces.Stairs.findStairs(p_189940_0_, p_189940_1_, p_189940_2_, p_189940_3_, p_189940_4_, p_189940_5_); + + if (structureboundingbox1 != null) + { + return new TestStructurePieces.Stairs(p_189940_6_, p_189940_1_, structureboundingbox1, p_189940_5_, p_189940_7_); + } + } + else + { + StructureBoundingBox structureboundingbox2 = TestStructurePieces.Corridor.findCorridorSize(p_189940_0_, p_189940_1_, p_189940_2_, p_189940_3_, p_189940_4_, p_189940_5_); + + if (structureboundingbox2 != null) + { + return new TestStructurePieces.Corridor(p_189940_6_, p_189940_1_, structureboundingbox2, p_189940_5_, p_189940_7_); + } + } + + return null; + } + + private static TestStructurePieces.Peice generateAndAddPiece(StructureComponent p_189938_0_, List p_189938_1_, Random p_189938_2_, int p_189938_3_, int p_189938_4_, int p_189938_5_, EnumFacing p_189938_6_, int p_189938_7_) + { + if (p_189938_7_ > 8) + { + return null; + } + else if (Math.abs(p_189938_3_ - p_189938_0_.getBoundingBox().minX) <= 80 && Math.abs(p_189938_5_ - p_189938_0_.getBoundingBox().minZ) <= 80) + { + MapGenMineshaft.Type mapgenmineshaft$type = ((TestStructurePieces.Peice)p_189938_0_).mineShaftType; + TestStructurePieces.Peice TestStructurePieces$peice = createRandomShaftPiece(p_189938_1_, p_189938_2_, p_189938_3_, p_189938_4_, p_189938_5_, p_189938_6_, p_189938_7_ + 1, mapgenmineshaft$type); + + if (TestStructurePieces$peice != null) + { + p_189938_1_.add(TestStructurePieces$peice); + TestStructurePieces$peice.buildComponent(p_189938_0_, p_189938_1_, p_189938_2_); + } + + return TestStructurePieces$peice; + } + else + { + return null; + } + } + + public static class Corridor extends TestStructurePieces.Peice + { + private boolean hasRails; + private boolean hasSpiders; + private boolean spawnerPlaced; + /** A count of the different sections of this mine. The space between ceiling supports. */ + private int sectionCount; + + public Corridor() + { + } + + /** + * (abstract) Helper method to write subclass data to NBT + */ + protected void writeStructureToNBT(NBTTagCompound tagCompound) + { + super.writeStructureToNBT(tagCompound); + tagCompound.setBoolean("hr", this.hasRails); + tagCompound.setBoolean("sc", this.hasSpiders); + tagCompound.setBoolean("hps", this.spawnerPlaced); + tagCompound.setInteger("Num", this.sectionCount); + } + + /** + * (abstract) Helper method to read subclass data from NBT + */ + protected void readStructureFromNBT(NBTTagCompound tagCompound, TemplateManager p_143011_2_) + { + super.readStructureFromNBT(tagCompound, p_143011_2_); + this.hasRails = tagCompound.getBoolean("hr"); + this.hasSpiders = tagCompound.getBoolean("sc"); + this.spawnerPlaced = tagCompound.getBoolean("hps"); + this.sectionCount = tagCompound.getInteger("Num"); + } + + public Corridor(int p_i47140_1_, Random p_i47140_2_, StructureBoundingBox p_i47140_3_, EnumFacing p_i47140_4_, MapGenMineshaft.Type p_i47140_5_) + { + super(p_i47140_1_, p_i47140_5_); + this.setCoordBaseMode(p_i47140_4_); + this.boundingBox = p_i47140_3_; + this.hasRails = p_i47140_2_.nextInt(3) == 0; + this.hasSpiders = !this.hasRails && p_i47140_2_.nextInt(23) == 0; + + if (this.getCoordBaseMode().getAxis() == EnumFacing.Axis.Z) + { + this.sectionCount = p_i47140_3_.getZSize() / 5; + } + else + { + this.sectionCount = p_i47140_3_.getXSize() / 5; + } + } + + public static StructureBoundingBox findCorridorSize(List p_175814_0_, Random rand, int x, int y, int z, EnumFacing facing) + { + StructureBoundingBox structureboundingbox = new StructureBoundingBox(x, y, z, x, y + 2, z); + int i; + + for (i = rand.nextInt(3) + 2; i > 0; --i) + { + int j = i * 5; + + switch (facing) + { + case NORTH: + default: + structureboundingbox.maxX = x + 2; + structureboundingbox.minZ = z - (j - 1); + break; + case SOUTH: + structureboundingbox.maxX = x + 2; + structureboundingbox.maxZ = z + (j - 1); + break; + case WEST: + structureboundingbox.minX = x - (j - 1); + structureboundingbox.maxZ = z + 2; + break; + case EAST: + structureboundingbox.maxX = x + (j - 1); + structureboundingbox.maxZ = z + 2; + } + + if (StructureComponent.findIntersecting(p_175814_0_, structureboundingbox) == null) + { + break; + } + } + + return i > 0 ? structureboundingbox : null; + } + + /** + * Initiates construction of the Structure Component picked, at the current Location of StructGen + */ + public void buildComponent(StructureComponent componentIn, List listIn, Random rand) + { + int i = this.getComponentType(); + int j = rand.nextInt(4); + EnumFacing enumfacing = this.getCoordBaseMode(); + + if (enumfacing != null) + { + switch (enumfacing) + { + case NORTH: + default: + + if (j <= 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ - 1, enumfacing, i); + } + else if (j == 2) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ, EnumFacing.WEST, i); + } + else + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ, EnumFacing.EAST, i); + } + + break; + case SOUTH: + + if (j <= 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.maxZ + 1, enumfacing, i); + } + else if (j == 2) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.maxZ - 3, EnumFacing.WEST, i); + } + else + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.maxZ - 3, EnumFacing.EAST, i); + } + + break; + case WEST: + + if (j <= 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ, enumfacing, i); + } + else if (j == 2) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + } + else + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + } + + break; + case EAST: + + if (j <= 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ, enumfacing, i); + } + else if (j == 2) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX - 3, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + } + else + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX - 3, this.boundingBox.minY - 1 + rand.nextInt(3), this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + } + } + } + + if (i < 8) + { + if (enumfacing != EnumFacing.NORTH && enumfacing != EnumFacing.SOUTH) + { + for (int i1 = this.boundingBox.minX + 3; i1 + 3 <= this.boundingBox.maxX; i1 += 5) + { + int j1 = rand.nextInt(5); + + if (j1 == 0) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, i1, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, i + 1); + } + else if (j1 == 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, i1, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i + 1); + } + } + } + else + { + for (int k = this.boundingBox.minZ + 3; k + 3 <= this.boundingBox.maxZ; k += 5) + { + int l = rand.nextInt(5); + + if (l == 0) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY, k, EnumFacing.WEST, i + 1); + } + else if (l == 1) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, k, EnumFacing.EAST, i + 1); + } + } + } + } + } + + /** + * Adds chest to the structure and sets its contents + */ + protected boolean generateChest(World worldIn, StructureBoundingBox structurebb, Random randomIn, int x, int y, int z, ResourceLocation loot) + { + BlockPos blockpos = new BlockPos(this.getXWithOffset(x, z), this.getYWithOffset(y), this.getZWithOffset(x, z)); + + if (structurebb.isVecInside(blockpos) && worldIn.getBlockState(blockpos).getMaterial() == Material.AIR && worldIn.getBlockState(blockpos.down()).getMaterial() != Material.AIR) + { + IBlockState iblockstate = Blocks.RAIL.getDefaultState().withProperty(BlockRail.SHAPE, randomIn.nextBoolean() ? BlockRailBase.EnumRailDirection.NORTH_SOUTH : BlockRailBase.EnumRailDirection.EAST_WEST); + this.setBlockState(worldIn, iblockstate, x, y, z, structurebb); + EntityMinecartChest entityminecartchest = new EntityMinecartChest(worldIn, (double)((float)blockpos.getX() + 0.5F), (double)((float)blockpos.getY() + 0.5F), (double)((float)blockpos.getZ() + 0.5F)); + entityminecartchest.setLootTable(loot, randomIn.nextLong()); + worldIn.spawnEntity(entityminecartchest); + return true; + } + else + { + return false; + } + } + + /** + * second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes + * Mineshafts at the end, it adds Fences... + */ + public boolean addComponentParts(World worldIn, Random randomIn, StructureBoundingBox structureBoundingBoxIn) + { + if (this.isLiquidInStructureBoundingBox(worldIn, structureBoundingBoxIn)) + { + return false; + } + else + { + int i = 0; + int j = 2; + int k = 0; + int l = 2; + int i1 = this.sectionCount * 5 - 1; + IBlockState iblockstate = this.getPlanksBlock(); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, 0, 0, 0, 2, 1, i1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.generateMaybeBox(worldIn, structureBoundingBoxIn, randomIn, 0.8F, 0, 2, 0, 2, 2, i1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false, 0); + + if (this.hasSpiders) + { + this.generateMaybeBox(worldIn, structureBoundingBoxIn, randomIn, 0.6F, 0, 0, 0, 2, 1, i1, Blocks.WEB.getDefaultState(), Blocks.AIR.getDefaultState(), false, 8); + } + + for (int j1 = 0; j1 < this.sectionCount; ++j1) + { + int k1 = 2 + j1 * 5; + this.placeSupport(worldIn, structureBoundingBoxIn, 0, 0, k1, 2, 2, randomIn); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.1F, 0, 2, k1 - 1); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.1F, 2, 2, k1 - 1); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.1F, 0, 2, k1 + 1); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.1F, 2, 2, k1 + 1); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.05F, 0, 2, k1 - 2); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.05F, 2, 2, k1 - 2); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.05F, 0, 2, k1 + 2); + this.placeCobWeb(worldIn, structureBoundingBoxIn, randomIn, 0.05F, 2, 2, k1 + 2); + + if (randomIn.nextInt(100) == 0) + { + this.generateChest(worldIn, structureBoundingBoxIn, randomIn, 2, 0, k1 - 1, LootTableList.CHESTS_ABANDONED_MINESHAFT); + } + + if (randomIn.nextInt(100) == 0) + { + this.generateChest(worldIn, structureBoundingBoxIn, randomIn, 0, 0, k1 + 1, LootTableList.CHESTS_ABANDONED_MINESHAFT); + } + + if (this.hasSpiders && !this.spawnerPlaced) + { + int l1 = this.getYWithOffset(0); + int i2 = k1 - 1 + randomIn.nextInt(3); + int j2 = this.getXWithOffset(1, i2); + int k2 = this.getZWithOffset(1, i2); + BlockPos blockpos = new BlockPos(j2, l1, k2); + + if (structureBoundingBoxIn.isVecInside(blockpos) && this.getSkyBrightness(worldIn, 1, 0, i2, structureBoundingBoxIn) < 8) + { + this.spawnerPlaced = true; + worldIn.setBlockState(blockpos, Blocks.MOB_SPAWNER.getDefaultState(), 2); + TileEntity tileentity = worldIn.getTileEntity(blockpos); + + if (tileentity instanceof TileEntityMobSpawner) + { + ((TileEntityMobSpawner)tileentity).getSpawnerBaseLogic().setEntityId(EntityList.getKey(EntityCaveSpider.class)); + } + } + } + } + + for (int l2 = 0; l2 <= 2; ++l2) + { + for (int i3 = 0; i3 <= i1; ++i3) + { + int k3 = -1; + IBlockState iblockstate3 = this.getBlockStateFromPos(worldIn, l2, -1, i3, structureBoundingBoxIn); + + if (iblockstate3.getMaterial() == Material.AIR && this.getSkyBrightness(worldIn, l2, -1, i3, structureBoundingBoxIn) < 8) + { + int l3 = -1; + this.setBlockState(worldIn, iblockstate, l2, -1, i3, structureBoundingBoxIn); + } + } + } + + if (this.hasRails) + { + IBlockState iblockstate1 = Blocks.RAIL.getDefaultState().withProperty(BlockRail.SHAPE, BlockRailBase.EnumRailDirection.NORTH_SOUTH); + + for (int j3 = 0; j3 <= i1; ++j3) + { + IBlockState iblockstate2 = this.getBlockStateFromPos(worldIn, 1, -1, j3, structureBoundingBoxIn); + + if (iblockstate2.getMaterial() != Material.AIR && iblockstate2.isFullBlock()) + { + float f = this.getSkyBrightness(worldIn, 1, 0, j3, structureBoundingBoxIn) > 8 ? 0.9F : 0.7F; + this.randomlyPlaceBlock(worldIn, structureBoundingBoxIn, randomIn, f, 1, 0, j3, iblockstate1); + } + } + } + + return true; + } + } + + private void placeSupport(World p_189921_1_, StructureBoundingBox p_189921_2_, int p_189921_3_, int p_189921_4_, int p_189921_5_, int p_189921_6_, int p_189921_7_, Random p_189921_8_) + { + if (this.isSupportingBox(p_189921_1_, p_189921_2_, p_189921_3_, p_189921_7_, p_189921_6_, p_189921_5_)) + { + IBlockState iblockstate = this.getPlanksBlock(); + IBlockState iblockstate1 = this.getFenceBlock(); + IBlockState iblockstate2 = Blocks.AIR.getDefaultState(); + this.fillWithBlocks(p_189921_1_, p_189921_2_, p_189921_3_, p_189921_4_, p_189921_5_, p_189921_3_, p_189921_6_ - 1, p_189921_5_, iblockstate1, iblockstate2, false); + this.fillWithBlocks(p_189921_1_, p_189921_2_, p_189921_7_, p_189921_4_, p_189921_5_, p_189921_7_, p_189921_6_ - 1, p_189921_5_, iblockstate1, iblockstate2, false); + + if (p_189921_8_.nextInt(4) == 0) + { + this.fillWithBlocks(p_189921_1_, p_189921_2_, p_189921_3_, p_189921_6_, p_189921_5_, p_189921_3_, p_189921_6_, p_189921_5_, iblockstate, iblockstate2, false); + this.fillWithBlocks(p_189921_1_, p_189921_2_, p_189921_7_, p_189921_6_, p_189921_5_, p_189921_7_, p_189921_6_, p_189921_5_, iblockstate, iblockstate2, false); + } + else + { + this.fillWithBlocks(p_189921_1_, p_189921_2_, p_189921_3_, p_189921_6_, p_189921_5_, p_189921_7_, p_189921_6_, p_189921_5_, iblockstate, iblockstate2, false); + this.randomlyPlaceBlock(p_189921_1_, p_189921_2_, p_189921_8_, 0.05F, p_189921_3_ + 1, p_189921_6_, p_189921_5_ - 1, Blocks.TORCH.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.NORTH)); + this.randomlyPlaceBlock(p_189921_1_, p_189921_2_, p_189921_8_, 0.05F, p_189921_3_ + 1, p_189921_6_, p_189921_5_ + 1, Blocks.TORCH.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.SOUTH)); + } + } + } + + private void placeCobWeb(World p_189922_1_, StructureBoundingBox p_189922_2_, Random p_189922_3_, float p_189922_4_, int p_189922_5_, int p_189922_6_, int p_189922_7_) + { + if (this.getSkyBrightness(p_189922_1_, p_189922_5_, p_189922_6_, p_189922_7_, p_189922_2_) < 8) + { + this.randomlyPlaceBlock(p_189922_1_, p_189922_2_, p_189922_3_, p_189922_4_, p_189922_5_, p_189922_6_, p_189922_7_, Blocks.WEB.getDefaultState()); + } + } + } + + public static class Cross extends TestStructurePieces.Peice + { + private EnumFacing corridorDirection; + private boolean isMultipleFloors; + + public Cross() + { + } + + /** + * (abstract) Helper method to write subclass data to NBT + */ + protected void writeStructureToNBT(NBTTagCompound tagCompound) + { + super.writeStructureToNBT(tagCompound); + tagCompound.setBoolean("tf", this.isMultipleFloors); + tagCompound.setInteger("D", this.corridorDirection.getHorizontalIndex()); + } + + /** + * (abstract) Helper method to read subclass data from NBT + */ + protected void readStructureFromNBT(NBTTagCompound tagCompound, TemplateManager p_143011_2_) + { + super.readStructureFromNBT(tagCompound, p_143011_2_); + this.isMultipleFloors = tagCompound.getBoolean("tf"); + this.corridorDirection = EnumFacing.getHorizontal(tagCompound.getInteger("D")); + } + + public Cross(int p_i47139_1_, Random p_i47139_2_, StructureBoundingBox p_i47139_3_, @Nullable EnumFacing p_i47139_4_, MapGenMineshaft.Type p_i47139_5_) + { + super(p_i47139_1_, p_i47139_5_); + this.corridorDirection = p_i47139_4_; + this.boundingBox = p_i47139_3_; + this.isMultipleFloors = p_i47139_3_.getYSize() > 3; + } + + public static StructureBoundingBox findCrossing(List listIn, Random rand, int x, int y, int z, EnumFacing facing) + { + StructureBoundingBox structureboundingbox = new StructureBoundingBox(x, y, z, x, y + 2, z); + + if (rand.nextInt(4) == 0) + { + structureboundingbox.maxY += 4; + } + + switch (facing) + { + case NORTH: + default: + structureboundingbox.minX = x - 1; + structureboundingbox.maxX = x + 3; + structureboundingbox.minZ = z - 4; + break; + case SOUTH: + structureboundingbox.minX = x - 1; + structureboundingbox.maxX = x + 3; + structureboundingbox.maxZ = z + 3 + 1; + break; + case WEST: + structureboundingbox.minX = x - 4; + structureboundingbox.minZ = z - 1; + structureboundingbox.maxZ = z + 3; + break; + case EAST: + structureboundingbox.maxX = x + 3 + 1; + structureboundingbox.minZ = z - 1; + structureboundingbox.maxZ = z + 3; + } + + return StructureComponent.findIntersecting(listIn, structureboundingbox) != null ? null : structureboundingbox; + } + + /** + * Initiates construction of the Structure Component picked, at the current Location of StructGen + */ + public void buildComponent(StructureComponent componentIn, List listIn, Random rand) + { + int i = this.getComponentType(); + + switch (this.corridorDirection) + { + case NORTH: + default: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.WEST, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.EAST, i); + break; + case SOUTH: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.WEST, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.EAST, i); + break; + case WEST: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.WEST, i); + break; + case EAST: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, EnumFacing.EAST, i); + } + + if (this.isMultipleFloors) + { + if (rand.nextBoolean()) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + } + + if (rand.nextBoolean()) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ + 1, EnumFacing.WEST, i); + } + + if (rand.nextBoolean()) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ + 1, EnumFacing.EAST, i); + } + + if (rand.nextBoolean()) + { + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + } + } + } + + /** + * second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes + * Mineshafts at the end, it adds Fences... + */ + public boolean addComponentParts(World worldIn, Random randomIn, StructureBoundingBox structureBoundingBoxIn) + { + if (this.isLiquidInStructureBoundingBox(worldIn, structureBoundingBoxIn)) + { + return false; + } + else + { + IBlockState iblockstate = this.getPlanksBlock(); + + if (this.isMultipleFloors) + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ, this.boundingBox.maxX - 1, this.boundingBox.minY + 3 - 1, this.boundingBox.maxZ, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ + 1, this.boundingBox.maxX, this.boundingBox.minY + 3 - 1, this.boundingBox.maxZ - 1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.maxY - 2, this.boundingBox.minZ, this.boundingBox.maxX - 1, this.boundingBox.maxY, this.boundingBox.maxZ, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.maxY - 2, this.boundingBox.minZ + 1, this.boundingBox.maxX, this.boundingBox.maxY, this.boundingBox.maxZ - 1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.minY + 3, this.boundingBox.minZ + 1, this.boundingBox.maxX - 1, this.boundingBox.minY + 3, this.boundingBox.maxZ - 1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + } + else + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ, this.boundingBox.maxX - 1, this.boundingBox.maxY, this.boundingBox.maxZ, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ + 1, this.boundingBox.maxX, this.boundingBox.maxY, this.boundingBox.maxZ - 1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + } + + this.placeSupportPillar(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, this.boundingBox.maxY); + this.placeSupportPillar(worldIn, structureBoundingBoxIn, this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ - 1, this.boundingBox.maxY); + this.placeSupportPillar(worldIn, structureBoundingBoxIn, this.boundingBox.maxX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, this.boundingBox.maxY); + this.placeSupportPillar(worldIn, structureBoundingBoxIn, this.boundingBox.maxX - 1, this.boundingBox.minY, this.boundingBox.maxZ - 1, this.boundingBox.maxY); + + for (int i = this.boundingBox.minX; i <= this.boundingBox.maxX; ++i) + { + for (int j = this.boundingBox.minZ; j <= this.boundingBox.maxZ; ++j) + { + if (this.getBlockStateFromPos(worldIn, i, this.boundingBox.minY - 1, j, structureBoundingBoxIn).getMaterial() == Material.AIR && this.getSkyBrightness(worldIn, i, this.boundingBox.minY - 1, j, structureBoundingBoxIn) < 8) + { + this.setBlockState(worldIn, iblockstate, i, this.boundingBox.minY - 1, j, structureBoundingBoxIn); + } + } + } + + return true; + } + } + + private void placeSupportPillar(World p_189923_1_, StructureBoundingBox p_189923_2_, int p_189923_3_, int p_189923_4_, int p_189923_5_, int p_189923_6_) + { + if (this.getBlockStateFromPos(p_189923_1_, p_189923_3_, p_189923_6_ + 1, p_189923_5_, p_189923_2_).getMaterial() != Material.AIR) + { + this.fillWithBlocks(p_189923_1_, p_189923_2_, p_189923_3_, p_189923_4_, p_189923_5_, p_189923_3_, p_189923_6_, p_189923_5_, this.getPlanksBlock(), Blocks.AIR.getDefaultState(), false); + } + } + } + + abstract static class Peice extends StructureComponent + { + protected MapGenMineshaft.Type mineShaftType; + + public Peice() + { + } + + public Peice(int p_i47138_1_, MapGenMineshaft.Type p_i47138_2_) + { + super(p_i47138_1_); + this.mineShaftType = p_i47138_2_; + } + + /** + * (abstract) Helper method to write subclass data to NBT + */ + protected void writeStructureToNBT(NBTTagCompound tagCompound) + { + tagCompound.setInteger("MST", this.mineShaftType.ordinal()); + } + + /** + * (abstract) Helper method to read subclass data from NBT + */ + protected void readStructureFromNBT(NBTTagCompound tagCompound, TemplateManager p_143011_2_) + { + this.mineShaftType = MapGenMineshaft.Type.byId(tagCompound.getInteger("MST")); + } + + protected IBlockState getPlanksBlock() + { + switch (this.mineShaftType) + { + case NORMAL: + default: + return Blocks.PLANKS.getDefaultState(); + case MESA: + return Blocks.PLANKS.getDefaultState().withProperty(BlockPlanks.VARIANT, BlockPlanks.EnumType.DARK_OAK); + } + } + + protected IBlockState getFenceBlock() + { + switch (this.mineShaftType) + { + case NORMAL: + default: + return Blocks.OAK_FENCE.getDefaultState(); + case MESA: + return Blocks.DARK_OAK_FENCE.getDefaultState(); + } + } + + protected boolean isSupportingBox(World p_189918_1_, StructureBoundingBox p_189918_2_, int p_189918_3_, int p_189918_4_, int p_189918_5_, int p_189918_6_) + { + for (int i = p_189918_3_; i <= p_189918_4_; ++i) + { + if (this.getBlockStateFromPos(p_189918_1_, i, p_189918_5_ + 1, p_189918_6_, p_189918_2_).getMaterial() == Material.AIR) + { + return false; + } + } + + return true; + } + } + + public static class Room extends TestStructurePieces.Peice + { + /** List of other Mineshaft components linked to this room. */ + private final List connectedRooms = Lists.newLinkedList(); + + public Room() + { + } + + public Room(int p_i47137_1_, Random p_i47137_2_, int p_i47137_3_, int p_i47137_4_, MapGenMineshaft.Type p_i47137_5_) + { + super(p_i47137_1_, p_i47137_5_); + this.mineShaftType = p_i47137_5_; + this.boundingBox = new StructureBoundingBox(p_i47137_3_, 50, p_i47137_4_, p_i47137_3_ + 7 + p_i47137_2_.nextInt(6), 54 + p_i47137_2_.nextInt(6), p_i47137_4_ + 7 + p_i47137_2_.nextInt(6)); + } + + /** + * Initiates construction of the Structure Component picked, at the current Location of StructGen + */ + public void buildComponent(StructureComponent componentIn, List listIn, Random rand) + { + int i = this.getComponentType(); + int j = this.boundingBox.getYSize() - 3 - 1; + + if (j <= 0) + { + j = 1; + } + + int k; + + for (k = 0; k < this.boundingBox.getXSize(); k = k + 4) + { + k = k + rand.nextInt(this.boundingBox.getXSize()); + + if (k + 3 > this.boundingBox.getXSize()) + { + break; + } + + TestStructurePieces.Peice TestStructurePieces$peice = TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + k, this.boundingBox.minY + rand.nextInt(j) + 1, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + + if (TestStructurePieces$peice != null) + { + StructureBoundingBox structureboundingbox = TestStructurePieces$peice.getBoundingBox(); + this.connectedRooms.add(new StructureBoundingBox(structureboundingbox.minX, structureboundingbox.minY, this.boundingBox.minZ, structureboundingbox.maxX, structureboundingbox.maxY, this.boundingBox.minZ + 1)); + } + } + + for (k = 0; k < this.boundingBox.getXSize(); k = k + 4) + { + k = k + rand.nextInt(this.boundingBox.getXSize()); + + if (k + 3 > this.boundingBox.getXSize()) + { + break; + } + + TestStructurePieces.Peice TestStructurePieces$peice1 = TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX + k, this.boundingBox.minY + rand.nextInt(j) + 1, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + + if (TestStructurePieces$peice1 != null) + { + StructureBoundingBox structureboundingbox1 = TestStructurePieces$peice1.getBoundingBox(); + this.connectedRooms.add(new StructureBoundingBox(structureboundingbox1.minX, structureboundingbox1.minY, this.boundingBox.maxZ - 1, structureboundingbox1.maxX, structureboundingbox1.maxY, this.boundingBox.maxZ)); + } + } + + for (k = 0; k < this.boundingBox.getZSize(); k = k + 4) + { + k = k + rand.nextInt(this.boundingBox.getZSize()); + + if (k + 3 > this.boundingBox.getZSize()) + { + break; + } + + TestStructurePieces.Peice TestStructurePieces$peice2 = TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY + rand.nextInt(j) + 1, this.boundingBox.minZ + k, EnumFacing.WEST, i); + + if (TestStructurePieces$peice2 != null) + { + StructureBoundingBox structureboundingbox2 = TestStructurePieces$peice2.getBoundingBox(); + this.connectedRooms.add(new StructureBoundingBox(this.boundingBox.minX, structureboundingbox2.minY, structureboundingbox2.minZ, this.boundingBox.minX + 1, structureboundingbox2.maxY, structureboundingbox2.maxZ)); + } + } + + for (k = 0; k < this.boundingBox.getZSize(); k = k + 4) + { + k = k + rand.nextInt(this.boundingBox.getZSize()); + + if (k + 3 > this.boundingBox.getZSize()) + { + break; + } + + StructureComponent structurecomponent = TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + rand.nextInt(j) + 1, this.boundingBox.minZ + k, EnumFacing.EAST, i); + + if (structurecomponent != null) + { + StructureBoundingBox structureboundingbox3 = structurecomponent.getBoundingBox(); + this.connectedRooms.add(new StructureBoundingBox(this.boundingBox.maxX - 1, structureboundingbox3.minY, structureboundingbox3.minZ, this.boundingBox.maxX, structureboundingbox3.maxY, structureboundingbox3.maxZ)); + } + } + } + + /** + * second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes + * Mineshafts at the end, it adds Fences... + */ + public boolean addComponentParts(World worldIn, Random randomIn, StructureBoundingBox structureBoundingBoxIn) + { + if (this.isLiquidInStructureBoundingBox(worldIn, structureBoundingBoxIn)) + { + return false; + } + else + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ, this.boundingBox.maxX, this.boundingBox.minY, this.boundingBox.maxZ, Blocks.DIRT.getDefaultState(), Blocks.AIR.getDefaultState(), true); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.minY + 1, this.boundingBox.minZ, this.boundingBox.maxX, Math.min(this.boundingBox.minY + 3, this.boundingBox.maxY), this.boundingBox.maxZ, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + + for (StructureBoundingBox structureboundingbox : this.connectedRooms) + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, structureboundingbox.minX, structureboundingbox.maxY - 2, structureboundingbox.minZ, structureboundingbox.maxX, structureboundingbox.maxY, structureboundingbox.maxZ, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + } + + this.randomlyRareFillWithBlocks(worldIn, structureBoundingBoxIn, this.boundingBox.minX, this.boundingBox.minY + 4, this.boundingBox.minZ, this.boundingBox.maxX, this.boundingBox.maxY, this.boundingBox.maxZ, Blocks.AIR.getDefaultState(), false); + return true; + } + } + + public void offset(int x, int y, int z) + { + super.offset(x, y, z); + + for (StructureBoundingBox structureboundingbox : this.connectedRooms) + { + structureboundingbox.offset(x, y, z); + } + } + + /** + * (abstract) Helper method to write subclass data to NBT + */ + protected void writeStructureToNBT(NBTTagCompound tagCompound) + { + super.writeStructureToNBT(tagCompound); + NBTTagList nbttaglist = new NBTTagList(); + + for (StructureBoundingBox structureboundingbox : this.connectedRooms) + { + nbttaglist.appendTag(structureboundingbox.toNBTTagIntArray()); + } + + tagCompound.setTag("Entrances", nbttaglist); + } + + /** + * (abstract) Helper method to read subclass data from NBT + */ + protected void readStructureFromNBT(NBTTagCompound tagCompound, TemplateManager p_143011_2_) + { + super.readStructureFromNBT(tagCompound, p_143011_2_); + NBTTagList nbttaglist = tagCompound.getTagList("Entrances", 11); + + for (int i = 0; i < nbttaglist.tagCount(); ++i) + { + this.connectedRooms.add(new StructureBoundingBox(nbttaglist.getIntArrayAt(i))); + } + } + } + + public static class Stairs extends TestStructurePieces.Peice + { + public Stairs() + { + } + + public Stairs(int p_i47136_1_, Random p_i47136_2_, StructureBoundingBox p_i47136_3_, EnumFacing p_i47136_4_, MapGenMineshaft.Type p_i47136_5_) + { + super(p_i47136_1_, p_i47136_5_); + this.setCoordBaseMode(p_i47136_4_); + this.boundingBox = p_i47136_3_; + } + + public static StructureBoundingBox findStairs(List listIn, Random rand, int x, int y, int z, EnumFacing facing) + { + StructureBoundingBox structureboundingbox = new StructureBoundingBox(x, y - 5, z, x, y + 2, z); + + switch (facing) + { + case NORTH: + default: + structureboundingbox.maxX = x + 2; + structureboundingbox.minZ = z - 8; + break; + case SOUTH: + structureboundingbox.maxX = x + 2; + structureboundingbox.maxZ = z + 8; + break; + case WEST: + structureboundingbox.minX = x - 8; + structureboundingbox.maxZ = z + 2; + break; + case EAST: + structureboundingbox.maxX = x + 8; + structureboundingbox.maxZ = z + 2; + } + + return StructureComponent.findIntersecting(listIn, structureboundingbox) != null ? null : structureboundingbox; + } + + /** + * Initiates construction of the Structure Component picked, at the current Location of StructGen + */ + public void buildComponent(StructureComponent componentIn, List listIn, Random rand) + { + int i = this.getComponentType(); + EnumFacing enumfacing = this.getCoordBaseMode(); + + if (enumfacing != null) + { + switch (enumfacing) + { + case NORTH: + default: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, i); + break; + case SOUTH: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, i); + break; + case WEST: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ, EnumFacing.WEST, i); + break; + case EAST: + TestStructurePieces.generateAndAddPiece(componentIn, listIn, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ, EnumFacing.EAST, i); + } + } + } + + /** + * second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes + * Mineshafts at the end, it adds Fences... + */ + public boolean addComponentParts(World worldIn, Random randomIn, StructureBoundingBox structureBoundingBoxIn) + { + if (this.isLiquidInStructureBoundingBox(worldIn, structureBoundingBoxIn)) + { + return false; + } + else + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, 0, 5, 0, 2, 7, 1, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + this.fillWithBlocks(worldIn, structureBoundingBoxIn, 0, 0, 7, 2, 2, 8, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + + for (int i = 0; i < 5; ++i) + { + this.fillWithBlocks(worldIn, structureBoundingBoxIn, 0, 5 - i - (i < 4 ? 1 : 0), 2 + i, 2, 7 - i, 2 + i, Blocks.AIR.getDefaultState(), Blocks.AIR.getDefaultState(), false); + } + + return true; + } + } + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/tree/WorldGenTestTree.java b/src/main/java/com/somebody/idlframewok/world/tree/WorldGenTestTree.java new file mode 100644 index 0000000..ee93246 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/tree/WorldGenTestTree.java @@ -0,0 +1,19 @@ +package com.somebody.idlframewok.world.tree; + +import java.util.Random; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.WorldGenAbstractTree; + +//just gen it in worldGenNew +public class WorldGenTestTree extends WorldGenAbstractTree { + public WorldGenTestTree(boolean notify) { + super(notify); + } + + @Override + public boolean generate(World worldIn, Random rand, BlockPos position) { + return false; + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/types/WorldTypeCustom.java b/src/main/java/com/somebody/idlframewok/world/types/WorldTypeCustom.java new file mode 100644 index 0000000..c277332 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/types/WorldTypeCustom.java @@ -0,0 +1,23 @@ +package com.somebody.idlframewok.world.types; + +import com.somebody.idlframewok.world.types.layer.GenLayerCustom; +import net.minecraft.world.WorldType; +import net.minecraft.world.gen.ChunkGeneratorSettings; +import net.minecraft.world.gen.layer.GenLayer; + +public class WorldTypeCustom extends WorldType { + /** + * Creates a new world type, the ID is hidden and should not be referenced by modders. + * It will automatically expand the underlying workdType array if there are no IDs left. + * + * @param name + */ + public WorldTypeCustom(String name) { + super(name); + } + + @Override + public GenLayer getBiomeLayer(long worldSeed, GenLayer parentLayer, ChunkGeneratorSettings chunkSettings) { + return new GenLayerCustom(worldSeed, parentLayer, this, chunkSettings); + } +} diff --git a/src/main/java/com/somebody/idlframewok/world/types/WorldTypeOne.java b/src/main/java/com/somebody/idlframewok/world/types/WorldTypeOne.java new file mode 100644 index 0000000..75e74ce --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/types/WorldTypeOne.java @@ -0,0 +1,25 @@ +package com.somebody.idlframewok.world.types; + +import net.minecraft.world.WorldType; + +public class WorldTypeOne extends WorldType { + /** + * Creates a new world type, the ID is hidden and should not be referenced by modders. + * It will automatically expand the underlying workdType array if there are no IDs left. + * + * @param name + */ + public WorldTypeOne(String name) { + super(name); + } + + public WorldTypeOne() { + super("TYPE_ONE"); + } + +// @Override +// public BiomeProvider getBiomeProvider(World world) { +// +// return new BiomeProviderSingle(InitBiome.BIOME_ONE); +// } +} diff --git a/src/main/java/com/somebody/idlframewok/world/types/layer/GenLayerCustom.java b/src/main/java/com/somebody/idlframewok/world/types/layer/GenLayerCustom.java new file mode 100644 index 0000000..2df8f2d --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/world/types/layer/GenLayerCustom.java @@ -0,0 +1,139 @@ +package com.somebody.idlframewok.world.types.layer; + +import net.minecraft.init.Biomes; +import net.minecraft.world.WorldType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.ChunkGeneratorSettings; +import net.minecraft.world.gen.layer.GenLayer; +import net.minecraft.world.gen.layer.IntCache; + +public class GenLayerCustom extends GenLayer +{ + @SuppressWarnings("unchecked") + private java.util.List[] biomes = new java.util.ArrayList[net.minecraftforge.common.BiomeManager.BiomeType.values().length]; + private final ChunkGeneratorSettings settings; + + public GenLayerCustom(long p_i45560_1_, GenLayer p_i45560_3_, WorldType p_i45560_4_, ChunkGeneratorSettings p_i45560_5_) + { + super(p_i45560_1_); + this.parent = p_i45560_3_; + + for (net.minecraftforge.common.BiomeManager.BiomeType type : net.minecraftforge.common.BiomeManager.BiomeType.values()) + { + com.google.common.collect.ImmutableList biomesToAdd = net.minecraftforge.common.BiomeManager.getBiomes(type); + int idx = type.ordinal(); + + if (biomes[idx] == null) biomes[idx] = new java.util.ArrayList(); + if (biomesToAdd != null) biomes[idx].addAll(biomesToAdd); + } + + int desertIdx = net.minecraftforge.common.BiomeManager.BiomeType.DESERT.ordinal(); + + biomes[desertIdx].add(new net.minecraftforge.common.BiomeManager.BiomeEntry(Biomes.EXTREME_HILLS, 30)); + //biomes[desertIdx].add(new net.minecraftforge.common.BiomeManager.BiomeEntry(BIOME_ONE, 30)); + + if (p_i45560_4_ == WorldType.DEFAULT_1_1) + { + biomes[desertIdx].clear(); + biomes[desertIdx].add(new net.minecraftforge.common.BiomeManager.BiomeEntry(Biomes.EXTREME_HILLS, 30)); + //biomes[desertIdx].add(new net.minecraftforge.common.BiomeManager.BiomeEntry(BIOME_ONE, 30)); + this.settings = null; + } + else + { + this.settings = p_i45560_5_; + } + } + + /** + * Returns a list of integer values generated by this layer. These may be interpreted as temperatures, rainfall + * amounts, or Biome ID's based on the particular GenLayer subclass. + */ + public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) + { + int[] aint = this.parent.getInts(areaX, areaY, areaWidth, areaHeight); + int[] aint1 = IntCache.getIntCache(areaWidth * areaHeight); + + for (int i = 0; i < areaHeight; ++i) + { + for (int j = 0; j < areaWidth; ++j) + { + this.initChunkSeed((long)(j + areaX), (long)(i + areaY)); + int k = aint[j + i * areaWidth]; + int l = (k & 3840) >> 8; + k = k & -3841; + + if (this.settings != null && this.settings.fixedBiome >= 0) + { + aint1[j + i * areaWidth] = this.settings.fixedBiome; + } + else if (isBiomeOceanic(k)) + { + aint1[j + i * areaWidth] = k; + } + else if (k == Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND)) + { + aint1[j + i * areaWidth] = k; + } + else if (k == 1) + { + if (l > 0) + { + if (this.nextInt(3) == 0) + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.MESA_CLEAR_ROCK); + } + else + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.MESA_ROCK); + } + } + else + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.DESERT).biome); + } + } + else if (k == 2) + { + if (l > 0) + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.JUNGLE); + } + else + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.WARM).biome); + } + } + else if (k == 3) + { + if (l > 0) + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.REDWOOD_TAIGA); + } + else + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.COOL).biome); + } + } + else if (k == 4) + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.ICY).biome); + } + else + { + aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND); + } + } + } + + return aint1; + } + + protected net.minecraftforge.common.BiomeManager.BiomeEntry getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType type) + { + java.util.List biomeList = biomes[type.ordinal()]; + int totalWeight = net.minecraft.util.WeightedRandom.getTotalWeight(biomeList); + int weight = net.minecraftforge.common.BiomeManager.isTypeListModded(type)?nextInt(totalWeight):nextInt(totalWeight / 10) * 10; + return (net.minecraftforge.common.BiomeManager.BiomeEntry)net.minecraft.util.WeightedRandom.getRandomItem(biomeList, weight); + } +} \ No newline at end of file diff --git a/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenNew.java b/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenNew.java new file mode 100644 index 0000000..0cd9343 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenNew.java @@ -0,0 +1,109 @@ +package com.somebody.idlframewok.worldgen; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldType; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraft.world.gen.feature.WorldGenerator; +import net.minecraftforge.fml.common.IWorldGenerator; + +public class ModWorldGenNew implements IWorldGenerator { + + //Please register this in preInitRegistries + + private WorldGenerator testGen1, testGen2; + + public ModWorldGenNew() { +// testGen1 = new WorldGenMinable(Blocks.DIAMOND_BLOCK.getDefaultState(), +// 9, BlockMatcher.forBlock(Blocks.NETHERRACK)); +// +// testGen2 = new WorldGenMinable(Blocks.GOLD_BLOCK.getDefaultState(), +// 4); + } + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) { + switch (world.provider.getDimension()) + { + case -1: + //nether + //runGenOre(testGen1, world, random, chunkX, chunkZ, 60, 16, 38); + break; + case 0: + //overworld + //IdlFramework.Log("world gen running"); + + //runGenOre(testGen2, world, random, chunkX, chunkZ, 32, 16, 18); + + break; + case 1: + //end + break; + } + } + + //Utility + + //Ore + void runGenOre(WorldGenerator gen, World world, Random rand, int chunkX, int chunkZ, int chances, int minHeight, int maxHeight) + { + if (minHeight > maxHeight || minHeight < 0 || maxHeight > 256) + { + throw new IllegalArgumentException("Ore gen out of bounds"); + } + + int heightDiff = maxHeight - minHeight + 1; + + for (int i = 0; i < chances; i++) { + int x = chunkX * 16 + rand.nextInt(16); + int y = minHeight + rand.nextInt(heightDiff); + int z = chunkZ * 16 + rand.nextInt(16); + + gen.generate(world, rand, new BlockPos(x,y,z)); + } + } + + //Trees + private void runGenerator(WorldGenerator generator, World world, Random random, int chunkX, int chunkZ, int chance, Block topBlock, Class... classes) + { + ArrayList> classesList = new ArrayList>(Arrays.asList(classes)); + + int x = (chunkX * 16) + random.nextInt(15); + int z = (chunkZ * 16) + random.nextInt(15); + int y = calculateGroundHeight(world, x, z, topBlock); + BlockPos pos = new BlockPos(x,y,z); + + Class biome = world.provider.getBiomeForCoords(pos).getClass(); + + if(world.getWorldType() != WorldType.FLAT) + { + if(classesList.contains(biome)) + { + if(random.nextInt(chance) == 0) + { + generator.generate(world, random, pos); + } + } + } + } + + private static int calculateGroundHeight(World world, int x, int z, Block groundBlock) + { + int y = world.getHeight(); + boolean foundGround = false; + + while(!foundGround && y-- >= 0) + { + Block block = world.getBlockState(new BlockPos(x,y,z)).getBlock(); + foundGround = block == groundBlock; + } + + return y; + } +} diff --git a/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenOld.java b/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenOld.java new file mode 100644 index 0000000..f4a1e66 --- /dev/null +++ b/src/main/java/com/somebody/idlframewok/worldgen/ModWorldGenOld.java @@ -0,0 +1,52 @@ +package com.somebody.idlframewok.worldgen; + +import java.util.Random; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraft.world.gen.feature.WorldGenMinable; +import net.minecraftforge.fml.common.IWorldGenerator; + +public class ModWorldGenOld implements IWorldGenerator { + + //Please register this in preInitRegistries + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, + IChunkProvider chunkProvider) { + + if (world.provider.getDimension() == 0) { + generateOverworld(random, chunkX, chunkZ, world, chunkGenerator, chunkProvider); + } + + + } + + private void generateOverworld(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, + IChunkProvider chunkProvider) + { + int perCluster = 3; + + //generateOre(ModBlocks.DIVINE_ORE.getDefaultState(), world, random, chunkX * 16, chunkZ * 16, 5, 12, random.nextInt(perCluster) + 4, 2); + + perCluster = 6; + //generateOre(ModBlocks.PURE_ORE.getDefaultState(), world, random, chunkX * 16, chunkZ * 16, 10, 58, random.nextInt(perCluster) + 2, 20); + //generateOre(ModBlocks.COPPER_ORE.getDefaultState(), world, random, chunkX * 16, chunkZ * 16, 16, 64, random.nextInt(perCluster) + 15, 18); + } + + private void generateOre(IBlockState ore, World world, Random random, int x, int z, int minY, int maxY, int size, int chances) + { + int deltaY = maxY - minY; + + for (int i = 0; i < chances; i++) { + BlockPos pos = new BlockPos(x + random.nextInt(16), minY + random.nextInt(deltaY), z + random.nextInt(16)); + + WorldGenMinable generator = new WorldGenMinable(ore, size); + generator.generate(world, random, pos); + } + } + +} diff --git a/src/main/java/mods/somebody/example/Example.java b/src/main/java/mods/somebody/example/Example.java deleted file mode 100644 index 610247f..0000000 --- a/src/main/java/mods/somebody/example/Example.java +++ /dev/null @@ -1,16 +0,0 @@ -package mods.somebody.example; - -import java.lang.String; - -import net.minecraftforge.fml.common.Mod; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -@Mod(modid = Example.MODID) -public class Example { - public static final String MODID = "modid"; - - public static Logger LOGGER = LogManager.getLogger(MODID); - -} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/backup.json b/src/main/resources/assets/idlframework/blockstates/backup.json new file mode 100644 index 0000000..6b75677 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/backup.json @@ -0,0 +1,12 @@ +{ + "variants": { + "half=true,open=false,powered=false": { "model": "idealland:idealland_extraction_door_closed", "x": 0, "y": 0 }, + "half=true,open=true,powered=false": { "model": "idealland:idealland_extraction_door_closed", "x": 0, "y": 0 }, + "half=true,powered=true,open=false": { "model": "idealland:idealland_extraction_door_opened_top", "x": 0, "y": 0 }, + "half=true,powered=true,open=true": { "model": "idealland:idealland_extraction_door_opened_top", "x": 0, "y": 0 }, + "half=false,powered=false,open=false": { "model": "idealland:idealland_extraction_door_closed", "x": 0, "y": 0 }, + "half=false,powered=false,open=true": { "model": "idealland:idealland_extraction_door_opened_top", "x": 180, "y": 0 }, + "half=false,powered=true,open=false": { "model": "idealland:idealland_extraction_door_closed", "x": 0, "y": 0 }, + "half=false,powered=true,open=true": { "model": "idealland:idealland_extraction_door_opened_top", "x": 180, "y": 0 }, + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/block_fence.json b/src/main/resources/assets/idlframework/blockstates/block_fence.json new file mode 100644 index 0000000..f539184 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/block_fence.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:block_fence" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/builder_farm.json b/src/main/resources/assets/idlframework/blockstates/builder_farm.json new file mode 100644 index 0000000..9e900b5 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/builder_farm.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:builder_farm" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/builder_farm_sin.json b/src/main/resources/assets/idlframework/blockstates/builder_farm_sin.json new file mode 100644 index 0000000..f7d2f7f --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/builder_farm_sin.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:builder_farm_sin" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/builder_house.json b/src/main/resources/assets/idlframework/blockstates/builder_house.json new file mode 100644 index 0000000..7aada7a --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/builder_house.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:builder_house" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/builder_one.json b/src/main/resources/assets/idlframework/blockstates/builder_one.json new file mode 100644 index 0000000..1686f5f --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/builder_one.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:builder_one" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/building_zabeen_site.json b/src/main/resources/assets/idlframework/blockstates/building_zabeen_site.json new file mode 100644 index 0000000..aa132b4 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/building_zabeen_site.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:building_zabeen_site" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/construction_site.json b/src/main/resources/assets/idlframework/blockstates/construction_site.json new file mode 100644 index 0000000..736ca55 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/construction_site.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:construction_site" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/de_arrow_orb.json b/src/main/resources/assets/idlframework/blockstates/de_arrow_orb.json new file mode 100644 index 0000000..c591bf6 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/de_arrow_orb.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:de_arrow_orb" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/de_boom_orb.json b/src/main/resources/assets/idlframework/blockstates/de_boom_orb.json new file mode 100644 index 0000000..682d035 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/de_boom_orb.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:de_boom_orb" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/de_water_orb.json b/src/main/resources/assets/idlframework/blockstates/de_water_orb.json new file mode 100644 index 0000000..0aabdc0 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/de_water_orb.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:de_water_orb" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/divine_ore.json b/src/main/resources/assets/idlframework/blockstates/divine_ore.json new file mode 100644 index 0000000..bf2c82e --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/divine_ore.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "dweapon:divine_ore" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/earth_mender_basic.json b/src/main/resources/assets/idlframework/blockstates/earth_mender_basic.json new file mode 100644 index 0000000..a61c1b0 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/earth_mender_basic.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:earth_mender_basic" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/fence_brick.json b/src/main/resources/assets/idlframework/blockstates/fence_brick.json new file mode 100644 index 0000000..c430c1a --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/fence_brick.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:fence_brick" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/grid_dark_2.json b/src/main/resources/assets/idlframework/blockstates/grid_dark_2.json new file mode 100644 index 0000000..28008a8 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/grid_dark_2.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:grid_dark_2" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/grid_lamp.json b/src/main/resources/assets/idlframework/blockstates/grid_lamp.json new file mode 100644 index 0000000..71cfe54 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/grid_lamp.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:grid_lamp" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/grid_normal.json b/src/main/resources/assets/idlframework/blockstates/grid_normal.json new file mode 100644 index 0000000..8e4b19c --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/grid_normal.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:grid_normal" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/idealland_extraction_door.json b/src/main/resources/assets/idlframework/blockstates/idealland_extraction_door.json new file mode 100644 index 0000000..b539a0f --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/idealland_extraction_door.json @@ -0,0 +1,20 @@ +{ + "variants": { + "facing=down_z,powered=false": { "model": "idealland:idealland_extraction_door", "x": 180, "y": 180 }, + "facing=down_x,powered=false": { "model": "idealland:idealland_extraction_door", "x": 180, "y": 90 }, + "facing=up_z,powered=false": { "model": "idealland:idealland_extraction_door" }, + "facing=up_x,powered=false": { "model": "idealland:idealland_extraction_door", "y": 270 }, + "facing=east,powered=false": { "model": "idealland:idealland_extraction_door", "x": 90, "y": 90 }, + "facing=west,powered=false": { "model": "idealland:idealland_extraction_door", "x": 90, "y": 270 }, + "facing=south,powered=false" : { "model": "idealland:idealland_extraction_door", "x": 90, "y": 180 }, + "facing=north,powered=false" : { "model": "idealland:idealland_extraction_door", "x": 90 }, + "facing=down_z,powered=true" : { "model": "idealland:idealland_extraction_door_opened", "x": 180, "y": 180 }, + "facing=down_x,powered=true" : { "model": "idealland:idealland_extraction_door_opened", "x": 180, "y": 90 }, + "facing=up_z,powered=true": { "model": "idealland:idealland_extraction_door_opened" }, + "facing=up_x,powered=true": { "model": "idealland:idealland_extraction_door_opened", "y": 270 }, + "facing=east,powered=true": { "model": "idealland:idealland_extraction_door_opened", "x": 90, "y": 90 }, + "facing=west,powered=true": { "model": "idealland:idealland_extraction_door_opened", "x": 90, "y": 270 }, + "facing=south,powered=true": { "model": "idealland:idealland_extraction_door_opened", "x": 90, "y": 180 }, + "facing=north,powered=true": { "model": "idealland:idealland_extraction_door_opened", "x": 90 } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/idealland_light_basic.json b/src/main/resources/assets/idlframework/blockstates/idealland_light_basic.json new file mode 100644 index 0000000..e0de54a --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/idealland_light_basic.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:idealland_light_basic" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/idl_glass.json b/src/main/resources/assets/idlframework/blockstates/idl_glass.json new file mode 100644 index 0000000..a7693be --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/idl_glass.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:idl_glass" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/moroon_block.json b/src/main/resources/assets/idlframework/blockstates/moroon_block.json new file mode 100644 index 0000000..e944dda --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/moroon_block.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:moroon_block" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/nullify_orb.json b/src/main/resources/assets/idlframework/blockstates/nullify_orb.json new file mode 100644 index 0000000..b803909 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/nullify_orb.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:nullify_orb" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/nullify_orb_mor.json b/src/main/resources/assets/idlframework/blockstates/nullify_orb_mor.json new file mode 100644 index 0000000..94e33f8 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/nullify_orb_mor.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:nullify_orb_mor" } + } +} diff --git a/src/main/resources/assets/idlframework/blockstates/pure_ore.json b/src/main/resources/assets/idlframework/blockstates/pure_ore.json new file mode 100644 index 0000000..f9d6e05 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/pure_ore.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "dweapon:pure_ore" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/blockstates/test.json b/src/main/resources/assets/idlframework/blockstates/test.json new file mode 100644 index 0000000..829b005 --- /dev/null +++ b/src/main/resources/assets/idlframework/blockstates/test.json @@ -0,0 +1,5 @@ +{ + "variants": { + "normal": { "model": "idealland:test" } + } +} diff --git a/src/main/resources/assets/idlframework/lang/en_us.lang b/src/main/resources/assets/idlframework/lang/en_us.lang new file mode 100644 index 0000000..21170e2 --- /dev/null +++ b/src/main/resources/assets/idlframework/lang/en_us.lang @@ -0,0 +1,83 @@ +#PARSE_ESCAPES +#tabs +itemGroup.ideallandMiscTab=IDL Hall + +generator.TYPE_ONE=Type One; +generator.TYPE_TWO=Type Two; + +#config +configgui.idealland.category.Menu0.GeneralConf=General Config +idealland.conf.general.welcome=Welcome Message Key + +#Enchantments +enchantment.idealland.test_enchantment=Early Access + +#Messages +idealland.moroon_incoming_herald=[IDL][Warn] The Moroon are interested in your fights. +idealland.msg.notice_meter_report=[IDL] Moroon notice value: %d, invasion: %d/%d, error:%d + +#Potions +idealland.potion.deadly=Deadly +idealland.potion.zen_heart=Countless Virtue + + +#Entities +entity.moroon_tainter.name=Moroon Pathfinder + +#Blocks +tile.idealland_light_basic.name=Idealland Lamp + +tile.test.name=Idealland Block A + +#Items +idealland.food.shared.xp_desc=Grants XP: %d +idealland.gua_enhance_no_free.desc=Use anvil to socket Gua(Elemental) +idealland.gua_enhance_free.desc=Free Gua Sockets(Direct craft): %d + +idealland.gua_enhance_total.desc=Gua Enhance Total: %d +idealland.shared.press_shift=Hold SHIFT to examine info. + +fading.duration.desc=Vanishes after %d seconds + +item.debug_test.name=Debug Item +item.debug_test.desc=For debuging. Not for playing. + +item.xie_geta.name=Geta of Mr.Xie +item.xie_geta.desc.0=Uphill mode. Grants Lv.%s Jump Boost. +item.xie_geta.desc.1=Flat ground mode. Grants Lv.%s Speed. +item.xie_geta.desc.2=Down hill mode. Reduces %s fall damage. + +item.p2w_goblet.name=P.2.W. Chalice +item.p2w_goblet.desc=Pay gold to increase your power. (Try crafting it with the 8 elements and gold) +item.p2w_goblet.contain.desc=Containing %d exp. +item.p2w_goblet.player.desc=Owner power: Lv.%d (%d/%d exp) + +#Skills +idealland.skill.shared.cool_down_desc=Cooldown: %.1fs +idealland.skill.shared.power_desc=Damage: %.1f +idealland.skill.shared.range_desc=Radius: %.1f block +idealland.skill.shared.duration_desc=Duration: %.1fs +idealland.skill.shared.error_desc=Error: +-%d +idealland.skill.shared.level_desc=Level: %d/%d +idealland.skill.shared.name_format=%s +idealland.skill.shared.name_format_with_lv=%s Lv.%s %s +idealland.skill.shared.lv_max=[MAX] + +idealland.gua_enhance_list.desc=Earth %s Thunder %s\nWater %s Mountain %s\nLake %s Fire %s\nWind%s Sky%s +idealland.gua_not_applicable.desc=- + +idealland.kill_count.desc=Kills: %d + +idealland.skill.msg.cool_down=Cooling Down. + +#Death +#examples +#death.fell.accident.ladder=%1$s fell off a ladder +#death.fell.accident.vines=%1$s fell off some vines +#death.fell.accident.water=%1$s fell out of the water +#death.fell.accident.generic=%1$s fell from a high place +#death.fell.killer=%1$s was doomed to fall +#death.fell.assist=%1$s was doomed to fall by %2$s +#death.fell.assist.item=%1$s was doomed to fall by %2$s using %3$s +#death.fell.finish=%1$s fell too far and was finished by %2$s +#death.fell.finish.item=%1$s fell too far and was finished by %2$s using %3$s diff --git a/src/main/resources/assets/idlframework/lang/zh_cn.lang b/src/main/resources/assets/idlframework/lang/zh_cn.lang new file mode 100644 index 0000000..40c3639 --- /dev/null +++ b/src/main/resources/assets/idlframework/lang/zh_cn.lang @@ -0,0 +1,67 @@ +# PARSE_ESCAPES +itemGroup.ideallandMiscTab=理境大厅 + +generator.TYPE_ONE=Type One; +generator.TYPE_TWO=Type Two; + +# config +configgui.idealland.category.Menu0.GeneralConf=综合选项 +idealland.conf.general.welcome=欢迎词 + +# Enchantments +enchantment.idealland.test_enchantment=测试期 + +idealland.moroon_incoming_herald=[IDL][注意] 摩隆密切关注着你的战斗。 +idealland.msg.notice_meter_report=[IDL]摩隆注意度: %d, 入侵准备: %d/%d, 测量误差:%d + +# Potions +idealland.potion.deadly=致死 +idealland.potion.zen_heart=功德无量 + + +entity.moroon_tainter.name=摩隆 拓荒者 + +tile.idealland_light_basic.name=理境灯 + +tile.test.name=理境测试块 + +idealland.food.shared.xp_desc=含有经验: %d +# Items +idealland.gua_enhance_no_free.desc=可用铁砧镶嵌卦象 +idealland.gua_enhance_free.desc=徒手卦象镶嵌槽: %d + +# Items +idealland.gua_enhance_total.desc=卦象强化: %d +idealland.shared.press_shift=长按SHIFT查看详情 + +fading.duration.desc=%d 秒后消失。 + +item.debug_test.name=调试物品 +item.debug_test.desc= 在主手时减少受到的伤害 %d ;\n 造成 %d 电击伤害;\n 付与虚弱 Lv.%d (%d s);\n 击退 Lv.%d;\n 付与自身击退抗性 Lv.%d (%d s);\n 付与 %d 火焰伤害并点燃目标(%d s);\n 治疗双方 %d 点生命. + +item.xie_geta.name=谢公屐 +item.xie_geta.desc.0=上山模式,赋予%s级跳跃提升\n 右键地面切换模式 +item.xie_geta.desc.1=平地模式,赋予%s级速度\n 右键地面切换模式 +item.xie_geta.desc.2=下山模式,赋予I级缓慢并减少受到的摔落伤害 %s 点。\n 右键地面切换模式 + +item.p2w_goblet.name=销金杯[装填模式] +item.p2w_goblet.desc=氪金让你变强,强到骨子里。(塞金子升级,塞八卦、镐、食物可以改变模式) +item.p2w_goblet.contain.desc=融解 %d 金 +item.p2w_goblet.player.desc=黄金之力:等级%d (%d/%d 金) + +idealland.skill.shared.cool_down_desc=冷却: %.1f秒 +idealland.skill.shared.power_desc=伤害: %.1f +idealland.skill.shared.range_desc=半径: %.1f 格 +idealland.skill.shared.duration_desc=持续: %.1f秒 +idealland.skill.shared.error_desc=误差: +-%d +idealland.skill.shared.level_desc=等级: %d/%d +idealland.skill.shared.name_format=%s +idealland.skill.shared.name_format_with_lv=%s (%s级) %s +idealland.skill.shared.lv_max=[满] + +idealland.gua_enhance_list.desc=地%s 雷%s 水%s 山%s \n 泽%s 火%s 风%s 天%s +idealland.gua_not_applicable.desc=- + +idealland.kill_count.desc=杀敌数: %d + +idealland.skill.msg.cool_down=冷却中 \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/loot_table/chests/abandoned_mineshaft.json b/src/main/resources/assets/idlframework/loot_table/chests/abandoned_mineshaft.json new file mode 100644 index 0000000..d3b0e2e --- /dev/null +++ b/src/main/resources/assets/idlframework/loot_table/chests/abandoned_mineshaft.json @@ -0,0 +1,276 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "minecraft:golden_apple", + "weight": 20 + }, + { + "type": "item", + "name": "minecraft:golden_apple", + "weight": 1, + "functions": [ + { + "function": "set_data", + "data": 1 + } + ] + }, + { + "type": "item", + "name": "minecraft:name_tag", + "weight": 30 + }, + { + "type": "item", + "name": "minecraft:book", + "weight": 10, + "functions": [ + { + "function": "enchant_randomly" + } + ] + }, + { + "type": "item", + "name": "minecraft:iron_pickaxe", + "weight": 5 + }, + { + "type": "empty", + "weight": 5 + } + ] + }, + { + "rolls": { + "min": 2, + "max": 4 + }, + "entries": [ + { + "type": "item", + "name": "minecraft:iron_ingot", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 5 + } + } + ], + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:gold_ingot", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 3 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:redstone", + "functions": [ + { + "function": "set_count", + "count": { + "min": 4, + "max": 9 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:dye", + "functions": [ + { + "function": "set_data", + "data": 4 + }, + { + "function": "set_count", + "count": { + "min": 4, + "max": 9 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:diamond", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 2 + } + } + ], + "weight": 3 + }, + { + "type": "item", + "name": "minecraft:coal", + "functions": [ + { + "function": "set_count", + "count": { + "min": 3, + "max": 8 + } + } + ], + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:bread", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 3 + } + } + ], + "weight": 15 + }, + { + "type": "item", + "name": "minecraft:melon_seeds", + "functions": [ + { + "function": "set_count", + "count": { + "min": 2, + "max": 4 + } + } + ], + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:pumpkin_seeds", + "functions": [ + { + "function": "set_count", + "count": { + "min": 2, + "max": 4 + } + } + ], + "weight": 10 + }, + { + "type": "item", + "name": "minecraft:beetroot_seeds", + "functions": [ + { + "function": "set_count", + "count": { + "min": 2, + "max": 4 + } + } + ], + "weight": 10 + } + ] + }, + { + "rolls": 3, + "entries": [ + { + "type": "item", + "name": "minecraft:rail", + "functions": [ + { + "function": "set_count", + "count": { + "min": 4, + "max": 8 + } + } + ], + "weight": 20 + }, + { + "type": "item", + "name": "minecraft:golden_rail", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 4 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:detector_rail", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 4 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:activator_rail", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 4 + } + } + ], + "weight": 5 + }, + { + "type": "item", + "name": "minecraft:torch", + "functions": [ + { + "function": "set_count", + "count": { + "min": 1, + "max": 16 + } + } + ], + "weight": 15 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/loot_table/empty.json b/src/main/resources/assets/idlframework/loot_table/empty.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/main/resources/assets/idlframework/loot_table/empty.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/loot_table/entities/mor_orbital_beacon.json b/src/main/resources/assets/idlframework/loot_table/entities/mor_orbital_beacon.json new file mode 100644 index 0000000..1e60e7e --- /dev/null +++ b/src/main/resources/assets/idlframework/loot_table/entities/mor_orbital_beacon.json @@ -0,0 +1,30 @@ +{ + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "item", + "name": "idealland:antenna", + "weight": 1, + "functions": [ + { + "function": "set_count", + "count": { + "min": 0, + "max": 1 + } + }, + { + "function": "looting_enchant", + "count": { + "min": 0, + "max": 1 + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/models/block/construction_site.json b/src/main/resources/assets/idlframework/models/block/construction_site.json new file mode 100644 index 0000000..cbae625 --- /dev/null +++ b/src/main/resources/assets/idlframework/models/block/construction_site.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "idealland:blocks/construction_site" + } +} diff --git a/src/main/resources/assets/idlframework/models/item/skill_base.json b/src/main/resources/assets/idlframework/models/item/skill_base.json new file mode 100644 index 0000000..1bf89ab --- /dev/null +++ b/src/main/resources/assets/idlframework/models/item/skill_base.json @@ -0,0 +1,5 @@ +{ "parent": "item/handheld", + "textures": { + "layer0":"idealland:items/skill/skill_base" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/recipes/emp_site.json b/src/main/resources/assets/idlframework/recipes/emp_site.json new file mode 100644 index 0000000..442eb3e --- /dev/null +++ b/src/main/resources/assets/idlframework/recipes/emp_site.json @@ -0,0 +1,32 @@ +{ + "type": "minecraft:crafting_shaped", + + "pattern": + [ + "1A1", + "1A1", + " 0 " + ], + + "key": + { + "1": + { + "item": "idealland:gua_1" + }, + "0": + { + "item": "idealland:gua_0" + }, + "A": + { + "item": "idealland:antenna" + } + }, + + "result": + { + "item": "idealland:emp_site", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/recipes/matter_original.json b/src/main/resources/assets/idlframework/recipes/matter_original.json new file mode 100644 index 0000000..1af136c --- /dev/null +++ b/src/main/resources/assets/idlframework/recipes/matter_original.json @@ -0,0 +1,32 @@ +{ + "result": { + "item": "idealland:matter_original" + }, + "ingredients": [ + [ + { "item": "idealland:gua_0" } + ], + [ + { "item": "idealland:gua_1" } + ], + [ + { "item": "idealland:gua_2" } + ], + [ + { "item": "idealland:gua_3" } + ], + [ + { "item": "idealland:gua_4" } + ], + [ + { "item": "idealland:gua_5" } + ], + [ + { "item": "idealland:gua_6" } + ], + [ + { "item": "idealland:gua_7" } + ] + ], + "type": "forge:ore_shapeless" +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/sounds.json b/src/main/resources/assets/idlframework/sounds.json new file mode 100644 index 0000000..0cc6177 --- /dev/null +++ b/src/main/resources/assets/idlframework/sounds.json @@ -0,0 +1,14 @@ +{ + "entity.moroon.ambient": + { + "category": "entity", + "subtitle": "entity.moroon.ambient", + "sounds": [{"name": "idlframework:entity/moroon/ambient", "stream": true}] + }, + "entity.moroon.hurt": + { + "category": "entity", + "subtitle": "entity.moroon.hurt", + "sounds": [{"name": "idlframework:entity/moroon/hurt", "stream": true}] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/idlframework/sounds/entity/moroon/ambient.ogg b/src/main/resources/assets/idlframework/sounds/entity/moroon/ambient.ogg new file mode 100644 index 0000000000000000000000000000000000000000..58301a045f310e3fe1d6f73bdea970da4c242c3b GIT binary patch literal 15382 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 TMq@MPAV>xT>?%RcdqDpWSc;J) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/sounds/entity/moroon/hurt.ogg b/src/main/resources/assets/idlframework/sounds/entity/moroon/hurt.ogg new file mode 100644 index 0000000000000000000000000000000000000000..58301a045f310e3fe1d6f73bdea970da4c242c3b GIT binary patch literal 15382 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 TMq@MPAV>xT>?%RcdqDpWSc;J) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/blocks/builder_farm.png b/src/main/resources/assets/idlframework/textures/blocks/builder_farm.png new file mode 100644 index 0000000000000000000000000000000000000000..142f7ca9d1dc6221ed79c0ecdd6e17c4f1db10dc GIT binary patch literal 1589 zcmV-52Fm$~P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1bxlH@21{O1&V1Oy1gaWIdFy}=%TlZRcl%hf&8 zGbYMl5J+T7f>QOrf1COTk0Ixj;~+kIukpC(qDg3op3kgFyYXHhdT(6%)iGeuWl`Jt z>FbhD=;zmj;8y>3?N=eMb!08Hue=ttU9&-B$;n#Cn%Ph5Tg5dmxzl#muVpiad7DG` zZx;YYVXSA3GS!mRc>Au!&R@dMjkkvoq4ajd+gbCBojRH~@Q&6EJDpa)y+Wb1UjqJy z(ds9D#%>^VV{O-b8E{bteSXf^wIZ$6xx3^%kn(D6YTwFeK@e~{JEnP*fFGkBMu{kb zEoLxQz~+XM6-6>YyOEZKtaAOe(!HDU)F(=TFHEd=#QVWP+>umrv2o#Xz9K(Nt6ZlYK z%T6(~=fJ{|legY^_TC5Ib5sg8xWK`O5G2Hq#EKIZFF{12q-df=3ghTwP*GxxDM4w% z(h0K@BvRVUW;eI-=C`oP7Ppk)KG|i?K8Gwh=2T3v1>s+O393kmB~_|$rRpkIUqh7| zYijVdW}9o=d<#ulZ0TTav3g~VZp?kn8ZFj3V{XWW7i;JaVPArJI^oV47&DH*c<2nk zp-tyZ3v#{b%yrImGzbbdV2!wwQ>Zfr23;k?jSlW!%zeq5V)t9TnNQ5APTk*NPIc-Q zbML%8uvXGIQS2b7M`6cQ+lIu}Tueq_k7RM9g(P^Z$@ePtQ)|}6jFFA42CYnEE{MPQ60oMt<_W1M6=?^m5RemKpPz;)r1F=xJ3 zpVHs$;9lo;ASOFvleL#kdTr1nEU#F~lPxVS>~R&ysyh84EDo${TC_I6(l(s!LvN_1 zhP+X16C>Yq+MT<@fVtY{t$efR9<*l*t9vuRR$lwThoJLOLVYcA-Nijp&vkc5O>q*A z%<1KWFeRQc3E8`uDaH*D!FSPAXVUIX9nki)M<8 z@uLR?S|DT}3^ksi#w~LS1s6CI*B(lOILD6?>Z6EWF^_}|R^;T+`N;tg zw785c{!4B)e-|P*Z`m(BhFgYSFd zJF=4dn3Z0JxeoSkWutpm(zZ-k)zdM$JL50!7=fjB?=(J4*d&&E64=M}`?#SaFt-u3 z?<(v%Lf%v5r7K&kJ6h`UiW#Cix&6@5O~ z&iTl`-HM)%eoMD)h^HOw!>S0iPf%P0mWyWG(RP>d>N^BN!*vh;_SOHzAojPdqgZnQ z000JJOGiWizyQDiz#5$gQ~&?~32;bRa{vG?BLDy{BLR4&KXw2B00(qQO+^Rf1O@{M zEAG&&^HED`D_;R`4uI&HZEL z-wl+C@^oO#Q=0|A$d{LTG`F1Z9bwE3;jnQI_Ykf~(W#l^>}%Cb3rT~*%l zm^%mmT0Mx94AT>^(s?hC?DhNDfio`*J{L1_C^RrIaeUaDxHc_ay5hJ4gWSm@f)^!2 S&U*rFVeoYIb6Mw<&;$T#2}Gg* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/entity/centaur.png b/src/main/resources/assets/idlframework/textures/entity/centaur.png new file mode 100644 index 0000000000000000000000000000000000000000..c3cc2d067e256e004470b7a4ea5ea9cb950beee5 GIT binary patch literal 7042 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/entity/moroon_humanoid.png b/src/main/resources/assets/idlframework/textures/entity/moroon_humanoid.png new file mode 100644 index 0000000000000000000000000000000000000000..9b141400b7d847fa543c506554efd90f51a4570e GIT binary patch literal 4675 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%0D)Uqi(9FtOAkcg=yX}De{ zfz6hOB=e-&3b0^QkvV0^jh2fn@@h94H3ZdLiXH@D?zf__a|boFmh}k55NntlHN0AI z!!t~HJ>G?eb>8qCuCd^V=k{U zOT`%RqEi~e3L~z93t{bO`bR4qy4Z99@~M*`)GPuCEJC{*`f)(+lC1e16#i84`vZvI z;9#yl0`eCCfsgq+fZh-04c{2gUMZaM@ICtp+$Jo2-Q5S%6Rm8xpFkDQGy47hc}5RB zJtyeY8ypk9uJK;s`vNcj+fzTf4N3K48FsF5)0=*G*^h$*V*c)`e}>)s1^+TzsOG;> zU?^tM#2>l<000JJOGiWi{{a60|De66lK=n!32;bRa{vG?BLDy{BLR4&KXw2B00(qQ zO+^Rf2N4ewGP&SL@c;k-4|GLXbVF}#ZDnqB08K+6Npxjx{5nsI000LFNkl7=O+=_j}50NK7+_W}mKQSy9%>SqSL_r^V@sxJs-c{^Ssa3 zOLU(9Src{RY<5XHo4w;=wOUY4Wc3nNFIDTAyNIkFqVg;9u9!nK_?!B_uZ}2NMRec; zweB9YtWRT>wezq4odAkx8Sc}xLJ_Usq6k(r64`O}oxR+6^xMXro{;Oz`}q71;54Fv zHloZTqOHr+XK!s%!X&e2T>wS=fj&jJ`BEagi>TsBB4@QEXzvF`fHx|19+h|WHyZ-% z1G@PBO({$!MKrKc3DSB<3GwmF2^T;SUtLXPcM>%$&RN(QQ5gDFVR!=wufg|QfnE6g zph5UDLy%g9-p^8?(LGWSzXjMp)ZU?lXgP4k1yID-olwN@T}>2P0ir7<;qcYKcR=_! za1VR zQmzv>Nudga=rsgKkPTfZJ%Q^EF2JnWl4qa*)k||f)Ro&B8Laq0I;}a#MW{=nO)cube+*9J(xW@zb7dWVCJsEc%Un|QG%YU%?ttJBrwnxI|(UX)xRkJOM;dbhZNz$ZTS!)uI_6rMcCU&(p{P`Q6!> z`g7pAb~_%q079Y3u~Es{$m1Ch^WMPq5Xk-z$c5E=z*(}e;w`GTEIfeL2k_h(I(MCT z=0{_VXz%}yb@SPH3u6m#KYluYKK6J9?XCYREDFnyK8r$T2?`m+9B&n_+Xj3c*S~=E zgGRkD)uiW z&d0EbhqReSvqFf@ggoz0!rp8MemSob*CUOlSqNki7wOrx4MQ9?3{`8)6?njsH)$&H zfbK!nPUgD|yAZn+cV(0>|$G5oc{s2;45SXEV<+o1t$ep$TftH9_&&vipM}DFIK2F9ObxJpkwJ@Mf7NOT`dvaS%`4 z0)&gFzLL$+Fw$&tmFx~ju!X%2qJcIwC%9p#L@%&)nHo9ePhPy~vJdAjjN8-{TsMV5 zMQRT4e!LjcRy416pf&S_AgTHaJFh(?J)m9 z3DJ5;#e~+iMBZWJrx1dmypI=*b9&--b-tYBa0RIaKqcoN3l3^*X!dlbfbohLvZVu8CMnE0s;Nl#-a%JTva zlH7lD8_MmoE=i5ys1_g=oWD7pF=2B`JknTvI=sC_5kCV%(c&Iq^Bvp1-G+!FjD$xj7Mr#FD6S}g#(G8qcX14^qupL#JGkZXp`ye93G90Pni6} vQ69MP+`;NK4o9ox;b?woK5>Vm=l$P*k#a%jVj&-G00000NkvXXu0mjfKlxsM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/entity/projectiles/bullet_norm.png b/src/main/resources/assets/idlframework/textures/entity/projectiles/bullet_norm.png new file mode 100644 index 0000000000000000000000000000000000000000..0abe48ecd7f95f10c27517f230e9e1d44271205a GIT binary patch literal 5136 zcmV+r6z}VaP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3#rcEq?1g#YstIf4l8$Km?k+#tu#2U6;`JsyuI zN%!lPxQI)kPyl7-zyDa~UwoV|+4zuhEHPeueDOspH~BiBy8rFv_y7LL-9-6Qy?HeV zRgSAW#T@VYNxi%W&;1^!QXf7HRQ%o0J~x#60m=6Scl|Swv-bpdKU434oSX)Gm)reZ zEIEDLLciPRv*LVyM*sZqjN?o4F~o6Qt4q;7;U4X4*(cB(fq9+Cbk)(blfX5*I#_TuJQ)^lcipF;AOsT_+mld?|SzI`1raq z&^HY>d~d03jt>(Dc}*;zRut@G%+D6l-&!NDHP7yg-# za{5m<3}V-9x3B?zzORq@U|5F*!-hGt!FshbL<{!KEw>5a=oh#izq4tm)nv28Gk0Jy z)?tDxS{H1zR}x9qLh+1&Dk~S~rC|XZf(#ZZ-nocvGCX2#o=JB1l^~}cfx|w*MSL%- zw_z;r1N=!o!=V~n@F9d4Qpll%YNCtkO);jZN?DUjK7|xhN;#EOv&%k*9COM!mt2b! zhmeL6ODegPQY&*-Z)&JKUFlJ4ljfRlp~aS3Zl%=@eY)?V$DVrbrPm?D4K!rLkwzY6 z)M+PFGSkm6<4iNpGV6kC%PqgciYu+W%BnA`-B$h6_a9iz-d2-sDeaeDR--m09cT|> zRcC_Q42y}kSUjl(Ahf8>u57&*wVc}QDyn%wSY%M!40}~$BPR6IN?7(~ySL?jZ8rnf ze`h!OjpdA*?*CvpG1Gmq+c#Dlb;mEaEu>zkm|hO=qkZNoxdOJFn;)-j4hJ;=t53I@ zONdct^4Jzj9}#^rqmP+!8+O7YSDIJqA(1}} zQ;TnYBukg!igxJ*0zsZMJlC-@5*mVKvw#z>m7DgOr6b{f=>4df6?wgV`j6c|;JbU) z&a|H&ShJ=zCQ8PD?0Pjno9@Ca-QeE2Z)LIbFhfhBvF;^d?)Tpih)bY6VDrg^zj*M)ZmmaJde@Y5uo4 zPuK$uK#;c-vvUMyl1G_q-+KZeyR(NvHu^eKi%OTQ9*16w-(__ZKp+n+*T@QjKJmh6 zY*Y?}$|@k>TI683ZAnvf*92)l3`tayWU2s zS)$_&9eT7*&D9@&B~f{?i$({#gg97tdjtrt1z?J3j@R@UKQy}>gXBDwFG?^ctwaa} zSKPy}2bwpdc%;O9{1bFc%QNP?M^cB)HReH#;PO%LNJ@UxJM!#Lg7HbHlI`#s4lefv!Tbq7a{#n2{IDgcNl0wr zn(e^T6~5$|KCiuY<=42J1MkJc+-#=JE0T&SImDj=k40aJb=IBWxfw~hBZ&5sSCB@y~y`WR5KY+(V$=HxGa`r2Q zqB;#4M+;H9n_c+g%$#E44iR}CFe9edOl9wPc7xn?^o}azZ&&56ilzEkHQAmS7&t{} zAR_qKJ~_EYy*;raS0tHmbmAq=K2(43#UytHPOb|&&WXE%@3`?Ld%-$!yF;EWn;P+7 z@H{^Ig5{UaOV-!WO-ajWszV;PG}S>+m$rZry&WkI;^#?pz*HXcXe#G4y7;}Aiq8R| zH(8Hi;{~!8ukTS*ZOCSKa4sxZBSF#p!n%IK|U3vD1KlsRX(}n$pN%&g+(2k^HvTx8i++R z>3tB=*iUd-JNPE@jggik_AZSrk>DFiVB?1qh*NW5HVsvsg*H3Kp`Y3N4hl^>WZL{9 z`O1$wZg0dFH&ptJY;#YVnw1?rm4Zl3PT`cBBxgrXcT>>3 zIcRFGAscll9MGipH&oxV^V-;lyDrgXLs5%vOQa5iO)spf}cH&oGRMoNYh&H-$5Om0ad?e5{lu!bGO zSMa9dVL9so+5`omn9|QABp@W*;k2Y|;C&*@NZ%+7w|E%fJ!x+Q=Fax5?3~ zFdXr9lH#(ezDX8R^YJ>j*Y{VWH$jgNXQq@}>CvC}4xyJFG4wpb0yvMPf~d#k^&kT3 zC6Q3_Ec^g$J=|Y~cpEOD9h-cyMp2K`Jt71_tQK$=0ru^F3gA9S0F^?9W{(XPSZP|m z4_5%0o+8JLIOk_@P{|F>b!~VyI_5JxVf+{H?5p{UhVNi|K>HRl^AR)q^8K{x<|{6| z-xf*O?~EYonwqeW)xE|f_=wO$`DMtUh+johN#FL%c7h4}ZY!7bD(S{%zd2gOoAa`Y zd$JmmLmVzG>x??iqv!W4ul>I28ClbXPh&qj))VM_gKi$wKY^bAIVH`$(KQ!5_&=}m zIN(q#fXx5^00v@9M??Vs0RI60puMM)00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF->u5f2j{i#Q|_0000FbVXQnLvL+uWo~o;O+z3_bY*S)I!}uL00=g-l4?g6b2`-!hKb^A#~FCU$v^)KJi`o||q9sL!! z|J!Rv00Di6?{ncZ0=9UQ&V^+_MfnW?Pz~>_^VNFRU9Sz>&YhdOEyU1zxW01(fInEc zeV#sZ{aYgDFY~<5@4XoCPaYA_izf(Z;cY;5b4yqTFiQYc!}}Bf(D3Nj8ut2`|2(JKY zHlGCmHJkGQKy~v3s7nMW298+*t~#zFOi8;>(Z zp3SGutb|U!#*t?trlbH9p-MVSfLTd?EDE6OMY_)@+;vg(uyN+HG26#?@pP&pyl2R9 zmii>%nbHhJAR^$IuV-q!W@V5PRD+ekDS#43o)uwJK&0Ott`l&Iyz)H)UglcjXX*FK zbe~bU7e%d1sqypONj1VdxT;HW!wR7KHo{p3y5uOJ#5F+HW&V7hlwb)-cLPoZNdYVU zCKJJtH(g2vgx(MUP#jC&A)>;m6b&_{&QM=GLB;Z(N_UM33b^nYMZWMhpgJr;jp8BQHbL{qQR=k*W(RH!-fM4$@d7OivD#hU=U!NTg^6i7I?D7RUt0!ngC zidH9;)3Yf;B;v>Na@{SGq8v^E>krZ?P~ylJJvTfdHYWh30QG2%1_4&Z+yW^hPwU2@ zRaiD=`}hE-H^f<{6matJxLB#ao3plWcTtGZWX zgTuzgCB#NpfHEN&P7y>YqXbvVlJn!DW&u;=`!V?eiF82EWum-xBwuI10Y6{h2_bs^ z9DvVt8(*dfn0vr4-cK+t4vvkC^mE(R($~ATXp%81Gf`XvGUHm|`T&uBkED)11NKvZ zD-5XTxj=!|ftE&QkHBlqJzxTmaX;fsXD{ohOU`Gd3v4D+Bhx9kDbuH-D@wAnLtWOX z>*Jbo@b!Ihdiej2HJS3T&JJ)00A@{7Bt`nct9*zQ0Wyyl-hY7sxk(OA+8MaLnGz2% zK38Y1>Ig}?iSbt_?=z8@E$$jkx^4m??BMIz(k;QchXC1#DEyHaL%ZzF1yDykx(if{ zi{hyb9WgX9TUWBOqaNj~Y7Cs5HS&O$21Jycw+5OWArmz`!@#(@?@tKA$w7K_ieKDM z5g{bRarF&FggU-uvZt4E>=}FbL`||F9}qP%O2_1y;iEv6VM(54tIIIJ9LQQ z_aTJzh99#sS{z{_M0`P-n96vkX^#Sad_o%yH2`Xj0a=U6!wS#i7I2xTvnXF>kIvSW z&ZCH=E<_lKe6W9?x4?=F*r)vf^Ls2x7`pE>VMY2LtU~xc{($!rsH+Ih30q?12!DDP zP~9U-h2=!s>K<82PJgOfa4c|UlJViHZmT~Vm1#8uzDvM}m5@+|qZIpo@VLceGQA({ z(7N)twR3~^2|oIBN*B0&o_@H_J1_J=6k)>=2G8Nro<cx3RLo$f zGa64bKB`F~RK!J6ym*+`Nkd}^5JMB#9A0;%yfql6fa-nMms~0URgb$sPQr4YOH!(H2c)P#IvWZtChU9tmEBZX;;bWFIHKk4nNih zrp6^!LPgt6)4!%~h`2=DnKNd)soNjS1Evvg*2;;Lka^rnovSVbFcC*y#?lIpwT)Eu zXRj{R+NQvo_yQ?vgIf|&0vhiRoNEXCfxZ5IgROo$ZCa94l-6+idYm$oZRH~iuV z5%F{$Fb#dSR!&Gi;IWi*-fl?rMB<*Lz}bURAkhulP8-{D*EZ)l6_OF34*a=ifrKKO zy8ZKAz+e{_Pte|5VP&k0@mR{kNrfVBQ=nmqXgMh$hopj7VL)a z+`~|!MjQw3De4**{-(XR#hWyD7nT9l%hLn*+_6=ppZF`xtqttxOdvCXZtvUx5OO;U y(Z2rAq~i8E{y8ceF3_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/gui/container/gui_demo.png b/src/main/resources/assets/idlframework/textures/gui/container/gui_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..eaea7f6ee79370fceee55cde00d3725540dfcece GIT binary patch literal 1627 zcmcIheLT~79RF^fCKrYXJ6m#;hv-W36vq(Nrktrx47KH{oH-9uHmS@Z(#bj|1UEP28{l31h&*$}deLwHd`~Ci8`Qv<6uQFN% z09ft26T1%p7?i>QLKO9%I>!z&b&5%obbvifMm^3x8+}ob?KS{LJ z7`kZr#>VE&o;pbgv=Vn3f$=6885U7s9ka{fClt2&++U*hDk8$YO-B2C^A-bfti> z*jO7=Q=?q(_gixQ4W-O8|3r~!{?&3c@4=8cl}zqHQF>fEL^-r-a9E4C;hmH^K0aO? z(Q{8CvkI&RbO7K00WhCQFkl-D0qio)-crjS5MeJxXtr;in|R1X9L6EVs6)t3Q3ie# zfk_44VeQ5g@A3#Q%)pmTa)+eHz_kHU^#HQ7tVIxZq80-BOR^t1>ijiKL9I49qUQ#s z7V*aDvvfW&MbP&^jQ_w`!Ak;UjyZzfHR+WMs7deRj_4FaDzf(`PplW#(-)Xt;ty`C z5%ma7_T;CIn{du5U)bQs<-+RJ-2vV3a3GPg$}Mw-ZD|+Kag&FGDNLo8I4@bCM;JQ` z%-&W-M!jyyF@c$NcX!`a4QN&2oj?uJT`!&9xcq#?#d!0cCmts~&tZwT2S9jA%EC** zQe>&QPvY=P5=gmiN7VN=!PNBXz?c{GUn-S0Bu$0TEN}&8w~I8CGe<%W4nR2*abJ$DX#<2&1-M;zR!2<#5)UhEpiBW93ENCa?`2plc)^Vt+jGF{9OB z97pL%iz5__%SkL@RJ&MAqV-qfE6U`aedoYX^GRb0g|e)XG7^7JE+3z64&KxutO>%S zE=#P5Ik4oFrG=8_xMvcHqsCgat;$(Lk}D{d1^}7{*pjw-m^C-PIKk@9m>+N}Ya7C=)(*liev4#8InKea>Yi*S^Nehoy=GT-VMF|gBqGzKEYOlK<*p3Z z;>dCbm<1nhu1#k!1gWXZdG!dF2V5O3lcsl5bx0(7$6Xw%jQ?SoQxzfCAAWc(sJc`o zr-PSGe~w$2Ug^3*6V%sl3weN+-E2|I3wi#*{|>OWndEMh3*0o(7s<%|2W#iFB=`cp zlTmt%#H|~WRt+lV--oA#$x-r0QVpew-;M`!wQWNk@IT2a_+5$9kFw{HY~x&msfb9n zj(mkf9`oD_x8v6Ja%V=y#O%yPNQdWulB(l&tHwB)JvO|4{cxh@%6 zR03^&v0jF>iL-Q@Yeula(zX;xXTFKuG4*vhMn=OZV4dG9Z=t+tc(|o;f*jpaN GQ~v;UsDTv# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/gui/container/gui_research.png b/src/main/resources/assets/idlframework/textures/gui/container/gui_research.png new file mode 100644 index 0000000000000000000000000000000000000000..547652f19f5885b8238b44f64485c4330ee1a521 GIT binary patch literal 4739 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 s-9r5i5 zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=KVjwB}#h5vI3AA#6dj>9VX20p$YBvswD%t$kC zX=JGrRVEo3JRm-{a^s)Br~3;Rw1#ceLpY$mU*zd`v-oPz4i;Z8iE8vQwq$b__?cJduc<+?9|432bsHK(0s=me7zOf? zIT9g`3497#&Z1mFfXuj)n_wdn04MRP8)YJGUpBtXSXuzWBuE4rOd!BgHH@FA31g_3 zm^w2H7A;w}5+rD_5JC)VjVe*1MvEcFm|~74Nz!B~q?l65sbtQACCqZj(dCqLE(Mhq zNEehY@F=Bnm8#WhsIjJ+YiSrhO`EmQVoNQz(z#2=^zWfZ*Hh2E3>p|pLx+tp;z%Qp zGBMVsOr18vj5EzV%bnVx`bdqQ$o-re9cqi1Zol|J4dxhc610{RTg*U=l|Vc$0vOP| znE6DiyvQwPJ~JkTF{qI(IGq+T5Y$0zlkV(3$o-U?GyNrQ{3CL1q5BGQZlOEmUb(%Y z*2~^eWCL2WaK+Ti#KH!LkqW1>_N3o_y8kNhE%Yt)=Y?i{nGEg=8uKmmzZ072%DR=u zYQ4>~Rv9=_`Srpzw}IWoNR4c*>fstYSgTvjy6k~*By8K;RT5#{`J#!!RZ+lRvpm;N zF4=&?N4Zohb~L?IvF>YGs`yhAMo4xV5v5=a@0Z+6Dg&p-TPLu|oQ7u^E!BRt$_MO& zdy1@1w8svOj}FC42%C^rx{3zu#5;@4^)$@8%DKO^H{sMfFWusM!|`Ypj7o^jrQ2I? zGq+pQgSa93W(xlL)0Hn;N4|yroDhyJ_}A+G1w$yfy`OS`RsaA124YJ`L;(K){{a7> zy{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jd7C1QG|J{N3~b004hUL_t(I z%k9!J3c^qjgyHYyJ!7GTn#K!w84v7bJb{I=(Lzb`EP@0iU5X(1cMG#Ku(JW#IN@s^ z)fFZ(zrp;3oOAx|BThC5a6V>>J#j zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ck{l@v{O1&V1SAj=$Ke^VH`wEEQqa{iJ!41M zZ+F@bjvb%}@&ODhGGlQ3>;MJcb~?{4pLr#|S5b?nTRYh>zUOZgY;kx)KwZO71M`v6O2BN6;C=H7%hjF2Pu@ zmeCALY*4I2&5G6>Wn!>BDN?6Glg8CIYDh8iU`5Z|I9xUh%9-0GN?eU5E9B`8T5xDk zEx^ooE_B7sSG-1s$erNH1hA#zhvq&r{!Y7r=3J#q6B1%))&KoBcNLH%en)KHNi z(TPYB6_YF_g%p#dlr*g~s%X%tqDfUvvla^$O)Qz3S+kt}gKEybW<9KGjg)U?D6pg53i z!`9rrwoxx1#b<3&(q8tnc-}jq-<>dQOX=QMx0=OZu=L+4|Yx*6~YaxH2 z%G-ES)z1Pf1|+sU+#jOo8|WM88|Xg=!k;?$pRW5CERV(Sg$kTG00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmYE+YT{E+YYWr9XB6000McNliru;|Li95*=NhB#r<80Ix|z zK~y-)-IK8m!axi~pL4l1K!K2;p=BC&U=BuLA{s_Xg+xIppdcy8UCtB-5=D|G1&A-X zvh{3#%c82v03{66_W=TsuN6B7GX=YVbOy-;%or31C4@WpE4VZG8~6fNdm%j>bHWCi z5l9w`LJg(_pT!R05g|?af>klz6SQ98v{gxLOsa$BPFm~IuHD=P#DXXU*X=*TPbbG34*&oF07*qoM6N<$f^a@bPXGV_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/items/basic/gua_5.png b/src/main/resources/assets/idlframework/textures/items/basic/gua_5.png new file mode 100644 index 0000000000000000000000000000000000000000..d86417f3cad416d6c7db63e9d58ffdf384ab217c GIT binary patch literal 1276 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cj^!u}{bv=k1Z-mr%OO0Z-oY$?4v*YhuWqTU zdNdlTE|oxxIW|7TPPzW~kKz8pk3B^f)Kbhbdi+8TnF|KV@89mphjl*>{vN!NyT=4z zy`Y!<82iyLkn3}Sg(JUS%bnGOlMc|0d;n!yW(v#x{}+d0>$yr%Wq zQ*WPxAs9`8C+xTjiN`%oD*_KBOF^G-XHlLK#`u=&$FXyd;hW$+MsH&0%aP0LP&glt zLVOdWBPabhb}K?}Si3F1nyC3<;(hE!OJnrCyAmQI72Vm?y_GeBBElJDEsJP|OEI?9 zGFrkGD;R5F^FphRGBKh(C{Uw9gZk<#Rk#?qv!Q3MEK8QeICEX3gxP4YfrjS54od}V z0x>^)p=CEOdzBI_H-aV;z$T0Dn)^ujnf3r0V;)^1pB}M-Up&t=+?dSGJG4LujT2K{ z@muBlg*jn^#a|oZQhJ^(Sv(8$)CcGHt3lQd073-Y3TH^bfR7|fk-RY* z5#pG@Pl4wwfiEyXs@%v8a3c~yPU2}BYmAmID{nDU3y4sOVxR^u3djmUaegc$oS~wk z!KrFg)1+BTlo+DM7%k2mRZJ|HS~Rm{*-DZWlBSp}rIb_2oCPUNbIj&)$~l(;qXp0f zs|z$rx%iSRTzbXJu5{(AR2-igs@7PorkZPM+@#_4Z?TzcspVEWbsVK0y7t(ur=EKm zIBP>j7&_vxkwzZn!P;T5j5Yz8B;FjRiApp)#~W#ce!%z16N|M~6hX zZI?3TY}*gye1C1Xshay%QV={^}Z*C@y;@7#44 zVDm8&2tkMopwI8%?VzGE<{{~J9i=g5)Ufs{{_bn1=NssM3WR?v8vfID{{WWCp|rib zAg%xa00v@9M??Vs0RI60puMM)00009a7bBm001r{001r{0eGc9b^rhX2XskIMF-;u z83Yps&fwf50001=Nkl!T!ve4GH$_T7?>F-3k)r3 z%@Cx5L@J>UUHGfNzn?8xR8{FALr)DKFuVlNj@rAv`dljcwEOh0_rgyBegR~0u0GN$ zBm>+EjE~$}b>D#FRv9h9PQlH<=HTWaSu`{igbUOKgaX19!WlLPi3G++7CUa6Z4Pb{ m3F=!ru_;0BApS-0{{@~iu_&R&a~3E70000 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/items/basic/yang_sign.png b/src/main/resources/assets/idlframework/textures/items/basic/yang_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0aa035d5e5fd77a2517ba75705ad77b51ebe6c GIT binary patch literal 1898 zcmV-w2bK7VP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|KvMeVI+;a*a0SN@+IE)d#fsgNGsOsVM`{Dn> z3oqOiT}4wMq)bh1`d@zz^9Mdm>W!DEA%$S^@yRF77^vN!{Uqzx{rs@k;AP(2FBnq} zPq%-De%5Eq%VR_IXTH47n^=z=J%TRDN1&T0GX`g!9zl-xJe}VroqgFqnRC9Q@_H?0 zzk2`eBfw|^d5#TtN6z9N<|z&uxa2aPiaR^uIl~wet~tY>u`~DZ4ZM5whMmo4-n~L$ zY&Z+T8%AfI;sSr<`{LEvPM`4IK5lj0w(#a4AfzV61`7f~y)z#6WwHr$(6u_4TY&p`z!`P>q=@yEUgSa^kv3@$;g=5%e?z zcGy+0<}l5-F0{@~>%2;elN(_r6NF6`zg*_i;;3q?KcAg6uAQ5h42Dou9fE?v{HugkXYgu?tBej4Calu7Ug8%|q-V6LE zdW8>VapH}L1c{=OBnKCKkPt!)Ge_mX6^3B>|^_4YxWA4|i(P3>e=GVITU=7nTULt6w6PcWWG4=$; z<75C1&66{$~ zle)v)SKdCb*7B+-ZV@!2aAIoRKw`s!u9-E@n)KtR`O(Hva$dviQXMK`3jzz@Zvk#= zI7)K8YT7Rn`?Sqa=WN~@*)@22a%toRUJ;NJ_rVN=YS&QRn~zv1c9LShN0>LBtwpv{41CLh*E#M& zW}b%NqqvtNkm~I#b^|rDz*cKY*`^|@Y~J<-1RkP)i$(gr%}JS#60J^mh;kWWhn6SB z`=z)a1&!9&`;|1sei>n34N4D#>fVjCceznY=>Npvi(c-+nQM+u`tI2P?{Mdg*+l5( zw4q_W@Q=A5)7~i<|ub$?2H~cT?zb@!0$-$4xQv|waKVAs}X{6dahoBYa&%P_V zXWdEB2tbk(cDDIE%ocz$`-n!LPvSv^6MwlbV&)3QW@GI;!$mZ?0~xQGyeA~V!TZU7 zu{9J!cf}r5_9Z^TEnoTLS!MI2Gy9WXlfBbNyVA$Q4x7hi1_@tg0Hdu%$d42l(RTEB zu{|68YXI#T;=j`= zh@=~ztoEz2X!#ECh3iQD6mo+mptFA8L!7!<9KdaN2fF?w z*+jSb51-g0U-5s!+}<%xTorU_vuOV#B_GjgF82uW06F}R8aMM>joN6*{0)v{C374m zv?Blj00v@9M??Ss00000`9r&Z00009a7bBm001r{001r{0eGc9b^rhX2XskIMF-;u z83YR#CQD?90004PNkl;(!j1#p1- zg!CPfIk*Vo3GCg1h+qMRM-CgP*wz$a1CSyJkbQy_Km-!NtHG$Hg)L|$EO=$`>MHi? zU@O`|8vdBY2S}tq0CCQ_b(}D)x&9v@0K=BU-_q&&+hFTpHq=U&hbVi8WCrnz+L=sX z|6Z{D@sR8k(y~rAnW=4F2uUHg@k1eLn8WfwEjs9rhwPj;v74F$Q&E`l^B~1}m?FsL z+QC6zmVj@_Zl{Ua08`3Cc`8io=~IH)q%S$Ep4?nLs>Up7CT= k3?SX!)#7q-()qIsUuMXZzzt*f>;M1&07*qoM6N<$g6ArVjQ{`u literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/items/basic/yin_sign.png b/src/main/resources/assets/idlframework/textures/items/basic/yin_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..c3aef4cee7fdee9b7e6f0e6fea5dcd1552ab3e04 GIT binary patch literal 1902 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 R1@r&_002ovPDHLkV1k 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/items/skill/skill_base.png b/src/main/resources/assets/idlframework/textures/items/skill/skill_base.png new file mode 100644 index 0000000000000000000000000000000000000000..38e24d3001f08eef07399e3d7066a56fca8a4326 GIT binary patch literal 2415 zcmV-#36S=QP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1b9S8_efP$E=;w!VpO>A8e*0u7m^F}I2f~`bemU44mm^Kf!O~N48PYrlXuYR3&jl~fOUP@y zZp426RDYOaV8;Y8&bo44EpzBPc3Hc>8$mRSgesixyVJtZhXJymnHqFFIktQp z^9v$QWA%^AKYpzh-&&oki^d_`Zl&dLp|%+)f)k_1G>2R8vyf%n0k=n{XQW3#?j+oq z0x>9SWT+^L)TmNHn<)dM;mU%RIkO&pUJD1#;F7fIH#HU=bkQEnW+Z^tMrl4+X!s4o zUq&64s}NL~V2m*3kGJ|s;Wu|{x#tnl37CM8r#w=(RWAdgsM^AAAfPG&WKjT#(>H2rce>Tk$pt4c?w_KmbUI6Rn^NJ|86GQX{Kh~H1^0baP3xCH%2)rpIhm> z;IH9Sy(J%?1T`dQ$>0xL(-x{vUBIa*K9$~SiWUc1n$IhNlsJ%sXgsNx`AxD^hD?VJ(03A>t5GgS$5tO!n; zZ$KA7HIS7>0+r=}wjZwcb1%~@__(OE_WBsMI5hKV>Hi~)=7jM$!q@;OI$*Pv*-pSqz zJxsi%y>X9 ze5XRxt7txauJ}9>Sw;7H8hl>qxAt+CsGoK5#fJa-)xT=P=RWeBj$Hr%00v@9 zM??Vs0Hgo{16b%|00009a7bBm001r{001r{0eGc9b^rhX2XskIMF->p2oDiBj`CCp z0000FbVXQnLvL+uWo~o;O+z3_bY*S)I!}uL00WarL_t(Y$E}rLXd_h=#=m=KCMks? zY(grlmW2dsq)SOD4m$WC^=;AUN_|L?NL#@QHctyhr7Yru+Xc1wB5Vu@&Oj9{Da40j zsV}p3x*Lj=l4dvKLq!X6Q`&&gWd2+q%w&d!>~_KPayY{b-|u|)+%p8{4Bn3OzE9fW z)lX;de)fY5;27`YI)D)F<9k4SRN-=?+$c8yJ8sAAIAF!CxD^NNjGeJFe(ilX{89O< zA2$fO^>Ol-zjeUaYub;S2EZ9-oB<_PVkHJtKe_Vm)hy>X ze>-|@?L|W5k-i&$egotm!+b0U&|bnk&C@*HEktE1QyCyKk;wzHkP~u34p?cdG*%kG zwb2WYzZ&BFoewK-#)g1C)*E00jyZKwttB7$8NZs1ywd#YvpR z135twBmoE+AtPh}KF{a*JTP!La5!)XlvYctrB$H%>6Pr&Ea&9Lf0IHz;p6CW^f(GM zm8Q~E0E=17Vn9o2DJ>;1Ts=A!RZ$gHK+ptD&;U^rHBkeknpBf&fMiOhWCH7p>x=7) ze#0FHJYk{`g(v`Jlu_nqTeo#v2S(>c=SJs%o#ak(C+T-er|1-&0>ou;SzHF7L4yX+ zExJXw0B&-Vo83p+1wa+5Pz4}GQY1w{EQkfM0JzL$E(1KLQY^(%%m?wp)m+Whe1|;Y z^8KAJw722zz&B~|f39Mw@B6`%$+sPS+BdKTd94D`x& z!7kW^fFo@X@2opB;MJyRihYjlmS0W?A*Gy*ufqdU5P zeZ`ts6Knp0@*+8zoJ>yotGctRe}4X8#=#5K;1VPn`B_V2$Gks?yWufuv+ z59>fk59uM@e;z{&F#zVKxoK|t0EvafLSmu&A3^SZP`-HQ6#$q1shn;Aq4DNl%{}09 z>g8u9F8LsykSFZrvp|Ez!Qx;MILII55Awj!?9lAcY`3sK1Fs{Dw}1;@Klx? zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1b>dMqgj{qHJf35p`P9DIG>>|mBZ2dlc%$<2La zCSB>$_(0^qfe!1RzjycxAL2%#uxM?yMtn*ujSL-)*T>E~#d6-~L-!Q^e>WbU6NI6R zHedg0y~h{E=}owfTaICzUj(&sPxSW_?cP9oA8?O94$A31;9eK(7L@6lNcaE!-dCH- z>lMa5zaARv^$q?ivp`O1QYzOO;~vy}4d2o}{$B*voQ!ib(aI@DS|L~0CSPB}SMa7> zu_$Fd{f0ODI@b!wP!yMb37xlQA^zm^QOn!d?~r=-V6X7$#0Lb+xX1Gc!`EjEL7z+{ z{v4?T$IHP?&x7fmMnj*j_zn^O?mczyb=}TNg}LkPmgk7@5QBxlq~x=$;t_lqeK}9V zqww?r_n7dVj%TEn2$1bm(hSMcPAg5cBMs94poSyoZ!7~K zY2Ucf|83^(*v*Lml`z4}tdh@M(93W#IqrKuT$#m4{cuB$83}sRV1hJ;f zsir7Ik`i280gyp+%7r=*NX#^$B$bS45>ogP&c+@|XDu;Z;~+TTg9t1ed2IMHL`~kO5 zP@8u0S3U@N6uM1gM)Ym&wzZL3*u5^38uOxJ7$DQ=javLt8@{^Xv(}Xf{niAwd#Hk( zP#AylD{c7dhOZ0aEd$+}SO(k%6OBO0eAbK~t{48VeLfY`*M93pIc8i}_c6CMtxrXT z|F6qCL4B=-v9{V~#;YjK&X*dM^J;pGBO~qtMuGKCmt`V5I>qELkMSNx{O@ge9gx{~ zX&pr%vZz@!nMJ+7tYe@lsN$hALnAHq=!{sOp{(WAEa(D8ZE!}{mZ9r>IKXv@?{!G1 z+zP^273P~As@TW`=9nDB*(E;pUu`1wyGrf&q%#+aiIv!PpXAr&Bw$yxNLM@7iL8nH z1-m@M9Y!(YF5_^bSbu3<2B;||)eRn;v<2*$dfSnY2@F@`F+n(K&$)-7lEQ$>NaD6% zjeV(rib2F{+6D)LNCix;7?QE!Uf?oU_5|UqHhVxMED_j$#SO$fBu?xsPe2|chxRry z-mx_Jo@ULgCl$CQ-I05(p}d*&*=fBA0N72I)s}C&PGrTO*%Jx!qk%^SFk78H2HA$g zbKYM3Bdg@Gt;dZ7=yz(pAkWrXI_#+dDG^*fJhrZQ!tDmaWg^FIte9pKxvAl21Z)8e za1SI__#=y5hTzht1sEURT6SC8lrQH(xwY2>Tx+kqJ$;qlA|JYgN9bMywfh!$msgf0 zx3L4R4qGb0yYueY*5_8)s1%lDH}y3K*OTZICflL8=;3R$lOPDyqYQ!W z=t`T60svV)Aao{{aB0^o%YER2hjOjI#5W;|TC67)_ z!w;QfY$C|!p%ugKuu?hM$m<*++Lr=d6j>fp1oF7>;@;@jHw^#DBr<0P4zNFun#7+i42IA}pg?!YWDErD9XB+S*#EM@Er7RY>3FlgDB5ppwe{4`u<2u^dhy0U$ z;~dx+$3%K4UQiZXyVl8i<>;yHl>@@(r0~0TySKU3TW52I?BRffUqv;|D@!IrIGg(9 z0?Dt3>sh^B?>NkGDI>!iLPuP3z>jQ)4*}?Xc!B}vNjT*D1lbx<(od8mY=0z^ ziXVPot{R|@7jP)4Cm)&Mcci0R=+?S!igJc}xlyV0=Na5Z9!+<+ulVkU7c8SZCHUGq zNaLHOeu%Yi3)=UZ`nkHQeL)*k&c8^00006VoOIv0RI5|0IesUDG~qx010qNS#tmYE+YT{E+YYW zr9XB6000McNliru1Ld+r5>%1{|9zKbjmF$fC8Z3i$=L9*PL-#5CN_w1J49V!*kvB1}*{-k3`Ikykqb>LI_lN{SWnqGnHzSLupUCDgu&5O5*OF zcdiGdRPMf)TtJkR#LIy8!uB`KPpVB0jbpVv7T{VJpztrkzaAbx@Q%1)2b_EM96Pl^ zZ6d8J=DC&(f(Ve?5yA(2&#-2Iv~GvEb3@DnF^fmf@CdeaS(-ccs7>8K*c6sR#$X-c zFS+)fr{Ax^x@on?fB#i&VpAxEi~x5F=UPu_a1n@~7r!lGgfXsZQz-uEwcH?N zdip8!ip^19`ErCm5V9=Gj$_5|{FihgWywpuLG&{TGB*B~#OV)BmE}6PKsb~Vx&TO8 zDM=6kN_8d0hNTVRwMA-^U1@)?%N-hm=<4Up14imcZjRq#j4Q2bJiNc4Du)iRnUn{7 zuea1z?9-rfbW1^LY!xz|iEhej_8%H9p`LaZ7~jqif{dUZ5c`(bPcIx^m4g~ri}huB zLdTJb%@H=|(#SDqW7%>kj?w{2XSF;Lp!Xf0(R`rnXzSX2Gb)mK9AAhmBnyS~Hf;sc zKDvADg3Bsh_mj%onopM)t8y|UV<#<8dj$F0`I~$W=xxPr5G)bZI3Xpo`)NB%2iV8# zCrku*Bd_460TNj&6$8T0LbmWIKnuytj{x&F#hhG`rqWe5w*9%kx?-1bFRu`m0<@CM z^f#dVbogrv!aQIC1>h?LZc>(&<=u+7F2rT|ijw3S7AT@N|)SrlL!)jqj|0aB?{Kv978t+wqYs{Vr* z;O}zZ3$}EaEhYH?)?p3Oy+*8)*RTw)j_aXAIv}r?^~eAe3!`7melGCP7;pd`zqM8$ zitz}EI6R^@`^(-v+wZ&Fe&_-q=Rwah0OZLz@B$$}k8AFu@?+1;U*sQzFi^tVc3fWm z-2_0I=H%{$?{+sT`+99D&c!IQ$I5c+kN-GI9|PoLFkqzDlpEwC@B5b7jVP@FqN_(w z$(rf=1j#}zymh5ZKu^sJFhB)FPaU-@>y1FIE6Xjj8&8(j1pZ_fh>#tG0$;GNg#|lr zpdjeh6z&;!?K}hiEpVgRp0Q8?_XR#gNpSG~1}FT_3%fmK1^#R7U)EWX!iDO=hX4Qo M07*qoM6N<$g8oHT>i_@% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/misc/potions.png b/src/main/resources/assets/idlframework/textures/misc/potions.png new file mode 100644 index 0000000000000000000000000000000000000000..4b81e54532c8d95510a6bf00361a7301a2f3acf1 GIT binary patch literal 12101 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_1.png b/src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a018d658477ca496e3a81868fa4a32258a0577ac GIT binary patch literal 5873 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 Hu0mjfh2ASy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_2.png b/src/main/resources/assets/idlframework/textures/models/armor/armor_qsh_layer_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6a08f9dda45918b5b00067a8c2f750a980f41eb8 GIT binary patch literal 5170 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 literal 0 HcmV?d00001 From b80929057c3bf423135fd46ec0eaf76c01cb292c Mon Sep 17 00:00:00 2001 From: Hileb <107909747+Ecdcaeb@users.noreply.github.com> Date: Thu, 2 May 2024 18:57:53 +0800 Subject: [PATCH 2/2] use snapshot_20171003 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3fb1c11..2f1ec97 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,8 +19,8 @@ mod_credits=Idealland - they provided this framework. mod_logo_path= # Mapping Properties -mapping_channel= stable -mapping_version= 39-1.12 +mapping_channel= snapshot +mapping_version= 20171003 use_dependency_at_files=true