From 06c079df7340ea3f1c043ac76dd6c3a47ba7acdd Mon Sep 17 00:00:00 2001 From: elucent <9532786+elucent@users.noreply.github.com> Date: Wed, 15 Dec 2021 17:53:25 -0800 Subject: [PATCH 1/3] Updated to 1.18.1 --- .github/ISSUE_TEMPLATE/bug_report.md | 20 - .gitignore | 3 + build.gradle | 27 +- gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 ++++--- gradlew.bat | 43 +- .../java/elucent/eidolon/ClientConfig.java | 3 +- .../java/elucent/eidolon/ClientEvents.java | 52 +- src/main/java/elucent/eidolon/Config.java | 23 +- src/main/java/elucent/eidolon/Eidolon.java | 144 ++-- src/main/java/elucent/eidolon/Events.java | 191 ++--- src/main/java/elucent/eidolon/Registry.java | 740 +++++++++++++----- src/main/java/elucent/eidolon/WorldGen.java | 246 +++--- .../java/elucent/eidolon/block/BlockBase.java | 87 +- .../elucent/eidolon/block/BrazierBlock.java | 47 ++ .../elucent/eidolon/block/CandleBlock.java | 56 +- .../eidolon/block/CandlestickBlock.java | 103 ++- .../elucent/eidolon/block/CisternBlock.java | 61 ++ .../elucent/eidolon/block/CrucibleBlock.java | 46 ++ .../elucent/eidolon/block/EffigyBlock.java | 32 + .../eidolon/block/EnchantedAshBlock.java | 259 +++--- .../java/elucent/eidolon/block/HandBlock.java | 31 + .../elucent/eidolon/block/HerbBlockBase.java | 70 ++ .../eidolon/block/HorizontalBlockBase.java | 35 +- .../block/HorizontalWaterloggableBlock.java | 54 +- .../eidolon/block/NecroticFocusBlock.java | 49 +- .../eidolon/block/PillarBlockBase.java | 75 ++ .../java/elucent/eidolon/block/PipeBlock.java | 110 +++ .../eidolon/block/PlinthBlockBase.java | 74 -- .../eidolon/block/ShroomBlockBase.java | 56 -- .../eidolon/block/SoulEnchanterBlock.java | 65 +- .../elucent/eidolon/block/TableBlockBase.java | 103 ++- .../eidolon/block/TwoHighBlockBase.java | 51 ++ .../eidolon/block/WoodenStandBlock.java | 111 +-- .../elucent/eidolon/block/WorktableBlock.java | 38 +- .../elucent/eidolon/capability/Facts.java | 2 +- .../eidolon/capability/IKnowledge.java | 39 +- .../eidolon/capability/IReputation.java | 95 ++- .../eidolon/capability/KnowledgeImpl.java | 53 +- .../eidolon/capability/KnowledgeProvider.java | 32 - .../eidolon/capability/KnowledgeStorage.java | 52 -- .../eidolon/capability/ReputationEntry.java | 2 +- .../eidolon/capability/ReputationImpl.java | 83 +- .../capability/ReputationProvider.java | 32 - .../eidolon/capability/ReputationStorage.java | 63 -- .../java/elucent/eidolon/codex/Category.java | 61 +- .../java/elucent/eidolon/codex/ChantPage.java | 98 ++- .../java/elucent/eidolon/codex/Chapter.java | 5 +- .../elucent/eidolon/codex/CodexChapters.java | 39 +- .../java/elucent/eidolon/codex/CodexGui.java | 130 +-- .../elucent/eidolon/codex/CraftingPage.java | 11 +- .../elucent/eidolon/codex/CruciblePage.java | 20 +- .../elucent/eidolon/codex/EntityPage.java | 51 +- .../java/elucent/eidolon/codex/IndexPage.java | 24 +- .../java/elucent/eidolon/codex/ListPage.java | 20 +- src/main/java/elucent/eidolon/codex/Page.java | 61 +- .../elucent/eidolon/codex/RitualPage.java | 45 +- .../elucent/eidolon/codex/SignIndexPage.java | 108 +-- .../java/elucent/eidolon/codex/SignPage.java | 73 +- .../elucent/eidolon/codex/SmeltingPage.java | 9 +- .../java/elucent/eidolon/codex/TextPage.java | 11 +- .../java/elucent/eidolon/codex/TitlePage.java | 17 +- .../eidolon/codex/TitledIndexPage.java | 19 +- .../eidolon/codex/TitledRitualPage.java | 20 +- .../elucent/eidolon/codex/WorktablePage.java | 9 +- .../java/elucent/eidolon/deity/DarkDeity.java | 8 +- .../java/elucent/eidolon/deity/Deities.java | 11 +- .../java/elucent/eidolon/deity/Deity.java | 12 +- .../elucent/eidolon/deity/DeityLocks.java | 6 +- .../elucent/eidolon/deity/LightDeity.java | 29 + .../eidolon/deity/RegisterDeitiesEvent.java | 7 + .../eidolon/entity/AngelArrowEntity.java | 137 ++++ .../eidolon/entity/AngelArrowRenderer.java | 25 + .../entity/BonechillProjectileEntity.java | 57 +- .../eidolon/entity/ChantCasterEntity.java | 124 +-- .../elucent/eidolon/entity/EmptyRenderer.java | 26 - .../eidolon/entity/NecromancerEntity.java | 178 +++-- .../eidolon/entity/NecromancerModel.java | 316 ++++---- .../eidolon/entity/NecromancerRenderer.java | 76 +- .../entity/NecromancerSpellEntity.java | 78 +- .../elucent/eidolon/entity/RavenEntity.java | 163 ++++ .../elucent/eidolon/entity/RavenModel.java | 116 +++ .../elucent/eidolon/entity/RavenRenderer.java | 35 + .../eidolon/entity/RavenVariantLayer.java | 40 + .../eidolon/entity/SlimySlugEntity.java | 74 ++ .../eidolon/entity/SlimySlugModel.java | 57 ++ .../eidolon/entity/SlimySlugRenderer.java | 27 + .../entity/SoulfireProjectileEntity.java | 57 +- .../eidolon/entity/SpellProjectileEntity.java | 86 +- .../elucent/eidolon/entity/WraithEntity.java | 124 ++- .../elucent/eidolon/entity/WraithModel.java | 155 ++-- .../eidolon/entity/WraithRenderer.java | 12 +- .../eidolon/entity/ZombieBruteEntity.java | 102 ++- .../eidolon/entity/ZombieBruteModel.java | 135 ++-- .../eidolon/entity/ZombieBruteRenderer.java | 15 +- .../eidolon/entity/ai/GenericBarterGoal.java | 79 +- .../eidolon/entity/ai/GoToPositionGoal.java | 21 +- .../eidolon/entity/ai/PriestBarterGoal.java | 20 +- .../eidolon/entity/ai/WitchBarterGoal.java | 21 +- .../eidolon/event/SpeedFactorEvent.java | 2 +- .../eidolon/gui/SoulEnchanterContainer.java | 236 +++--- .../eidolon/gui/SoulEnchanterScreen.java | 263 ++++--- .../gui/WoodenBrewingStandContainer.java | 98 ++- .../eidolon/gui/WoodenBrewingStandScreen.java | 39 +- .../eidolon/gui/WorktableContainer.java | 126 ++- .../eidolon/gui/WorktableResultSlot.java | 85 +- .../elucent/eidolon/gui/WorktableScreen.java | 36 +- .../eidolon/gui/jei/CrucibleCategory.java | 46 +- .../elucent/eidolon/gui/jei/JEIRegistry.java | 7 +- .../eidolon/gui/jei/RecipeWrappers.java | 3 - .../eidolon/gui/jei/RitualCategory.java | 33 +- .../eidolon/gui/jei/WorktableCategory.java | 36 +- .../java/elucent/eidolon/item/AthameItem.java | 128 +++ .../eidolon/item/BonechillWandItem.java | 67 +- .../elucent/eidolon/item/CleavingAxeItem.java | 28 +- .../java/elucent/eidolon/item/CodexItem.java | 30 +- .../java/elucent/eidolon/item/ItemBase.java | 27 +- .../eidolon/item/ReaperScytheItem.java | 27 +- .../eidolon/item/ReversalPickItem.java | 41 +- .../eidolon/item/SappingSwordItem.java | 42 +- .../elucent/eidolon/item/SilverArmorItem.java | 110 +++ .../eidolon/item/SoulfireWandItem.java | 82 +- src/main/java/elucent/eidolon/item/Tiers.java | 84 +- .../java/elucent/eidolon/item/TongsItem.java | 31 + .../java/elucent/eidolon/item/TopHatItem.java | 87 +- .../eidolon/item/UnholySymbolItem.java | 41 +- .../java/elucent/eidolon/item/WandItem.java | 11 +- .../eidolon/item/WarlockRobesItem.java | 79 +- .../eidolon/item/curio/AngelSightItem.java | 113 +++ .../eidolon/item/curio/BasicAmuletItem.java | 32 +- .../eidolon/item/curio/BasicBeltItem.java | 18 +- .../eidolon/item/curio/BasicRingItem.java | 20 +- .../eidolon/item/curio/EidolonCurio.java | 11 +- .../item/curio/EnervatingRingItem.java | 24 + .../eidolon/item/curio/GlassHandItem.java | 19 +- .../eidolon/item/curio/GravityBeltItem.java | 19 +- .../item/curio/MindShieldingPlateItem.java | 36 +- .../item/curio/PrestigiousPalmItem.java | 17 +- .../eidolon/item/curio/ResoluteBeltItem.java | 41 +- .../item/curio/SanguineAmuletItem.java | 138 ++-- .../item/curio/TerminusMirrorItem.java | 59 ++ .../eidolon/item/curio/VoidAmuletItem.java | 59 +- .../eidolon/item/curio/WardedMailItem.java | 23 +- .../eidolon/item/model/ArmorModel.java | 168 ++-- .../eidolon/item/model/SilverArmorModel.java | 51 ++ .../eidolon/item/model/TopHatModel.java | 73 +- .../eidolon/item/model/UnholySymbolModel.java | 228 ++++++ .../eidolon/item/model/WarlockArmorModel.java | 240 ++---- .../eidolon/mixin/AbstractArrowMixin.java | 17 + .../eidolon/mixin/LevelRendererMixin.java | 19 + .../eidolon/mixin/LivingEntityMixin.java | 29 +- .../eidolon/mixin/PlayerRendererMixin.java | 17 + .../eidolon/mixin/PotionBrewingMixin.java | 9 +- .../eidolon/mixin/StructureSettingsMixin.java | 25 + .../mixin/ZombieVillagerEntityMixin.java | 14 - .../eidolon/mixin/ZombieVillagerMixin.java | 13 + .../eidolon/network/AttemptCastPacket.java | 59 +- .../eidolon/network/ChilledEffectPacket.java | 39 +- .../eidolon/network/CrucibleFailPacket.java | 26 +- .../network/CrucibleSuccessPacket.java | 28 +- .../network/CrystallizeEffectPacket.java | 22 +- .../network/ExtinguishEffectPacket.java | 26 +- .../eidolon/network/FlameEffectPacket.java | 28 +- .../eidolon/network/IgniteEffectPacket.java | 28 +- .../network/KnowledgeUpdatePacket.java | 62 +- .../network/LifestealEffectPacket.java | 24 +- .../network/MagicBurstEffectPacket.java | 22 +- .../elucent/eidolon/network/Networking.java | 28 +- .../eidolon/network/RitualCompletePacket.java | 28 +- .../eidolon/network/RitualConsumePacket.java | 28 +- .../eidolon/network/SpellCastPacket.java | 52 +- .../elucent/eidolon/network/TESyncPacket.java | 48 +- .../eidolon/particle/BubbleParticle.java | 27 +- .../eidolon/particle/BubbleParticleType.java | 21 +- .../eidolon/particle/FlameParticle.java | 17 +- .../eidolon/particle/FlameParticleType.java | 21 +- .../eidolon/particle/GenericParticle.java | 52 +- .../eidolon/particle/GenericParticleData.java | 22 +- .../particle/GlowParticleRenderType.java | 38 +- .../eidolon/particle/LineWispParticle.java | 49 +- .../particle/LineWispParticleType.java | 21 +- .../elucent/eidolon/particle/Particles.java | 16 +- .../eidolon/particle/SignParticle.java | 51 +- .../eidolon/particle/SignParticleData.java | 27 +- .../particle/SignParticleRenderType.java | 31 +- .../eidolon/particle/SignParticleType.java | 27 +- .../eidolon/particle/SmokeParticle.java | 20 +- .../eidolon/particle/SmokeParticleType.java | 21 +- .../eidolon/particle/SparkleParticle.java | 21 +- .../eidolon/particle/SparkleParticleType.java | 21 +- .../particle/SpriteParticleRenderType.java | 38 +- .../eidolon/particle/SteamParticle.java | 21 +- .../eidolon/particle/SteamParticleType.java | 21 +- .../eidolon/particle/WispParticle.java | 17 +- .../eidolon/particle/WispParticleType.java | 21 +- .../eidolon/potion/AnchoredEffect.java | 71 +- .../elucent/eidolon/potion/ChilledEffect.java | 128 ++- .../eidolon/potion/ReinforcedEffect.java | 37 + .../eidolon/potion/StrictBrewingRecipe.java | 14 +- .../eidolon/potion/VulnerableEffect.java | 37 + .../elucent/eidolon/proxy/ClientProxy.java | 12 +- .../elucent/eidolon/proxy/ISidedProxy.java | 8 +- .../elucent/eidolon/proxy/ServerProxy.java | 10 +- .../eidolon/reagent/CrimsolReagent.java | 20 + .../eidolon/reagent/EspritReagent.java | 20 + .../eidolon/reagent/IReagentTankProvider.java | 10 + .../java/elucent/eidolon/reagent/Reagent.java | 40 + .../eidolon/reagent/ReagentRegistry.java | 33 + .../elucent/eidolon/reagent/ReagentStack.java | 30 + .../elucent/eidolon/reagent/ReagentTank.java | 54 ++ .../reagent/RegisterReagentsEvent.java | 7 + .../elucent/eidolon/reagent/SteamReagent.java | 20 + .../eidolon/recipe/CrucibleRecipe.java | 178 +++-- .../eidolon/recipe/CrucibleRegistry.java | 191 +++-- .../eidolon/recipe/WorktableRecipe.java | 168 +++- .../eidolon/recipe/WorktableRegistry.java | 236 +----- .../elucent/eidolon/ritual/AllureRitual.java | 32 +- .../elucent/eidolon/ritual/CrystalRitual.java | 31 +- .../eidolon/ritual/DaylightRitual.java | 35 +- .../elucent/eidolon/ritual/DeceitRitual.java | 30 +- .../eidolon/ritual/FocusItemRequirement.java | 42 +- .../eidolon/ritual/HealthRequirement.java | 39 +- .../elucent/eidolon/ritual/IRequirement.java | 8 +- .../eidolon/ritual/IRitualItemFocus.java | 2 - .../eidolon/ritual/IRitualItemProvider.java | 2 +- .../eidolon/ritual/ItemRequirement.java | 43 +- .../eidolon/ritual/MoonlightRitual.java | 29 +- .../elucent/eidolon/ritual/PurifyRitual.java | 79 +- .../eidolon/ritual/RepellingRitual.java | 47 +- .../eidolon/ritual/RequirementInfo.java | 2 +- .../java/elucent/eidolon/ritual/Ritual.java | 52 +- .../eidolon/ritual/RitualRegistry.java | 72 +- .../eidolon/ritual/SanguineRitual.java | 16 +- .../elucent/eidolon/ritual/SummonRitual.java | 24 +- .../elucent/eidolon/spell/AltarEntries.java | 40 +- .../elucent/eidolon/spell/AltarEntry.java | 4 +- .../java/elucent/eidolon/spell/AltarInfo.java | 41 +- .../java/elucent/eidolon/spell/AltarKeys.java | 6 +- .../eidolon/spell/AnimalSacrificeSpell.java | 90 ++- .../elucent/eidolon/spell/DarkTouchSpell.java | 85 +- .../elucent/eidolon/spell/KnowledgeUtil.java | 44 +- .../elucent/eidolon/spell/PrayerSpell.java | 73 +- src/main/java/elucent/eidolon/spell/Sign.java | 4 +- .../java/elucent/eidolon/spell/Signs.java | 13 +- .../java/elucent/eidolon/spell/Spell.java | 14 +- .../java/elucent/eidolon/spell/Spells.java | 13 +- .../elucent/eidolon/spell/StaticSpell.java | 19 +- .../eidolon/spell/VillagerSacrificeSpell.java | 93 ++- .../eidolon/tile/BrazierTileEntity.java | 162 ++-- .../eidolon/tile/BrazierTileRenderer.java | 42 +- .../eidolon/tile/CrucibleTileEntity.java | 175 ++--- .../eidolon/tile/CrucibleTileRenderer.java | 92 +-- .../eidolon/tile/EffigyTileEntity.java | 25 +- .../eidolon/tile/GobletTileEntity.java | 25 +- .../eidolon/tile/GobletTileRenderer.java | 46 +- .../elucent/eidolon/tile/HandTileEntity.java | 69 +- .../eidolon/tile/HandTileRenderer.java | 34 +- .../eidolon/tile/NecroticFocusTileEntity.java | 69 +- .../tile/NecroticFocusTileRenderer.java | 37 +- .../eidolon/tile/SoulEnchanterTileEntity.java | 79 +- .../tile/SoulEnchanterTileRenderer.java | 66 +- .../elucent/eidolon/tile/TileEntityBase.java | 56 +- .../eidolon/tile/WoodenStandTileEntity.java | 159 ++-- .../tile/reagent/CisternTileEntity.java | 83 ++ .../tile/reagent/CisternTileRenderer.java | 40 + .../eidolon/tile/reagent/PipeTileEntity.java | 29 + .../tile/reagent/PipeTileRenderer.java | 102 +++ .../tile/reagent/ReagentTankTileEntity.java | 103 +++ .../java/elucent/eidolon/util/ChunkUtil.java | 18 +- .../java/elucent/eidolon/util/ColorUtil.java | 3 - .../java/elucent/eidolon/util/EntityUtil.java | 6 +- .../java/elucent/eidolon/util/RecipeUtil.java | 53 ++ .../java/elucent/eidolon/util/RenderUtil.java | 333 ++++---- .../java/elucent/eidolon/util/StackUtil.java | 39 - .../elucent/eidolon/world/BasicPiece.java | 79 +- .../elucent/eidolon/world/CatacombPieces.java | 76 +- .../eidolon/world/CatacombStructure.java | 152 ++-- .../elucent/eidolon/world/LabStructure.java | 158 ++-- .../eidolon/world/RandomlyRotatedPiece.java | 35 +- .../eidolon/world/StrayTowerStructure.java | 154 ++-- .../resources/META-INF/accesstransformer.cfg | 16 +- src/main/resources/META-INF/mods.toml | 4 +- .../eidolon/blockstates/avennian_sprig.json | 10 + .../assets/eidolon/blockstates/cistern.json | 16 + .../eidolon/blockstates/deep_lead_ore.json | 7 + .../eidolon/blockstates/deep_silver_ore.json | 7 + .../eidolon/blockstates/glass_tube.json | 375 +++++++++ .../assets/eidolon/blockstates/incubator.json | 10 + .../eidolon/blockstates/merammer_root.json | 10 + .../eidolon/blockstates/oanna_bloom.json | 10 + .../assets/eidolon/blockstates/obelisk.json | 16 + .../eidolon/blockstates/raw_lead_block.json | 7 + .../eidolon/blockstates/raw_silver_block.json | 7 + .../eidolon/blockstates/shadow_gem_block.json | 7 + .../eidolon/blockstates/sildrian_seed.json | 10 + .../eidolon/blockstates/silver_block.json | 7 + .../eidolon/blockstates/silver_ore.json | 7 + .../resources/assets/eidolon/lang/en_us.json | 68 ++ .../assets/eidolon/models/block/aludel.json | 177 +++++ .../models/block/avennian_sprig_0.json | 6 + .../models/block/avennian_sprig_1.json | 6 + .../assets/eidolon/models/block/censer.json | 154 ++++ .../eidolon/models/block/cistern_lower.json | 36 + .../eidolon/models/block/cistern_mid.json | 21 + .../eidolon/models/block/cistern_upper.json | 36 + .../models/block/coalfired_engine_on.json | 115 +++ .../eidolon/models/block/glass_tube_bend.json | 20 + .../eidolon/models/block/glass_tube_down.json | 20 + .../eidolon/models/block/glass_tube_east.json | 20 + .../models/block/glass_tube_input.json | 24 + .../models/block/glass_tube_north.json | 20 + .../models/block/glass_tube_output.json | 24 + .../models/block/glass_tube_south.json | 20 + .../models/block/glass_tube_straight.json | 21 + .../eidolon/models/block/glass_tube_up.json | 20 + .../eidolon/models/block/glass_tube_west.json | 20 + .../models/block/incubator_bottom.json | 158 ++++ .../eidolon/models/block/incubator_top.json | 157 ++++ .../models/block/inscription_table.json | 278 +++++++ .../eidolon/models/block/merammer_root_0.json | 6 + .../eidolon/models/block/merammer_root_1.json | 6 + .../eidolon/models/block/oanna_bloom_0.json | 6 + .../eidolon/models/block/oanna_bloom_1.json | 6 + .../eidolon/models/block/obelisk_bottom.json | 113 +++ .../eidolon/models/block/obelisk_mid.json | 24 + .../eidolon/models/block/obelisk_top.json | 36 + .../eidolon/models/block/sildrian_seed_0.json | 6 + .../eidolon/models/block/sildrian_seed_1.json | 6 + .../eidolon/models/item/alchemists_tongs.json | 6 + .../eidolon/models/item/angels_sight.json | 6 + .../assets/eidolon/models/item/athame.json | 6 + .../eidolon/models/item/avennian_sprig.json | 6 + .../assets/eidolon/models/item/cistern.json | 49 ++ .../eidolon/models/item/coalfired_engine.json | 115 +++ .../eidolon/models/item/deep_lead_ore.json | 6 + .../eidolon/models/item/deep_silver_ore.json | 6 + .../eidolon/models/item/enervating_ring.json | 6 + .../eidolon/models/item/glass_tube.json | 47 ++ .../assets/eidolon/models/item/incubator.json | 320 ++++++++ .../eidolon/models/item/merammer_resin.json | 6 + .../eidolon/models/item/merammer_root.json | 6 + .../eidolon/models/item/oanna_bloom.json | 6 + .../assets/eidolon/models/item/obelisk.json | 124 +++ .../assets/eidolon/models/item/planter.json | 3 +- .../eidolon/models/item/raven_feather.json | 6 + .../assets/eidolon/models/item/raw_lead.json | 6 + .../eidolon/models/item/raw_lead_block.json | 6 + .../eidolon/models/item/raw_silver.json | 6 + .../eidolon/models/item/raw_silver_block.json | 6 + .../eidolon/models/item/shadow_gem_block.json | 6 + .../eidolon/models/item/sildrian_seed.json | 6 + .../eidolon/models/item/silver_axe.json | 6 + .../eidolon/models/item/silver_block.json | 6 + .../eidolon/models/item/silver_boots.json | 6 + .../models/item/silver_chestplate.json | 6 + .../eidolon/models/item/silver_helmet.json | 6 + .../eidolon/models/item/silver_hoe.json | 6 + .../eidolon/models/item/silver_ingot.json | 6 + .../eidolon/models/item/silver_leggings.json | 6 + .../eidolon/models/item/silver_nugget.json | 6 + .../eidolon/models/item/silver_ore.json | 6 + .../eidolon/models/item/silver_pickaxe.json | 6 + .../eidolon/models/item/silver_shovel.json | 6 + .../eidolon/models/item/silver_sword.json | 6 + .../eidolon/models/item/spawn_raven.json | 3 + .../eidolon/models/item/spawn_slimy_slug.json | 3 + .../eidolon/models/item/terminus_mirror.json | 6 + .../eidolon/models/item/unholy_symbol.json | 45 +- .../assets/eidolon/models/item/worktable.json | 52 -- .../assets/eidolon/shaders/core/glowing.fsh | 15 + .../assets/eidolon/shaders/core/glowing.json | 19 + .../assets/eidolon/shaders/core/glowing.vsh | 15 + .../eidolon/shaders/core/glowing_entity.fsh | 23 + .../eidolon/shaders/core/glowing_entity.json | 24 + .../eidolon/shaders/core/glowing_entity.vsh | 21 + .../eidolon/shaders/core/glowing_particle.fsh | 24 + .../shaders/core/glowing_particle.json | 27 + .../eidolon/shaders/core/glowing_particle.vsh | 23 + .../eidolon/shaders/core/glowing_sprite.fsh | 18 + .../eidolon/shaders/core/glowing_sprite.json | 22 + .../eidolon/shaders/core/glowing_sprite.vsh | 18 + .../assets/eidolon/shaders/core/vapor.fsh | 17 + .../assets/eidolon/shaders/core/vapor.json | 24 + .../assets/eidolon/shaders/core/vapor.vsh | 24 + .../eidolon/textures/block/aludel_front.png | Bin 0 -> 399 bytes .../textures/block/aludel_jar_side.png | Bin 0 -> 529 bytes .../eidolon/textures/block/aludel_jar_top.png | Bin 0 -> 287 bytes .../eidolon/textures/block/aludel_parts.png | Bin 0 -> 318 bytes .../eidolon/textures/block/aludel_power.png | Bin 0 -> 550 bytes .../eidolon/textures/block/aludel_side.png | Bin 0 -> 457 bytes .../textures/block/avennian_sprig_0.png | Bin 0 -> 123 bytes .../textures/block/avennian_sprig_1.png | Bin 0 -> 248 bytes .../assets/eidolon/textures/block/censer.png | Bin 0 -> 441 bytes .../eidolon/textures/block/censer_cage.png | Bin 0 -> 213 bytes .../eidolon/textures/block/cistern_bottom.png | Bin 0 -> 416 bytes .../eidolon/textures/block/cistern_ends.png | Bin 0 -> 328 bytes .../eidolon/textures/block/cistern_mid.png | Bin 0 -> 365 bytes .../eidolon/textures/block/cistern_side.png | Bin 0 -> 500 bytes .../eidolon/textures/block/cistern_top.png | Bin 0 -> 328 bytes .../eidolon/textures/block/cistern_upper.png | Bin 0 -> 427 bytes .../block/coalfired_engine_bottom.png | Bin 0 -> 310 bytes .../textures/block/coalfired_engine_front.png | Bin 0 -> 423 bytes .../textures/block/coalfired_engine_on.png | Bin 0 -> 525 bytes .../textures/block/coalfired_engine_parts.png | Bin 0 -> 448 bytes .../textures/block/coalfired_engine_side.png | Bin 0 -> 421 bytes .../textures/block/coalfired_engine_top.png | Bin 0 -> 483 bytes .../assets/eidolon/textures/block/crimsol.png | Bin 0 -> 9203 bytes .../eidolon/textures/block/crimsol.png.mcmeta | 6 + .../eidolon/textures/block/deep_lead_ore.png | Bin 0 -> 777 bytes .../textures/block/deep_silver_ore.png | Bin 0 -> 755 bytes .../assets/eidolon/textures/block/esprit.png | Bin 0 -> 7513 bytes .../eidolon/textures/block/esprit.png.mcmeta | 6 + .../eidolon/textures/block/glass_tube.png | Bin 0 -> 364 bytes .../textures/block/incubator_bottom.png | Bin 0 -> 381 bytes .../textures/block/incubator_detail.png | Bin 0 -> 539 bytes .../textures/block/incubator_shared.png | Bin 0 -> 460 bytes .../eidolon/textures/block/incubator_top.png | Bin 0 -> 392 bytes .../block/inscription_table_bottom.png | Bin 0 -> 229 bytes .../block/inscription_table_detail.png | Bin 0 -> 427 bytes .../textures/block/inscription_table_mid.png | Bin 0 -> 348 bytes .../textures/block/inscription_table_side.png | Bin 0 -> 459 bytes .../textures/block/inscription_table_top.png | Bin 0 -> 386 bytes .../textures/block/merammer_root_0.png | Bin 0 -> 121 bytes .../textures/block/merammer_root_1.png | Bin 0 -> 241 bytes .../eidolon/textures/block/oanna_bloom_0.png | Bin 0 -> 152 bytes .../eidolon/textures/block/oanna_bloom_1.png | Bin 0 -> 264 bytes .../eidolon/textures/block/obelisk_bottom.png | Bin 0 -> 230 bytes .../eidolon/textures/block/obelisk_parts.png | Bin 0 -> 311 bytes .../eidolon/textures/block/obelisk_side.png | Bin 0 -> 324 bytes .../textures/block/obelisk_side_lower.png | Bin 0 -> 287 bytes .../textures/block/obelisk_side_mid.png | Bin 0 -> 291 bytes .../textures/block/obelisk_side_top.png | Bin 0 -> 313 bytes .../eidolon/textures/block/obelisk_top.png | Bin 0 -> 212 bytes .../textures/block/obelisk_top_mid.png | Bin 0 -> 239 bytes .../eidolon/textures/block/planter_side.png | Bin 500 -> 671 bytes .../eidolon/textures/block/planter_soil.png | Bin 328 -> 334 bytes .../eidolon/textures/block/raw_lead_block.png | Bin 0 -> 705 bytes .../textures/block/raw_silver_block.png | Bin 0 -> 668 bytes .../textures/block/shadow_gem_block.png | Bin 0 -> 437 bytes .../textures/block/sildrian_seed_0.png | Bin 0 -> 129 bytes .../textures/block/sildrian_seed_1.png | Bin 0 -> 295 bytes .../eidolon/textures/block/silver_block.png | Bin 0 -> 404 bytes .../eidolon/textures/block/silver_ore.png | Bin 0 -> 751 bytes .../assets/eidolon/textures/block/vapor.png | Bin 0 -> 5364 bytes .../eidolon/textures/block/vapor.png.mcmeta | 6 + .../eidolon/textures/block/worktable_side.png | Bin 481 -> 465 bytes .../eidolon/textures/block/worktable_top.png | Bin 525 -> 440 bytes .../eidolon/textures/entity/banana_slug.png | Bin 0 -> 502 bytes .../eidolon/textures/entity/brown_slug.png | Bin 0 -> 479 bytes .../textures/entity/necromancer_eyes.png | Bin 286 -> 287 bytes .../assets/eidolon/textures/entity/raven.png | Bin 0 -> 744 bytes .../textures/entity/shattered_soul.png | Bin 0 -> 1023 bytes .../eidolon/textures/entity/silver_armor.png | Bin 0 -> 1502 bytes .../eidolon/textures/entity/slimy_slug.png | Bin 0 -> 475 bytes .../eidolon/textures/entity/tranquil_soul.png | Bin 0 -> 1078 bytes .../eidolon/textures/entity/zombie_brute.png | Bin 2803 -> 2754 bytes .../textures/gui/codex_crucible_page.png | Bin 2827 -> 2820 bytes .../assets/eidolon/textures/gui/worktable.png | Bin 4100 -> 4116 bytes .../textures/item/alchemists_tongs.png | Bin 0 -> 384 bytes .../eidolon/textures/item/angels_sight.png | Bin 0 -> 547 bytes .../assets/eidolon/textures/item/athame.png | Bin 0 -> 374 bytes .../eidolon/textures/item/avennian_sprig.png | Bin 0 -> 468 bytes .../eidolon/textures/item/basic_ring.png | Bin 409 -> 670 bytes .../eidolon/textures/item/ebon_wings.png | Bin 0 -> 587 bytes .../eidolon/textures/item/enervating_ring.png | Bin 417 -> 552 bytes .../textures/item/essence_of_crimson.png | Bin 412 -> 424 bytes .../textures/item/essence_of_death.png | Bin 363 -> 399 bytes .../eidolon/textures/item/holy_symbol.png | Bin 0 -> 614 bytes .../eidolon/textures/item/lesser_soul_gem.png | Bin 358 -> 366 bytes .../eidolon/textures/item/merammer_resin.png | Bin 0 -> 488 bytes .../eidolon/textures/item/merammer_root.png | Bin 0 -> 491 bytes .../eidolon/textures/item/oanna_bloom.png | Bin 0 -> 521 bytes .../eidolon/textures/item/pewter_nugget.png | Bin 226 -> 242 bytes .../eidolon/textures/item/raven_feather.png | Bin 370 -> 352 bytes .../assets/eidolon/textures/item/raw_lead.png | Bin 0 -> 622 bytes .../eidolon/textures/item/raw_silver.png | Bin 0 -> 603 bytes .../eidolon/textures/item/refined_crimson.png | Bin 424 -> 424 bytes .../eidolon/textures/item/sildrian_seed.png | Bin 0 -> 420 bytes .../eidolon/textures/item/silver_axe.png | Bin 0 -> 334 bytes .../eidolon/textures/item/silver_boots.png | Bin 0 -> 293 bytes .../textures/item/silver_chestplate.png | Bin 0 -> 432 bytes .../eidolon/textures/item/silver_helmet.png | Bin 0 -> 370 bytes .../eidolon/textures/item/silver_hoe.png | Bin 0 -> 265 bytes .../eidolon/textures/item/silver_ingot.png | Bin 0 -> 411 bytes .../eidolon/textures/item/silver_leggings.png | Bin 0 -> 308 bytes .../eidolon/textures/item/silver_nugget.png | Bin 0 -> 220 bytes .../eidolon/textures/item/silver_pickaxe.png | Bin 0 -> 300 bytes .../eidolon/textures/item/silver_shovel.png | Bin 0 -> 287 bytes .../eidolon/textures/item/silver_sword.png | Bin 0 -> 344 bytes .../eidolon/textures/item/terminus_mirror.png | Bin 0 -> 633 bytes .../textures/item/unholy_symbol_base.png | Bin 0 -> 555 bytes .../eidolon/textures/item/warping_mail.png | Bin 0 -> 568 bytes .../textures/mob_effect/reinforced.png | Bin 0 -> 568 bytes .../textures/mob_effect/vulnerable.png | Bin 0 -> 633 bytes .../eidolon/textures/particle/bubble.png | Bin 457 -> 342 bytes .../eidolon/textures/particle/burst.png | Bin 454 -> 217 bytes .../eidolon/textures/particle/flame_sign.png | Bin 0 -> 466 bytes .../data/curios/tags/items/necklace.json | 3 +- .../data/curios/tags/items/ring.json | 3 +- .../loot_tables/blocks/avennian_sprig.json | 43 + .../loot_tables/blocks/deep_lead_ore.json | 49 ++ .../loot_tables/blocks/deep_silver_ore.json | 49 ++ .../eidolon/loot_tables/blocks/lead_ore.json | 46 +- .../loot_tables/blocks/merammer_root.json | 43 + .../loot_tables/blocks/oanna_bloom.json | 43 + .../eidolon/loot_tables/blocks/obelisk.json | 19 + .../eidolon/loot_tables/blocks/planter.json | 19 + .../blocks/polished_planks_slab.json | 23 +- .../blocks/polished_wood_pillar.json | 19 + .../loot_tables/blocks/raw_lead_block.json | 19 + .../loot_tables/blocks/raw_silver_block.json | 19 + .../loot_tables/blocks/shadow_gem_block.json | 19 + .../loot_tables/blocks/sildrian_seed.json | 43 + .../loot_tables/blocks/silver_block.json | 19 + .../loot_tables/blocks/silver_ore.json | 49 ++ .../blocks/smooth_stone_bricks_slab.json | 23 +- .../blocks/smooth_stone_tiles_slab.json | 23 +- .../eidolon/loot_tables/entities/raven.json | 31 + .../loot_tables/entities/slimy_slug.json | 31 + .../eidolon/recipes/arcane_gold_block.json | 2 +- .../eidolon/recipes/arcane_gold_ingot.json | 2 +- .../recipes/arcane_gold_ingot_alchemy.json | 22 + .../data/eidolon/recipes/athame.json | 29 + .../data/eidolon/recipes/basic_amulet.json | 2 +- .../data/eidolon/recipes/basic_ring.json | 2 +- .../data/eidolon/recipes/beef_to_flesh.json | 14 + .../data/eidolon/recipes/blast_raw_lead.json | 9 + .../eidolon/recipes/blast_raw_silver.json | 9 + .../eidolon/recipes/blast_silver_dust.json | 25 + .../eidolon/recipes/blast_silver_ore.json | 9 + .../data/eidolon/recipes/bonechill_wand.json | 32 + .../data/eidolon/recipes/brazier.json | 4 +- .../data/eidolon/recipes/candle.json | 2 +- .../eidolon/recipes/chicken_to_flesh.json | 14 + .../data/eidolon/recipes/cleaving_axe.json | 26 + .../recipes/crimson_essence_fungus.json | 21 + .../recipes/crimson_essence_roots.json | 21 + .../recipes/crimson_essence_vines.json | 21 + .../data/eidolon/recipes/death_essence.json | 27 + .../recipes/decompress_arcane_gold_block.json | 2 +- .../recipes/decompress_arcane_gold_ingot.json | 2 +- .../recipes/decompress_pewter_block.json | 2 +- .../recipes/decompress_pewter_ingot.json | 2 +- .../recipes/decompress_raw_lead_block.json | 13 + .../recipes/decompress_raw_silver_block.json | 13 + .../recipes/decompress_shadow_gem_block.json | 13 + .../recipes/decompress_silver_block.json | 13 + .../recipes/decompress_silver_ingot.json | 13 + .../data/eidolon/recipes/ender_calx.json | 15 + .../eidolon/recipes/flesh_to_leather.json | 20 + .../data/eidolon/recipes/fungus_sprouts.json | 25 + .../data/eidolon/recipes/gilding_apple.json | 25 + .../data/eidolon/recipes/gilding_carrot.json | 25 + .../data/eidolon/recipes/gilding_melon.json | 25 + .../data/eidolon/recipes/glass_hand.json | 32 + .../data/eidolon/recipes/goblet.json | 2 +- .../data/eidolon/recipes/gold_inlay.json | 2 +- .../data/eidolon/recipes/gravity_belt.json | 32 + .../eidolon/recipes/gunpowder_alchemy.json | 21 + .../data/eidolon/recipes/lesser_soul_gem.json | 30 + .../eidolon/recipes/mind_shielding_plate.json | 26 + .../data/eidolon/recipes/mutton_to_flesh.json | 14 + .../data/eidolon/recipes/necrotic_focus.json | 2 +- .../data/eidolon/recipes/obelisk.json | 20 + .../data/eidolon/recipes/pewter_block.json | 2 +- .../data/eidolon/recipes/pewter_ingot.json | 2 +- .../data/eidolon/recipes/pewter_inlay.json | 2 +- .../data/eidolon/recipes/planter.json | 32 + .../data/eidolon/recipes/polished_planks.json | 28 + .../recipes/polished_planks_pillar.json | 10 +- .../recipes/polished_planks_stairs.json | 10 +- .../data/eidolon/recipes/pork_to_flesh.json | 14 + .../eidolon/recipes/prestigious_palm.json | 29 + .../data/eidolon/recipes/rabbit_to_flesh.json | 14 + .../eidolon/recipes/raven_feather_arrows.json | 24 + .../data/eidolon/recipes/raw_lead_block.json | 17 + .../eidolon/recipes/raw_silver_block.json | 17 + .../data/eidolon/recipes/reaper_scythe.json | 29 + .../data/eidolon/recipes/resolute_belt.json | 35 + .../data/eidolon/recipes/reversal_pick.json | 35 + .../data/eidolon/recipes/shadow_gem.json | 33 + .../eidolon/recipes/shadow_gem_block.json | 17 + .../data/eidolon/recipes/silver_axe.json | 20 + .../data/eidolon/recipes/silver_block.json | 17 + .../data/eidolon/recipes/silver_boots.json | 16 + .../eidolon/recipes/silver_chestplate.json | 17 + .../data/eidolon/recipes/silver_helmet.json | 16 + .../data/eidolon/recipes/silver_hoe.json | 20 + .../data/eidolon/recipes/silver_ingot.json | 17 + .../data/eidolon/recipes/silver_leggings.json | 17 + .../data/eidolon/recipes/silver_pickaxe.json | 20 + .../data/eidolon/recipes/silver_shovel.json | 20 + .../data/eidolon/recipes/silver_sword.json | 20 + .../data/eidolon/recipes/smelt_raw_lead.json | 9 + .../eidolon/recipes/smelt_raw_silver.json | 9 + .../eidolon/recipes/smelt_silver_dust.json | 25 + .../eidolon/recipes/smelt_silver_ore.json | 9 + .../eidolon/recipes/smelt_stone_brick.json | 9 - .../data/eidolon/recipes/soul_enchanter.json | 29 + .../data/eidolon/recipes/soulfire_wand.json | 32 + .../data/eidolon/recipes/stone_altar.json | 27 + .../data/eidolon/recipes/sulfur.json | 15 + .../data/eidolon/recipes/unholy_effigy.json | 26 + .../data/eidolon/recipes/void_amulet.json | 29 + .../data/eidolon/recipes/warded_mail.json | 26 + .../data/eidolon/recipes/warlock_boots.json | 20 + .../data/eidolon/recipes/warlock_cloak.json | 20 + .../data/eidolon/recipes/warlock_hat.json | 20 + .../data/eidolon/recipes/warped_sprouts.json | 25 + .../data/eidolon/recipes/wicked_weave.json | 27 + .../eidolon/recipes/wooden_brewing_stand.json | 4 +- .../data/eidolon/recipes/worktable.json | 8 +- .../data/forge/tags/blocks/ores.json | 5 +- .../data/forge/tags/blocks/ores/lead.json | 3 +- .../data/forge/tags/blocks/ores/silver.json | 7 + .../forge/tags/blocks/storage_blocks.json | 4 +- .../blocks/storage_blocks/shadow_gem.json | 6 + .../tags/blocks/storage_blocks/silver.json | 6 + .../data/forge/tags/items/dusts.json | 6 + .../data/forge/tags/items/feathers.json | 6 + .../resources/data/forge/tags/items/gems.json | 6 + .../forge/tags/items/gems/shadow_gem.json | 6 + .../data/forge/tags/items/ingots.json | 9 + .../data/forge/tags/items/ingots/silver.json | 6 + .../data/forge/tags/items/nuggets/silver.json | 6 + .../resources/data/forge/tags/items/ores.json | 3 +- .../data/forge/tags/items/ores/lead.json | 3 +- .../data/forge/tags/items/ores/silver.json | 7 + .../data/forge/tags/items/storage_blocks.json | 4 +- .../tags/items/storage_blocks/shadow_gem.json | 6 + .../tags/items/storage_blocks/silver.json | 6 + .../data/forge/tags/items/tallow.json | 6 + .../minecraft/tags/blocks/mineable/axe.json | 15 + .../tags/blocks/mineable/pickaxe.json | 31 + .../tags/blocks/needs_iron_tool.json | 16 + src/main/resources/eidolon.mixins.json | 8 +- 637 files changed, 15487 insertions(+), 7140 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 src/main/java/elucent/eidolon/block/BrazierBlock.java create mode 100644 src/main/java/elucent/eidolon/block/CisternBlock.java create mode 100644 src/main/java/elucent/eidolon/block/CrucibleBlock.java create mode 100644 src/main/java/elucent/eidolon/block/EffigyBlock.java create mode 100644 src/main/java/elucent/eidolon/block/HandBlock.java create mode 100644 src/main/java/elucent/eidolon/block/HerbBlockBase.java create mode 100644 src/main/java/elucent/eidolon/block/PillarBlockBase.java create mode 100644 src/main/java/elucent/eidolon/block/PipeBlock.java delete mode 100644 src/main/java/elucent/eidolon/block/PlinthBlockBase.java delete mode 100644 src/main/java/elucent/eidolon/block/ShroomBlockBase.java create mode 100644 src/main/java/elucent/eidolon/block/TwoHighBlockBase.java delete mode 100644 src/main/java/elucent/eidolon/capability/KnowledgeProvider.java delete mode 100644 src/main/java/elucent/eidolon/capability/KnowledgeStorage.java delete mode 100644 src/main/java/elucent/eidolon/capability/ReputationProvider.java delete mode 100644 src/main/java/elucent/eidolon/capability/ReputationStorage.java create mode 100644 src/main/java/elucent/eidolon/deity/LightDeity.java create mode 100644 src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java create mode 100644 src/main/java/elucent/eidolon/entity/AngelArrowEntity.java create mode 100644 src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java delete mode 100644 src/main/java/elucent/eidolon/entity/EmptyRenderer.java create mode 100644 src/main/java/elucent/eidolon/entity/RavenEntity.java create mode 100644 src/main/java/elucent/eidolon/entity/RavenModel.java create mode 100644 src/main/java/elucent/eidolon/entity/RavenRenderer.java create mode 100644 src/main/java/elucent/eidolon/entity/RavenVariantLayer.java create mode 100644 src/main/java/elucent/eidolon/entity/SlimySlugEntity.java create mode 100644 src/main/java/elucent/eidolon/entity/SlimySlugModel.java create mode 100644 src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java create mode 100644 src/main/java/elucent/eidolon/item/AthameItem.java create mode 100644 src/main/java/elucent/eidolon/item/SilverArmorItem.java create mode 100644 src/main/java/elucent/eidolon/item/TongsItem.java create mode 100644 src/main/java/elucent/eidolon/item/curio/AngelSightItem.java create mode 100644 src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java create mode 100644 src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java create mode 100644 src/main/java/elucent/eidolon/item/model/SilverArmorModel.java create mode 100644 src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java create mode 100644 src/main/java/elucent/eidolon/mixin/AbstractArrowMixin.java create mode 100644 src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java create mode 100644 src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java create mode 100644 src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java delete mode 100644 src/main/java/elucent/eidolon/mixin/ZombieVillagerEntityMixin.java create mode 100644 src/main/java/elucent/eidolon/mixin/ZombieVillagerMixin.java create mode 100644 src/main/java/elucent/eidolon/potion/ReinforcedEffect.java create mode 100644 src/main/java/elucent/eidolon/potion/VulnerableEffect.java create mode 100644 src/main/java/elucent/eidolon/reagent/CrimsolReagent.java create mode 100644 src/main/java/elucent/eidolon/reagent/EspritReagent.java create mode 100644 src/main/java/elucent/eidolon/reagent/IReagentTankProvider.java create mode 100644 src/main/java/elucent/eidolon/reagent/Reagent.java create mode 100644 src/main/java/elucent/eidolon/reagent/ReagentRegistry.java create mode 100644 src/main/java/elucent/eidolon/reagent/ReagentStack.java create mode 100644 src/main/java/elucent/eidolon/reagent/ReagentTank.java create mode 100644 src/main/java/elucent/eidolon/reagent/RegisterReagentsEvent.java create mode 100644 src/main/java/elucent/eidolon/reagent/SteamReagent.java create mode 100644 src/main/java/elucent/eidolon/tile/reagent/CisternTileEntity.java create mode 100644 src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java create mode 100644 src/main/java/elucent/eidolon/tile/reagent/PipeTileEntity.java create mode 100644 src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java create mode 100644 src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java create mode 100644 src/main/java/elucent/eidolon/util/RecipeUtil.java delete mode 100644 src/main/java/elucent/eidolon/util/StackUtil.java create mode 100644 src/main/resources/assets/eidolon/blockstates/avennian_sprig.json create mode 100644 src/main/resources/assets/eidolon/blockstates/cistern.json create mode 100644 src/main/resources/assets/eidolon/blockstates/deep_lead_ore.json create mode 100644 src/main/resources/assets/eidolon/blockstates/deep_silver_ore.json create mode 100644 src/main/resources/assets/eidolon/blockstates/glass_tube.json create mode 100644 src/main/resources/assets/eidolon/blockstates/incubator.json create mode 100644 src/main/resources/assets/eidolon/blockstates/merammer_root.json create mode 100644 src/main/resources/assets/eidolon/blockstates/oanna_bloom.json create mode 100644 src/main/resources/assets/eidolon/blockstates/obelisk.json create mode 100644 src/main/resources/assets/eidolon/blockstates/raw_lead_block.json create mode 100644 src/main/resources/assets/eidolon/blockstates/raw_silver_block.json create mode 100644 src/main/resources/assets/eidolon/blockstates/shadow_gem_block.json create mode 100644 src/main/resources/assets/eidolon/blockstates/sildrian_seed.json create mode 100644 src/main/resources/assets/eidolon/blockstates/silver_block.json create mode 100644 src/main/resources/assets/eidolon/blockstates/silver_ore.json create mode 100644 src/main/resources/assets/eidolon/models/block/aludel.json create mode 100644 src/main/resources/assets/eidolon/models/block/avennian_sprig_0.json create mode 100644 src/main/resources/assets/eidolon/models/block/avennian_sprig_1.json create mode 100644 src/main/resources/assets/eidolon/models/block/censer.json create mode 100644 src/main/resources/assets/eidolon/models/block/cistern_lower.json create mode 100644 src/main/resources/assets/eidolon/models/block/cistern_mid.json create mode 100644 src/main/resources/assets/eidolon/models/block/cistern_upper.json create mode 100644 src/main/resources/assets/eidolon/models/block/coalfired_engine_on.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_bend.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_down.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_east.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_input.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_north.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_output.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_south.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_straight.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_up.json create mode 100644 src/main/resources/assets/eidolon/models/block/glass_tube_west.json create mode 100644 src/main/resources/assets/eidolon/models/block/incubator_bottom.json create mode 100644 src/main/resources/assets/eidolon/models/block/incubator_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/inscription_table.json create mode 100644 src/main/resources/assets/eidolon/models/block/merammer_root_0.json create mode 100644 src/main/resources/assets/eidolon/models/block/merammer_root_1.json create mode 100644 src/main/resources/assets/eidolon/models/block/oanna_bloom_0.json create mode 100644 src/main/resources/assets/eidolon/models/block/oanna_bloom_1.json create mode 100644 src/main/resources/assets/eidolon/models/block/obelisk_bottom.json create mode 100644 src/main/resources/assets/eidolon/models/block/obelisk_mid.json create mode 100644 src/main/resources/assets/eidolon/models/block/obelisk_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/sildrian_seed_0.json create mode 100644 src/main/resources/assets/eidolon/models/block/sildrian_seed_1.json create mode 100644 src/main/resources/assets/eidolon/models/item/alchemists_tongs.json create mode 100644 src/main/resources/assets/eidolon/models/item/angels_sight.json create mode 100644 src/main/resources/assets/eidolon/models/item/athame.json create mode 100644 src/main/resources/assets/eidolon/models/item/avennian_sprig.json create mode 100644 src/main/resources/assets/eidolon/models/item/cistern.json create mode 100644 src/main/resources/assets/eidolon/models/item/coalfired_engine.json create mode 100644 src/main/resources/assets/eidolon/models/item/deep_lead_ore.json create mode 100644 src/main/resources/assets/eidolon/models/item/deep_silver_ore.json create mode 100644 src/main/resources/assets/eidolon/models/item/enervating_ring.json create mode 100644 src/main/resources/assets/eidolon/models/item/glass_tube.json create mode 100644 src/main/resources/assets/eidolon/models/item/incubator.json create mode 100644 src/main/resources/assets/eidolon/models/item/merammer_resin.json create mode 100644 src/main/resources/assets/eidolon/models/item/merammer_root.json create mode 100644 src/main/resources/assets/eidolon/models/item/oanna_bloom.json create mode 100644 src/main/resources/assets/eidolon/models/item/obelisk.json create mode 100644 src/main/resources/assets/eidolon/models/item/raven_feather.json create mode 100644 src/main/resources/assets/eidolon/models/item/raw_lead.json create mode 100644 src/main/resources/assets/eidolon/models/item/raw_lead_block.json create mode 100644 src/main/resources/assets/eidolon/models/item/raw_silver.json create mode 100644 src/main/resources/assets/eidolon/models/item/raw_silver_block.json create mode 100644 src/main/resources/assets/eidolon/models/item/shadow_gem_block.json create mode 100644 src/main/resources/assets/eidolon/models/item/sildrian_seed.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_axe.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_block.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_boots.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_chestplate.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_helmet.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_hoe.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_ingot.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_leggings.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_nugget.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_ore.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_pickaxe.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_shovel.json create mode 100644 src/main/resources/assets/eidolon/models/item/silver_sword.json create mode 100644 src/main/resources/assets/eidolon/models/item/spawn_raven.json create mode 100644 src/main/resources/assets/eidolon/models/item/spawn_slimy_slug.json create mode 100644 src/main/resources/assets/eidolon/models/item/terminus_mirror.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing.vsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_entity.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_entity.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_entity.vsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_particle.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_particle.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_particle.vsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_sprite.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_sprite.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/glowing_sprite.vsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/vapor.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/vapor.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/vapor.vsh create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_front.png create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_jar_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_jar_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_parts.png create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_power.png create mode 100644 src/main/resources/assets/eidolon/textures/block/aludel_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/avennian_sprig_0.png create mode 100644 src/main/resources/assets/eidolon/textures/block/avennian_sprig_1.png create mode 100644 src/main/resources/assets/eidolon/textures/block/censer.png create mode 100644 src/main/resources/assets/eidolon/textures/block/censer_cage.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_ends.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_mid.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cistern_upper.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_front.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_on.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_parts.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/coalfired_engine_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/crimsol.png create mode 100644 src/main/resources/assets/eidolon/textures/block/crimsol.png.mcmeta create mode 100644 src/main/resources/assets/eidolon/textures/block/deep_lead_ore.png create mode 100644 src/main/resources/assets/eidolon/textures/block/deep_silver_ore.png create mode 100644 src/main/resources/assets/eidolon/textures/block/esprit.png create mode 100644 src/main/resources/assets/eidolon/textures/block/esprit.png.mcmeta create mode 100644 src/main/resources/assets/eidolon/textures/block/glass_tube.png create mode 100644 src/main/resources/assets/eidolon/textures/block/incubator_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/incubator_detail.png create mode 100644 src/main/resources/assets/eidolon/textures/block/incubator_shared.png create mode 100644 src/main/resources/assets/eidolon/textures/block/incubator_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/inscription_table_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/inscription_table_detail.png create mode 100644 src/main/resources/assets/eidolon/textures/block/inscription_table_mid.png create mode 100644 src/main/resources/assets/eidolon/textures/block/inscription_table_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/inscription_table_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/merammer_root_0.png create mode 100644 src/main/resources/assets/eidolon/textures/block/merammer_root_1.png create mode 100644 src/main/resources/assets/eidolon/textures/block/oanna_bloom_0.png create mode 100644 src/main/resources/assets/eidolon/textures/block/oanna_bloom_1.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_parts.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_side_lower.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_side_mid.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_side_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/obelisk_top_mid.png create mode 100644 src/main/resources/assets/eidolon/textures/block/raw_lead_block.png create mode 100644 src/main/resources/assets/eidolon/textures/block/raw_silver_block.png create mode 100644 src/main/resources/assets/eidolon/textures/block/shadow_gem_block.png create mode 100644 src/main/resources/assets/eidolon/textures/block/sildrian_seed_0.png create mode 100644 src/main/resources/assets/eidolon/textures/block/sildrian_seed_1.png create mode 100644 src/main/resources/assets/eidolon/textures/block/silver_block.png create mode 100644 src/main/resources/assets/eidolon/textures/block/silver_ore.png create mode 100644 src/main/resources/assets/eidolon/textures/block/vapor.png create mode 100644 src/main/resources/assets/eidolon/textures/block/vapor.png.mcmeta create mode 100644 src/main/resources/assets/eidolon/textures/entity/banana_slug.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/brown_slug.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/raven.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/shattered_soul.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/silver_armor.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/slimy_slug.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/tranquil_soul.png create mode 100644 src/main/resources/assets/eidolon/textures/item/alchemists_tongs.png create mode 100644 src/main/resources/assets/eidolon/textures/item/angels_sight.png create mode 100644 src/main/resources/assets/eidolon/textures/item/athame.png create mode 100644 src/main/resources/assets/eidolon/textures/item/avennian_sprig.png create mode 100644 src/main/resources/assets/eidolon/textures/item/ebon_wings.png create mode 100644 src/main/resources/assets/eidolon/textures/item/holy_symbol.png create mode 100644 src/main/resources/assets/eidolon/textures/item/merammer_resin.png create mode 100644 src/main/resources/assets/eidolon/textures/item/merammer_root.png create mode 100644 src/main/resources/assets/eidolon/textures/item/oanna_bloom.png create mode 100644 src/main/resources/assets/eidolon/textures/item/raw_lead.png create mode 100644 src/main/resources/assets/eidolon/textures/item/raw_silver.png create mode 100644 src/main/resources/assets/eidolon/textures/item/sildrian_seed.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_axe.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_boots.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_chestplate.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_helmet.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_hoe.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_ingot.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_leggings.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_nugget.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_pickaxe.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_shovel.png create mode 100644 src/main/resources/assets/eidolon/textures/item/silver_sword.png create mode 100644 src/main/resources/assets/eidolon/textures/item/terminus_mirror.png create mode 100644 src/main/resources/assets/eidolon/textures/item/unholy_symbol_base.png create mode 100644 src/main/resources/assets/eidolon/textures/item/warping_mail.png create mode 100644 src/main/resources/assets/eidolon/textures/mob_effect/reinforced.png create mode 100644 src/main/resources/assets/eidolon/textures/mob_effect/vulnerable.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/flame_sign.png create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/avennian_sprig.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/deep_lead_ore.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/deep_silver_ore.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/merammer_root.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/oanna_bloom.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/obelisk.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/planter.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/polished_wood_pillar.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/raw_lead_block.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/raw_silver_block.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/shadow_gem_block.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/sildrian_seed.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/silver_block.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/silver_ore.json create mode 100644 src/main/resources/data/eidolon/loot_tables/entities/raven.json create mode 100644 src/main/resources/data/eidolon/loot_tables/entities/slimy_slug.json create mode 100644 src/main/resources/data/eidolon/recipes/arcane_gold_ingot_alchemy.json create mode 100644 src/main/resources/data/eidolon/recipes/athame.json create mode 100644 src/main/resources/data/eidolon/recipes/beef_to_flesh.json create mode 100644 src/main/resources/data/eidolon/recipes/blast_raw_lead.json create mode 100644 src/main/resources/data/eidolon/recipes/blast_raw_silver.json create mode 100644 src/main/resources/data/eidolon/recipes/blast_silver_dust.json create mode 100644 src/main/resources/data/eidolon/recipes/blast_silver_ore.json create mode 100644 src/main/resources/data/eidolon/recipes/bonechill_wand.json create mode 100644 src/main/resources/data/eidolon/recipes/chicken_to_flesh.json create mode 100644 src/main/resources/data/eidolon/recipes/cleaving_axe.json create mode 100644 src/main/resources/data/eidolon/recipes/crimson_essence_fungus.json create mode 100644 src/main/resources/data/eidolon/recipes/crimson_essence_roots.json create mode 100644 src/main/resources/data/eidolon/recipes/crimson_essence_vines.json create mode 100644 src/main/resources/data/eidolon/recipes/death_essence.json create mode 100644 src/main/resources/data/eidolon/recipes/decompress_raw_lead_block.json create mode 100644 src/main/resources/data/eidolon/recipes/decompress_raw_silver_block.json create mode 100644 src/main/resources/data/eidolon/recipes/decompress_shadow_gem_block.json create mode 100644 src/main/resources/data/eidolon/recipes/decompress_silver_block.json create mode 100644 src/main/resources/data/eidolon/recipes/decompress_silver_ingot.json create mode 100644 src/main/resources/data/eidolon/recipes/ender_calx.json create mode 100644 src/main/resources/data/eidolon/recipes/flesh_to_leather.json create mode 100644 src/main/resources/data/eidolon/recipes/fungus_sprouts.json create mode 100644 src/main/resources/data/eidolon/recipes/gilding_apple.json create mode 100644 src/main/resources/data/eidolon/recipes/gilding_carrot.json create mode 100644 src/main/resources/data/eidolon/recipes/gilding_melon.json create mode 100644 src/main/resources/data/eidolon/recipes/glass_hand.json create mode 100644 src/main/resources/data/eidolon/recipes/gravity_belt.json create mode 100644 src/main/resources/data/eidolon/recipes/gunpowder_alchemy.json create mode 100644 src/main/resources/data/eidolon/recipes/lesser_soul_gem.json create mode 100644 src/main/resources/data/eidolon/recipes/mind_shielding_plate.json create mode 100644 src/main/resources/data/eidolon/recipes/mutton_to_flesh.json create mode 100644 src/main/resources/data/eidolon/recipes/obelisk.json create mode 100644 src/main/resources/data/eidolon/recipes/planter.json create mode 100644 src/main/resources/data/eidolon/recipes/polished_planks.json create mode 100644 src/main/resources/data/eidolon/recipes/pork_to_flesh.json create mode 100644 src/main/resources/data/eidolon/recipes/prestigious_palm.json create mode 100644 src/main/resources/data/eidolon/recipes/rabbit_to_flesh.json create mode 100644 src/main/resources/data/eidolon/recipes/raven_feather_arrows.json create mode 100644 src/main/resources/data/eidolon/recipes/raw_lead_block.json create mode 100644 src/main/resources/data/eidolon/recipes/raw_silver_block.json create mode 100644 src/main/resources/data/eidolon/recipes/reaper_scythe.json create mode 100644 src/main/resources/data/eidolon/recipes/resolute_belt.json create mode 100644 src/main/resources/data/eidolon/recipes/reversal_pick.json create mode 100644 src/main/resources/data/eidolon/recipes/shadow_gem.json create mode 100644 src/main/resources/data/eidolon/recipes/shadow_gem_block.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_axe.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_block.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_boots.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_chestplate.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_helmet.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_hoe.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_ingot.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_leggings.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_pickaxe.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_shovel.json create mode 100644 src/main/resources/data/eidolon/recipes/silver_sword.json create mode 100644 src/main/resources/data/eidolon/recipes/smelt_raw_lead.json create mode 100644 src/main/resources/data/eidolon/recipes/smelt_raw_silver.json create mode 100644 src/main/resources/data/eidolon/recipes/smelt_silver_dust.json create mode 100644 src/main/resources/data/eidolon/recipes/smelt_silver_ore.json delete mode 100644 src/main/resources/data/eidolon/recipes/smelt_stone_brick.json create mode 100644 src/main/resources/data/eidolon/recipes/soul_enchanter.json create mode 100644 src/main/resources/data/eidolon/recipes/soulfire_wand.json create mode 100644 src/main/resources/data/eidolon/recipes/stone_altar.json create mode 100644 src/main/resources/data/eidolon/recipes/sulfur.json create mode 100644 src/main/resources/data/eidolon/recipes/unholy_effigy.json create mode 100644 src/main/resources/data/eidolon/recipes/void_amulet.json create mode 100644 src/main/resources/data/eidolon/recipes/warded_mail.json create mode 100644 src/main/resources/data/eidolon/recipes/warlock_boots.json create mode 100644 src/main/resources/data/eidolon/recipes/warlock_cloak.json create mode 100644 src/main/resources/data/eidolon/recipes/warlock_hat.json create mode 100644 src/main/resources/data/eidolon/recipes/warped_sprouts.json create mode 100644 src/main/resources/data/eidolon/recipes/wicked_weave.json create mode 100644 src/main/resources/data/forge/tags/blocks/ores/silver.json create mode 100644 src/main/resources/data/forge/tags/blocks/storage_blocks/shadow_gem.json create mode 100644 src/main/resources/data/forge/tags/blocks/storage_blocks/silver.json create mode 100644 src/main/resources/data/forge/tags/items/dusts.json create mode 100644 src/main/resources/data/forge/tags/items/feathers.json create mode 100644 src/main/resources/data/forge/tags/items/gems.json create mode 100644 src/main/resources/data/forge/tags/items/gems/shadow_gem.json create mode 100644 src/main/resources/data/forge/tags/items/ingots.json create mode 100644 src/main/resources/data/forge/tags/items/ingots/silver.json create mode 100644 src/main/resources/data/forge/tags/items/nuggets/silver.json create mode 100644 src/main/resources/data/forge/tags/items/ores/silver.json create mode 100644 src/main/resources/data/forge/tags/items/storage_blocks/shadow_gem.json create mode 100644 src/main/resources/data/forge/tags/items/storage_blocks/silver.json create mode 100644 src/main/resources/data/forge/tags/items/tallow.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/mineable/axe.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/needs_iron_tool.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 35d8cef..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Bug report -about: Report a crash, or behavior that seems incorrect. -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -What went wrong? - -**To Reproduce** -What were you doing when the bug happened? - -**Environment** -What version of the mod were you using? Are you on singleplayer or multiplayer? - -**Crash Report** -If the problem crashed the game, please attach a log using a [GitHub Gist](https://gist.github.com/). diff --git a/.gitignore b/.gitignore index 5c2530c..80173c3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ out # gradle build .gradle +gradle/ +gradlew* # other eclipse @@ -25,3 +27,4 @@ logs # Files from Forge MDK forge*changelog.txt changelog.txt +LICENSE.txt diff --git a/build.gradle b/build.gradle index aa52924..63d2b75 100644 --- a/build.gradle +++ b/build.gradle @@ -4,9 +4,10 @@ buildscript { jcenter() mavenCentral() maven {url='https://dist.creeper.host/Sponge/maven'} + maven {url='https://repo.spongepowered.org/repository/maven-public'} } dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } @@ -14,23 +15,17 @@ apply plugin: 'net.minecraftforge.gradle' // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. apply plugin: 'eclipse' apply plugin: 'maven-publish' +// apply from: 'https://raw.githubusercontent.com/SizableShrimp/Forge-Class-Remapper/main/classremapper.gradle' -version = '0.2.7' +version = '0.3' group = 'elucent.eidolon' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'eidolon' -sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) minecraft { - // The mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD Snapshot are built nightly. - // stable_# Stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'snapshot', version: '20201028-1.16.3' - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - + mappings channel: 'official', version: '1.18.1' // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Default run configurations. @@ -110,13 +105,13 @@ repositories { } dependencies { - minecraft 'net.minecraftforge:forge:1.16.4-35.1.28' + minecraft 'net.minecraftforge:forge:1.18.1-39.0.5' - compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.16.2-4.0.0.1:api") - runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.16.2-4.0.0.1") + compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.18-5.0.2.4:api") + runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.18-5.0.2.4") - compileOnly fg.deobf('mezz.jei:jei-1.16.4:7.6.0.58') - runtimeOnly fg.deobf('mezz.jei:jei-1.16.4:7.6.0.58') + compileOnly fg.deobf('mezz.jei:jei-1.18.1:9.1.0.46') + runtimeOnly fg.deobf('mezz.jei:jei-1.18.1:9.1.0.46') } // Example for how to get properties into the manifest for reading by the runtime.. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 54708 zcmagFV|ZrKvM!pAZQHhO+qP}9lTNj?q^^Y^VFp)SH8qbSJ)2BQ2girk4u zvO<3q)c?v~^Z#E_K}1nTQbJ9gQ9<%vVRAxVj)8FwL5_iTdUB>&m3fhE=kRWl;g`&m z!W5kh{WsV%fO*%je&j+Lv4xxK~zsEYQls$Q-p&dwID|A)!7uWtJF-=Tm1{V@#x*+kUI$=%KUuf2ka zjiZ{oiL1MXE2EjciJM!jrjFNwCh`~hL>iemrqwqnX?T*MX;U>>8yRcZb{Oy+VKZos zLiFKYPw=LcaaQt8tj=eoo3-@bG_342HQ%?jpgAE?KCLEHC+DmjxAfJ%Og^$dpC8Xw zAcp-)tfJm}BPNq_+6m4gBgBm3+CvmL>4|$2N$^Bz7W(}fz1?U-u;nE`+9`KCLuqg} zwNstNM!J4Uw|78&Y9~9>MLf56to!@qGkJw5Thx%zkzj%Ek9Nn1QA@8NBXbwyWC>9H z#EPwjMNYPigE>*Ofz)HfTF&%PFj$U6mCe-AFw$U%-L?~-+nSXHHKkdgC5KJRTF}`G zE_HNdrE}S0zf4j{r_f-V2imSqW?}3w-4=f@o@-q+cZgaAbZ((hn))@|eWWhcT2pLpTpL!;_5*vM=sRL8 zqU##{U#lJKuyqW^X$ETU5ETeEVzhU|1m1750#f}38_5N9)B_2|v@1hUu=Kt7-@dhA zq_`OMgW01n`%1dB*}C)qxC8q;?zPeF_r;>}%JYmlER_1CUbKa07+=TV45~symC*g8 zW-8(gag#cAOuM0B1xG8eTp5HGVLE}+gYTmK=`XVVV*U!>H`~j4+ROIQ+NkN$LY>h4 zqpwdeE_@AX@PL};e5vTn`Ro(EjHVf$;^oiA%@IBQq>R7_D>m2D4OwwEepkg}R_k*M zM-o;+P27087eb+%*+6vWFCo9UEGw>t&WI17Pe7QVuoAoGHdJ(TEQNlJOqnjZ8adCb zI`}op16D@v7UOEo%8E-~m?c8FL1utPYlg@m$q@q7%mQ4?OK1h%ODjTjFvqd!C z-PI?8qX8{a@6d&Lb_X+hKxCImb*3GFemm?W_du5_&EqRq!+H?5#xiX#w$eLti-?E$;Dhu`{R(o>LzM4CjO>ICf z&DMfES#FW7npnbcuqREgjPQM#gs6h>`av_oEWwOJZ2i2|D|0~pYd#WazE2Bbsa}X@ zu;(9fi~%!VcjK6)?_wMAW-YXJAR{QHxrD5g(ou9mR6LPSA4BRG1QSZT6A?kelP_g- zH(JQjLc!`H4N=oLw=f3{+WmPA*s8QEeEUf6Vg}@!xwnsnR0bl~^2GSa5vb!Yl&4!> zWb|KQUsC$lT=3A|7vM9+d;mq=@L%uWKwXiO9}a~gP4s_4Yohc!fKEgV7WbVo>2ITbE*i`a|V!^p@~^<={#?Gz57 zyPWeM2@p>D*FW#W5Q`1`#5NW62XduP1XNO(bhg&cX`-LYZa|m-**bu|>}S;3)eP8_ zpNTnTfm8 ze+7wDH3KJ95p)5tlwk`S7mbD`SqHnYD*6`;gpp8VdHDz%RR_~I_Ar>5)vE-Pgu7^Y z|9Px+>pi3!DV%E%4N;ii0U3VBd2ZJNUY1YC^-e+{DYq+l@cGtmu(H#Oh%ibUBOd?C z{y5jW3v=0eV0r@qMLgv1JjZC|cZ9l9Q)k1lLgm))UR@#FrJd>w^`+iy$c9F@ic-|q zVHe@S2UAnc5VY_U4253QJxm&Ip!XKP8WNcnx9^cQ;KH6PlW8%pSihSH2(@{2m_o+m zr((MvBja2ctg0d0&U5XTD;5?d?h%JcRJp{_1BQW1xu&BrA3(a4Fh9hon-ly$pyeHq zG&;6q?m%NJ36K1Sq_=fdP(4f{Hop;_G_(i?sPzvB zDM}>*(uOsY0I1j^{$yn3#U(;B*g4cy$-1DTOkh3P!LQ;lJlP%jY8}Nya=h8$XD~%Y zbV&HJ%eCD9nui-0cw!+n`V~p6VCRqh5fRX z8`GbdZ@73r7~myQLBW%db;+BI?c-a>Y)m-FW~M=1^|<21_Sh9RT3iGbO{o-hpN%d6 z7%++#WekoBOP^d0$$|5npPe>u3PLvX_gjH2x(?{&z{jJ2tAOWTznPxv-pAv<*V7r$ z6&glt>7CAClWz6FEi3bToz-soY^{ScrjwVPV51=>n->c(NJngMj6TyHty`bfkF1hc zkJS%A@cL~QV0-aK4>Id!9dh7>0IV;1J9(myDO+gv76L3NLMUm9XyPauvNu$S<)-|F zZS}(kK_WnB)Cl`U?jsdYfAV4nrgzIF@+%1U8$poW&h^c6>kCx3;||fS1_7JvQT~CV zQ8Js+!p)3oW>Df(-}uqC`Tcd%E7GdJ0p}kYj5j8NKMp(KUs9u7?jQ94C)}0rba($~ zqyBx$(1ae^HEDG`Zc@-rXk1cqc7v0wibOR4qpgRDt#>-*8N3P;uKV0CgJE2SP>#8h z=+;i_CGlv+B^+$5a}SicVaSeaNn29K`C&=}`=#Nj&WJP9Xhz4mVa<+yP6hkrq1vo= z1rX4qg8dc4pmEvq%NAkpMK>mf2g?tg_1k2%v}<3`$6~Wlq@ItJ*PhHPoEh1Yi>v57 z4k0JMO)*=S`tKvR5gb-(VTEo>5Y>DZJZzgR+j6{Y`kd|jCVrg!>2hVjz({kZR z`dLlKhoqT!aI8=S+fVp(5*Dn6RrbpyO~0+?fy;bm$0jmTN|t5i6rxqr4=O}dY+ROd zo9Et|x}!u*xi~>-y>!M^+f&jc;IAsGiM_^}+4|pHRn{LThFFpD{bZ|TA*wcGm}XV^ zr*C6~@^5X-*R%FrHIgo-hJTBcyQ|3QEj+cSqp#>&t`ZzB?cXM6S(lRQw$I2?m5=wd z78ki`R?%;o%VUhXH?Z#(uwAn9$m`npJ=cA+lHGk@T7qq_M6Zoy1Lm9E0UUysN)I_x zW__OAqvku^>`J&CB=ie@yNWsaFmem}#L3T(x?a`oZ+$;3O-icj2(5z72Hnj=9Z0w% z<2#q-R=>hig*(t0^v)eGq2DHC%GymE-_j1WwBVGoU=GORGjtaqr0BNigOCqyt;O(S zKG+DoBsZU~okF<7ahjS}bzwXxbAxFfQAk&O@>LsZMsZ`?N?|CDWM(vOm%B3CBPC3o z%2t@%H$fwur}SSnckUm0-k)mOtht`?nwsDz=2#v=RBPGg39i#%odKq{K^;bTD!6A9 zskz$}t)sU^=a#jLZP@I=bPo?f-L}wpMs{Tc!m7-bi!Ldqj3EA~V;4(dltJmTXqH0r z%HAWKGutEc9vOo3P6Q;JdC^YTnby->VZ6&X8f{obffZ??1(cm&L2h7q)*w**+sE6dG*;(H|_Q!WxU{g)CeoT z(KY&bv!Usc|m+Fqfmk;h&RNF|LWuNZ!+DdX*L=s-=_iH=@i` z?Z+Okq^cFO4}_n|G*!)Wl_i%qiMBaH8(WuXtgI7EO=M>=i_+;MDjf3aY~6S9w0K zUuDO7O5Ta6+k40~xh~)D{=L&?Y0?c$s9cw*Ufe18)zzk%#ZY>Tr^|e%8KPb0ht`b( zuP@8#Ox@nQIqz9}AbW0RzE`Cf>39bOWz5N3qzS}ocxI=o$W|(nD~@EhW13Rj5nAp; zu2obEJa=kGC*#3=MkdkWy_%RKcN=?g$7!AZ8vBYKr$ePY(8aIQ&yRPlQ=mudv#q$q z4%WzAx=B{i)UdLFx4os?rZp6poShD7Vc&mSD@RdBJ=_m^&OlkEE1DFU@csgKcBifJ zz4N7+XEJhYzzO=86 z#%eBQZ$Nsf2+X0XPHUNmg#(sNt^NW1Y0|M(${e<0kW6f2q5M!2YE|hSEQ*X-%qo(V zHaFwyGZ0on=I{=fhe<=zo{=Og-_(to3?cvL4m6PymtNsdDINsBh8m>a%!5o3s(en) z=1I z6O+YNertC|OFNqd6P=$gMyvmfa`w~p9*gKDESFqNBy(~Zw3TFDYh}$iudn)9HxPBi zdokK@o~nu?%imcURr5Y~?6oo_JBe}t|pU5qjai|#JDyG=i^V~7+a{dEnO<(y>ahND#_X_fcEBNiZ)uc&%1HVtx8Ts z*H_Btvx^IhkfOB#{szN*n6;y05A>3eARDXslaE>tnLa>+`V&cgho?ED+&vv5KJszf zG4@G;7i;4_bVvZ>!mli3j7~tPgybF5|J6=Lt`u$D%X0l}#iY9nOXH@(%FFJLtzb%p zzHfABnSs;v-9(&nzbZytLiqqDIWzn>JQDk#JULcE5CyPq_m#4QV!}3421haQ+LcfO*>r;rg6K|r#5Sh|y@h1ao%Cl)t*u`4 zMTP!deC?aL7uTxm5^nUv#q2vS-5QbBKP|drbDXS%erB>fYM84Kpk^au99-BQBZR z7CDynflrIAi&ahza+kUryju5LR_}-Z27g)jqOc(!Lx9y)e z{cYc&_r947s9pteaa4}dc|!$$N9+M38sUr7h(%@Ehq`4HJtTpA>B8CLNO__@%(F5d z`SmX5jbux6i#qc}xOhumzbAELh*Mfr2SW99=WNOZRZgoCU4A2|4i|ZVFQt6qEhH#B zK_9G;&h*LO6tB`5dXRSBF0hq0tk{2q__aCKXYkP#9n^)@cq}`&Lo)1KM{W+>5mSed zKp~=}$p7>~nK@va`vN{mYzWN1(tE=u2BZhga5(VtPKk(*TvE&zmn5vSbjo zZLVobTl%;t@6;4SsZ>5+U-XEGUZGG;+~|V(pE&qqrp_f~{_1h@5ZrNETqe{bt9ioZ z#Qn~gWCH!t#Ha^n&fT2?{`}D@s4?9kXj;E;lWV9Zw8_4yM0Qg-6YSsKgvQ*fF{#Pq z{=(nyV>#*`RloBVCs;Lp*R1PBIQOY=EK4CQa*BD0MsYcg=opP?8;xYQDSAJBeJpw5 zPBc_Ft9?;<0?pBhCmOtWU*pN*;CkjJ_}qVic`}V@$TwFi15!mF1*m2wVX+>5p%(+R zQ~JUW*zWkalde{90@2v+oVlkxOZFihE&ZJ){c?hX3L2@R7jk*xjYtHi=}qb+4B(XJ z$gYcNudR~4Kz_WRq8eS((>ALWCO)&R-MXE+YxDn9V#X{_H@j616<|P(8h(7z?q*r+ zmpqR#7+g$cT@e&(%_|ipI&A%9+47%30TLY(yuf&*knx1wNx|%*H^;YB%ftt%5>QM= z^i;*6_KTSRzQm%qz*>cK&EISvF^ovbS4|R%)zKhTH_2K>jP3mBGn5{95&G9^a#4|K zv+!>fIsR8z{^x4)FIr*cYT@Q4Z{y}};rLHL+atCgHbfX*;+k&37DIgENn&=k(*lKD zG;uL-KAdLn*JQ?@r6Q!0V$xXP=J2i~;_+i3|F;_En;oAMG|I-RX#FwnmU&G}w`7R{ z788CrR-g1DW4h_`&$Z`ctN~{A)Hv_-Bl!%+pfif8wN32rMD zJDs$eVWBYQx1&2sCdB0!vU5~uf)=vy*{}t{2VBpcz<+~h0wb7F3?V^44*&83Z2#F` z32!rd4>uc63rQP$3lTH3zb-47IGR}f)8kZ4JvX#toIpXH`L%NnPDE~$QI1)0)|HS4 zVcITo$$oWWwCN@E-5h>N?Hua!N9CYb6f8vTFd>h3q5Jg-lCI6y%vu{Z_Uf z$MU{{^o~;nD_@m2|E{J)q;|BK7rx%`m``+OqZAqAVj-Dy+pD4-S3xK?($>wn5bi90CFAQ+ACd;&m6DQB8_o zjAq^=eUYc1o{#+p+ zn;K<)Pn*4u742P!;H^E3^Qu%2dM{2slouc$AN_3V^M7H_KY3H)#n7qd5_p~Za7zAj|s9{l)RdbV9e||_67`#Tu*c<8!I=zb@ z(MSvQ9;Wrkq6d)!9afh+G`!f$Ip!F<4ADdc*OY-y7BZMsau%y?EN6*hW4mOF%Q~bw z2==Z3^~?q<1GTeS>xGN-?CHZ7a#M4kDL zQxQr~1ZMzCSKFK5+32C%+C1kE#(2L=15AR!er7GKbp?Xd1qkkGipx5Q~FI-6zt< z*PTpeVI)Ngnnyaz5noIIgNZtb4bQdKG{Bs~&tf)?nM$a;7>r36djllw%hQxeCXeW^ z(i6@TEIuxD<2ulwLTt|&gZP%Ei+l!(%p5Yij6U(H#HMkqM8U$@OKB|5@vUiuY^d6X zW}fP3;Kps6051OEO(|JzmVU6SX(8q>*yf*x5QoxDK={PH^F?!VCzES_Qs>()_y|jg6LJlJWp;L zKM*g5DK7>W_*uv}{0WUB0>MHZ#oJZmO!b3MjEc}VhsLD~;E-qNNd?x7Q6~v zR=0$u>Zc2Xr}>x_5$-s#l!oz6I>W?lw;m9Ae{Tf9eMX;TI-Wf_mZ6sVrMnY#F}cDd z%CV*}fDsXUF7Vbw>PuDaGhu631+3|{xp<@Kl|%WxU+vuLlcrklMC!Aq+7n~I3cmQ! z`e3cA!XUEGdEPSu``&lZEKD1IKO(-VGvcnSc153m(i!8ohi`)N2n>U_BemYJ`uY>8B*Epj!oXRLV}XK}>D*^DHQ7?NY*&LJ9VSo`Ogi9J zGa;clWI8vIQqkngv2>xKd91K>?0`Sw;E&TMg&6dcd20|FcTsnUT7Yn{oI5V4@Ow~m zz#k~8TM!A9L7T!|colrC0P2WKZW7PNj_X4MfESbt<-soq*0LzShZ}fyUx!(xIIDwx zRHt^_GAWe0-Vm~bDZ(}XG%E+`XhKpPlMBo*5q_z$BGxYef8O!ToS8aT8pmjbPq)nV z%x*PF5ZuSHRJqJ!`5<4xC*xb2vC?7u1iljB_*iUGl6+yPyjn?F?GOF2_KW&gOkJ?w z3e^qc-te;zez`H$rsUCE0<@7PKGW?7sT1SPYWId|FJ8H`uEdNu4YJjre`8F*D}6Wh z|FQ`xf7yiphHIAkU&OYCn}w^ilY@o4larl?^M7&8YI;hzBIsX|i3UrLsx{QDKwCX< zy;a>yjfJ6!sz`NcVi+a!Fqk^VE^{6G53L?@Tif|j!3QZ0fk9QeUq8CWI;OmO-Hs+F zuZ4sHLA3{}LR2Qlyo+{d@?;`tpp6YB^BMoJt?&MHFY!JQwoa0nTSD+#Ku^4b{5SZVFwU9<~APYbaLO zu~Z)nS#dxI-5lmS-Bnw!(u15by(80LlC@|ynj{TzW)XcspC*}z0~8VRZq>#Z49G`I zgl|C#H&=}n-ajxfo{=pxPV(L*7g}gHET9b*s=cGV7VFa<;Htgjk>KyW@S!|z`lR1( zGSYkEl&@-bZ*d2WQ~hw3NpP=YNHF^XC{TMG$Gn+{b6pZn+5=<()>C!N^jncl0w6BJ zdHdnmSEGK5BlMeZD!v4t5m7ct7{k~$1Ie3GLFoHjAH*b?++s<|=yTF+^I&jT#zuMx z)MLhU+;LFk8bse|_{j+d*a=&cm2}M?*arjBPnfPgLwv)86D$6L zLJ0wPul7IenMvVAK$z^q5<^!)7aI|<&GGEbOr=E;UmGOIa}yO~EIr5xWU_(ol$&fa zR5E(2vB?S3EvJglTXdU#@qfDbCYs#82Yo^aZN6`{Ex#M)easBTe_J8utXu(fY1j|R z9o(sQbj$bKU{IjyhosYahY{63>}$9_+hWxB3j}VQkJ@2$D@vpeRSldU?&7I;qd2MF zSYmJ>zA(@N_iK}m*AMPIJG#Y&1KR)6`LJ83qg~`Do3v^B0>fU&wUx(qefuTgzFED{sJ65!iw{F2}1fQ3= ziFIP{kezQxmlx-!yo+sC4PEtG#K=5VM9YIN0z9~c4XTX?*4e@m;hFM!zVo>A`#566 z>f&3g94lJ{r)QJ5m7Xe3SLau_lOpL;A($wsjHR`;xTXgIiZ#o&vt~ zGR6KdU$FFbLfZCC3AEu$b`tj!9XgOGLSV=QPIYW zjI!hSP#?8pn0@ezuenOzoka8!8~jXTbiJ6+ZuItsWW03uzASFyn*zV2kIgPFR$Yzm zE<$cZlF>R8?Nr2_i?KiripBc+TGgJvG@vRTY2o?(_Di}D30!k&CT`>+7ry2!!iC*X z<@=U0_C#16=PN7bB39w+zPwDOHX}h20Ap);dx}kjXX0-QkRk=cr};GYsjSvyLZa-t zzHONWddi*)RDUH@RTAsGB_#&O+QJaaL+H<<9LLSE+nB@eGF1fALwjVOl8X_sdOYme z0lk!X=S(@25=TZHR7LlPp}fY~yNeThMIjD}pd9+q=j<_inh0$>mIzWVY+Z9p<{D^#0Xk+b_@eNSiR8;KzSZ#7lUsk~NGMcB8C2c=m2l5paHPq`q{S(kdA7Z1a zyfk2Y;w?^t`?@yC5Pz9&pzo}Hc#}mLgDmhKV|PJ3lKOY(Km@Fi2AV~CuET*YfUi}u zfInZnqDX(<#vaS<^fszuR=l)AbqG{}9{rnyx?PbZz3Pyu!eSJK`uwkJU!ORQXy4x83r!PNgOyD33}}L=>xX_93l6njNTuqL8J{l%*3FVn3MG4&Fv*`lBXZ z?=;kn6HTT^#SrPX-N)4EZiIZI!0ByXTWy;;J-Tht{jq1mjh`DSy7yGjHxIaY%*sTx zuy9#9CqE#qi>1misx=KRWm=qx4rk|}vd+LMY3M`ow8)}m$3Ggv&)Ri*ON+}<^P%T5 z_7JPVPfdM=Pv-oH<tecoE}(0O7|YZc*d8`Uv_M*3Rzv7$yZnJE6N_W=AQ3_BgU_TjA_T?a)U1csCmJ&YqMp-lJe`y6>N zt++Bi;ZMOD%%1c&-Q;bKsYg!SmS^#J@8UFY|G3!rtyaTFb!5@e(@l?1t(87ln8rG? z--$1)YC~vWnXiW3GXm`FNSyzu!m$qT=Eldf$sMl#PEfGmzQs^oUd=GIQfj(X=}dw+ zT*oa0*oS%@cLgvB&PKIQ=Ok?>x#c#dC#sQifgMwtAG^l3D9nIg(Zqi;D%807TtUUCL3_;kjyte#cAg?S%e4S2W>9^A(uy8Ss0Tc++ZTjJw1 z&Em2g!3lo@LlDyri(P^I8BPpn$RE7n*q9Q-c^>rfOMM6Pd5671I=ZBjAvpj8oIi$! zl0exNl(>NIiQpX~FRS9UgK|0l#s@#)p4?^?XAz}Gjb1?4Qe4?j&cL$C8u}n)?A@YC zfmbSM`Hl5pQFwv$CQBF=_$Sq zxsV?BHI5bGZTk?B6B&KLdIN-40S426X3j_|ceLla*M3}3gx3(_7MVY1++4mzhH#7# zD>2gTHy*%i$~}mqc#gK83288SKp@y3wz1L_e8fF$Rb}ex+`(h)j}%~Ld^3DUZkgez zOUNy^%>>HHE|-y$V@B}-M|_{h!vXpk01xaD%{l{oQ|~+^>rR*rv9iQen5t?{BHg|% zR`;S|KtUb!X<22RTBA4AAUM6#M?=w5VY-hEV)b`!y1^mPNEoy2K)a>OyA?Q~Q*&(O zRzQI~y_W=IPi?-OJX*&&8dvY0zWM2%yXdFI!D-n@6FsG)pEYdJbuA`g4yy;qrgR?G z8Mj7gv1oiWq)+_$GqqQ$(ZM@#|0j7})=#$S&hZwdoijFI4aCFLVI3tMH5fLreZ;KD zqA`)0l~D2tuIBYOy+LGw&hJ5OyE+@cnZ0L5+;yo2pIMdt@4$r^5Y!x7nHs{@>|W(MzJjATyWGNwZ^4j+EPU0RpAl-oTM@u{lx*i0^yyWPfHt6QwPvYpk9xFMWfBFt!+Gu6TlAmr zeQ#PX71vzN*_-xh&__N`IXv6`>CgV#eA_%e@7wjgkj8jlKzO~Ic6g$cT`^W{R{606 zCDP~+NVZ6DMO$jhL~#+!g*$T!XW63#(ngDn#Qwy71yj^gazS{e;3jGRM0HedGD@pt z?(ln3pCUA(ekqAvvnKy0G@?-|-dh=eS%4Civ&c}s%wF@0K5Bltaq^2Os1n6Z3%?-Q zAlC4goQ&vK6TpgtzkHVt*1!tBYt-`|5HLV1V7*#45Vb+GACuU+QB&hZ=N_flPy0TY zR^HIrdskB#<$aU;HY(K{a3(OQa$0<9qH(oa)lg@Uf>M5g2W0U5 zk!JSlhrw8quBx9A>RJ6}=;W&wt@2E$7J=9SVHsdC?K(L(KACb#z)@C$xXD8^!7|uv zZh$6fkq)aoD}^79VqdJ!Nz-8$IrU(_-&^cHBI;4 z^$B+1aPe|LG)C55LjP;jab{dTf$0~xbXS9!!QdcmDYLbL^jvxu2y*qnx2%jbL%rB z{aP85qBJe#(&O~Prk%IJARcdEypZ)vah%ZZ%;Zk{eW(U)Bx7VlzgOi8)x z`rh4l`@l_Ada7z&yUK>ZF;i6YLGwI*Sg#Fk#Qr0Jg&VLax(nNN$u-XJ5=MsP3|(lEdIOJ7|(x3iY;ea)5#BW*mDV%^=8qOeYO&gIdJVuLLN3cFaN=xZtFB=b zH{l)PZl_j^u+qx@89}gAQW7ofb+k)QwX=aegihossZq*+@PlCpb$rpp>Cbk9UJO<~ zDjlXQ_Ig#W0zdD3&*ei(FwlN#3b%FSR%&M^ywF@Fr>d~do@-kIS$e%wkIVfJ|Ohh=zc zF&Rnic^|>@R%v?@jO}a9;nY3Qrg_!xC=ZWUcYiA5R+|2nsM*$+c$TOs6pm!}Z}dfM zGeBhMGWw3$6KZXav^>YNA=r6Es>p<6HRYcZY)z{>yasbC81A*G-le8~QoV;rtKnkx z;+os8BvEe?0A6W*a#dOudsv3aWs?d% z0oNngyVMjavLjtjiG`!007#?62ClTqqU$@kIY`=x^$2e>iqIy1>o|@Tw@)P)B8_1$r#6>DB_5 zmaOaoE~^9TolgDgooKFuEFB#klSF%9-~d2~_|kQ0Y{Ek=HH5yq9s zDq#1S551c`kSiWPZbweN^A4kWiP#Qg6er1}HcKv{fxb1*BULboD0fwfaNM_<55>qM zETZ8TJDO4V)=aPp_eQjX%||Ud<>wkIzvDlpNjqW>I}W!-j7M^TNe5JIFh#-}zAV!$ICOju8Kx)N z0vLtzDdy*rQN!7r>Xz7rLw8J-(GzQlYYVH$WK#F`i_i^qVlzTNAh>gBWKV@XC$T-` z3|kj#iCquDhiO7NKum07i|<-NuVsX}Q}mIP$jBJDMfUiaWR3c|F_kWBMw0_Sr|6h4 zk`_r5=0&rCR^*tOy$A8K;@|NqwncjZ>Y-75vlpxq%Cl3EgH`}^^~=u zoll6xxY@a>0f%Ddpi;=cY}fyG!K2N-dEyXXmUP5u){4VnyS^T4?pjN@Ot4zjL(Puw z_U#wMH2Z#8Pts{olG5Dy0tZj;N@;fHheu>YKYQU=4Bk|wcD9MbA`3O4bj$hNRHwzb zSLcG0SLV%zywdbuwl(^E_!@&)TdXge4O{MRWk2RKOt@!8E{$BU-AH(@4{gxs=YAz9LIob|Hzto0}9cWoz6Tp2x0&xi#$ zHh$dwO&UCR1Ob2w00-2eG7d4=cN(Y>0R#$q8?||q@iTi+7-w-xR%uMr&StFIthC<# zvK(aPduwuNB}oJUV8+Zl)%cnfsHI%4`;x6XW^UF^e4s3Z@S<&EV8?56Wya;HNs0E> z`$0dgRdiUz9RO9Au3RmYq>K#G=X%*_dUbSJHP`lSfBaN8t-~@F>)BL1RT*9I851A3 z<-+Gb#_QRX>~av#Ni<#zLswtu-c6{jGHR>wflhKLzC4P@b%8&~u)fosoNjk4r#GvC zlU#UU9&0Hv;d%g72Wq?Ym<&&vtA3AB##L}=ZjiTR4hh7J)e>ei} zt*u+>h%MwN`%3}b4wYpV=QwbY!jwfIj#{me)TDOG`?tI!%l=AwL2G@9I~}?_dA5g6 zCKgK(;6Q0&P&K21Tx~k=o6jwV{dI_G+Ba*Zts|Tl6q1zeC?iYJTb{hel*x>^wb|2RkHkU$!+S4OU4ZOKPZjV>9OVsqNnv5jK8TRAE$A&^yRwK zj-MJ3Pl?)KA~fq#*K~W0l4$0=8GRx^9+?w z!QT8*-)w|S^B0)ZeY5gZPI2G(QtQf?DjuK(s^$rMA!C%P22vynZY4SuOE=wX2f8$R z)A}mzJi4WJnZ`!bHG1=$lwaxm!GOnRbR15F$nRC-M*H<*VfF|pQw(;tbSfp({>9^5 zw_M1-SJ9eGF~m(0dvp*P8uaA0Yw+EkP-SWqu zqal$hK8SmM7#Mrs0@OD+%_J%H*bMyZiWAZdsIBj#lkZ!l2c&IpLu(5^T0Ge5PHzR} zn;TXs$+IQ_&;O~u=Jz+XE0wbOy`=6>m9JVG} zJ~Kp1e5m?K3x@@>!D)piw^eMIHjD4RebtR`|IlckplP1;r21wTi8v((KqNqn%2CB< zifaQc&T}*M&0i|LW^LgdjIaX|o~I$`owHolRqeH_CFrqCUCleN130&vH}dK|^kC>) z-r2P~mApHotL4dRX$25lIcRh_*kJaxi^%ZN5-GAAMOxfB!6flLPY-p&QzL9TE%ho( zRwftE3sy5<*^)qYzKkL|rE>n@hyr;xPqncY6QJ8125!MWr`UCWuC~A#G1AqF1@V$kv>@NBvN&2ygy*{QvxolkRRb%Ui zsmKROR%{*g*WjUUod@@cS^4eF^}yQ1>;WlGwOli z+Y$(8I`0(^d|w>{eaf!_BBM;NpCoeem2>J}82*!em=}}ymoXk>QEfJ>G(3LNA2-46 z5PGvjr)Xh9>aSe>vEzM*>xp{tJyZox1ZRl}QjcvX2TEgNc^(_-hir@Es>NySoa1g^ zFow_twnHdx(j?Q_3q51t3XI7YlJ4_q&(0#)&a+RUy{IcBq?)eaWo*=H2UUVIqtp&lW9JTJiP&u zw8+4vo~_IJXZIJb_U^&=GI1nSD%e;P!c{kZALNCm5c%%oF+I3DrA63_@4)(v4(t~JiddILp7jmoy+>cD~ivwoctFfEL zP*#2Rx?_&bCpX26MBgp^4G>@h`Hxc(lnqyj!*t>9sOBcXN(hTwEDpn^X{x!!gPX?1 z*uM$}cYRwHXuf+gYTB}gDTcw{TXSOUU$S?8BeP&sc!Lc{{pEv}x#ELX>6*ipI1#>8 zKes$bHjiJ1OygZge_ak^Hz#k;=od1wZ=o71ba7oClBMq>Uk6hVq|ePPt)@FM5bW$I z;d2Or@wBjbTyZj|;+iHp%Bo!Vy(X3YM-}lasMItEV_QrP-Kk_J4C>)L&I3Xxj=E?| zsAF(IfVQ4w+dRRnJ>)}o^3_012YYgFWE)5TT=l2657*L8_u1KC>Y-R{7w^ShTtO;VyD{dezY;XD@Rwl_9#j4Uo!1W&ZHVe0H>f=h#9k>~KUj^iUJ%@wU{Xuy z3FItk0<;}6D02$u(RtEY#O^hrB>qgxnOD^0AJPGC9*WXw_$k%1a%-`>uRIeeAIf3! zbx{GRnG4R$4)3rVmg63gW?4yIWW_>;t3>4@?3}&ct0Tk}<5ljU>jIN1 z&+mzA&1B6`v(}i#vAzvqWH~utZzQR;fCQGLuCN|p0hey7iCQ8^^dr*hi^wC$bTk`8M(JRKtQuXlSf$d(EISvuY0dM z7&ff;p-Ym}tT8^MF5ACG4sZmAV!l;0h&Mf#ZPd--_A$uv2@3H!y^^%_&Iw$*p79Uc5@ZXLGK;edg%)6QlvrN`U7H@e^P*0Atd zQB%>4--B1!9yeF(3vk;{>I8+2D;j`zdR8gd8dHuCQ_6|F(5-?gd&{YhLeyq_-V--4 z(SP#rP=-rsSHJSHDpT1{dMAb7-=9K1-@co_!$dG^?c(R-W&a_C5qy2~m3@%vBGhgnrw|H#g9ABb7k{NE?m4xD?;EV+fPdE>S2g$U(&_zGV+TPvaot>W_ zf8yY@)yP8k$y}UHVgF*uxtjW2zX4Hc3;W&?*}K&kqYpi%FHarfaC$ETHpSoP;A692 zR*LxY1^BO1ry@7Hc9p->hd==U@cuo*CiTnozxen;3Gct=?{5P94TgQ(UJoBb`7z@BqY z;q&?V2D1Y%n;^Dh0+eD)>9<}=A|F5{q#epBu#sf@lRs`oFEpkE%mrfwqJNFCpJC$| zy6#N;GF8XgqX(m2yMM2yq@TxStIR7whUIs2ar$t%Avh;nWLwElVBSI#j`l2$lb-!y zK|!?0hJ1T-wL{4uJhOFHp4?@28J^Oh61DbeTeSWub(|dL-KfxFCp0CjQjV`WaPW|U z=ev@VyC>IS@{ndzPy||b3z-bj5{Y53ff}|TW8&&*pu#?qs?)#&M`ACfb;%m+qX{Or zb+FNNHU}mz!@!EdrxmP_6eb3Cah!mL0ArL#EA1{nCY-!jL8zzz7wR6wAw(8K|IpW; zUvH*b1wbuRlwlUt;dQhx&pgsvJcUpm67rzkNc}2XbC6mZAgUn?VxO6YYg=M!#e=z8 zjX5ZLyMyz(VdPVyosL0}ULO!Mxu>hh`-MItnGeuQ;wGaU0)gIq3ZD=pDc(Qtk}APj z#HtA;?idVKNF)&0r|&w#l7DbX%b91b2;l2=L8q#}auVdk{RuYn3SMDo1%WW0tD*62 zaIj65Y38;?-~@b82AF!?Nra2;PU)t~qYUhl!GDK3*}%@~N0GQH7zflSpfP-ydOwNe zOK~w((+pCD&>f!b!On);5m+zUBFJtQ)mV^prS3?XgPybC2%2LiE5w+S4B|lP z+_>3$`g=%P{IrN|1Oxz30R{kI`}ZL!r|)RS@8Do;ZD3_=PbBrrP~S@EdsD{V+`!4v z{MSF}j!6odl33rA+$odIMaK%ersg%xMz>JQ^R+!qNq$5S{KgmGN#gAApX*3ib)TDsVVi>4ypIX|Ik4d6E}v z=8+hs9J=k3@Eiga^^O|ESMQB-O6i+BL*~*8coxjGs{tJ9wXjGZ^Vw@j93O<&+bzAH z9+N^ALvDCV<##cGoo5fX;wySGGmbH zHsslio)cxlud=iP2y=nM>v8vBn*hJ0KGyNOy7dr8yJKRh zywBOa4Lhh58y06`5>ESYXqLt8ZM1axd*UEp$wl`APU}C9m1H8-ModG!(wfSUQ%}rT3JD*ud~?WJdM}x>84)Cra!^J9wGs6^G^ze~eV(d&oAfm$ z_gwq4SHe=<#*FN}$5(0d_NumIZYaqs|MjFtI_rJb^+ZO?*XQ*47mzLNSL7~Nq+nw8 zuw0KwWITC43`Vx9eB!0Fx*CN9{ea$xjCvtjeyy>yf!ywxvv6<*h0UNXwkEyRxX{!e$TgHZ^db3r;1qhT)+yt@|_!@ zQG2aT`;lj>qjY`RGfQE?KTt2mn=HmSR>2!E38n8PlFs=1zsEM}AMICb z86Dbx(+`!hl$p=Z)*W~+?_HYp+CJacrCS-Fllz!7E>8*!E(yCh-cWbKc7)mPT6xu= zfKpF3I+p%yFXkMIq!ALiXF89-aV{I6v+^k#!_xwtQ*Nl#V|hKg=nP=fG}5VB8Ki7) z;19!on-iq&Xyo#AowvpA)RRgF?YBdDc$J8*)2Wko;Y?V6XMOCqT(4F#U2n1jg*4=< z8$MfDYL|z731iEKB3WW#kz|c3qh7AXjyZ}wtSg9xA(ou-pLoxF{4qk^KS?!d3J0!! zqE#R9NYGUyy>DEs%^xW;oQ5Cs@fomcrsN}rI2Hg^6y9kwLPF`K3llX00aM_r)c?ay zevlHA#N^8N+AI=)vx?4(=?j^ba^{umw140V#g58#vtnh8i7vRs*UD=lge;T+I zl1byCNr5H%DF58I2(rk%8hQ;zuCXs=sipbQy?Hd;umv4!fav@LE4JQ^>J{aZ=!@Gc~p$JudMy%0{=5QY~S8YVP zaP6gRqfZ0>q9nR3p+Wa8icNyl0Zn4k*bNto-(+o@-D8cd1Ed7`}dN3%wezkFxj_#_K zyV{msOOG;n+qbU=jBZk+&S$GEwJ99zSHGz8hF1`Xxa^&l8aaD8OtnIVsdF0cz=Y)? zP$MEdfKZ}_&#AC)R%E?G)tjrKsa-$KW_-$QL}x$@$NngmX2bHJQG~77D1J%3bGK!- zl!@kh5-uKc@U4I_Er;~epL!gej`kdX>tSXVFP-BH#D-%VJOCpM(-&pOY+b#}lOe)Z z0MP5>av1Sy-dfYFy%?`p`$P|`2yDFlv(8MEsa++Qv5M?7;%NFQK0E`Ggf3@2aUwtBpCoh`D}QLY%QAnJ z%qcf6!;cjOTYyg&2G27K(F8l^RgdV-V!~b$G%E=HP}M*Q*%xJV3}I8UYYd)>*nMvw zemWg`K6Rgy+m|y!8&*}=+`STm(dK-#b%)8nLsL&0<8Zd^|# z;I2gR&e1WUS#v!jX`+cuR;+yi(EiDcRCouW0AHNd?;5WVnC_Vg#4x56#0FOwTH6_p z#GILFF0>bb_tbmMM0|sd7r%l{U!fI0tGza&?65_D7+x9G zf3GA{c|mnO(|>}y(}%>|2>p0X8wRS&Eb0g)rcICIctfD_I9Wd+hKuEqv?gzEZBxG-rG~e!-2hqaR$Y$I@k{rLyCccE}3d)7Fn3EvfsEhA|bnJ374&pZDq&i zr(9#eq(g8^tG??ZzVk(#jU+-ce`|yiQ1dgrJ)$|wk?XLEqv&M+)I*OZ*oBCizjHuT zjZ|mW=<1u$wPhyo#&rIO;qH~pu4e3X;!%BRgmX%?&KZ6tNl386-l#a>ug5nHU2M~{fM2jvY*Py< zbR&^o&!T19G6V-pV@CB)YnEOfmrdPG%QByD?=if99ihLxP6iA8$??wUPWzptC{u5H z38Q|!=IW`)5Gef4+pz|9fIRXt>nlW)XQvUXBO8>)Q=$@gtwb1iEkU4EOWI4`I4DN5 zTC-Pk6N>2%7Hikg?`Poj5lkM0T_i zoCXfXB&}{TG%IB)ENSfI_Xg3=lxYc6-P059>oK;L+vGMy_h{y9soj#&^q5E!pl(Oq zl)oCBi56u;YHkD)d`!iOAhEJ0A^~T;uE9~Yp0{E%G~0q|9f34F!`P56-ZF{2hSaWj zio%9RR%oe~he22r@&j_d(y&nAUL*ayBY4#CWG&gZ8ybs#UcF?8K#HzziqOYM-<`C& z1gD?j)M0bp1w*U>X_b1@ag1Fx=d*wlr zEAcpmI#5LtqcX95LeS=LXlzh*l;^yPl_6MKk)zPuTz_p8ynQ5;oIOUAoPED=+M6Q( z8YR!DUm#$zTM9tbNhxZ4)J0L&Hpn%U>wj3z<=g;`&c_`fGufS!o|1%I_sA&;14bRC z3`BtzpAB-yl!%zM{Aiok8*X%lDNrPiAjBnzHbF0=Ua*3Lxl(zN3Thj2x6nWi^H7Jlwd2fxIvnI-SiC%*j z2~wIWWKT^5fYipo-#HSrr;(RkzzCSt?THVEH2EPvV-4c#Gu4&1X% z<1zTAM7ZM(LuD@ZPS?c30Ur`;2w;PXPVevxT)Ti25o}1JL>MN5i1^(aCF3 zbp>RI?X(CkR9*Hnv!({Ti@FBm;`Ip%e*D2tWEOc62@$n7+gWb;;j}@G()~V)>s}Bd zw+uTg^ibA(gsp*|&m7Vm=heuIF_pIukOedw2b_uO8hEbM4l=aq?E-7M_J`e(x9?{5 zpbgu7h}#>kDQAZL;Q2t?^pv}Y9Zlu=lO5e18twH&G&byq9XszEeXt$V93dQ@Fz2DV zs~zm*L0uB`+o&#{`uVYGXd?)Fv^*9mwLW4)IKoOJ&(8uljK?3J`mdlhJF1aK;#vlc zJdTJc2Q>N*@GfafVw45B03)Ty8qe>Ou*=f#C-!5uiyQ^|6@Dzp9^n-zidp*O`YuZ|GO28 zO0bqi;)fspT0dS2;PLm(&nLLV&&=Ingn(0~SB6Fr^AxPMO(r~y-q2>gRWv7{zYW6c zfiuqR)Xc41A7Eu{V7$-yxYT-opPtqQIJzMVkxU)cV~N0ygub%l9iHT3eQtB>nH0c` zFy}Iwd9vocxlm!P)eh0GwKMZ(fEk92teSi*fezYw3qRF_E-EcCh-&1T)?beW?9Q_+pde8&UW*(avPF4P}M#z*t~KlF~#5TT!&nu z>FAKF8vQl>Zm(G9UKi4kTqHj`Pf@Z@Q(bmZkseb1^;9k*`a9lKXceKX#dMd@ds`t| z2~UPsbn2R0D9Nm~G*oc@(%oYTD&yK)scA?36B7mndR9l*hNg!3?6>CR+tF1;6sr?V zzz8FBrZ@g4F_!O2igIGZcWd zRe_0*{d6cyy9QQ(|Ct~WTM1pC3({5qHahk*M*O}IPE6icikx48VZ?!0Oc^FVoq`}eu~ zpRq0MYHaBA-`b_BVID}|oo-bem76;B2zo7j7yz(9JiSY6JTjKz#+w{9mc{&#x}>E? zSS3mY$_|scfP3Mo_F5x;r>y&Mquy*Q1b3eF^*hg3tap~%?@ASeyodYa=dF&k=ZyWy z3C+&C95h|9TAVM~-8y(&xcy0nvl}6B*)j0FOlSz%+bK-}S4;F?P`j55*+ZO0Ogk7D z5q30zE@Nup4lqQoG`L%n{T?qn9&WC94%>J`KU{gHIq?n_L;75kkKyib;^?yXUx6BO zju%DyU(l!Vj(3stJ>!pMZ*NZFd60%oSAD1JUXG0~2GCXpB0Am(YPyhzQda-e)b^+f zzFaEZdVTJRJXPJo%w z$?T;xq^&(XjmO>0bNGsT|1{1UqGHHhasPC;H!oX52(AQ7h9*^npOIRdQbNrS0X5#5G?L4V}WsAYcpq-+JNXhSl)XbxZ)L@5Q+?wm{GAU z9a7X8hAjAo;4r_eOdZfXGL@YpmT|#qECEcPTQ;nsjIkQ;!0}g?T>Zr*Fg}%BZVA)4 zCAzvWr?M&)KEk`t9eyFi_GlPV9a2kj9G(JgiZadd_&Eb~#DyZ%2Zcvrda_A47G&uW z^6TnBK|th;wHSo8ivpScU?AM5HDu2+ayzExMJc@?4{h-c`!b($ExB`ro#vkl<;=BA z961c*n(4OR!ebT*7UV7sqL;rZ3+Z)BYs<1I|9F|TOKebtLPxahl|ZXxj4j!gjj!3*+iSb5Zni&EKVt$S{0?2>A}d@3PSF3LUu)5 z*Y#a1uD6Y!$=_ghsPrOqX!OcIP`IW};tZzx1)h_~mgl;0=n zdP|Te_7)~R?c9s>W(-d!@nzQyxqakrME{Tn@>0G)kqV<4;{Q?Z-M)E-|IFLTc}WQr z1Qt;u@_dN2kru_9HMtz8MQx1aDYINH&3<+|HA$D#sl3HZ&YsjfQBv~S>4=u z7gA2*X6_cI$2}JYLIq`4NeXTz6Q3zyE717#>RD&M?0Eb|KIyF;xj;+3#DhC-xOj~! z$-Kx#pQ)_$eHE3Zg?V>1z^A%3jW0JBnd@z`kt$p@lch?A9{j6hXxt$(3|b>SZiBxOjA%LsIPii{=o(B`yRJ>OK;z_ELTi8xHX)il z--qJ~RWsZ%9KCNuRNUypn~<2+mQ=O)kd59$Lul?1ev3c&Lq5=M#I{ zJby%%+Top_ocqv!jG6O6;r0Xwb%vL6SP{O(hUf@8riADSI<|y#g`D)`x^vHR4!&HY`#TQMqM`Su}2(C|KOmG`wyK>uh@3;(prdL{2^7T3XFGznp{-sNLLJH@mh* z^vIyicj9yH9(>~I-Ev7p=yndfh}l!;3Q65}K}()(jp|tC;{|Ln1a+2kbctWEX&>Vr zXp5=#pw)@-O6~Q|><8rd0>H-}0Nsc|J6TgCum{XnH2@hFB09FsoZ_ow^Nv@uGgz3# z<6dRDt1>>-!kN58&K1HFrgjTZ^q<>hNI#n8=hP&pKAL4uDcw*J66((I?!pE0fvY6N zu^N=X8lS}(=w$O_jlE(;M9F={-;4R(K5qa=P#ZVW>}J&s$d0?JG8DZJwZcx3{CjLg zJA>q-&=Ekous)vT9J>fbnZYNUtvox|!Rl@e^a6ue_4-_v=(sNB^I1EPtHCFEs!>kK6B@-MS!(B zST${=v9q6q8YdSwk4}@c6cm$`qZ86ipntH8G~51qIlsYQ)+2_Fg1@Y-ztI#aa~tFD_QUxb zU-?g5B}wU@`tnc_l+B^mRogRghXs!7JZS=A;In1|f(1T(+xfIi zvjccLF$`Pkv2w|c5BkSj>>k%`4o6#?ygojkV78%zzz`QFE6nh{(SSJ9NzVdq>^N>X zpg6+8u7i(S>c*i*cO}poo7c9%i^1o&3HmjY!s8Y$5aO(!>u1>-eai0;rK8hVzIh8b zL53WCXO3;=F4_%CxMKRN^;ggC$;YGFTtHtLmX%@MuMxvgn>396~ zEp>V(dbfYjBX^!8CSg>P2c5I~HItbe(dl^Ax#_ldvCh;D+g6-%WD|$@S6}Fvv*eHc zaKxji+OG|_KyMe2D*fhP<3VP0J1gTgs6JZjE{gZ{SO-ryEhh;W237Q0 z{yrDobsM6S`bPMUzr|lT|99m6XDI$RzW4tQ$|@C2RjhBYPliEXFV#M*5G4;Kb|J8E z0IH}-d^S-53kFRZ)ZFrd2%~Sth-6BN?hnMa_PC4gdWyW3q-xFw&L^x>j<^^S$y_3_ zdZxouw%6;^mg#jG@7L!g9Kdw}{w^X9>TOtHgxLLIbfEG^Qf;tD=AXozE6I`XmOF=# zGt$Wl+7L<8^VI-eSK%F%dqXieK^b!Z3yEA$KL}X@>fD9)g@=DGt|=d(9W%8@Y@!{PI@`Nd zyF?Us(0z{*u6|X?D`kKSa}}Q*HP%9BtDEA^buTlI5ihwe)CR%OR46b+>NakH3SDbZmB2X>c8na&$lk zYg$SzY+EXtq2~$Ep_x<~+YVl<-F&_fbayzTnf<7?Y-un3#+T~ahT+eW!l83sofNt; zZY`eKrGqOux)+RMLgGgsJdcA3I$!#zy!f<$zL0udm*?M5w=h$Boj*RUk8mDPVUC1RC8A`@7PgoBIU+xjB7 z25vky+^7k_|1n1&jKNZkBWUu1VCmS}a|6_+*;fdUZAaIR4G!wv=bAZEXBhcjch6WH zdKUr&>z^P%_LIx*M&x{!w|gij?nigT8)Ol3VicXRL0tU}{vp2fi!;QkVc#I38op3O z=q#WtNdN{x)OzmH;)j{cor)DQ;2%m>xMu_KmTisaeCC@~rQwQTfMml7FZ_ zU2AR8yCY_CT$&IAn3n#Acf*VKzJD8-aphMg(12O9cv^AvLQ9>;f!4mjyxq_a%YH2+{~=3TMNE1 z#r3@ynnZ#p?RCkPK36?o{ILiHq^N5`si(T_cKvO9r3^4pKG0AgDEB@_72(2rvU^-; z%&@st2+HjP%H)u50t81p>(McL{`dTq6u-{JM|d=G1&h-mtjc2{W0%*xuZVlJpUSP-1=U6@5Q#g(|nTVN0icr-sdD~DWR=s}`$#=Wa zt5?|$`5`=TWZevaY9J9fV#Wh~Fw@G~0vP?V#Pd=|nMpSmA>bs`j2e{)(827mU7rxM zJ@ku%Xqhq!H)It~yXm=)6XaPk=$Rpk*4i4*aSBZe+h*M%w6?3&0>>|>GHL>^e4zR!o%aGzUn40SR+TdN%=Dbn zsRfXzGcH#vjc-}7v6yRhl{V5PhE-r~)dnmNz=sDt?*1knNZ>xI5&vBwrosF#qRL-Y z;{W)4W&cO0XMKy?{^d`Xh(2B?j0ioji~G~p5NQJyD6vouyoFE9w@_R#SGZ1DR4GnN z{b=sJ^8>2mq3W;*u2HeCaKiCzK+yD!^i6QhTU5npwO+C~A#5spF?;iuOE>o&p3m1C zmT$_fH8v+5u^~q^ic#pQN_VYvU>6iv$tqx#Sulc%|S7f zshYrWq7IXCiGd~J(^5B1nGMV$)lo6FCTm1LshfcOrGc?HW7g>pV%#4lFbnt#94&Rg{%Zbg;Rh?deMeOP(du*)HryI zCdhO$3|SeaWK<>(jSi%qst${Z(q@{cYz7NA^QO}eZ$K@%YQ^Dt4CXzmvx~lLG{ef8 zyckIVSufk>9^e_O7*w2z>Q$8me4T~NQDq=&F}Ogo#v1u$0xJV~>YS%mLVYqEf~g*j zGkY#anOI9{(f4^v21OvYG<(u}UM!-k;ziH%GOVU1`$0VuO@Uw2N{$7&5MYjTE?Er) zr?oZAc~Xc==KZx-pmoh9KiF_JKU7u0#b_}!dWgC>^fmbVOjuiP2FMq5OD9+4TKg^2 z>y6s|sQhI`=fC<>BnQYV433-b+jBi+N6unz%6EQR%{8L#=4sktI>*3KhX+qAS>+K#}y5KnJ8YuOuzG(Ea5;$*1P$-9Z+V4guyJ#s) zRPH(JPN;Es;H72%c8}(U)CEN}Xm>HMn{n!d(=r*YP0qo*^APwwU5YTTeHKy#85Xj< zEboiH=$~uIVMPg!qbx~0S=g&LZ*IyTJG$hTN zv%2>XF``@S9lnLPC?|myt#P)%7?%e_j*aU4TbTyxO|3!h%=Udp;THL+^oPp<6;TLlIOa$&xeTG_a*dbRDy+(&n1T=MU z+|G5{2UprrhN^AqODLo$9Z2h(3^wtdVIoSk@}wPajVgIoZipRft}^L)2Y@mu;X-F{LUw|s7AQD-0!otW#W9M@A~08`o%W;Bq-SOQavG*e-sy8) zwtaucR0+64B&Pm++-m56MQ$@+t{_)7l-|`1kT~1s!swfc4D9chbawUt`RUOdoxU|j z$NE$4{Ysr@2Qu|K8pD37Yv&}>{_I5N49a@0<@rGHEs}t zwh_+9T0oh@ptMbjy*kbz<&3>LGR-GNsT8{x1g{!S&V7{5tPYX(GF>6qZh>O&F)%_I zkPE-pYo3dayjNQAG+xrI&yMZy590FA1unQ*k*Zfm#f9Z5GljOHBj-B83KNIP1a?<^1vOhDJkma0o- zs(TP=@e&s6fRrU(R}{7eHL*(AElZ&80>9;wqj{|1YQG=o2Le-m!UzUd?Xrn&qd8SJ0mmEYtW;t(;ncW_j6 zGWh4y|KMK^s+=p#%fWxjXo434N`MY<8W`tNH-aM6x{@o?D3GZM&+6t4V3I*3fZd{a z0&D}DI?AQl{W*?|*%M^D5{E>V%;=-r&uQ>*e)cqVY52|F{ptA*`!iS=VKS6y4iRP6 zKUA!qpElT5vZvN}U5k-IpeNOr6KF`-)lN1r^c@HnT#RlZbi(;yuvm9t-Noh5AfRxL@j5dU-X37(?S)hZhRDbf5cbhDO5nSX@WtApyp` zT$5IZ*4*)h8wShkPI45stQH2Y7yD*CX^Dh@B%1MJSEn@++D$AV^ttKXZdQMU`rxiR z+M#45Z2+{N#uR-hhS&HAMFK@lYBWOzU^Xs-BlqQDyN4HwRtP2$kks@UhAr@wlJii%Rq?qy25?Egs z*a&iAr^rbJWlv+pYAVUq9lor}#Cm|D$_ev2d2Ko}`8kuP(ljz$nv3OCDc7zQp|j6W zbS6949zRvj`bhbO(LN3}Pq=$Ld3a_*9r_24u_n)1)}-gRq?I6pdHPYHgIsn$#XQi~ z%&m_&nnO9BKy;G%e~fa7i9WH#MEDNQ8WCXhqqI+oeE5R7hLZT_?7RWVzEGZNz4*Po ze&*a<^Q*ze72}UM&$c%FuuEIN?EQ@mnILwyt;%wV-MV+|d%>=;3f0(P46;Hwo|Wr0 z>&FS9CCb{?+lDpJMs`95)C$oOQ}BSQEv0Dor%-Qj0@kqlIAm1-qSY3FCO2j$br7_w zlpRfAWz3>Gh~5`Uh?ER?@?r0cXjD0WnTx6^AOFii;oqM?|M9QjHd*GK3WwA}``?dK15`ZvG>_nB2pSTGc{n2hYT6QF^+&;(0c`{)*u*X7L_ zaxqyvVm$^VX!0YdpSNS~reC+(uRqF2o>jqIJQkC&X>r8|mBHvLaduM^Mh|OI60<;G zDHx@&jUfV>cYj5+fAqvv(XSmc(nd@WhIDvpj~C#jhZ6@M3cWF2HywB1yJv2#=qoY| zIiaxLsSQa7w;4YE?7y&U&e6Yp+2m(sb5q4AZkKtey{904rT08pJpanm->Z75IdvW^ z!kVBy|CIUZn)G}92_MgoLgHa?LZJDp_JTbAEq8>6a2&uKPF&G!;?xQ*+{TmNB1H)_ z-~m@CTxDry_-rOM2xwJg{fcZ41YQDh{DeI$4!m8c;6XtFkFyf`fOsREJ`q+Bf4nS~ zKDYs4AE7Gugv?X)tu4<-M8ag{`4pfQ14z<(8MYQ4u*fl*DCpq66+Q1-gxNCQ!c$me zyTrmi7{W-MGP!&S-_qJ%9+e08_9`wWGG{i5yLJ;8qbt-n_0*Q371<^u@tdz|;>fPW zE=&q~;wVD_4IQ^^jyYX;2shIMiYdvIpIYRT>&I@^{kL9Ka2ECG>^l>Ae!GTn{r~o= z|I9=J#wNe)zYRqGZ7Q->L{dfewyC$ZYcLaoNormZ3*gfM=da*{heC)&46{yTS!t10 zn_o0qUbQOs$>YuY>YHi|NG^NQG<_@jD&WnZcW^NTC#mhVE7rXlZ=2>mZkx{bc=~+2 z{zVH=Xs0`*K9QAgq9cOtfQ^BHh-yr=qX8hmW*0~uCup89IJMvWy%#yt_nz@6dTS)L{O3vXye< zW4zUNb6d|Tx`XIVwMMgqnyk?c;Kv`#%F0m^<$9X!@}rI##T{iXFC?(ui{;>_9Din8 z7;(754q!Jx(~sb!6+6Lf*l{fqD7GW*v{>3wp+)@wq2abADBK!kI8To}7zooF%}g-z zJ1-1lp-lQI6w^bov9EfhpxRI}`$PTpJI3uo@ZAV729JJ2Hs68{r$C0U=!d$Bm+s(p z8Kgc(Ixf4KrN%_jjJjTx5`&`Ak*Il%!}D_V)GM1WF!k$rDJ-SudXd_Xhl#NWnET&e-P!rH~*nNZTzxj$?^oo3VWc-Ay^`Phze3(Ft!aNW-f_ zeMy&BfNCP^-FvFzR&rh!w(pP5;z1$MsY9Voozmpa&A}>|a{eu}>^2s)So>&kmi#7$ zJS_-DVT3Yi(z+ruKbffNu`c}s`Uo`ORtNpUHa6Q&@a%I%I;lm@ea+IbCLK)IQ~)JY zp`kdQ>R#J*i&Ljer3uz$m2&Un9?W=Ue|hHv?xlM`I&*-M;2{@so--0OAiraN1TLra z>EYQu#)Q@UszfJj&?kr%RraFyi*eG+HD_(!AWB;hPgB5Gd-#VDRxxv*VWMY0hI|t- zR=;TL%EKEg*oet7GtmkM zgH^y*1bfJ*af(_*S1^PWqBVVbejFU&#m`_69IwO!aRW>Rcp~+7w^ptyu>}WFYUf;) zZrgs;EIN9$Immu`$umY%$I)5INSb}aV-GDmPp!d_g_>Ar(^GcOY%2M)Vd7gY9llJR zLGm*MY+qLzQ+(Whs8-=ty2l)G9#82H*7!eo|B6B$q%ak6eCN%j?{SI9|K$u3)ORoz zw{bAGaWHrMb|X^!UL~_J{jO?l^}lI^|7jIn^p{n%JUq9{tC|{GM5Az3SrrPkuCt_W zq#u0JfDw{`wAq`tAJmq~sz`D_P-8qr>kmms>I|);7Tn zLl^n*Ga7l=U)bQmgnSo5r_&#Pc=eXm~W75X9Cyy0WDO|fbSn5 zLgpFAF4fa90T-KyR4%%iOq6$6BNs@3ZV<~B;7V=u zdlB8$lpe`w-LoS;0NXFFu@;^^bc?t@r3^XTe*+0;o2dt&>eMQeDit(SfDxYxuA$uS z**)HYK7j!vJVRNfrcokVc@&(ke5kJzvi};Lyl7@$!`~HM$T!`O`~MQ1k~ZH??fQr zNP)33uBWYnTntKRUT*5lu&8*{fv>syNgxVzEa=qcKQ86Vem%Lpae2LM=TvcJLs?`=o9%5Mh#k*_7zQD|U7;A%=xo^_4+nX{~b1NJ6@ z*=55;+!BIj1nI+)TA$fv-OvydVQB=KK zrGWLUS_Chm$&yoljugU=PLudtJ2+tM(xj|E>Nk?c{-RD$sGYNyE|i%yw>9gPItE{ zD|BS=M>V^#m8r?-3swQofD8j$h-xkg=F+KM%IvcnIvc)y zl?R%u48Jeq7E*26fqtLe_b=9NC_z|axW#$e0adI#r(Zsui)txQ&!}`;;Z%q?y2Kn! zXzFNe+g7+>>`9S0K1rmd)B_QVMD?syc3e0)X*y6(RYH#AEM9u?V^E0GHlAAR)E^4- zjKD+0K=JKtf5DxqXSQ!j?#2^ZcQoG5^^T+JaJa3GdFeqIkm&)dj76WaqGukR-*&`13ls8lU2ayVIR%;79HYAr5aEhtYa&0}l}eAw~qKjUyz4v*At z?})QplY`3cWB6rl7MI5mZx&#%I0^iJm3;+J9?RA(!JXjl?(XgmA-D#2cY-^?g1c*Q z3GVLh!8Jhe;QqecbMK#XIJxKMb=6dcs?1vbb?@ov-raj`hnYO92y8pv@>RVr=9Y-F zv`BK)9R6!m4Pfllu4uy0WBL+ZaUFFzbZZtI@J8{OoQ^wL-b$!FpGT)jYS-=vf~b-@ zIiWs7j~U2yI=G5;okQz%gh6}tckV5wN;QDbnu|5%%I(#)8Q#)wTq8YYt$#f9=id;D zJbC=CaLUyDIPNOiDcV9+=|$LE9v2;Qz;?L+lG{|g&iW9TI1k2_H;WmGH6L4tN1WL+ zYfSVWq(Z_~u~U=g!RkS|YYlWpKfZV!X%(^I3gpV%HZ_{QglPSy0q8V+WCC2opX&d@eG2BB#(5*H!JlUzl$DayI5_J-n zF@q*Fc-nlp%Yt;$A$i4CJ_N8vyM5fNN`N(CN53^f?rtya=p^MJem>JF2BEG|lW|E) zxf)|L|H3Oh7mo=9?P|Y~|6K`B3>T)Gw`0ESP9R`yKv}g|+qux(nPnU(kQ&&x_JcYg9+6`=; z-EI_wS~l{T3K~8}8K>%Ke`PY!kNt415_x?^3QOvX(QUpW&$LXKdeZM-pCI#%EZ@ta zv(q-(xXIwvV-6~(Jic?8<7ain4itN>7#AqKsR2y(MHMPeL)+f+v9o8Nu~p4ve*!d3 z{Lg*NRTZsi;!{QJknvtI&QtQM_9Cu%1QcD0f!Fz+UH4O#8=hvzS+^(e{iG|Kt7C#u zKYk7{LFc+9Il>d6)blAY-9nMd(Ff0;AKUo3B0_^J&ESV@4UP8PO0no7G6Gp_;Z;YnzW4T-mCE6ZfBy(Y zXOq^Of&?3#Ra?khzc7IJT3!%IKK8P(N$ST47Mr=Gv@4c!>?dQ-&uZihAL1R<_(#T8Y`Ih~soL6fi_hQmI%IJ5qN995<{<@_ z;^N8AGQE+?7#W~6X>p|t<4@aYC$-9R^}&&pLo+%Ykeo46-*Yc(%9>X>eZpb8(_p{6 zwZzYvbi%^F@)-}5%d_z^;sRDhjqIRVL3U3yK0{Q|6z!PxGp?|>!%i(!aQODnKUHsk^tpeB<0Qt7`ZBlzRIxZMWR+|+ z3A}zyRZ%0Ck~SNNov~mN{#niO**=qc(faGz`qM16H+s;Uf`OD1{?LlH!K!+&5xO%6 z5J80-41C{6)j8`nFvDaeSaCu_f`lB z_Y+|LdJX=YYhYP32M556^^Z9MU}ybL6NL15ZTV?kfCFfpt*Pw5FpHp#2|ccrz#zoO zhs=+jQI4fk*H0CpG?{fpaSCmXzU8bB`;kCLB8T{_3t>H&DWj0q0b9B+f$WG=e*89l zzUE)b9a#aWsEpgnJqjVQETpp~R7gn)CZd$1B8=F*tl+(iPH@s9jQtE33$dBDOOr=% ziOpR8R|1eLI?Rn*d+^;_U#d%bi$|#obe0(-HdB;K>=Y=mg{~jTA_WpChe8QquhF`N z>hJ}uV+pH`l_@d>%^KQNm*$QNJ(lufH>zv9M`f+C-y*;hAH(=h;kp@eL=qPBeXrAo zE7my75EYlFB30h9sdt*Poc9)2sNP9@K&4O7QVPQ^m$e>lqzz)IFJWpYrpJs)Fcq|P z5^(gnntu!+oujqGpqgY_o0V&HL72uOF#13i+ngg*YvPcqpk)Hoecl$dx>C4JE4DWp z-V%>N7P-}xWv%9Z73nn|6~^?w$5`V^xSQbZceV<_UMM&ijOoe{Y^<@3mLSq_alz8t zr>hXX;zTs&k*igKAen1t1{pj94zFB;AcqFwV)j#Q#Y8>hYF_&AZ?*ar1u%((E2EfZ zcRsy@s%C0({v=?8oP=DML`QsPgzw3|9|C22Y>;=|=LHSm7~+wQyI|;^WLG0_NSfrf zamq!5%EzdQ&6|aTP2>X=Z^Jl=w6VHEZ@=}n+@yeu^ke2Yurrkg9up3g$0SI8_O-WQu$bCsKc(juv|H;vz6}%7ONww zKF%!83W6zO%0X(1c#BM}2l^ddrAu^*`9g&1>P6m%x{gYRB)}U`40r>6YmWSH(|6Ic zH~QNgxlH*;4jHg;tJiKia;`$n_F9L~M{GiYW*sPmMq(s^OPOKm^sYbBK(BB9dOY`0 z{0!=03qe*Sf`rcp5Co=~pfQyqx|umPHj?a6;PUnO>EZGb!pE(YJgNr{j;s2+nNV(K zDi#@IJ|To~Zw)vqGnFwb2}7a2j%YNYxe2qxLk)VWJIux$BC^oII=xv-_}h@)Vkrg1kpKokCmX({u=lSR|u znu_fA0PhezjAW{#Gu0Mdhe8F4`!0K|lEy+<1v;$ijSP~A9w%q5-4Ft|(l7UqdtKao zs|6~~nmNYS>fc?Nc=yzcvWNp~B0sB5ForO5SsN(z=0uXxl&DQsg|Y?(zS)T|X``&8 z*|^p?~S!vk8 zg>$B{oW}%rYkgXepmz;iqCKY{R@%@1rcjuCt}%Mia@d8Vz5D@LOSCbM{%JU#cmIp! z^{4a<3m%-p@JZ~qg)Szb-S)k{jv92lqB(C&KL(jr?+#ES5=pUH$(;CO9#RvDdErmW z3(|f{_)dcmF-p*D%qUa^yYngNP&Dh2gq5hr4J!B5IrJ?ODsw@*!0p6Fm|(ebRT%l) z#)l22@;4b9RDHl1ys$M2qFc;4BCG-lp2CN?Ob~Be^2wQJ+#Yz}LP#8fmtR%o7DYzoo1%4g4D+=HonK7b!3nvL0f1=oQp93dPMTsrjZRI)HX-T}ApZ%B#B;`s? z9Kng{|G?yw7rxo(T<* z1+O`)GNRmXq3uc(4SLX?fPG{w*}xDCn=iYo2+;5~vhWUV#e5e=Yfn4BoS@3SrrvV9 zrM-dPU;%~+3&>(f3sr$Rcf4>@nUGG*vZ~qnxJznDz0irB(wcgtyATPd&gSuX^QK@+ z)7MGgxj!RZkRnMSS&ypR94FC$;_>?8*{Q110XDZ)L);&SA8n>72s1#?6gL>gydPs` zM4;ert4-PBGB@5E` zBaWT=CJUEYV^kV%@M#3(E8>g8Eg|PXg`D`;K8(u{?}W`23?JgtNcXkUxrH}@H_4qN zw_Pr@g%;CKkgP(`CG6VTIS4ZZ`C22{LO{tGi6+uPvvHkBFK|S6WO{zo1MeK$P zUBe}-)3d{55lM}mDVoU@oGtPQ+a<=wwDol}o=o1z*)-~N!6t09du$t~%MlhM9B5~r zy|zs^LmEF#yWpXZq!+Nt{M;bE%Q8z7L8QJDLie^5MKW|I1jo}p)YW(S#oLf(sWn~* zII>pocNM5#Z+-n2|495>?H?*oyr0!SJIl(}q-?r`Q;Jbqqr4*_G8I7agO298VUr9x z8ZcHdCMSK)ZO@Yr@c0P3{`#GVVdZ{zZ$WTO zuvO4ukug&& ze#AopTVY3$B>c3p8z^Yyo8eJ+(@FqyDWlR;uxy0JnSe`gevLF`+ZN6OltYr>oN(ZV z>76nIiVoll$rDNkck6_eh%po^u16tD)JXcii|#Nn(7=R9mA45jz>v}S%DeMc(%1h> zoT2BlF9OQ080gInWJ3)bO9j$ z`h6OqF0NL4D3Kz?PkE8nh;oxWqz?<3_!TlN_%qy*T7soZ>Pqik?hWWuya>T$55#G9 zxJv=G&=Tm4!|p1#!!hsf*uQe}zWTKJg`hkuj?ADST2MX6fl_HIDL7w`5Dw1Btays1 zz*aRwd&>4*H%Ji2bt-IQE$>sbCcI1Poble0wL`LAhedGRZp>%>X6J?>2F*j>`BX|P zMiO%!VFtr_OV!eodgp-WgcA-S=kMQ^zihVAZc!vdx*YikuDyZdHlpy@Y3i!r%JI85$-udM6|7*?VnJ!R)3Qfm4mMm~Z#cvNrGUy|i0u zb|(7WsYawjBK0u1>@lLhMn}@X>gyDlx|SMXQo|yzkg-!wIcqfGrA!|t<3NC2k` zq;po50dzvvHD>_mG~>W0iecTf@3-)<$PM5W@^yMcu@U;)(^eu@e4jAX7~6@XrSbIE zVG6v2miWY^g8bu5YH$c2QDdLkg2pU8xHnh`EUNT+g->Q8Tp4arax&1$?CH($1W&*} zW&)FQ>k5aCim$`Ph<9Zt?=%|pz&EX@_@$;3lQT~+;EoD(ho|^nSZDh*M0Z&&@9T+e zHYJ;xB*~UcF^*7a_T)9iV5}VTYKda8n*~PSy@>h7c(mH~2AH@qz{LMQCb+-enMhX} z2k0B1JQ+6`?Q3Lx&(*CBQOnLBcq;%&Nf<*$CX2<`8MS9c5zA!QEbUz1;|(Ua%CiuL zF2TZ>@t7NKQ->O#!;0s;`tf$veXYgq^SgG>2iU9tCm5&^&B_aXA{+fqKVQ*S9=58y zddWqy1lc$Y@VdB?E~_B5w#so`r552qhPR649;@bf63_V@wgb!>=ij=%ptnsq&zl8^ zQ|U^aWCRR3TnoKxj0m0QL2QHM%_LNJ(%x6aK?IGlO=TUoS%7YRcY{!j(oPcUq{HP=eR1>0o^(KFl-}WdxGRjsT);K8sGCkK0qVe{xI`# z@f+_kTYmLbOTxRv@wm2TNBKrl+&B>=VaZbc(H`WWLQhT=5rPtHf)#B$Q6m1f8We^)f6ylbO=t?6Y;{?&VL|j$VXyGV!v8eceRk zl>yOWPbk%^wv1t63Zd8X^Ck#12$*|yv`v{OA@2;-5Mj5sk#ptfzeX(PrCaFgn{3*hau`-a+nZhuJxO;Tis51VVeKAwFML#hF9g26NjfzLs8~RiM_MFl1mgDOU z=ywk!Qocatj1Q1yPNB|FW>!dwh=aJxgb~P%%7(Uydq&aSyi?&b@QCBiA8aP%!nY@c z&R|AF@8}p7o`&~>xq9C&X6%!FAsK8gGhnZ$TY06$7_s%r*o;3Y7?CenJUXo#V-Oag z)T$d-V-_O;H)VzTM&v8^Uk7hmR8v0)fMquWHs6?jXYl^pdM#dY?T5XpX z*J&pnyJ<^n-d<0@wm|)2SW9e73u8IvTbRx?Gqfy_$*LI_Ir9NZt#(2T+?^AorOv$j zcsk+t<#!Z!eC|>!x&#l%**sSAX~vFU0|S<;-ei}&j}BQ#ekRB-;c9~vPDIdL5r{~O zMiO3g0&m-O^gB}<$S#lCRxX@c3g}Yv*l)Hh+S^my28*fGImrl<-nbEpOw-BZ;WTHL zgHoq&ftG|~ouV<>grxRO6Z%{!O+j`Cw_4~BIzrjpkdA5jH40{1kDy|pEq#7`$^m*? zX@HxvW`e}$O$mJvm+65Oc4j7W@iVe)rF&-}R>KKz>rF&*Qi3%F0*tz!vNtl@m8L9= zyW3%|X}0KsW&!W<@tRNM-R>~~QHz?__kgnA(G`jWOMiEaFjLzCdRrqzKlP1vYLG`Y zh6_knD3=9$weMn4tBD|5=3a9{sOowXHu(z5y^RYrxJK z|L>TUvbDuO?3=YJ55N5}Kj0lC(PI*Te0>%eLNWLnawD54geX5>8AT(oT6dmAacj>o zC`Bgj-RV0m3Dl2N=w3e0>wWWG5!mcal`Xu<(1=2$b{k(;kC(2~+B}a(w;xaHPk^@V zGzDR|pt%?(1xwNxV!O6`JLCM!MnvpbLoHzKziegT_2LLWAi4}UHIo6uegj#WTQLet z9Dbjyr{8NAk+$(YCw~_@Az9N|iqsliRYtR7Q|#ONIV|BZ7VKcW$phH9`ZAlnMTW&9 zIBqXYuv*YY?g*cJRb(bXG}ts-t0*|HXId4fpnI>$9A?+BTy*FG8f8iRRKYRd*VF_$ zoo$qc+A(d#Lx0@`ck>tt5c$L1y7MWohMnZd$HX++I9sHoj5VXZRZkrq`v@t?dfvC} z>0h!c4HSb8%DyeF#zeU@rJL2uhZ^8dt(s+7FNHJeY!TZJtyViS>a$~XoPOhHsdRH* zwW+S*rIgW0qSPzE6w`P$Jv^5dsyT6zoby;@z=^yWLG^x;e557RnndY>ph!qCF;ov$ ztSW1h3@x{zm*IMRx|3lRWeI3znjpbS-0*IL4LwwkWyPF1CRpQK|s42dJ{ddA#BDDqio-Y+mF-XcP-z4bi zAhfXa2=>F0*b;F0ftEPm&O+exD~=W^qjtv&>|%(4q#H=wbA>7QorDK4X3~bqeeXv3 zV1Q<>_Fyo!$)fD`fd@(7(%6o-^x?&+s=)jjbQ2^XpgyYq6`}ISX#B?{I$a&cRcW?X zhx(i&HWq{=8pxlA2w~7521v-~lu1M>4wL~hDA-j(F2;9ICMg+6;Zx2G)ulp7j;^O_ zQJIRUWQam(*@?bYiRTKR<;l_Is^*frjr-Dj3(fuZtK{Sn8F;d*t*t{|_lnlJ#e=hx zT9?&_n?__2mN5CRQ}B1*w-2Ix_=CF@SdX-cPjdJN+u4d-N4ir*AJn&S(jCpTxiAms zzI5v(&#_#YrKR?B?d~ge1j*g<2yI1kp`Lx>8Qb;aq1$HOX4cpuN{2ti!2dXF#`AG{ zp<iD=Z#qN-yEwLwE7%8w8&LB<&6{WO$#MB-|?aEc@S1a zt%_p3OA|kE&Hs47Y8`bdbt_ua{-L??&}uW zmwE7X4Y%A2wp-WFYPP_F5uw^?&f zH%NCcbw_LKx!c!bMyOBrHDK1Wzzc5n7A7C)QrTj_Go#Kz7%+y^nONjnnM1o5Sw(0n zxU&@41(?-faq?qC^kO&H301%|F9U-Qm(EGd3}MYTFdO+SY8%fCMTPMU3}bY7ML1e8 zrdOF?E~1uT)v?UX(XUlEIUg3*UzuT^g@QAxEkMb#N#q0*;r zF6ACHP{ML*{Q{M;+^4I#5bh#c)xDGaIqWc#ka=0fh*_Hlu%wt1rBv$B z%80@8%MhIwa0Zw$1`D;Uj1Bq`lsdI^g_18yZ9XUz2-u6&{?Syd zHGEh-3~HH-vO<)_2^r|&$(q7wG{@Q~un=3)Nm``&2T99L(P+|aFtu1sTy+|gwL*{z z)WoC4rsxoWhz0H$rG|EwhDT z0zcOAod_k_Ql&Y`YV!#&Mjq{2ln|;LMuF$-G#jX_2~oNioTHb4GqFatn@?_KgsA7T z(ouy$cGKa!m}6$=C1Wmb;*O2p*@g?wi-}X`v|QA4bNDU*4(y8*jZy-Ku)S3iBN(0r ztfLyPLfEPqj6EV}xope=?b0Nyf*~vDz-H-Te@B`{ib?~F<*(MmG+8zoYS77$O*3vayg#1kkKN+Bu9J9;Soev<%2S&J zr8*_PKV4|?RVfb#SfNQ;TZC$8*9~@GR%xFl1 z3MD?%`1PxxupvVO>2w#8*zV<-!m&Lis&B>)pHahPQ@I_;rY~Z$1+!4V1jde&L8y0! zha7@F+rOENF{~0$+a~oId0R|_!PhO=8)$>LcO)ca6YeOQs?ZG;`4O`x=Pd??Bl?Qf zgkaNj7X5@3_==zlQ-u6?omteA!_e-6gfDtw6CBnP2o1wo-7U!Y@89rU1HFb|bIr!I z=qIz=AW(}L^m z=I9RiS{DRtTYS6jsnvt1zs)W;kSVFOK|WMyZ@dxs+8{*W9-aTmS79J4R{Cis>EIqS zw+~gJqwz)(!z>)KDyhS{lM*xQ-8mNvo$A=IwGu+iS564tgX`|MeEuis!aN-=7!L&e zhNs;g1MBqDyx{y@AI&{_)+-?EEg|5C*!=OgD#$>HklRVU+R``HYZZq5{F9C0KKo!d z$bE2XC(G=I^YUxYST+Hk>0T;JP_iAvCObcrPV1Eau865w6d^Wh&B?^#h2@J#!M2xp zLGAxB^i}4D2^?RayxFqBgnZ-t`j+~zVqr+9Cz9Rqe%1a)c*keP#r54AaR2*TH^}7j zmJ48DN);^{7+5|+GmbvY2v#qJy>?$B(lRlS#kyodlxA&Qj#9-y4s&|eq$5} zgI;4u$cZWKWj`VU%UY#SH2M$8?PjO-B-rNPMr=8d=-D(iLW#{RWJ}@5#Z#EK=2(&LvfW&{P4_jsDr^^rg9w#B7h`mBwdL9y)Ni;= zd$jFDxnW7n-&ptjnk#<0zmNNt{;_30vbQW!5CQ7SuEjR1be!vxvO53!30iOermrU1 zXhXaen8=4Q(574KO_h$e$^1khO&tQL59=)Dc^8iPxz8+tC3`G$w|yUzkGd%Wg4(3u zJ<&7r^HAaEfG?F8?2I64j4kPpsNQk7qBJa9_hFT;*j;A%H%;QI@QWqJaiOl=;u>G8 zG`5Ow4K5ifd=OS|7F;EFc1+GzLld0RCQxG>Fn?~5Wl5VHJ=$DeR-2zwBgzSrQsGG0 zBqrILuB+_SgLxh~S~^QNHWW(2P;Z?d!Rd1lnEM=z23xPzyrbO_L0k43zruDkrJO*D zlzN(peBMLji`xfgYUirul-7c#3t(*=x6A^KSU-L|$(0pp9A*43#=Q!cu%9ZHP!$J| zSk8k=Z8cl811Vvn(4p8xx+EdKQV(sjC4_mEvlWeuIfwEVcF2LiC{H!oW)LSW=0ul| zT?$5PCc(pf-zKzUH`p7I7coVvCK;Dv-3_c?%~bPz`#ehbfrSrFf{RAz0I5e*W1S)kTW{0gf5X2v2k=S=W{>pr44tQ?o` zih8gE29VGR_SL~YJtcA)lRLozPg!<3Mh(`Hp)5{bclb)reTScXzJ>7{?i^yR@{(^% z#=$BYXPIX%fhgsofP-T`3b<5#V(TTS)^$vlhV&Kn=(LXOTAADIR1v8UqmW5c`n`S% zC8SOW$e?>&0dwKD%Jt{+67PfCLnqX0{8K^(q_^^2#puPYPkJsyXWMa~?V?p5{flYi z-1!uqI2x%puPG)r7b8y+Pc0Z5C%aA6`Q1_?W9k!YbiVVJVJwGLL?)P0M&vo{^IgEE zrX3eTgrJl_AeXYmiciYX9OP?NPN%-7Ji%z3U`-iXX=T~OI0M=ek|5IvIsvXM$%S&v zKw{`Kj(JVc+Pp^?vLKEyoycfnk)Hd>et78P^Z*{#rBY~_>V7>{gtB$0G99nbNBt+r zyXvEg_2=#jjK+YX1A>cj5NsFz9rjB_LB%hhx4-2I73gr~CW_5pD=H|e`?#CQ2)p4& z^v?Dlxm-_j6bO5~eeYFZGjW3@AGkIxY=XB*{*ciH#mjQ`dgppNk4&AbaRYKKY-1CT z>)>?+ME)AcCM7RRZQsH5)db7y!&jY-qHp%Ex9N|wKbN$!86i>_LzaD=f4JFc6Dp(a z%z>%=q(sXlJ=w$y^|tcTy@j%AP`v1n0oAt&XC|1kA`|#jsW(gwI0vi3a_QtKcL+yh z1Y=`IRzhiUvKeZXH6>>TDej)?t_V8Z7;WrZ_7@?Z=HRhtXY+{hlY?x|;7=1L($?t3 z6R$8cmez~LXopZ^mH9=^tEeAhJV!rGGOK@sN_Zc-vmEr;=&?OBEN)8aI4G&g&gdOb zfRLZ~dVk3194pd;=W|Z*R|t{}Evk&jw?JzVERk%JNBXbMDX82q~|bv%!2%wFP9;~-H?={C1sZ( zuDvY5?M8gGX*DyN?nru)UvdL|Rr&mXzgZ;H<^KYvzIlet!aeFM@I?JduKj=!(+ zM7`37KYhd*^MrKID^Y1}*sZ#6akDBJyKna%xK%vLlBqzDxjQ3}jx8PBOmXkvf@B{@ zc#J;~wQ<6{B;``j+B!#7s$zONYdXunbuKvl@zvaWq;`v2&iCNF2=V9Kl|77-mpCp= z2$SxhcN=pZ?V{GW;t6s)?-cNPAyTi&8O0QMGo#DcdRl#+px!h3ayc*(VOGR95*Anj zL0YaiVN2mifzZ){X+fl`Z^P=_(W@=*cIe~BJd&n@HD@;lRmu8cx7K8}wPbIK)GjF> zQGQ2h#21o6b2FZI1sPl}9_(~R|2lE^h}UyM5A0bJQk2~Vj*O)l-4WC4$KZ>nVZS|d zZv?`~2{uPYkc?254B9**q6tS|>We?uJ&wK3KIww|zzSuj>ncI4D~K z1Y6irVFE{?D-|R{!rLhZxAhs+Ka9*-(ltIUgC;snNek4_5xhO}@+r9Sl*5=7ztnXO zAVZLm$Kdh&rqEtdxxrE9hw`aXW1&sTE%aJ%3VL3*<7oWyz|--A^qvV3!FHBu9B-Jj z4itF)3dufc&2%V_pZsjUnN=;s2B9<^Zc83>tzo)a_Q$!B9jTjS->%_h`ZtQPz@{@z z5xg~s*cz`Tj!ls3-hxgnX}LDGQp$t7#d3E}>HtLa12z&06$xEQfu#k=(4h{+p%aCg zzeudlLc$=MVT+|43#CXUtRR%h5nMchy}EJ;n7oHfTq6wN6PoalAy+S~2l}wK;qg9o zcf#dX>ke;z^13l%bwm4tZcU1RTXnDhf$K3q-cK576+TCwgHl&?9w>>_(1Gxt@jXln zt3-Qxo3ITr&sw1wP%}B>J$Jy>^-SpO#3e=7iZrXCa2!N69GDlD{97|S*og)3hG)Lk zuqxK|PkkhxV$FP45%z*1Z?(LVy+ruMkZx|(@1R(0CoS6`7FWfr4-diailmq&Q#ehn zc)b&*&Ub;7HRtFVjL%((d$)M=^6BV@Kiusmnr1_2&&aEGBpbK7OWs;+(`tRLF8x?n zfKJB3tB^F~N`_ak3^exe_3{=aP)3tuuK2a-IriHcWv&+u7p z_yXsd6kyLV@k=(QoSs=NRiKNYZ>%4wAF;2#iu1p^!6>MZUPd;=2LY~l2ydrx10b#OSAlltILY%OKTp{e{ zzNogSk~SJBqi<_wRa#JqBW8Ok=6vb%?#H(hG}Dv98{JST5^SSh>_GQ@UK-0J`6l#E za}X#ud0W?cp-NQE@jAx>NUv65U~%YYS%BC0Cr$5|2_A)0tW;(nqoGJUHG5R`!-{1M-4T{<^pOE!Dvyuu1x7?Wt#YIgq zA$Vwj`St+M#ZxJXXGkepIF6`xL&XPu^qiFlZcX+@fOAdQ9d(h{^xCiAWJ0Ixp~3&E z(WwdT$O$7ez?pw>Jf{`!T-205_zJv+y~$w@XmQ;CiL8d*-x_z~0@vo4|3xUermJ;Q z9KgxjkN8Vh)xZ2xhX0N@{~@^d@BLoYFW%Uys83=`15+YZ%KecmWXjVV2}YbjBonSh zVOwOfI7^gvlC~Pq$QDHMQ6_Pd10OV{q_Zai^Yg({5XysuT`3}~3K*8u>a2FLBQ%#_YT6$4&6(?ZGwDE*C-p8>bM?hj*XOIoj@C!L5) zH1y!~wZ^dX5N&xExrKV>rEJJjkJDq*$K>qMi`Lrq08l4bQW~!Fbxb>m4qMHu6weTiV6_9(a*mZ23kr9AM#gCGE zBXg8#m8{ad@214=#w0>ylE7qL$4`xm!**E@pw484-VddzN}DK2qg&W~?%hcv3lNHx zg(CE<2)N=p!7->aJ4=1*eB%fbAGJcY65f3=cKF4WOoCgVelH$qh0NpIka5J-6+sY* zBg<5!R=I*5hk*CR@$rY6a8M%yX%o@D%{q1Jn=8wAZ;;}ol>xFv5nXvjFggCQ_>N2} zXHiC~pCFG*oEy!h_sqF$^NJIpQzXhtRU`LR0yU;MqrYUG0#iFW4mbHe)zN&4*Wf)G zV6(WGOq~OpEoq##E{rC?!)8ygAaAaA0^`<8kXmf%uIFfNHAE|{AuZd!HW9C^4$xW; zmIcO#ti!~)YlIU4sH(h&s6}PH-wSGtDOZ+%H2gAO(%2Ppdec9IMViuwwWW)qnqblH9xe1cPQ@C zS4W|atjGDGKKQAQlPUVUi1OvGC*Gh2i&gkh0up%u-9ECa7(Iw}k~0>r*WciZyRC%l z7NX3)9WBXK{mS|=IK5mxc{M}IrjOxBMzFbK59VI9k8Yr$V4X_^wI#R^~RFcme2)l!%kvUa zJ{zpM;;=mz&>jLvON5j>*cOVt1$0LWiV>x)g)KKZnhn=%1|2E|TWNfRQ&n?vZxQh* zG+YEIf33h%!tyVBPj>|K!EB{JZU{+k`N9c@x_wxD7z~eFVw%AyU9htoH6hmo0`%kb z55c#c80D%0^*6y|9xdLG$n4Hn%62KIp`Md9Jhyp8)%wkB8<%RlPEwC&FL z;hrH(yRr(Ke$%TZ09J=gGMC3L?bR2F4ZU!}pu)*8@l(d9{v^^(j>y+GF*nGran5*M z{pl5ig0CVsG1etMB8qlF4MDFRkLAg4N=l{Sc*F>K_^AZQc{dSXkvonBI)qEN1*U&? zKqMr?Wu)q9c>U~CZUG+-ImNrU#c`bS?RpvVgWXqSsOJrCK#HNIJ+k_1Iq^QNr(j|~ z-rz67Lf?}jj^9Ik@VIMBU2tN{Ts>-O%5f?=T^LGl-?iC%vfx{}PaoP7#^EH{6HP!( zG%3S1oaiR;OmlKhLy@yLNns`9K?60Zg7~NyT0JF(!$jPrm^m_?rxt~|J2)*P6tdTU z25JT~k4RH9b_1H3-y?X4=;6mrBxu$6lsb@xddPGKA*6O`Cc^>Ul`f9c&$SHFhHN!* zjj=(Jb`P}R%5X@cC%+1ICCRh1^G&u548#+3NpYTVr54^SbFhjTuO-yf&s%r4VIU!lE!j(JzHSc9zRD_fw@CP0pkL(WX6 zn+}LarmQP9ZGF9So^+jr<(LGLlOxGiCsI^SnuC{xE$S;DA+|z+cUk=j^0ipB(WTZ} zR0osv{abBd)HOjc(SAV&pcP@37SLnsbtADj?bT#cPZq|?W1Ar;4Vg5m!l{@{TA~|g zXYOeU`#h-rT@(#msh%%kH>D=`aN}2Rysez?E@R6|@SB(_gS0}HC>83pE`obNA9vsH zSu^r>6W-FSxJA}?oTuH>-y9!pQg|*<7J$09tH=nq4GTx+5($$+IGlO^bptmxy#=)e zuz^beIPpUB_YK^?eb@gu(D%pJJwj3QUk6<3>S>RN^0iO|DbTZNheFX?-jskc5}Nho zf&1GCbE^maIL$?i=nXwi)^?NiK`Khb6A*kmen^*(BI%Kw&Uv4H;<3ib-2UwG{7M&* zn$qyi8wD9cKOuxWhRmFupwLuFn!G5Vj6PZ#GCNJLlTQuQ?bqAYd7Eva5YR~OBbIim zf(6yXS4pei1Bz4w4rrB6Ke~gKYErlC=l9sm*Zp_vwJe7<+N&PaZe|~kYVO%uChefr%G4-=0eSPS{HNf=vB;p~ z5b9O1R?WirAZqcdRn9wtct>$FU2T8p=fSp;E^P~zR!^C!)WHe=9N$5@DHk6(L|7s@ zcXQ6NM9Q~fan1q-u8{ez;RADoIqwkf4|6LfsMZK6h{ZUGYo>vD%JpY<@w;oIN-*sK zxp4@+d{zxe>Z-pH#_)%|d(AC`fa!@Jq)5K8hd71!;CEG|ZI{I2XI`X~n|ae;B!q{I zJDa#T+fRviR&wAN^Sl{z8Ar1LQOF&$rDs18h0{yMh^pZ#hG?c5OL8v07qRZ-Lj5(0 zjFY(S4La&`3IjOT%Jqx4z~08($iVS;M10d@q~*H=Py)xnKt(+G-*o33c7S3bJ8cmwgj45` zU|b7xCoozC!-7CPOR194J-m9N*g`30ToBo!Io?m>T)S{CusNZx0J^Hu6hOmvv;0~W zFHRYJgyRhP1sM_AQ%pkD!X-dPu_>)`8HunR4_v$4T78~R<})-@K2LBt03PBLnjHzuYY)AK?>0TJe9 zmmOjwSL%CTaLYvYlJ~|w?vc*R+$@vEAYghtgGhZ2LyF+UdOn+v^yvD9R%xbU$fUjK{{VQ4VL&&UqAFa>CZuX4kX zJ)njewLWfKXneB+r}Y$`ezzwDoRT3r{9(@=I3-z>8tT)n3whDyi(r*lAnxQJefj_x z-8lc=r!Vua{b}v;LT)oXW>~6Q03~RAp~R}TZq9sGbeUBMS)?ZrJqiu|E&ZE)uN1uL zXcAj3#aEz zzbcCF)+;Hia#OGBvOatkPQfE{*RtBlO1QFVhi+3q0HeuFa*p+Dj)#8Mq9yGtIx%0A znV5EmN(j!&b%kNz4`Vr-)mX_?$ng&M^a6loFO(G3SA!~eBUEY!{~>C|Ht1Q4cw)X5~dPiEYQJNg?B2&P>bU7N(#e5cr8qc7A{a7J9cdMcRx)N|?;$L~O|E)p~ zIC}oi3iLZKb>|@=ApsDAfa_<$0Nm<3nOPdr+8Y@dnb|u2S<7CUmTGKd{G57JR*JTo zb&?qrusnu}jb0oKHTzh42P00C{i^`v+g=n|Q6)iINjWk4mydBo zf0g=ikV*+~{rIUr%MXdz|9ebUP)<@zR8fgeR_rChk0<^^3^?rfr;-A=x3M?*8|RPz z@}DOF`aXXuZGih9PyAbp|DULSw8PJ`54io)ga6JG@Hgg@_Zo>OfJ)8+TIfgqu%877 z@aFykK*+|%@rSs-t*oAzH6Whyr=TpuQ}B0ptSsMg9p8@ZE5A6LfMk1qdsf8T^zkdC3rUhB$`s zBdanX%L3tF7*YZ4^A8MvOvhfr&B)QOWCLJ^02kw5;P%n~5e`sa6MG{E2N^*2ZX@ge zI2>ve##O?I}sWX)UqK^_bRz@;5HWp5{ziyg?QuEjXfMP!j zpr(McSAQz>ME?M-3NSoCn$91#_iNnULp6tD0NN7Z0s#G~-~xWZFWN-%KUVi^yz~-` zn;AeGvjLJ~{1p#^?$>zM4vu=3mjBI$(_tC~NC0o@6<{zS_*3nGfUsHr3Gdgn%XedF zQUP=j5Mb>9=#f7aPl;cm$=I0u*WP}aVE!lCYw2Ht{Z_j9mp1h>dHGKkEZP6f^6O@J zndJ2+rWjxp|3#<2oO=8v!oHMX{|Vb|^G~pU_A6=ckBQvt>o+dpgYy(D=VCj65GE&jJj{&-*iq?z)PHNee&-@Mie~#LD*={ex8h(-)<@|55 zUr(}L?mz#;d|mrD%zrh<-*=;5*7K$B`zPjJ%m2pwr*G6tf8tN%a

_x$+l{{cH8$W#CT diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1d5b29f..e750102 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip diff --git a/gradlew b/gradlew index cccdd3d..c53aefa 100644 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/main/java/elucent/eidolon/ClientConfig.java b/src/main/java/elucent/eidolon/ClientConfig.java index e6d3218..2b44c86 100644 --- a/src/main/java/elucent/eidolon/ClientConfig.java +++ b/src/main/java/elucent/eidolon/ClientConfig.java @@ -1,8 +1,9 @@ package elucent.eidolon; -import net.minecraftforge.common.ForgeConfigSpec; import org.apache.commons.lang3.tuple.Pair; +import net.minecraftforge.common.ForgeConfigSpec; + public class ClientConfig { // graphics public static ForgeConfigSpec.ConfigValue BETTER_LAYERING; diff --git a/src/main/java/elucent/eidolon/ClientEvents.java b/src/main/java/elucent/eidolon/ClientEvents.java index c61d129..3b7bc07 100644 --- a/src/main/java/elucent/eidolon/ClientEvents.java +++ b/src/main/java/elucent/eidolon/ClientEvents.java @@ -1,57 +1,67 @@ package elucent.eidolon; +import java.util.HashMap; +import java.util.Map; + import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.IRenderTypeBuffer; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.math.Matrix4f; + +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.client.event.RenderLevelLastEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import java.util.HashMap; -import java.util.Map; - public class ClientEvents { @OnlyIn(Dist.CLIENT) - static IRenderTypeBuffer.Impl DELAYED_RENDER = null; + static MultiBufferSource.BufferSource DELAYED_RENDER = null; @OnlyIn(Dist.CLIENT) - public static IRenderTypeBuffer.Impl getDelayedRender() { + public static MultiBufferSource.BufferSource getDelayedRender() { if (DELAYED_RENDER == null) { Map buffers = new HashMap<>(); for (RenderType type : new RenderType[]{ + RenderUtil.VAPOR_TRANSLUCENT, RenderUtil.DELAYED_PARTICLE, RenderUtil.GLOWING_PARTICLE, RenderUtil.GLOWING_BLOCK_PARTICLE, RenderUtil.GLOWING, RenderUtil.GLOWING_SPRITE}) { - buffers.put(type, new BufferBuilder(type.getBufferSize())); + buffers.put(type, new BufferBuilder(type.bufferSize())); } - DELAYED_RENDER = IRenderTypeBuffer.getImpl(buffers, new BufferBuilder(256)); + DELAYED_RENDER = MultiBufferSource.immediateWithBuffers(buffers, new BufferBuilder(256)); } return DELAYED_RENDER; } @OnlyIn(Dist.CLIENT) static float clientTicks = 0; + + @OnlyIn(Dist.CLIENT) + public static Matrix4f particleMVMatrix = null; @OnlyIn(Dist.CLIENT) @SubscribeEvent - public void onRenderLast(RenderWorldLastEvent event) { + public void onRenderLast(RenderLevelLastEvent event) { if (ClientConfig.BETTER_LAYERING.get()) { - RenderSystem.pushMatrix(); // this feels...cheaty - RenderSystem.multMatrix(event.getMatrixStack().getLast().getMatrix()); - getDelayedRender().finish(RenderUtil.DELAYED_PARTICLE); - getDelayedRender().finish(RenderUtil.GLOWING_PARTICLE); - getDelayedRender().finish(RenderUtil.GLOWING_BLOCK_PARTICLE); - RenderSystem.popMatrix(); - - getDelayedRender().finish(RenderUtil.GLOWING_SPRITE); - getDelayedRender().finish(RenderUtil.GLOWING); + RenderSystem.getModelViewStack().pushPose(); // this feels...cheaty + RenderSystem.getModelViewStack().setIdentity(); + if (particleMVMatrix != null) RenderSystem.getModelViewStack().mulPoseMatrix(particleMVMatrix); + RenderSystem.applyModelViewMatrix(); + getDelayedRender().endBatch(RenderUtil.DELAYED_PARTICLE); + getDelayedRender().endBatch(RenderUtil.GLOWING_PARTICLE); + getDelayedRender().endBatch(RenderUtil.GLOWING_BLOCK_PARTICLE); + RenderSystem.getModelViewStack().popPose(); + RenderSystem.applyModelViewMatrix(); + + getDelayedRender().endBatch(RenderUtil.GLOWING_SPRITE); + getDelayedRender().endBatch(RenderUtil.GLOWING); } - clientTicks += event.getPartialTicks(); + clientTicks += event.getPartialTick(); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/elucent/eidolon/Config.java b/src/main/java/elucent/eidolon/Config.java index 27ff749..198a448 100644 --- a/src/main/java/elucent/eidolon/Config.java +++ b/src/main/java/elucent/eidolon/Config.java @@ -1,17 +1,20 @@ package elucent.eidolon; +import org.apache.commons.lang3.tuple.Pair; + import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; -import org.apache.commons.lang3.tuple.Pair; public class Config { // mobs - public static ConfigValue WRAITH_SPAWN_WEIGHT, ZOMBIE_BRUTE_SPAWN_WEIGHT; + public static ConfigValue WRAITH_SPAWN_WEIGHT, ZOMBIE_BRUTE_SPAWN_WEIGHT, RAVEN_SPAWN_WEIGHT; // world public static ConfigValue LEAD_MIN_Y, LEAD_MAX_Y, LEAD_VEIN_SIZE, LEAD_VEIN_COUNT; + public static ConfigValue SILVER_MIN_Y, SILVER_MAX_Y, SILVER_VEIN_SIZE, SILVER_VEIN_COUNT; public static ConfigValue LAB_RARITY, STRAY_TOWER_RARITY, CATACOMB_RARITY; - public static ConfigValue LEAD_ENABLED, LAB_ENABLED, STRAY_TOWER_ENABLED, CATACOMB_ENABLED; + public static ConfigValue LEAD_ENABLED, SILVER_ENABLED, + LAB_ENABLED, STRAY_TOWER_ENABLED, CATACOMB_ENABLED; public Config(ForgeConfigSpec.Builder builder) { builder.comment("Mob settings").push("mobs"); @@ -19,19 +22,31 @@ public Config(ForgeConfigSpec.Builder builder) { .defineInRange("wraithSpawnWeight", 40, 0, 1000); ZOMBIE_BRUTE_SPAWN_WEIGHT = builder.comment("Spawn weight for zombie brute entity. Set to zero to disable spawning.") .defineInRange("zombieBruteSpawnWeight", 40, 0, 1000); + RAVEN_SPAWN_WEIGHT = builder.comment("Spawn weight for raven entity. Set to zero to disable spawning.") + .defineInRange("ravenSpawnWeight", 6, 0, 1000); builder.pop(); builder.comment("World generation settings").push("world"); LEAD_ENABLED = builder.comment("Whether lead ore is enabled. Set to false to disable spawning.") .define("leadEnabled", true); LEAD_MIN_Y = builder.comment("Minimum Y value for lead ore veins") - .defineInRange("leadOreMinY", 0, 0, 254); + .defineInRange("leadOreMinY", -27, 0, 254); LEAD_MAX_Y = builder.comment("Maximum Y value for lead ore veins") .defineInRange("leadOreMaxY", 41, 1, 255); LEAD_VEIN_SIZE = builder.comment("Maximum number of blocks per lead ore vein") .defineInRange("leadOreVeinSize", 6, 1, 255); LEAD_VEIN_COUNT = builder.comment("Number of lead ore veins per chunk") .defineInRange("leadOreVeinCount", 6, 0, 255); + SILVER_ENABLED = builder.comment("Whether silver ore is enabled. Set to false to disable spawning.") + .define("silverEnabled", true); + SILVER_MIN_Y = builder.comment("Minimum Y value for silver ore veins") + .defineInRange("silverOreMinY", -60, 0, 254); + SILVER_MAX_Y = builder.comment("Maximum Y value for silver ore veins") + .defineInRange("silverOreMaxY", 33, 1, 255); + SILVER_VEIN_SIZE = builder.comment("Maximum number of blocks per silver ore vein") + .defineInRange("silverOreVeinSize", 6, 1, 255); + SILVER_VEIN_COUNT = builder.comment("Number of silver ore veins per chunk") + .defineInRange("silverOreVeinCount", 5, 0, 255); LAB_ENABLED = builder.comment("Whether the lab structure is enabled. Set to false to disable spawning.") .define("labEnabled", true); LAB_RARITY = builder.comment("Rarity of the lab structure. Higher numbers mean rarer structures.") diff --git a/src/main/java/elucent/eidolon/Eidolon.java b/src/main/java/elucent/eidolon/Eidolon.java index 09886f2..fbdddab 100644 --- a/src/main/java/elucent/eidolon/Eidolon.java +++ b/src/main/java/elucent/eidolon/Eidolon.java @@ -1,51 +1,67 @@ package elucent.eidolon; -import com.google.common.collect.Lists; -import elucent.eidolon.capability.*; +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.capability.KnowledgeImpl; +import elucent.eidolon.capability.ReputationImpl; import elucent.eidolon.codex.CodexChapters; -import elucent.eidolon.entity.*; +import elucent.eidolon.deity.RegisterDeitiesEvent; +import elucent.eidolon.entity.AngelArrowRenderer; +import elucent.eidolon.entity.NecromancerEntity; +import elucent.eidolon.entity.NecromancerModel; +import elucent.eidolon.entity.NecromancerRenderer; +import elucent.eidolon.entity.RavenEntity; +import elucent.eidolon.entity.RavenModel; +import elucent.eidolon.entity.RavenRenderer; +import elucent.eidolon.entity.WraithEntity; +import elucent.eidolon.entity.WraithModel; +import elucent.eidolon.entity.WraithRenderer; +import elucent.eidolon.entity.ZombieBruteEntity; +import elucent.eidolon.entity.ZombieBruteModel; +import elucent.eidolon.entity.ZombieBruteRenderer; import elucent.eidolon.gui.SoulEnchanterScreen; import elucent.eidolon.gui.WoodenBrewingStandScreen; import elucent.eidolon.gui.WorktableScreen; +import elucent.eidolon.item.AthameItem; import elucent.eidolon.network.Networking; import elucent.eidolon.proxy.ClientProxy; import elucent.eidolon.proxy.ISidedProxy; import elucent.eidolon.proxy.ServerProxy; +import elucent.eidolon.reagent.RegisterReagentsEvent; import elucent.eidolon.recipe.CrucibleRegistry; -import elucent.eidolon.recipe.WorktableRegistry; import elucent.eidolon.ritual.RitualRegistry; import elucent.eidolon.spell.AltarEntries; -import elucent.eidolon.spell.AltarInfo; -import elucent.eidolon.tile.*; -import mezz.jei.api.JeiPlugin; -import mezz.jei.plugins.vanilla.brewing.BrewingRecipeUtil; -import mezz.jei.runtime.JeiHelpers; -import mezz.jei.startup.JeiStarter; -import net.minecraft.client.gui.ScreenManager; +import elucent.eidolon.tile.BrazierTileRenderer; +import elucent.eidolon.tile.CrucibleTileRenderer; +import elucent.eidolon.tile.GobletTileRenderer; +import elucent.eidolon.tile.HandTileRenderer; +import elucent.eidolon.tile.NecroticFocusTileRenderer; +import elucent.eidolon.tile.SoulEnchanterTileRenderer; +import elucent.eidolon.tile.reagent.CisternTileRenderer; +import elucent.eidolon.tile.reagent.PipeTileRenderer; +import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.RenderTypeLookup; -import net.minecraft.entity.EntitySpawnPlacementRegistry; -import net.minecraft.entity.ai.attributes.GlobalEntityTypeAttributes; -import net.minecraft.entity.monster.MonsterEntity; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.potion.EffectInstance; -import net.minecraft.potion.PotionUtils; -import net.minecraft.potion.Potions; -import net.minecraft.world.gen.Heightmap; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; +import net.minecraft.client.renderer.entity.EntityRenderers; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.world.entity.SpawnPlacements; +import net.minecraft.world.entity.ai.attributes.DefaultAttributes; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.brewing.BrewingRecipeRegistry; import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.event.entity.EntityAttributeModificationEvent; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.InterModComms; -import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.client.registry.ClientRegistry; -import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @@ -61,9 +77,9 @@ public class Eidolon { public static final String MODID = "eidolon"; - public static final ItemGroup TAB = new ItemGroup(MODID) { + public static final CreativeModeTab TAB = new CreativeModeTab(MODID) { @Override - public ItemStack createIcon() { + public ItemStack makeIcon() { return new ItemStack(Registry.SHADOW_GEM.get(), 1); } }; @@ -76,6 +92,7 @@ public Eidolon() { FMLJavaModLoadingContext.get().getModEventBus().register(new Registry()); Registry.init(); proxy.init(); + MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(new WorldGen()); WorldGen.preInit(); MinecraftForge.EVENT_BUS.register(new Events()); @@ -90,58 +107,57 @@ public void setup(final FMLCommonSetupEvent event) { WorldGen.init(); event.enqueueWork(() -> { CrucibleRegistry.init(); - WorktableRegistry.init(); RitualRegistry.init(); CodexChapters.init(); Registry.addBrewingRecipes(); AltarEntries.init(); + MinecraftForge.EVENT_BUS.post(new RegisterDeitiesEvent()); + MinecraftForge.EVENT_BUS.post(new RegisterReagentsEvent()); + AthameItem.initHarvestables(); }); - event.enqueueWork(this::defineAttributes); - CapabilityManager.INSTANCE.register(IReputation.class, new ReputationStorage(), ReputationImpl::new); - CapabilityManager.INSTANCE.register(IKnowledge.class, new KnowledgeStorage(), KnowledgeImpl::new); - - EntitySpawnPlacementRegistry.register(Registry.ZOMBIE_BRUTE.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, - MonsterEntity::canMonsterSpawnInLight); - EntitySpawnPlacementRegistry.register(Registry.WRAITH.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, - MonsterEntity::canMonsterSpawnInLight); + SpawnPlacements.register(Registry.ZOMBIE_BRUTE.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, + Monster::checkMonsterSpawnRules); + SpawnPlacements.register(Registry.WRAITH.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, + Monster::checkMonsterSpawnRules); + SpawnPlacements.register(Registry.RAVEN.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, + Animal::checkAnimalSpawnRules); + SpawnPlacements.register(Registry.SLIMY_SLUG.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, + (e, w, t, pos, rand) -> pos.getY() < w.getHeight(Types.WORLD_SURFACE, pos.getX(), pos.getZ())); } @OnlyIn(Dist.CLIENT) public static void clientSetup(final FMLClientSetupEvent event){ - RenderingRegistry.registerEntityRenderingHandler(Registry.ZOMBIE_BRUTE.get(), (erm) -> new ZombieBruteRenderer(erm, new ZombieBruteModel(), 0.6f)); - RenderingRegistry.registerEntityRenderingHandler(Registry.WRAITH.get(), (erm) -> new WraithRenderer(erm, new WraithModel(), 0.6f)); - RenderingRegistry.registerEntityRenderingHandler(Registry.NECROMANCER.get(), (erm) -> new NecromancerRenderer(erm, new NecromancerModel(0), 0.6f)); - RenderingRegistry.registerEntityRenderingHandler(Registry.SOULFIRE_PROJECTILE.get(), (erm) -> new EmptyRenderer(erm)); - RenderingRegistry.registerEntityRenderingHandler(Registry.BONECHILL_PROJECTILE.get(), (erm) -> new EmptyRenderer(erm)); - RenderingRegistry.registerEntityRenderingHandler(Registry.NECROMANCER_SPELL.get(), (erm) -> new EmptyRenderer(erm)); - RenderingRegistry.registerEntityRenderingHandler(Registry.CHANT_CASTER.get(), (erm) -> new EmptyRenderer(erm)); - ClientRegistry.bindTileEntityRenderer(Registry.HAND_TILE_ENTITY, (trd) -> new HandTileRenderer(trd)); - ClientRegistry.bindTileEntityRenderer(Registry.BRAZIER_TILE_ENTITY, (trd) -> new BrazierTileRenderer(trd)); - ClientRegistry.bindTileEntityRenderer(Registry.NECROTIC_FOCUS_TILE_ENTITY, (trd) -> new NecroticFocusTileRenderer(trd)); - ClientRegistry.bindTileEntityRenderer(Registry.CRUCIBLE_TILE_ENTITY, (trd) -> new CrucibleTileRenderer(trd)); - ClientRegistry.bindTileEntityRenderer(Registry.SOUL_ENCHANTER_TILE_ENTITY, (trd) -> new SoulEnchanterTileRenderer(trd)); - ClientRegistry.bindTileEntityRenderer(Registry.GOBLET_TILE_ENTITY, (trd) -> new GobletTileRenderer(trd)); + BlockEntityRenderers.register(Registry.HAND_TILE_ENTITY, (trd) -> new HandTileRenderer()); + BlockEntityRenderers.register(Registry.BRAZIER_TILE_ENTITY, (trd) -> new BrazierTileRenderer()); + BlockEntityRenderers.register(Registry.NECROTIC_FOCUS_TILE_ENTITY, (trd) -> new NecroticFocusTileRenderer()); + BlockEntityRenderers.register(Registry.CRUCIBLE_TILE_ENTITY, (trd) -> new CrucibleTileRenderer()); + BlockEntityRenderers.register(Registry.SOUL_ENCHANTER_TILE_ENTITY, (trd) -> new SoulEnchanterTileRenderer()); + BlockEntityRenderers.register(Registry.GOBLET_TILE_ENTITY, (trd) -> new GobletTileRenderer()); + BlockEntityRenderers.register(Registry.CISTERN_TILE_ENTITY, (trd) -> new CisternTileRenderer()); + BlockEntityRenderers.register(Registry.PIPE_TILE_ENTITY, (trd) -> new PipeTileRenderer()); - RenderTypeLookup.setRenderLayer(Registry.ENCHANTED_ASH.get(), RenderType.getCutoutMipped()); - RenderTypeLookup.setRenderLayer(Registry.WOODEN_STAND.get(), RenderType.getCutoutMipped()); - RenderTypeLookup.setRenderLayer(Registry.GOBLET.get(), RenderType.getCutoutMipped()); - RenderTypeLookup.setRenderLayer(Registry.UNHOLY_EFFIGY.get(), RenderType.getCutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.ENCHANTED_ASH.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.WOODEN_STAND.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.GOBLET.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.UNHOLY_EFFIGY.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.INCUBATOR.get(), (t) -> t == RenderType.solid() || t == RenderType.translucent()); + ItemBlockRenderTypes.setRenderLayer(Registry.GLASS_TUBE.get(), RenderType.translucent()); + ItemBlockRenderTypes.setRenderLayer(Registry.CISTERN.get(), RenderType.translucent()); + ItemBlockRenderTypes.setRenderLayer(Registry.MERAMMER_ROOT.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.SILDRIAN_SEED.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.OANNA_BLOOM.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.AVENNIAN_SPRIG.get(), RenderType.cutoutMipped()); event.enqueueWork(() -> { - ScreenManager.registerFactory(Registry.WORKTABLE_CONTAINER.get(), WorktableScreen::new); - ScreenManager.registerFactory(Registry.SOUL_ENCHANTER_CONTAINER.get(), SoulEnchanterScreen::new); - ScreenManager.registerFactory(Registry.WOODEN_STAND_CONTAINER.get(), WoodenBrewingStandScreen::new); + MenuScreens.register(Registry.WORKTABLE_CONTAINER.get(), WorktableScreen::new); + MenuScreens.register(Registry.SOUL_ENCHANTER_CONTAINER.get(), SoulEnchanterScreen::new); + MenuScreens.register(Registry.WOODEN_STAND_CONTAINER.get(), WoodenBrewingStandScreen::new); }); } - public void defineAttributes() { - GlobalEntityTypeAttributes.put(Registry.ZOMBIE_BRUTE.get(), ZombieBruteEntity.createAttributes()); - GlobalEntityTypeAttributes.put(Registry.WRAITH.get(), WraithEntity.createAttributes()); - GlobalEntityTypeAttributes.put(Registry.NECROMANCER.get(), NecromancerEntity.createAttributes()); - } - public void sendImc(InterModEnqueueEvent evt) { + InterModComms.sendTo("consecration", "holy_material", () -> "silver"); InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.CHARM.getMessageBuilder().build()); InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.RING.getMessageBuilder().size(2).build()); InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.BELT.getMessageBuilder().build()); diff --git a/src/main/java/elucent/eidolon/Events.java b/src/main/java/elucent/eidolon/Events.java index 85ba7f7..47b90f7 100644 --- a/src/main/java/elucent/eidolon/Events.java +++ b/src/main/java/elucent/eidolon/Events.java @@ -1,10 +1,12 @@ package elucent.eidolon; +import java.util.Comparator; +import java.util.List; + import com.mojang.authlib.GameProfile; + import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.KnowledgeProvider; -import elucent.eidolon.capability.ReputationProvider; -import elucent.eidolon.entity.ai.GenericBarterGoal; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.entity.ai.PriestBarterGoal; import elucent.eidolon.entity.ai.WitchBarterGoal; import elucent.eidolon.event.SpeedFactorEvent; @@ -19,29 +21,38 @@ import elucent.eidolon.spell.Signs; import elucent.eidolon.tile.GobletTileEntity; import elucent.eidolon.util.EntityUtil; -import net.minecraft.entity.*; -import net.minecraft.entity.boss.dragon.EnderDragonEntity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.merchant.villager.VillagerEntity; -import net.minecraft.entity.monster.*; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.NBTUtil; -import net.minecraft.potion.Effects; -import net.minecraft.util.DamageSource; -import net.minecraft.util.RegistryKey; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.MobSpawnInfo; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.monster.Creeper; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.monster.Skeleton; +import net.minecraft.world.entity.monster.Witch; +import net.minecraft.world.entity.monster.WitherSkeleton; +import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.MobSpawnSettings; import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; @@ -54,30 +65,26 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.registries.ForgeRegistries; -import java.util.Comparator; -import java.util.List; - public class Events { @SubscribeEvent - public void attachWorldCaps(AttachCapabilitiesEvent event) { - if (event.getObject() instanceof World) event.addCapability(new ResourceLocation(Eidolon.MODID, "reputation"), new ReputationProvider()); + public void attachWorldCaps(AttachCapabilitiesEvent event) { + if (event.getObject() instanceof Level) event.addCapability(new ResourceLocation(Eidolon.MODID, "reputation"), new IReputation.Provider()); } @SubscribeEvent public void attachEntityCaps(AttachCapabilitiesEvent event) { - if (event.getObject() instanceof Entity) event.addCapability(new ResourceLocation(Eidolon.MODID, "knowledge"), new KnowledgeProvider()); + if (event.getObject() instanceof Player) event.addCapability(new ResourceLocation(Eidolon.MODID, "knowledge"), new IKnowledge.Provider()); } @SubscribeEvent public void onClone(PlayerEvent.Clone event) { - Capability KNOWLEDGE = KnowledgeProvider.CAPABILITY; - KNOWLEDGE.getStorage().readNBT( - KNOWLEDGE, - event.getPlayer().getCapability(KNOWLEDGE, null).resolve().get(), - null, - KNOWLEDGE.getStorage().writeNBT(KNOWLEDGE, event.getOriginal().getCapability(KNOWLEDGE, null).resolve().get(), null) - ); - if (!event.getPlayer().world.isRemote) { + Capability KNOWLEDGE = IKnowledge.INSTANCE; + event.getPlayer().getCapability(KNOWLEDGE).ifPresent((k) -> { + event.getOriginal().getCapability(KNOWLEDGE).ifPresent((o) -> { + ((INBTSerializable)k).deserializeNBT(((INBTSerializable)o).serializeNBT()); + }); + }); + if (!event.getPlayer().level.isClientSide) { Networking.sendTo(event.getPlayer(), new KnowledgeUpdatePacket(event.getPlayer(), false)); } } @@ -85,25 +92,25 @@ public void onClone(PlayerEvent.Clone event) { @SubscribeEvent public void onTarget(LivingSetAttackTargetEvent event) { if (EntityUtil.isEnthralledBy(event.getEntityLiving(), event.getTarget())) - ((MobEntity)event.getEntityLiving()).setAttackTarget(null); + ((Mob)event.getEntityLiving()).setTarget(null); } @SubscribeEvent public void onDeath(LivingDropsEvent event) { LivingEntity entity = event.getEntityLiving(); - if (!(entity instanceof MonsterEntity)) { - World world = entity.world; - BlockPos pos = entity.getPosition(); - List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AxisAlignedBB(pos.add(-2, -2, -2), pos.add(3, 3, 3))); + if (!(entity instanceof Monster)) { + Level world = entity.level; + BlockPos pos = entity.blockPosition(); + List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AABB(pos.offset(-2, -2, -2), pos.offset(3, 3, 3))); if (goblets.size() > 0) { - GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((g) -> g.getPos().distanceSq(pos))).get(); + GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((g) -> g.getBlockPos().distSqr(pos))).get(); goblet.setEntityType(entity.getType()); } } - if (entity instanceof WitchEntity || entity instanceof VillagerEntity) { - if (entity.getHeldItemMainhand().getItem() instanceof CodexItem) - event.getDrops().add(new ItemEntity(entity.world, entity.getPosX(), entity.getPosY(), entity.getPosZ(), entity.getHeldItemMainhand().copy())); + if (entity instanceof Witch || entity instanceof Villager) { + if (entity.getMainHandItem().getItem() instanceof CodexItem) + event.getDrops().add(new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), entity.getMainHandItem().copy())); } if (EntityUtil.isEnthralled(entity)) { @@ -111,42 +118,42 @@ public void onDeath(LivingDropsEvent event) { return; } - if (event.getSource().getTrueSource() != null && event.getSource().getTrueSource() instanceof LivingEntity) { - LivingEntity source = (LivingEntity) event.getSource().getTrueSource(); - ItemStack held = source.getHeldItemMainhand(); - if (!entity.world.isRemote && held.getItem() instanceof ReaperScytheItem && entity.isEntityUndead()) { + if (event.getSource().getEntity() != null && event.getSource().getEntity() instanceof LivingEntity) { + LivingEntity source = (LivingEntity) event.getSource().getEntity(); + ItemStack held = source.getMainHandItem(); + if (!entity.level.isClientSide && held.getItem() instanceof ReaperScytheItem && entity.isInvertedHealAndHarm()) { int looting = ForgeHooks.getLootingLevel(entity, source, event.getSource()); - ItemEntity drop = new ItemEntity(source.world, entity.getPosX(), entity.getPosY(), entity.getPosZ(), - new ItemStack(Registry.SOUL_SHARD.get(), source.world.rand.nextInt(2 + looting))); - drop.setDefaultPickupDelay(); + ItemEntity drop = new ItemEntity(source.level, entity.getX(), entity.getY(), entity.getZ(), + new ItemStack(Registry.SOUL_SHARD.get(), source.level.random.nextInt(2 + looting))); + drop.setDefaultPickUpDelay(); event.getDrops().add(drop); - Networking.sendToTracking(entity.world, entity.getPosition(), new CrystallizeEffectPacket(entity.getPosition())); + Networking.sendToTracking(entity.level, entity.blockPosition(), new CrystallizeEffectPacket(entity.blockPosition())); } - if (!entity.world.isRemote && held.getItem() instanceof CleavingAxeItem) { + if (!entity.level.isClientSide && held.getItem() instanceof CleavingAxeItem) { int looting = ForgeHooks.getLootingLevel(entity, source, event.getSource()); ItemStack head = ItemStack.EMPTY; - if (entity instanceof WitherSkeletonEntity) head = new ItemStack(Items.WITHER_SKELETON_SKULL); - else if (entity instanceof SkeletonEntity) head = new ItemStack(Items.SKELETON_SKULL); - else if (entity instanceof ZombieEntity) head = new ItemStack(Items.ZOMBIE_HEAD); - else if (entity instanceof CreeperEntity) head = new ItemStack(Items.CREEPER_HEAD); - else if (entity instanceof EnderDragonEntity) head = new ItemStack(Items.DRAGON_HEAD); - else if (entity instanceof PlayerEntity) { + if (entity instanceof WitherSkeleton) head = new ItemStack(Items.WITHER_SKELETON_SKULL); + else if (entity instanceof Skeleton) head = new ItemStack(Items.SKELETON_SKULL); + else if (entity instanceof Zombie) head = new ItemStack(Items.ZOMBIE_HEAD); + else if (entity instanceof Creeper) head = new ItemStack(Items.CREEPER_HEAD); + else if (entity instanceof EnderDragon) head = new ItemStack(Items.DRAGON_HEAD); + else if (entity instanceof Player) { head = new ItemStack(Items.PLAYER_HEAD); - GameProfile gameprofile = ((PlayerEntity)entity).getGameProfile(); - head.getOrCreateTag().put("SkullOwner", NBTUtil.writeGameProfile(new CompoundNBT(), gameprofile)); + GameProfile gameprofile = ((Player)entity).getGameProfile(); + head.getOrCreateTag().put("SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), gameprofile)); } if (!head.isEmpty()) { boolean doDrop = false; - if (entity.world.rand.nextInt(20) == 0) doDrop = true; + if (entity.level.random.nextInt(20) == 0) doDrop = true; else for (int i = 0; i < looting; i++) { - if (entity.world.rand.nextInt(40) == 0) { + if (entity.level.random.nextInt(40) == 0) { doDrop = true; break; } } if (doDrop) { - ItemEntity drop = new ItemEntity(source.world, entity.getPosX(), entity.getPosY(), entity.getPosZ(), head); - drop.setDefaultPickupDelay(); + ItemEntity drop = new ItemEntity(source.level, entity.getX(), entity.getY(), entity.getZ(), head); + drop.setDefaultPickUpDelay(); event.getDrops().add(drop); } } @@ -156,31 +163,35 @@ else if (entity instanceof PlayerEntity) { @SubscribeEvent public void registerSpawns(BiomeLoadingEvent ev) { - RegistryKey key = RegistryKey.getOrCreateKey(ForgeRegistries.Keys.BIOMES, ev.getName()); - if (BiomeDictionary.hasType(key, BiomeDictionary.Type.OVERWORLD) && ev.getCategory() != Biome.Category.MUSHROOM) { - ev.getSpawns().withSpawner(EntityClassification.MONSTER, - new MobSpawnInfo.Spawners(Registry.WRAITH.get(), Config.WRAITH_SPAWN_WEIGHT.get(), 1, 2)); - ev.getSpawns().withSpawner(EntityClassification.MONSTER, - new MobSpawnInfo.Spawners(Registry.ZOMBIE_BRUTE.get(), Config.ZOMBIE_BRUTE_SPAWN_WEIGHT.get(), 1, 2)); + ResourceKey key = ResourceKey.create(ForgeRegistries.Keys.BIOMES, ev.getName()); + if (BiomeDictionary.hasType(key, BiomeDictionary.Type.OVERWORLD) && ev.getCategory() != Biome.BiomeCategory.MUSHROOM) { + ev.getSpawns().addSpawn(MobCategory.MONSTER, + new MobSpawnSettings.SpawnerData(Registry.WRAITH.get(), Config.WRAITH_SPAWN_WEIGHT.get(), 1, 2)); + ev.getSpawns().addSpawn(MobCategory.MONSTER, + new MobSpawnSettings.SpawnerData(Registry.ZOMBIE_BRUTE.get(), Config.ZOMBIE_BRUTE_SPAWN_WEIGHT.get(), 1, 2)); + } + if (BiomeDictionary.hasType(key, BiomeDictionary.Type.OVERWORLD) && BiomeDictionary.hasType(key, BiomeDictionary.Type.FOREST)) { + ev.getSpawns().addSpawn(MobCategory.CREATURE, + new MobSpawnSettings.SpawnerData(Registry.RAVEN.get(), Config.RAVEN_SPAWN_WEIGHT.get(), 2, 5)); } } @SubscribeEvent public void registerCustomAI(EntityJoinWorldEvent event) { - if (event.getEntity() instanceof LivingEntity && !event.getWorld().isRemote) { - if (event.getEntity() instanceof PlayerEntity) { - Networking.sendTo((PlayerEntity)event.getEntity(), new KnowledgeUpdatePacket((PlayerEntity)event.getEntity(), false)); + if (event.getEntity() instanceof LivingEntity && !event.getWorld().isClientSide) { + if (event.getEntity() instanceof Player) { + Networking.sendTo((Player)event.getEntity(), new KnowledgeUpdatePacket((Player)event.getEntity(), false)); } - if (event.getEntity() instanceof WitchEntity) { - ((WitchEntity)event.getEntity()).goalSelector.addGoal(1, new WitchBarterGoal( - (WitchEntity)event.getEntity(), + if (event.getEntity() instanceof Witch) { + ((Witch)event.getEntity()).goalSelector.addGoal(1, new WitchBarterGoal( + (Witch)event.getEntity(), (stack) -> stack.getItem() == Registry.CODEX.get(), (stack) -> CodexItem.withSign(stack, Signs.WICKED_SIGN) )); } - if (event.getEntity() instanceof VillagerEntity) { - ((VillagerEntity)event.getEntity()).goalSelector.addGoal(1, new PriestBarterGoal( - (VillagerEntity)event.getEntity(), + if (event.getEntity() instanceof Villager) { + ((Villager)event.getEntity()).goalSelector.addGoal(1, new PriestBarterGoal( + (Villager)event.getEntity(), (stack) -> stack.getItem() == Registry.CODEX.get(), (stack) -> CodexItem.withSign(stack, Signs.SACRED_SIGN) )); @@ -190,28 +201,28 @@ public void registerCustomAI(EntityJoinWorldEvent event) { @SubscribeEvent public void onApplyPotion(PotionEvent.PotionApplicableEvent event) { - if (event.getPotionEffect().getPotion() == Effects.SLOWNESS && event.getEntityLiving().getItemStackFromSlot(EquipmentSlotType.FEET).getItem() instanceof WarlockRobesItem) { + if (event.getPotionEffect().getEffect() == MobEffects.MOVEMENT_SLOWDOWN && event.getEntityLiving().getItemBySlot(EquipmentSlot.FEET).getItem() instanceof WarlockRobesItem) { event.setResult(Event.Result.DENY); } } @SubscribeEvent public void onLivingHurt(LivingHurtEvent event) { - if ((event.getSource().getDamageType() == DamageSource.WITHER.getDamageType() || event.getSource().isMagicDamage())) { - if (event.getSource().getTrueSource() instanceof LivingEntity - && ((LivingEntity)event.getSource().getTrueSource()).getItemStackFromSlot(EquipmentSlotType.HEAD).getItem() instanceof WarlockRobesItem) { + if ((event.getSource().getMsgId() == DamageSource.WITHER.getMsgId() || event.getSource().isMagic())) { + if (event.getSource().getEntity() instanceof LivingEntity + && ((LivingEntity)event.getSource().getEntity()).getItemBySlot(EquipmentSlot.HEAD).getItem() instanceof WarlockRobesItem) { event.setAmount(event.getAmount() * 1.5f); - if (event.getSource().getDamageType() == DamageSource.WITHER.getDamageType()) - ((LivingEntity) event.getSource().getTrueSource()).heal(event.getAmount() / 2); + if (event.getSource().getMsgId() == DamageSource.WITHER.getMsgId()) + ((LivingEntity) event.getSource().getEntity()).heal(event.getAmount() / 2); } - if (event.getEntityLiving().getItemStackFromSlot(EquipmentSlotType.CHEST).getItem() instanceof WarlockRobesItem) + if (event.getEntityLiving().getItemBySlot(EquipmentSlot.CHEST).getItem() instanceof WarlockRobesItem) event.setAmount(event.getAmount() / 2); } } @SubscribeEvent public void onGetSpeedFactor(SpeedFactorEvent event) { - if (event.getSpeedFactor() < 1.0f && event.getEntity() instanceof LivingEntity && ((LivingEntity)event.getEntity()).getItemStackFromSlot(EquipmentSlotType.FEET).getItem() instanceof WarlockRobesItem) { + if (event.getSpeedFactor() < 1.0f && event.getEntity() instanceof LivingEntity && ((LivingEntity)event.getEntity()).getItemBySlot(EquipmentSlot.FEET).getItem() instanceof WarlockRobesItem) { float diff = 1.0f - event.getSpeedFactor(); event.setSpeedFactor(1.0f - diff / 2); } diff --git a/src/main/java/elucent/eidolon/Registry.java b/src/main/java/elucent/eidolon/Registry.java index be9faa5..fa115a7 100644 --- a/src/main/java/elucent/eidolon/Registry.java +++ b/src/main/java/elucent/eidolon/Registry.java @@ -1,80 +1,225 @@ package elucent.eidolon; -import com.google.common.collect.Lists; -import elucent.eidolon.block.*; -import elucent.eidolon.entity.*; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; + +import elucent.eidolon.block.BlockBase; +import elucent.eidolon.block.BrazierBlock; +import elucent.eidolon.block.CandleBlock; +import elucent.eidolon.block.CandlestickBlock; +import elucent.eidolon.block.CisternBlock; +import elucent.eidolon.block.CrucibleBlock; +import elucent.eidolon.block.EffigyBlock; +import elucent.eidolon.block.EnchantedAshBlock; +import elucent.eidolon.block.HandBlock; +import elucent.eidolon.block.HerbBlockBase; +import elucent.eidolon.block.HorizontalWaterloggableBlock; +import elucent.eidolon.block.NecroticFocusBlock; +import elucent.eidolon.block.PillarBlockBase; +import elucent.eidolon.block.PipeBlock; +import elucent.eidolon.block.SoulEnchanterBlock; +import elucent.eidolon.block.TableBlockBase; +import elucent.eidolon.block.TwoHighBlockBase; +import elucent.eidolon.block.WoodenStandBlock; +import elucent.eidolon.block.WorktableBlock; +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.entity.AngelArrowEntity; +import elucent.eidolon.entity.AngelArrowRenderer; +import elucent.eidolon.entity.BonechillProjectileEntity; +import elucent.eidolon.entity.ChantCasterEntity; +import elucent.eidolon.entity.NecromancerEntity; +import elucent.eidolon.entity.NecromancerModel; +import elucent.eidolon.entity.NecromancerRenderer; +import elucent.eidolon.entity.NecromancerSpellEntity; +import elucent.eidolon.entity.RavenEntity; +import elucent.eidolon.entity.RavenModel; +import elucent.eidolon.entity.RavenRenderer; +import elucent.eidolon.entity.SlimySlugEntity; +import elucent.eidolon.entity.SlimySlugModel; +import elucent.eidolon.entity.SlimySlugRenderer; +import elucent.eidolon.entity.SoulfireProjectileEntity; +import elucent.eidolon.entity.WraithEntity; +import elucent.eidolon.entity.WraithModel; +import elucent.eidolon.entity.WraithRenderer; +import elucent.eidolon.entity.ZombieBruteEntity; +import elucent.eidolon.entity.ZombieBruteModel; +import elucent.eidolon.entity.ZombieBruteRenderer; import elucent.eidolon.gui.SoulEnchanterContainer; import elucent.eidolon.gui.WoodenBrewingStandContainer; import elucent.eidolon.gui.WorktableContainer; -import elucent.eidolon.item.*; -import elucent.eidolon.item.curio.*; +import elucent.eidolon.item.AthameItem; +import elucent.eidolon.item.BonechillWandItem; +import elucent.eidolon.item.CleavingAxeItem; +import elucent.eidolon.item.CodexItem; +import elucent.eidolon.item.ItemBase; +import elucent.eidolon.item.ReaperScytheItem; +import elucent.eidolon.item.ReversalPickItem; +import elucent.eidolon.item.SappingSwordItem; +import elucent.eidolon.item.SilverArmorItem; +import elucent.eidolon.item.SoulfireWandItem; +import elucent.eidolon.item.Tiers; +import elucent.eidolon.item.TongsItem; +import elucent.eidolon.item.TopHatItem; +import elucent.eidolon.item.UnholySymbolItem; +import elucent.eidolon.item.WarlockRobesItem; +import elucent.eidolon.item.curio.AngelSightItem; +import elucent.eidolon.item.curio.BasicAmuletItem; +import elucent.eidolon.item.curio.BasicBeltItem; +import elucent.eidolon.item.curio.BasicRingItem; +import elucent.eidolon.item.curio.EnervatingRingItem; +import elucent.eidolon.item.curio.GlassHandItem; +import elucent.eidolon.item.curio.GravityBeltItem; +import elucent.eidolon.item.curio.MindShieldingPlateItem; +import elucent.eidolon.item.curio.PrestigiousPalmItem; +import elucent.eidolon.item.curio.ResoluteBeltItem; +import elucent.eidolon.item.curio.SanguineAmuletItem; +import elucent.eidolon.item.curio.TerminusMirrorItem; +import elucent.eidolon.item.curio.VoidAmuletItem; +import elucent.eidolon.item.curio.WardedMailItem; +import elucent.eidolon.item.model.SilverArmorModel; +import elucent.eidolon.item.model.TopHatModel; +import elucent.eidolon.item.model.WarlockArmorModel; import elucent.eidolon.mixin.PotionBrewingMixin; -import elucent.eidolon.particle.*; +import elucent.eidolon.particle.BubbleParticleType; +import elucent.eidolon.particle.FlameParticleType; +import elucent.eidolon.particle.LineWispParticleType; +import elucent.eidolon.particle.SignParticleType; +import elucent.eidolon.particle.SmokeParticleType; +import elucent.eidolon.particle.SparkleParticleType; +import elucent.eidolon.particle.SteamParticleType; +import elucent.eidolon.particle.WispParticleType; import elucent.eidolon.potion.AnchoredEffect; import elucent.eidolon.potion.ChilledEffect; -import elucent.eidolon.potion.StrictBrewingRecipe; -import elucent.eidolon.ritual.*; +import elucent.eidolon.potion.ReinforcedEffect; +import elucent.eidolon.potion.VulnerableEffect; +import elucent.eidolon.reagent.Reagent; +import elucent.eidolon.reagent.ReagentRegistry; +import elucent.eidolon.recipe.CrucibleRecipe; +import elucent.eidolon.recipe.WorktableRecipe; +import elucent.eidolon.ritual.AllureRitual; +import elucent.eidolon.ritual.CrystalRitual; +import elucent.eidolon.ritual.DaylightRitual; +import elucent.eidolon.ritual.DeceitRitual; +import elucent.eidolon.ritual.MoonlightRitual; +import elucent.eidolon.ritual.PurifyRitual; +import elucent.eidolon.ritual.RepellingRitual; +import elucent.eidolon.ritual.SanguineRitual; +import elucent.eidolon.ritual.SummonRitual; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; -import elucent.eidolon.tile.*; -import net.minecraft.block.*; -import net.minecraft.block.material.Material; -import net.minecraft.block.material.MaterialColor; +import elucent.eidolon.tile.BrazierTileEntity; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.EffigyTileEntity; +import elucent.eidolon.tile.GobletTileEntity; +import elucent.eidolon.tile.HandTileEntity; +import elucent.eidolon.tile.NecroticFocusTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileRenderer; +import elucent.eidolon.tile.WoodenStandTileEntity; +import elucent.eidolon.tile.reagent.CisternTileEntity; +import elucent.eidolon.tile.reagent.PipeTileEntity; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FenceBlock; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.RotatedPillarBlock; +import net.minecraft.world.level.block.SlabBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.StairBlock; +import net.minecraft.world.level.block.WallBlock; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; import net.minecraft.client.Minecraft; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityClassification; -import net.minecraft.entity.EntityType; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.inventory.container.Container; -import net.minecraft.inventory.container.ContainerType; -import net.minecraft.item.*; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.particles.ParticleType; -import net.minecraft.potion.*; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.shapes.IBooleanFunction; -import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.client.model.Model; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.client.renderer.entity.EntityRenderers; +import net.minecraft.client.renderer.entity.NoopRenderer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.AxeItem; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.HoeItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.RecordItem; +import net.minecraft.world.item.PickaxeItem; +import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.ShovelItem; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.SwordItem; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.BlockEntityType.BlockEntitySupplier; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.phys.shapes.Shapes; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.ParticleFactoryRegisterEvent; +import net.minecraftforge.client.event.RegisterShadersEvent; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.Tags; -import net.minecraftforge.common.ToolType; -import net.minecraftforge.common.brewing.BrewingRecipeRegistry; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.IForgeRegistry; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; +import net.minecraftforge.registries.RegistryObject; public class Registry { + public static Tags.IOptionalNamedTag + INGOTS_LEAD = ItemTags.createOptional(new ResourceLocation("forge", "ingots/lead")), + INGOTS_PEWTER = ItemTags.createOptional(new ResourceLocation("forge", "ingots/pewter")), + INGOTS_ARCANE_GOLD = ItemTags.createOptional(new ResourceLocation("forge", "ingots/arcane_gold")), + INGOTS_SILVER = ItemTags.createOptional(new ResourceLocation("forge", "ingots/silver")), + GEMS_SHADOW = ItemTags.createOptional(new ResourceLocation("forge", "gems/shadow_gem")); + static Map BLOCK_MAP = new HashMap<>(); static Map ITEM_MAP = new HashMap<>(); static DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, Eidolon.MODID); static DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Eidolon.MODID); static DeferredRegister> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITIES, Eidolon.MODID); - static DeferredRegister> TILE_ENTITIES = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, Eidolon.MODID); - static DeferredRegister POTIONS = DeferredRegister.create(ForgeRegistries.POTIONS, Eidolon.MODID); - static DeferredRegister POTION_TYPES = DeferredRegister.create(ForgeRegistries.POTION_TYPES, Eidolon.MODID); + static DeferredRegister> TILE_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITIES, Eidolon.MODID); + static DeferredRegister POTIONS = DeferredRegister.create(ForgeRegistries.MOB_EFFECTS, Eidolon.MODID); + static DeferredRegister POTION_TYPES = DeferredRegister.create(ForgeRegistries.POTIONS, Eidolon.MODID); static DeferredRegister SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Eidolon.MODID); - static DeferredRegister> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Eidolon.MODID); + static DeferredRegister> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Eidolon.MODID); + static DeferredRegister> RECIPE_TYPES = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Eidolon.MODID); static Item.Properties itemProps() { - return new Item.Properties().group(Eidolon.TAB); + return new Item.Properties().tab(Eidolon.TAB); } - static AbstractBlock.Properties blockProps(Material mat, MaterialColor color) { - return AbstractBlock.Properties.create(mat, color); + static BlockBehaviour.Properties blockProps(Material mat, MaterialColor color) { + return BlockBehaviour.Properties.of(mat, color); } static RegistryObject addItem(String name) { @@ -110,16 +255,16 @@ static RegistryObject addBlock(String name, Block block) { public static class DecoBlockPack { DeferredRegister registry; String basename; - AbstractBlock.Properties props; + BlockBehaviour.Properties props; RegistryObject full = null, slab = null, stair = null, wall = null, fence = null, fence_gate = null; - public DecoBlockPack(DeferredRegister blocks, String basename, AbstractBlock.Properties props) { + public DecoBlockPack(DeferredRegister blocks, String basename, BlockBehaviour.Properties props) { this.registry = blocks; this.basename = basename; this.props = props; full = addBlock(basename, new Block(props)); slab = addBlock(basename + "_slab", new SlabBlock(props)); - stair = addBlock(basename + "_stairs", new StairsBlock(() -> full.get().getDefaultState(), props)); + stair = addBlock(basename + "_stairs", new StairBlock(() -> full.get().defaultBlockState(), props)); } public DecoBlockPack addWall() { @@ -140,22 +285,22 @@ public DecoBlockPack addFence() { public Block getFence() { return fence.get(); } } - static RegistryObject> addEntity(String name, float width, float height, EntityType.IFactory factory, EntityClassification kind) { - EntityType type = EntityType.Builder.create(factory, kind) + static RegistryObject> addEntity(String name, float width, float height, EntityType.EntityFactory factory, MobCategory kind) { + EntityType type = EntityType.Builder.of(factory, kind) .setTrackingRange(64) .setUpdateInterval(1) - .size(width, height) + .sized(width, height) .build(Eidolon.MODID + ":" + name); return ENTITIES.register(name, () -> type); } - static RegistryObject> addEntity(String name, int color1, int color2, float width, float height, EntityType.IFactory factory, EntityClassification kind) { - EntityType type = EntityType.Builder.create(factory, kind) + static RegistryObject> addEntity(String name, int color1, int color2, float width, float height, EntityType.EntityFactory factory, MobCategory kind) { + EntityType type = EntityType.Builder.of(factory, kind) .setTrackingRange(64) .setUpdateInterval(1) - .size(width, height) + .sized(width, height) .build(Eidolon.MODID + ":" + name); - ITEMS.register("spawn_" + name, () -> new SpawnEggItem(type, color1, color2, itemProps().group(ItemGroup.MISC))); + ITEMS.register("spawn_" + name, () -> new SpawnEggItem((EntityType) type, color1, color2, itemProps().tab(CreativeModeTab.TAB_MISC))); return ENTITIES.register(name, () -> type); } @@ -164,15 +309,14 @@ static RegistryObject addSound(String name) { return SOUND_EVENTS.register(name, () -> event); } - static RegistryObject> addContainer(String name, ContainerType.IFactory factory) { - return CONTAINERS.register(name, () -> new ContainerType(factory)); + static RegistryObject> addContainer(String name, MenuType.MenuSupplier factory) { + return CONTAINERS.register(name, () -> new MenuType(factory)); } - static TileEntityType addTileEntity(IForgeRegistry> registry, String name, Supplier factory, Block... blocks) { - TileEntityType type = TileEntityType.Builder.create(factory, blocks).build(null); + static BlockEntityType addTileEntity(IForgeRegistry> registry, String name, BlockEntitySupplier factory, Block... blocks) { + BlockEntityType type = BlockEntityType.Builder.of(factory, blocks).build(null); type.setRegistryName(Eidolon.MODID, name); registry.register(type); - for (Block block : blocks) if (block instanceof BlockBase) ((BlockBase)block).setTile(type); return type; } @@ -185,19 +329,33 @@ static TileEntityType addTileEntity(IForgeRegistry + public static RegistryObject CHILLED_EFFECT = POTIONS.register("chilled", () -> new ChilledEffect()), - ANCHORED_EFFECT = POTIONS.register("anchored", () -> new AnchoredEffect()); + ANCHORED_EFFECT = POTIONS.register("anchored", () -> new AnchoredEffect()), + REINFORCED_EFFECT = POTIONS.register("reinforced", () -> new ReinforcedEffect() + .addAttributeModifier(Attributes.ARMOR, "483b6415-421e-45d1-ab28-d85d11a19c70", 0.25, Operation.MULTIPLY_TOTAL)), + VULNERABLE_EFFECT = POTIONS.register("vulnerable", () -> new VulnerableEffect() + .addAttributeModifier(Attributes.ARMOR, "e5bae4de-2019-4316-b8cc-b4d879d676f9", -0.25, Operation.MULTIPLY_TOTAL)); public static RegistryObject - CHILLED_POTION = POTION_TYPES.register("chilled", () -> new Potion(new EffectInstance(CHILLED_EFFECT.get(), 3600))), - LONG_CHILLED_POTION = POTION_TYPES.register("long_chilled", () -> new Potion(new EffectInstance(CHILLED_EFFECT.get(), 9600))), - ANCHORED_POTION = POTION_TYPES.register("anchored", () -> new Potion(new EffectInstance(ANCHORED_EFFECT.get(), 3600))), - LONG_ANCHORED_POTION = POTION_TYPES.register("long_anchored", () -> new Potion(new EffectInstance(ANCHORED_EFFECT.get(), 9600))); + CHILLED_POTION = POTION_TYPES.register("chilled", () -> new Potion(new MobEffectInstance(CHILLED_EFFECT.get(), 3600))), + LONG_CHILLED_POTION = POTION_TYPES.register("long_chilled", () -> new Potion(new MobEffectInstance(CHILLED_EFFECT.get(), 9600))), + ANCHORED_POTION = POTION_TYPES.register("anchored", () -> new Potion(new MobEffectInstance(ANCHORED_EFFECT.get(), 3600))), + LONG_ANCHORED_POTION = POTION_TYPES.register("long_anchored", () -> new Potion(new MobEffectInstance(ANCHORED_EFFECT.get(), 9600))), + REINFORCED_POTION = POTION_TYPES.register("reinforced", () -> new Potion(new MobEffectInstance(REINFORCED_EFFECT.get(), 3600))), + LONG_REINFORCED_POTION = POTION_TYPES.register("long_reinforced", () -> new Potion(new MobEffectInstance(REINFORCED_EFFECT.get(), 9600))), + STRONG_REINFORCED_POTION = POTION_TYPES.register("strong_reinforced", () -> new Potion(new MobEffectInstance(REINFORCED_EFFECT.get(), 1800, 1))), + VULNERABLE_POTION = POTION_TYPES.register("vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 3600))), + LONG_VULNERABLE_POTION = POTION_TYPES.register("long_vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 9600))), + STRONG_VULNERABLE_POTION = POTION_TYPES.register("strong_vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 1800, 1))); public static RegistryObject LEAD_INGOT = addItem("lead_ingot"), + RAW_LEAD = addItem("raw_lead"), LEAD_NUGGET = addItem("lead_nugget"), + SILVER_INGOT = addItem("silver_ingot"), + RAW_SILVER = addItem("raw_silver"), + SILVER_NUGGET = addItem("silver_nugget"), PEWTER_BLEND = addItem("pewter_blend"), PEWTER_INGOT = addItem("pewter_ingot"), PEWTER_NUGGET = addItem("pewter_nugget"), @@ -211,181 +369,246 @@ static TileEntityType addTileEntity(IForgeRegistry new EffectInstance(ANCHORED_EFFECT.get(), 900), 1).build())), + FUNGUS_SPROUTS = addItem("fungus_sprouts", itemProps().food(new FoodProperties.Builder().nutrition(2).saturationMod(0.1f).build())), + WARPED_SPROUTS = addItem("warped_sprouts", itemProps().food(new FoodProperties.Builder().nutrition(4).saturationMod(0.6f).effect(() -> new MobEffectInstance(ANCHORED_EFFECT.get(), 900), 1).build())), ENDER_CALX = addItem("ender_calx"), TALLOW = addItem("tallow"), LESSER_SOUL_GEM = addItem("lesser_soul_gem"), - UNHOLY_SYMBOL = addItem("unholy_symbol", new UnholySymbolItem(itemProps().rarity(Rarity.UNCOMMON).maxStackSize(1))), + UNHOLY_SYMBOL = addItem("unholy_symbol", new UnholySymbolItem(itemProps().rarity(Rarity.UNCOMMON).stacksTo(1))), REAPER_SCYTHE = addItem("reaper_scythe", new ReaperScytheItem(itemProps().rarity(Rarity.UNCOMMON)) .setLore("lore.eidolon.reaper_scythe")), CLEAVING_AXE = addItem("cleaving_axe", new CleavingAxeItem(itemProps().rarity(Rarity.UNCOMMON)) .setLore("lore.eidolon.cleaving_axe")), SHADOW_GEM = addItem("shadow_gem"), WICKED_WEAVE = addItem("wicked_weave"), - WARLOCK_HAT = addItem("warlock_hat", new WarlockRobesItem(EquipmentSlotType.HEAD, itemProps())), - WARLOCK_CLOAK = addItem("warlock_cloak", new WarlockRobesItem(EquipmentSlotType.CHEST, itemProps())), - WARLOCK_BOOTS = addItem("warlock_boots", new WarlockRobesItem(EquipmentSlotType.FEET, itemProps())), + WARLOCK_HAT = addItem("warlock_hat", new WarlockRobesItem(EquipmentSlot.HEAD, itemProps())), + WARLOCK_CLOAK = addItem("warlock_cloak", new WarlockRobesItem(EquipmentSlot.CHEST, itemProps())), + WARLOCK_BOOTS = addItem("warlock_boots", new WarlockRobesItem(EquipmentSlot.FEET, itemProps())), + SILVER_HELMET = addItem("silver_helmet", new SilverArmorItem(EquipmentSlot.HEAD, itemProps())), + SILVER_CHESTPLATE = addItem("silver_chestplate", new SilverArmorItem(EquipmentSlot.CHEST, itemProps())), + SILVER_LEGGINGS = addItem("silver_leggings", new SilverArmorItem(EquipmentSlot.LEGS, itemProps())), + SILVER_BOOTS = addItem("silver_boots", new SilverArmorItem(EquipmentSlot.FEET, itemProps())), + SILVER_SWORD = addItem("silver_sword", new SwordItem(Tiers.SilverTier.INSTANCE, 3, -2.4f, itemProps())), + SILVER_PICKAXE = addItem("silver_pickaxe", new PickaxeItem(Tiers.SilverTier.INSTANCE, 1, -2.4f, itemProps())), + SILVER_AXE = addItem("silver_axe", new AxeItem(Tiers.SilverTier.INSTANCE, 6, -2.4f, itemProps())), + SILVER_SHOVEL = addItem("silver_shovel", new ShovelItem(Tiers.SilverTier.INSTANCE, 1.5f, -2.4f, itemProps())), + SILVER_HOE = addItem("silver_hoe", new HoeItem(Tiers.SilverTier.INSTANCE, 0, -2.4f, itemProps())), + ATHAME = addItem("athame", new AthameItem(itemProps().stacksTo(1))), REVERSAL_PICK = addItem("reversal_pick", new ReversalPickItem(itemProps() .rarity(Rarity.UNCOMMON))), VOID_AMULET = addItem("void_amulet", new VoidAmuletItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.void_amulet")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.void_amulet")), WARDED_MAIL = addItem("warded_mail", new WardedMailItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.warded_mail")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.warded_mail")), SAPPING_SWORD = addItem("sapping_sword", new SappingSwordItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.sapping_sword")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.sapping_sword")), SANGUINE_AMULET = addItem("sanguine_amulet", new SanguineAmuletItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.sanguine_amulet")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.sanguine_amulet")), + ENERVATING_RING = addItem("enervating_ring", new EnervatingRingItem(itemProps() + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.enervating_ring")), SOULFIRE_WAND = addItem("soulfire_wand", new SoulfireWandItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1).maxDamage(253).setNoRepair()) + .rarity(Rarity.UNCOMMON).stacksTo(1).durability(253).setNoRepair()) .setLore("lore.eidolon.soulfire_wand")), BONECHILL_WAND = addItem("bonechill_wand", new BonechillWandItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1).maxDamage(253).setNoRepair()) + .rarity(Rarity.UNCOMMON).stacksTo(1).durability(253).setNoRepair()) .setLore("lore.eidolon.bonechill_wand")), GRAVITY_BELT = addItem("gravity_belt", new GravityBeltItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.gravity_belt")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.gravity_belt")), RESOLUTE_BELT = addItem("resolute_belt", new ResoluteBeltItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.resolute_belt")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.resolute_belt")), PRESTIGIOUS_PALM = addItem("prestigious_palm", new PrestigiousPalmItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.prestigious_palm")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.prestigious_palm")), MIND_SHIELDING_PLATE = addItem("mind_shielding_plate", new MindShieldingPlateItem(itemProps() - .rarity(Rarity.UNCOMMON).maxStackSize(1)).setLore("lore.eidolon.mind_shielding_plate")), + .rarity(Rarity.UNCOMMON).stacksTo(1)).setLore("lore.eidolon.mind_shielding_plate")), GLASS_HAND = addItem("glass_hand", new GlassHandItem(itemProps() - .rarity(Rarity.RARE).maxStackSize(1)).setLore("lore.eidolon.glass_hand")), - PAROUSIA_DISC = addItem("music_disc_parousia", new MusicDiscItem(9, () -> PAROUSIA.get(), - itemProps().maxStackSize(1).group(ItemGroup.MISC).rarity(Rarity.RARE))); + .rarity(Rarity.RARE).stacksTo(1)).setLore("lore.eidolon.glass_hand")), + TERMINUS_MIRROR = addItem("terminus_mirror", new TerminusMirrorItem(itemProps() + .rarity(Rarity.RARE).stacksTo(1)).setLore("lore.eidolon.terminus_mirror")), + ANGELS_SIGHT = addItem("angels_sight", new AngelSightItem(itemProps() + .rarity(Rarity.RARE).stacksTo(1)).setLore("lore.eidolon.angels_sight")), + PAROUSIA_DISC = addItem("music_disc_parousia", new RecordItem(9, () -> PAROUSIA.get(), + itemProps().stacksTo(1).tab(CreativeModeTab.TAB_MISC).rarity(Rarity.RARE))), + RAVEN_FEATHER = addItem("raven_feather"), + ALCHEMISTS_TONGS = addItem("alchemists_tongs", new TongsItem(itemProps().stacksTo(1))), + MERAMMER_RESIN = addItem("merammer_resin"); public static RegistryObject - LEAD_ORE = addBlock("lead_ore", blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.8f, 3.0f) - .harvestLevel(2).harvestTool(ToolType.PICKAXE)), - LEAD_BLOCK = addBlock("lead_block", blockProps(Material.ROCK, MaterialColor.PURPLE_TERRACOTTA) - .sound(SoundType.METAL).hardnessAndResistance(3.0f, 3.0f) - .harvestLevel(2).harvestTool(ToolType.PICKAXE)), - PEWTER_BLOCK = addBlock("pewter_block", blockProps(Material.ROCK, MaterialColor.LIGHT_GRAY) - .sound(SoundType.METAL).hardnessAndResistance(4.0f, 4.0f) - .harvestLevel(2).harvestTool(ToolType.PICKAXE)), - ARCANE_GOLD_BLOCK = addBlock("arcane_gold_block", blockProps(Material.ROCK, MaterialColor.GOLD) - .sound(SoundType.METAL).hardnessAndResistance(3.0f, 4.0f) - .harvestLevel(2).harvestTool(ToolType.PICKAXE)), + LEAD_ORE = addBlock("lead_ore", blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.8f, 3.0f)), + DEEP_LEAD_ORE = addBlock("deep_lead_ore", blockProps(Material.STONE, MaterialColor.DEEPSLATE) + .sound(SoundType.STONE).strength(3.2f, 3.0f)), + LEAD_BLOCK = addBlock("lead_block", blockProps(Material.STONE, MaterialColor.TERRACOTTA_PURPLE) + .sound(SoundType.METAL).strength(3.0f, 3.0f)), + RAW_LEAD_BLOCK = addBlock("raw_lead_block", blockProps(Material.STONE, MaterialColor.TERRACOTTA_PURPLE) + .sound(SoundType.STONE).strength(2.4f, 3.0f)), + SILVER_ORE = addBlock("silver_ore", blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(3.2f, 3.0f)), + DEEP_SILVER_ORE = addBlock("deep_silver_ore", blockProps(Material.STONE, MaterialColor.DEEPSLATE) + .sound(SoundType.STONE).strength(3.6f, 3.0f)), + SILVER_BLOCK = addBlock("silver_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_BLUE) + .sound(SoundType.METAL).strength(3.0f, 3.0f)), + RAW_SILVER_BLOCK = addBlock("raw_silver_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_BLUE) + .sound(SoundType.STONE).strength(2.4f, 3.0f)), + PEWTER_BLOCK = addBlock("pewter_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_GRAY) + .sound(SoundType.METAL).strength(4.0f, 4.0f)), + ARCANE_GOLD_BLOCK = addBlock("arcane_gold_block", blockProps(Material.STONE, MaterialColor.GOLD) + .sound(SoundType.METAL).strength(3.0f, 4.0f)), + SHADOW_GEM_BLOCK = addBlock("shadow_gem_block", blockProps(Material.STONE, MaterialColor.COLOR_PURPLE) + .sound(SoundType.METAL).strength(3.0f, 4.0f)), WOODEN_ALTAR = addBlock("wooden_altar", new TableBlockBase(blockProps(Material.WOOD, MaterialColor.WOOD) - .sound(SoundType.WOOD).hardnessAndResistance(1.6f, 3.0f) - .harvestTool(ToolType.AXE))), - STONE_ALTAR = addBlock("stone_altar", new TableBlockBase(blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.8f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE).notSolid()) - .setMainShape(VoxelShapes.or( - VoxelShapes.create(0, 0.375, 0, 1, 1, 1), - VoxelShapes.create(0.0625, 0.125, 0.0625, 0.9375, 0.375, 0.9375) + .sound(SoundType.WOOD).strength(1.6f, 3.0f))), + STONE_ALTAR = addBlock("stone_altar", new TableBlockBase(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.8f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setMainShape(Shapes.or( + Shapes.box(0, 0.375, 0, 1, 1, 1), + Shapes.box(0.0625, 0.125, 0.0625, 0.9375, 0.375, 0.9375) ))), - CANDLE = addBlock("candle", new CandleBlock(blockProps(Material.MISCELLANEOUS, MaterialColor.WHITE_TERRACOTTA) - .sound(SoundType.STONE).setLightLevel((state) -> 15).hardnessAndResistance(0.6f, 0.8f).notSolid())), - CANDLESTICK = addBlock("candlestick", new CandlestickBlock(blockProps(Material.IRON, MaterialColor.GOLD) - .sound(SoundType.STONE).setLightLevel((state) -> 15).hardnessAndResistance(1.2f, 2.0f).notSolid())), - STRAW_EFFIGY = addBlock("straw_effigy", new HorizontalWaterloggableBlock(blockProps(Material.PLANTS, MaterialColor.YELLOW) - .sound(SoundType.WOOD).hardnessAndResistance(1.4f, 2.0f) - .notSolid()).setShape( - VoxelShapes.create(0.28125, 0, 0.28125, 0.71875, 1, 0.71875) + CANDLE = addBlock("candle", new CandleBlock(blockProps(Material.DECORATION, MaterialColor.TERRACOTTA_WHITE) + .sound(SoundType.STONE).lightLevel((state) -> 15).strength(0.6f, 0.8f).noOcclusion())), + CANDLESTICK = addBlock("candlestick", new CandlestickBlock(blockProps(Material.METAL, MaterialColor.GOLD) + .sound(SoundType.STONE).lightLevel((state) -> 15).strength(1.2f, 2.0f).noOcclusion())), + STRAW_EFFIGY = addBlock("straw_effigy", new EffigyBlock(blockProps(Material.PLANT, MaterialColor.COLOR_YELLOW) + .sound(SoundType.WOOD).strength(1.4f, 2.0f) + .noOcclusion()).setShape( + Shapes.box(0.28125, 0, 0.28125, 0.71875, 1, 0.71875) )), - GOBLET = addBlock("goblet", new BlockBase(blockProps(Material.IRON, MaterialColor.GOLD) - .sound(SoundType.METAL).hardnessAndResistance(1.4f, 2.0f).setRequiresTool().harvestTool(ToolType.PICKAXE) - .notSolid()).setShape(VoxelShapes.create(0.3125, 0, 0.3125, 0.6875, 0.5, 0.6875))), - UNHOLY_EFFIGY = addBlock("unholy_effigy", new HorizontalWaterloggableBlock(blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.8f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE) - .notSolid()).setShape( - VoxelShapes.create(0.25, 0, 0.25, 0.75, 1, 0.75) + GOBLET = addBlock("goblet", new BlockBase(blockProps(Material.METAL, MaterialColor.GOLD) + .sound(SoundType.METAL).strength(1.4f, 2.0f).requiresCorrectToolForDrops() + .noOcclusion()).setShape(Shapes.box(0.3125, 0, 0.3125, 0.6875, 0.5, 0.6875))), + UNHOLY_EFFIGY = addBlock("unholy_effigy", new EffigyBlock(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.8f, 3.0f) + .requiresCorrectToolForDrops() + .noOcclusion()).setShape( + Shapes.box(0.25, 0, 0.25, 0.75, 1, 0.75) )), WORKTABLE = addBlock("worktable", new WorktableBlock(blockProps(Material.WOOD, MaterialColor.WOOD) - .sound(SoundType.WOOD).hardnessAndResistance(1.6f, 3.0f) - .harvestTool(ToolType.AXE).notSolid()).setShape(VoxelShapes.or( - VoxelShapes.create(0, 0, 0, 1, 0.25, 1), - VoxelShapes.create(0.125, 0.25, 0.125, 0.875, 0.625, 0.875), - VoxelShapes.create(0, 0.625, 0, 1, 1, 1) + .sound(SoundType.WOOD).strength(1.6f, 3.0f) + .noOcclusion()).setShape(Shapes.or( + Shapes.box(0, 0, 0, 1, 0.25, 1), + Shapes.box(0.125, 0.25, 0.125, 0.875, 0.625, 0.875), + Shapes.box(0, 0.625, 0, 1, 1, 1) ))), - PLINTH = addBlock("plinth", new PlinthBlockBase(blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.0f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE).notSolid()) - .setShape(VoxelShapes.create(0.25, 0, 0.25, 0.75, 1, 0.75))), - BRAZIER = addBlock("brazier", new BlockBase(blockProps(Material.WOOD, MaterialColor.IRON) - .sound(SoundType.METAL).hardnessAndResistance(2.5f, 3.0f) - .notSolid()) - .setShape(VoxelShapes.create(0.1875, 0, 0.1875, 0.8125, 0.75, 0.8125))), - CRUCIBLE = addBlock("crucible", new BlockBase(blockProps(Material.IRON, MaterialColor.IRON) - .sound(SoundType.METAL).hardnessAndResistance(4.0f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE).notSolid()) - .setShape(VoxelShapes.or( - VoxelShapes.create(0.0625, 0.875, 0.0625, 0.1875, 1, 0.9375), - VoxelShapes.create(0.8125, 0.875, 0.0625, 0.9375, 1, 0.9375), - VoxelShapes.create(0.0625, 0.875, 0.0625, 0.9375, 1, 0.1875), - VoxelShapes.create(0.0625, 0.875, 0.8125, 0.9375, 1, 0.9375), - VoxelShapes.create(0, 0.125, 0, 0.125, 0.875, 1), - VoxelShapes.create(0.875, 0.125, 0, 1, 0.875, 1), - VoxelShapes.create(0, 0.125, 0, 1, 0.875, 0.125), - VoxelShapes.create(0, 0.125, 0.875, 1, 0.875, 1), - VoxelShapes.create(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375) + PLINTH = addBlock("plinth", new PillarBlockBase(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.0f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.box(0.25, 0, 0.25, 0.75, 1, 0.75))), + OBELISK = addBlock("obelisk", new PillarBlockBase(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.0f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.box(0.125, 0, 0.125, 0.875, 1, 0.875))), + BRAZIER = addBlock("brazier", new BrazierBlock(blockProps(Material.WOOD, MaterialColor.METAL) + .sound(SoundType.METAL).strength(2.5f, 3.0f) + .noOcclusion()) + .setShape(Shapes.box(0.1875, 0, 0.1875, 0.8125, 0.75, 0.8125))), + CRUCIBLE = addBlock("crucible", new CrucibleBlock(blockProps(Material.METAL, MaterialColor.METAL) + .sound(SoundType.METAL).strength(4.0f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.or( + Shapes.box(0.0625, 0.875, 0.0625, 0.1875, 1, 0.9375), + Shapes.box(0.8125, 0.875, 0.0625, 0.9375, 1, 0.9375), + Shapes.box(0.0625, 0.875, 0.0625, 0.9375, 1, 0.1875), + Shapes.box(0.0625, 0.875, 0.8125, 0.9375, 1, 0.9375), + Shapes.box(0, 0.125, 0, 0.125, 0.875, 1), + Shapes.box(0.875, 0.125, 0, 1, 0.875, 1), + Shapes.box(0, 0.125, 0, 1, 0.875, 0.125), + Shapes.box(0, 0.125, 0.875, 1, 0.875, 1), + Shapes.box(0.0625, 0, 0.0625, 0.9375, 0.125, 0.9375) ))), - STONE_HAND = addBlock("stone_hand", new HorizontalWaterloggableBlock(blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.0f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE).notSolid()) - .setShape(VoxelShapes.create(0.25, 0, 0.25, 0.75, 0.75, 0.75))), - ENCHANTED_ASH = addBlock("enchanted_ash", new EnchantedAshBlock(blockProps(Material.MISCELLANEOUS, MaterialColor.WHITE_TERRACOTTA) - .sound(SoundType.STONE).hardnessAndResistance(0.0f, 0.75f).notSolid()) - .setShape(VoxelShapes.empty())), - NECROTIC_FOCUS = addBlock("necrotic_focus", new NecroticFocusBlock(blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).hardnessAndResistance(2.8f, 3.0f) - .setRequiresTool().harvestTool(ToolType.PICKAXE).notSolid()) - .setShape(VoxelShapes.create(0.25, 0, 0.25, 0.75, 0.75, 0.75))), - SOUL_ENCHANTER = addBlock("soul_enchanter", new SoulEnchanterBlock(blockProps(Material.ROCK, MaterialColor.OBSIDIAN) - .sound(SoundType.STONE).hardnessAndResistance(5.0f, 1200.0f) - .harvestTool(ToolType.PICKAXE).setRequiresTool().notSolid()) - .setShape(VoxelShapes.create(0, 0, 0, 1, 0.75, 1))), - WOODEN_STAND = addBlock("wooden_brewing_stand", new WoodenStandBlock(blockProps(Material.IRON, MaterialColor.WOOD) - .sound(SoundType.STONE).hardnessAndResistance(2.0f, 3.0f) - .harvestTool(ToolType.PICKAXE).notSolid())); + STONE_HAND = addBlock("stone_hand", new HandBlock(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.0f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.box(0.25, 0, 0.25, 0.75, 0.75, 0.75))), + ENCHANTED_ASH = addBlock("enchanted_ash", new EnchantedAshBlock(blockProps(Material.DECORATION, MaterialColor.TERRACOTTA_WHITE) + .sound(SoundType.STONE).strength(0.0f, 0.75f).noOcclusion()) + .setShape(Shapes.empty())), + NECROTIC_FOCUS = addBlock("necrotic_focus", new NecroticFocusBlock(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.8f, 3.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.box(0.25, 0, 0.25, 0.75, 0.75, 0.75))), + PLANTER = addBlock("planter", new BlockBase(blockProps(Material.WOOD, MaterialColor.WOOD) + .sound(SoundType.WOOD).strength(2.0f, 3.0f) + .noOcclusion()) + .setShape(Shapes.or( + Shapes.box(0, 0.25, 0, 1, 1, 1), + Shapes.box(0.25, 0, 0.25, 0.75, 0.25, 0.75)))), + MERAMMER_ROOT = addBlock("merammer_root", new HerbBlockBase(blockProps(Material.PLANT, MaterialColor.GRASS) + .sound(SoundType.GRASS).noOcclusion())), + AVENNIAN_SPRIG = addBlock("avennian_sprig", new HerbBlockBase(blockProps(Material.PLANT, MaterialColor.GRASS) + .sound(SoundType.GRASS).noOcclusion())), + OANNA_BLOOM = addBlock("oanna_bloom", new HerbBlockBase(blockProps(Material.PLANT, MaterialColor.GRASS) + .sound(SoundType.GRASS).noOcclusion())), + SILDRIAN_SEED = addBlock("sildrian_seed", new HerbBlockBase(blockProps(Material.PLANT, MaterialColor.GRASS) + .sound(SoundType.GRASS).noOcclusion())), + SOUL_ENCHANTER = addBlock("soul_enchanter", new SoulEnchanterBlock(blockProps(Material.STONE, MaterialColor.PODZOL) + .sound(SoundType.STONE).strength(5.0f, 1200.0f) + .requiresCorrectToolForDrops().noOcclusion()) + .setShape(Shapes.box(0, 0, 0, 1, 0.75, 1))), + WOODEN_STAND = addBlock("wooden_brewing_stand", new WoodenStandBlock(blockProps(Material.METAL, MaterialColor.WOOD) + .sound(SoundType.STONE).strength(2.0f, 3.0f) + .noOcclusion())), + INCUBATOR = addBlock("incubator", new TwoHighBlockBase(blockProps(Material.METAL, MaterialColor.METAL) + .sound(SoundType.GLASS).strength(2.0f, 3.0f) + .noOcclusion()).setShape(Shapes.box(0.0625, 0, 0.0625, 0.9375, 1, 0.9375))), + GLASS_TUBE = addBlock("glass_tube", new PipeBlock(blockProps(Material.GLASS, MaterialColor.COLOR_LIGHT_BLUE) + .sound(SoundType.GLASS).strength(1.0f, 1.5f).noOcclusion())), + CISTERN = addBlock("cistern", new CisternBlock(blockProps(Material.GLASS, MaterialColor.COLOR_LIGHT_BLUE) + .sound(SoundType.GLASS).strength(1.5f, 1.5f).noOcclusion()) + .setShape(Shapes.box(0.0625, 0, 0.0625, 0.9375, 1, 0.9375))); public static DecoBlockPack - SMOOTH_STONE_BRICK = new DecoBlockPack(BLOCKS, "smooth_stone_bricks", blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).setRequiresTool().harvestTool(ToolType.PICKAXE).hardnessAndResistance(2.0f, 3.0f)) + SMOOTH_STONE_BRICK = new DecoBlockPack(BLOCKS, "smooth_stone_bricks", blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).requiresCorrectToolForDrops().strength(2.0f, 3.0f)) .addWall(), - SMOOTH_STONE_TILES = new DecoBlockPack(BLOCKS, "smooth_stone_tiles", blockProps(Material.ROCK, MaterialColor.STONE) - .sound(SoundType.STONE).setRequiresTool().harvestTool(ToolType.PICKAXE).hardnessAndResistance(2.0f, 3.0f)), + SMOOTH_STONE_TILES = new DecoBlockPack(BLOCKS, "smooth_stone_tiles", blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).requiresCorrectToolForDrops().strength(2.0f, 3.0f)), POLISHED_PLANKS = new DecoBlockPack(BLOCKS, "polished_planks", blockProps(Material.WOOD, MaterialColor.WOOD) - .sound(SoundType.WOOD).harvestTool(ToolType.AXE).hardnessAndResistance(1.6f, 3.0f)) + .sound(SoundType.WOOD).strength(1.6f, 3.0f)) .addFence(); public static RegistryObject POLISHED_WOOD_PILLAR = addBlock("polished_wood_pillar", new RotatedPillarBlock(blockProps(Material.WOOD, MaterialColor.WOOD) - .harvestTool(ToolType.AXE).hardnessAndResistance(1.6f, 3.0f))); + .strength(1.6f, 3.0f))); public static RegistryObject> - ZOMBIE_BRUTE = addEntity("zombie_brute", 7969893, 44975, 1.2f, 2.5f, ZombieBruteEntity::new, EntityClassification.MONSTER); + ZOMBIE_BRUTE = addEntity("zombie_brute", 7969893, 44975, 1.2f, 2.5f, ZombieBruteEntity::new, MobCategory.MONSTER); public static RegistryObject> - WRAITH = addEntity("wraith", 0x706e6b, 0xadacbd, 0.6f, 1.9f, WraithEntity::new, EntityClassification.MONSTER); + WRAITH = addEntity("wraith", 0x706e6b, 0xadacbd, 0.6f, 1.9f, WraithEntity::new, MobCategory.MONSTER); public static RegistryObject> - SOULFIRE_PROJECTILE = addEntity("soulfire_projectile", 0.4f, 0.4f, SoulfireProjectileEntity::new, EntityClassification.MISC); + SOULFIRE_PROJECTILE = addEntity("soulfire_projectile", 0.4f, 0.4f, SoulfireProjectileEntity::new, MobCategory.MISC); public static RegistryObject> - BONECHILL_PROJECTILE = addEntity("bonechill_projectile", 0.4f, 0.4f, BonechillProjectileEntity::new, EntityClassification.MISC); + BONECHILL_PROJECTILE = addEntity("bonechill_projectile", 0.4f, 0.4f, BonechillProjectileEntity::new, MobCategory.MISC); public static RegistryObject> - NECROMANCER_SPELL = addEntity("necromancer_spell", 0.4f, 0.4f, NecromancerSpellEntity::new, EntityClassification.MISC); + NECROMANCER_SPELL = addEntity("necromancer_spell", 0.4f, 0.4f, NecromancerSpellEntity::new, MobCategory.MISC); public static RegistryObject> - CHANT_CASTER = addEntity("chant_caster", 0.1f, 0.1f, ChantCasterEntity::new, EntityClassification.MISC); + CHANT_CASTER = addEntity("chant_caster", 0.1f, 0.1f, ChantCasterEntity::new, MobCategory.MISC); + public static RegistryObject> + ANGEL_ARROW = addEntity("angel_arrow", 0.5f, 0.5f, AngelArrowEntity::new, MobCategory.MISC); public static RegistryObject> - NECROMANCER = addEntity("necromancer", 0x69255e, 0x9ce8ff, 0.6f, 1.9f, NecromancerEntity::new, EntityClassification.MONSTER); + NECROMANCER = addEntity("necromancer", 0x69255e, 0x9ce8ff, 0.6f, 1.9f, NecromancerEntity::new, MobCategory.MONSTER); + public static RegistryObject> + RAVEN = addEntity("raven", 0x1e1f24, 0x404f66, 0.375f, 0.5f, RavenEntity::new, MobCategory.CREATURE); + public static RegistryObject> + SLIMY_SLUG = addEntity("slimy_slug", 0xdbe388, 0x5f9e42, 0.5f, 0.25f, SlimySlugEntity::new, MobCategory.CREATURE); - public static RegistryObject> + public static RegistryObject> WORKTABLE_CONTAINER = addContainer("worktable", WorktableContainer::new); - public static RegistryObject> + public static RegistryObject> SOUL_ENCHANTER_CONTAINER = addContainer("soul_enchanter", SoulEnchanterContainer::new); - public static RegistryObject> + public static RegistryObject> WOODEN_STAND_CONTAINER = addContainer("wooden_brewing_stand", WoodenBrewingStandContainer::new); + public static RegistryObject> + WORKTABLE_RECIPE = RECIPE_TYPES.register("worktable", () -> new WorktableRecipe.Serializer()); + public static RegistryObject> + CRUCIBLE_RECIPE = RECIPE_TYPES.register("crucible", () -> new CrucibleRecipe.Serializer()); + public static void init() { BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus()); ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); @@ -396,32 +619,40 @@ public static void init() { PARTICLES.register(FMLJavaModLoadingContext.get().getModEventBus()); SOUND_EVENTS.register(FMLJavaModLoadingContext.get().getModEventBus()); CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus()); + RECIPE_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus()); } public static void addBrewingRecipes() { - System.out.println("calling addBrewingRecipes"); PotionBrewingMixin.callAddMix(Potions.WATER, Registry.FUNGUS_SPROUTS.get(), Potions.AWKWARD); PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.WRAITH_HEART.get(), Registry.CHILLED_POTION.get()); PotionBrewingMixin.callAddMix(Registry.CHILLED_POTION.get(), Items.REDSTONE, Registry.LONG_CHILLED_POTION.get()); PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.WARPED_SPROUTS.get(), Registry.ANCHORED_POTION.get()); PotionBrewingMixin.callAddMix(Registry.ANCHORED_POTION.get(), Items.REDSTONE, Registry.LONG_ANCHORED_POTION.get()); + PotionBrewingMixin.callAddMix(Potions.AWKWARD, Items.LEATHER, Registry.REINFORCED_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.REINFORCED_POTION.get(), Items.REDSTONE, Registry.LONG_REINFORCED_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.REINFORCED_POTION.get(), Items.GLOWSTONE, Registry.STRONG_REINFORCED_POTION.get()); + PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.TATTERED_CLOTH.get(), Registry.VULNERABLE_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.VULNERABLE_POTION.get(), Items.REDSTONE, Registry.LONG_VULNERABLE_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.VULNERABLE_POTION.get(), Items.GLOWSTONE, Registry.STRONG_VULNERABLE_POTION.get()); } @OnlyIn(Dist.CLIENT) public static void clientInit() { } - public static TileEntityType HAND_TILE_ENTITY; - public static TileEntityType BRAZIER_TILE_ENTITY; - public static TileEntityType NECROTIC_FOCUS_TILE_ENTITY; - public static TileEntityType CRUCIBLE_TILE_ENTITY; - public static TileEntityType EFFIGY_TILE_ENTITY; - public static TileEntityType SOUL_ENCHANTER_TILE_ENTITY; - public static TileEntityType WOODEN_STAND_TILE_ENTITY; - public static TileEntityType GOBLET_TILE_ENTITY; + public static BlockEntityType HAND_TILE_ENTITY; + public static BlockEntityType BRAZIER_TILE_ENTITY; + public static BlockEntityType NECROTIC_FOCUS_TILE_ENTITY; + public static BlockEntityType CRUCIBLE_TILE_ENTITY; + public static BlockEntityType EFFIGY_TILE_ENTITY; + public static BlockEntityType SOUL_ENCHANTER_TILE_ENTITY; + public static BlockEntityType WOODEN_STAND_TILE_ENTITY; + public static BlockEntityType GOBLET_TILE_ENTITY; + public static BlockEntityType CISTERN_TILE_ENTITY; + public static BlockEntityType PIPE_TILE_ENTITY; @SubscribeEvent - public void registerTiles(RegistryEvent.Register> evt) { + public void registerTiles(RegistryEvent.Register> evt) { HAND_TILE_ENTITY = addTileEntity(evt.getRegistry(), "hand_tile", HandTileEntity::new, STONE_HAND.get()); BRAZIER_TILE_ENTITY = addTileEntity(evt.getRegistry(), "brazier_tile", BrazierTileEntity::new, BRAZIER.get()); NECROTIC_FOCUS_TILE_ENTITY = addTileEntity(evt.getRegistry(), "necrotic_focus", NecroticFocusTileEntity::new, NECROTIC_FOCUS.get()); @@ -430,10 +661,26 @@ public void registerTiles(RegistryEvent.Register> evt) { SOUL_ENCHANTER_TILE_ENTITY = addTileEntity(evt.getRegistry(), "soul_enchanter", SoulEnchanterTileEntity::new, SOUL_ENCHANTER.get()); WOODEN_STAND_TILE_ENTITY = addTileEntity(evt.getRegistry(), "wooden_brewing_stand", WoodenStandTileEntity::new, WOODEN_STAND.get()); GOBLET_TILE_ENTITY = addTileEntity(evt.getRegistry(), "goblet", GobletTileEntity::new, GOBLET.get()); + CISTERN_TILE_ENTITY = addTileEntity(evt.getRegistry(), "cistern", CisternTileEntity::new, CISTERN.get()); + PIPE_TILE_ENTITY = addTileEntity(evt.getRegistry(), "pipe", PipeTileEntity::new, GLASS_TUBE.get()); } - public static DamageSource RITUAL_DAMAGE = new DamageSource("ritual").setDamageBypassesArmor().setDamageIsAbsolute(); + public static DamageSource RITUAL_DAMAGE = new DamageSource("ritual").bypassArmor().bypassMagic(); public static DamageSource FROST_DAMAGE = new DamageSource("frost"); + + public void registerCaps(RegisterCapabilitiesEvent event) { + event.register(IReputation.class); + event.register(IKnowledge.class); + } + + @SubscribeEvent + public void defineAttributes(EntityAttributeCreationEvent event) { + event.put(Registry.ZOMBIE_BRUTE.get(), ZombieBruteEntity.createAttributes()); + event.put(Registry.WRAITH.get(), WraithEntity.createAttributes()); + event.put(Registry.NECROMANCER.get(), NecromancerEntity.createAttributes()); + event.put(Registry.RAVEN.get(), RavenEntity.createAttributes()); + event.put(Registry.SLIMY_SLUG.get(), SlimySlugEntity.createAttributes()); + } static DeferredRegister> PARTICLES = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, Eidolon.MODID); @@ -457,14 +704,14 @@ public void registerTiles(RegistryEvent.Register> evt) { @OnlyIn(Dist.CLIENT) @SubscribeEvent public void registerFactories(ParticleFactoryRegisterEvent evt) { - Minecraft.getInstance().particles.registerFactory(FLAME_PARTICLE.get(), FlameParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(SMOKE_PARTICLE.get(), SmokeParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(SPARKLE_PARTICLE.get(), SparkleParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(WISP_PARTICLE.get(), WispParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(BUBBLE_PARTICLE.get(), BubbleParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(STEAM_PARTICLE.get(), SteamParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(LINE_WISP_PARTICLE.get(), LineWispParticleType.Factory::new); - Minecraft.getInstance().particles.registerFactory(SIGN_PARTICLE.get(), (sprite) -> new SignParticleType.Factory()); + Minecraft.getInstance().particleEngine.register(FLAME_PARTICLE.get(), FlameParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(SMOKE_PARTICLE.get(), SmokeParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(SPARKLE_PARTICLE.get(), SparkleParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(WISP_PARTICLE.get(), WispParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(BUBBLE_PARTICLE.get(), BubbleParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(STEAM_PARTICLE.get(), SteamParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(LINE_WISP_PARTICLE.get(), LineWispParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(SIGN_PARTICLE.get(), (sprite) -> new SignParticleType.Factory()); } @OnlyIn(Dist.CLIENT) @@ -481,6 +728,93 @@ public void onTextureStitch(TextureStitchEvent.Pre event) { event.addSprite(SanguineRitual.SYMBOL); event.addSprite(SoulEnchanterTileRenderer.BOOK_TEXTURE); + for (Reagent r : ReagentRegistry.getReagents()) event.addSprite(r.getTexture()); for (Sign s : Signs.getSigns()) event.addSprite(s.getSprite()); } + + public static ModelLayerLocation + SILVER_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "silver_armor"), "main"), + WARLOCK_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "warlock_armor"), "main"), + TOP_HAT_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "top_hat"), "main"), + RAVEN_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "raven"), "main"), + NECROMANCER_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "necromancer"), "main"), + WRAITH_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "wraith"), "main"), + ZOMBIE_BRUTE_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "zombie_brute"), "main"), + SLUG_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "slimy_slug"), "main"); + + public static WarlockArmorModel WARLOCK_ARMOR_MODEL = null; + public static TopHatModel TOP_HAT_MODEL = null; + public static SilverArmorModel SILVER_ARMOR_MODEL = null; + public static ZombieBruteModel ZOMBIE_BRUTE_MODEL = null; + public static WraithModel WRAITH_MODEL = null; + public static RavenModel RAVEN_MODEL = null; + public static NecromancerModel NECROMANCER_MODEL = null; + public static SlimySlugModel SLUG_MODEL = null; + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public void onRegisterLayers(EntityRenderersEvent.RegisterLayerDefinitions event) { + event.registerLayerDefinition(WARLOCK_ARMOR_LAYER, WarlockArmorModel::createBodyLayer); + event.registerLayerDefinition(TOP_HAT_LAYER, TopHatModel::createBodyLayer); + event.registerLayerDefinition(SILVER_ARMOR_LAYER, SilverArmorModel::createBodyLayer); + + event.registerLayerDefinition(RAVEN_LAYER, RavenModel::createBodyLayer); + event.registerLayerDefinition(ZOMBIE_BRUTE_LAYER, ZombieBruteModel::createBodyLayer); + event.registerLayerDefinition(WRAITH_LAYER, WraithModel::createBodyLayer); + event.registerLayerDefinition(NECROMANCER_LAYER, NecromancerModel::createBodyLayer); + event.registerLayerDefinition(SLUG_LAYER, SlimySlugModel::createBodyLayer); + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public void onRegisterLayers(EntityRenderersEvent.AddLayers event) { + WARLOCK_ARMOR_MODEL = new WarlockArmorModel(event.getEntityModels().bakeLayer(WARLOCK_ARMOR_LAYER)); + TOP_HAT_MODEL = new TopHatModel(event.getEntityModels().bakeLayer(TOP_HAT_LAYER)); + SILVER_ARMOR_MODEL = new SilverArmorModel(event.getEntityModels().bakeLayer(SILVER_ARMOR_LAYER)); + + RAVEN_MODEL = new RavenModel(event.getEntityModels().bakeLayer(RAVEN_LAYER)); + ZOMBIE_BRUTE_MODEL = new ZombieBruteModel(event.getEntityModels().bakeLayer(ZOMBIE_BRUTE_LAYER)); + WRAITH_MODEL = new WraithModel(event.getEntityModels().bakeLayer(WRAITH_LAYER)); + NECROMANCER_MODEL = new NecromancerModel(event.getEntityModels().bakeLayer(NECROMANCER_LAYER)); + SLUG_MODEL = new SlimySlugModel(event.getEntityModels().bakeLayer(SLUG_LAYER)); + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public void onRegisterEntityRenders(EntityRenderersEvent.RegisterRenderers event) { + EntityRenderers.register(Registry.ZOMBIE_BRUTE.get(), ZombieBruteRenderer::new); + EntityRenderers.register(Registry.WRAITH.get(), WraithRenderer::new); + EntityRenderers.register(Registry.NECROMANCER.get(), NecromancerRenderer::new); + EntityRenderers.register(Registry.SOULFIRE_PROJECTILE.get(), NoopRenderer::new); + EntityRenderers.register(Registry.BONECHILL_PROJECTILE.get(), NoopRenderer::new); + EntityRenderers.register(Registry.NECROMANCER_SPELL.get(), NoopRenderer::new); + EntityRenderers.register(Registry.CHANT_CASTER.get(), NoopRenderer::new); + EntityRenderers.register(Registry.RAVEN.get(), RavenRenderer::new); + EntityRenderers.register(Registry.ANGEL_ARROW.get(), AngelArrowRenderer::new); + EntityRenderers.register(Registry.SLIMY_SLUG.get(), SlimySlugRenderer::new); + } + + @OnlyIn(Dist.CLIENT) + public static ShaderInstance GLOWING_SHADER, GLOWING_SPRITE_SHADER, GLOWING_PARTICLE_SHADER, VAPOR_SHADER, GLOWING_ENTITY_SHADER; + + public static ShaderInstance getGlowingShader() { return GLOWING_SHADER; } + public static ShaderInstance getGlowingSpriteShader() { return GLOWING_SPRITE_SHADER; } + public static ShaderInstance getGlowingParticleShader() { return GLOWING_PARTICLE_SHADER; } + public static ShaderInstance getGlowingEntityShader() { return GLOWING_ENTITY_SHADER; } + public static ShaderInstance getVaporShader() { return VAPOR_SHADER; } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public void shaderRegistry(RegisterShadersEvent event) throws IOException { + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing"), DefaultVertexFormat.POSITION_COLOR), + shader -> { GLOWING_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_sprite"), DefaultVertexFormat.POSITION_TEX_COLOR), + shader -> { GLOWING_SPRITE_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_particle"), DefaultVertexFormat.PARTICLE), + shader -> { GLOWING_PARTICLE_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_entity"), DefaultVertexFormat.NEW_ENTITY), + shader -> { GLOWING_ENTITY_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:vapor"), DefaultVertexFormat.BLOCK), + shader -> { VAPOR_SHADER = shader; }); + } } diff --git a/src/main/java/elucent/eidolon/WorldGen.java b/src/main/java/elucent/eidolon/WorldGen.java index b8b240e..361fe41 100644 --- a/src/main/java/elucent/eidolon/WorldGen.java +++ b/src/main/java/elucent/eidolon/WorldGen.java @@ -1,144 +1,204 @@ package elucent.eidolon; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import elucent.eidolon.world.*; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.WorldGenRegistries; -import net.minecraft.world.Dimension; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.DimensionSettings; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.feature.*; -import net.minecraft.world.gen.feature.structure.IStructurePieceType; -import net.minecraft.world.gen.feature.structure.IglooStructure; -import net.minecraft.world.gen.feature.structure.Structure; -import net.minecraft.world.gen.feature.template.RuleTest; -import net.minecraft.world.gen.feature.template.TagMatchRuleTest; -import net.minecraft.world.gen.settings.DimensionStructuresSettings; -import net.minecraft.world.gen.settings.StructureSeparationSettings; +import com.google.common.collect.ImmutableMultimap; + +import elucent.eidolon.world.CatacombPieces; +import elucent.eidolon.world.CatacombStructure; +import elucent.eidolon.world.LabStructure; +import elucent.eidolon.world.RandomlyRotatedPiece; +import elucent.eidolon.world.StrayTowerStructure; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.data.worldgen.features.OreFeatures; +import net.minecraft.data.worldgen.placement.PlacementUtils; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; +import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; +import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest; +import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest; +import net.minecraft.world.level.levelgen.StructureSettings; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration; +import net.minecraft.world.level.levelgen.placement.BiomeFilter; +import net.minecraft.world.level.levelgen.placement.CountPlacement; +import net.minecraft.world.level.levelgen.placement.HeightRangePlacement; +import net.minecraft.world.level.levelgen.placement.InSquarePlacement; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraftforge.common.Tags; import net.minecraftforge.event.world.BiomeLoadingEvent; +import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class WorldGen { - static List> ORES = new ArrayList<>(); - static ConfiguredFeature LEAD_ORE_GEN; - static DeferredRegister> STRUCTURES = DeferredRegister.create(ForgeRegistries.STRUCTURE_FEATURES, Eidolon.MODID); - static List> STRUCTURE_LIST = new ArrayList<>(); - static Map STRUCTURE_SETTINGS = new HashMap<>(); - static RuleTest IN_STONE = new TagMatchRuleTest(Tags.Blocks.STONE); + static List ORES = new ArrayList<>(); + static PlacedFeature LEAD_ORE_GEN, SILVER_ORE_GEN, DEEP_LEAD_ORE_GEN, DEEP_SILVER_ORE_GEN; + static DeferredRegister> STRUCTURES = DeferredRegister.create(ForgeRegistries.STRUCTURE_FEATURES, Eidolon.MODID); + static List> STRUCTURE_LIST = new ArrayList<>(); + static Map STRUCTURE_SETTINGS = new HashMap<>(); + static RuleTest IN_STONE = new TagMatchTest(Tags.Blocks.STONE); + static RuleTest IN_DEEPSLATE = new BlockMatchTest(Blocks.DEEPSLATE); - static IStructurePieceType register(IStructurePieceType type, String name) { - net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.STRUCTURE_PIECE, new ResourceLocation(Eidolon.MODID, name), type); + static StructurePieceType register(StructurePieceType type, String name) { + net.minecraft.core.Registry.register(net.minecraft.core.Registry.STRUCTURE_PIECE, new ResourceLocation(Eidolon.MODID, name), type); return type; } - static > ConfiguredFeature register(ConfiguredFeature feature, String name) { - WorldGenRegistries.register(WorldGenRegistries.CONFIGURED_FEATURE, new ResourceLocation(Eidolon.MODID, name), feature); + static > ConfiguredFeature register(ConfiguredFeature feature, String name) { + BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(Eidolon.MODID, name), feature); return feature; } - static > StructureFeature register(StructureFeature feature, String name) { - WorldGenRegistries.register(WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE, new ResourceLocation(Eidolon.MODID, name), feature); + static > ConfiguredStructureFeature register(ConfiguredStructureFeature feature, String name) { + BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, new ResourceLocation(Eidolon.MODID, name), feature); return feature; } - static RegistryObject> addStructure(String name, Structure structure, GenerationStage.Decoration stage, StructureSeparationSettings settings) { - Structure.NAME_STRUCTURE_BIMAP.put(Eidolon.MODID + ":" + name, structure); - Structure.STRUCTURE_DECORATION_STAGE_MAP.put(structure, stage); + static RegistryObject> addStructure(String name, StructureFeature structure, GenerationStep.Decoration stage, StructureFeatureConfiguration settings) { + StructureFeature.STRUCTURES_REGISTRY.put(Eidolon.MODID + ":" + name, structure); + StructureFeature.STEP.put(structure, stage); STRUCTURE_LIST.add(structure); STRUCTURE_SETTINGS.put(new ResourceLocation(Eidolon.MODID, name), settings); - if (stage != GenerationStage.Decoration.UNDERGROUND_STRUCTURES) { - Structure.field_236384_t_ = ImmutableList.>builder().addAll(Structure.field_236384_t_).add(structure).build(); + if (stage != GenerationStep.Decoration.UNDERGROUND_STRUCTURES) { + StructureFeature.NOISE_AFFECTING_FEATURES = ImmutableList.>builder().addAll(StructureFeature.NOISE_AFFECTING_FEATURES).add(structure).build(); } return STRUCTURES.register(name, () -> structure); } - public static IStructurePieceType LAB_PIECE, STRAY_TOWER_PIECE; + public static StructurePieceType LAB_PIECE, STRAY_TOWER_PIECE; - public static RegistryObject> LAB_STRUCTURE = addStructure("lab", - new LabStructure(NoFeatureConfig.field_236558_a_), - GenerationStage.Decoration.UNDERGROUND_STRUCTURES, - new StructureSeparationSettings(7, 5, 1337)); + public static RegistryObject> LAB_STRUCTURE = addStructure("lab", + new LabStructure(NoneFeatureConfiguration.CODEC), + GenerationStep.Decoration.UNDERGROUND_STRUCTURES, + new StructureFeatureConfiguration(7, 5, 1337)); - public static RegistryObject> STRAY_TOWER_STRUCTURE = addStructure("stray_tower", - new StrayTowerStructure(NoFeatureConfig.field_236558_a_), - GenerationStage.Decoration.UNDERGROUND_STRUCTURES, - new StructureSeparationSettings(16, 8, 1341)); + public static RegistryObject> STRAY_TOWER_STRUCTURE = addStructure("stray_tower", + new StrayTowerStructure(NoneFeatureConfiguration.CODEC), + GenerationStep.Decoration.UNDERGROUND_STRUCTURES, + new StructureFeatureConfiguration(16, 8, 1341)); - public static RegistryObject> CATACOMB_STRUCTURE = addStructure("catacomb", - new CatacombStructure(NoFeatureConfig.field_236558_a_), - GenerationStage.Decoration.UNDERGROUND_STRUCTURES, - new StructureSeparationSettings(11, 7, 1347)); + public static RegistryObject> CATACOMB_STRUCTURE = addStructure("catacomb", + new CatacombStructure(NoneFeatureConfiguration.CODEC), + GenerationStep.Decoration.UNDERGROUND_STRUCTURES, + new StructureFeatureConfiguration(11, 7, 1347)); - public static StructureFeature> LAB_FEATURE, STRAY_TOWER_FEATURE, CATACOMB_FEATURE; + public static ConfiguredStructureFeature> LAB_FEATURE, STRAY_TOWER_FEATURE, CATACOMB_FEATURE; public static void preInit() { STRUCTURES.register(FMLJavaModLoadingContext.get().getModEventBus()); } public static void init() { - LEAD_ORE_GEN = register(Feature.ORE.withConfiguration(new OreFeatureConfig(IN_STONE, - Registry.LEAD_ORE.get().getDefaultState(), Config.LEAD_VEIN_SIZE.get())) - .square() - .func_242731_b(Config.LEAD_VEIN_COUNT.get()) // per chunk - .range(Config.LEAD_MAX_Y.get() // maximum Y - ), "lead_ore"); - if (Config.LEAD_ENABLED.get()) ORES.add(LEAD_ORE_GEN); - - LAB_PIECE = register(LabStructure.Piece::new, "lab"); - LAB_FEATURE = register(LAB_STRUCTURE.get().withConfiguration(NoFeatureConfig.field_236559_b_), "lab"); - - STRAY_TOWER_PIECE = register(StrayTowerStructure.Piece::new, "stray_tower"); - STRAY_TOWER_FEATURE = register(STRAY_TOWER_STRUCTURE.get().withConfiguration(NoFeatureConfig.field_236559_b_), "stray_tower"); - - CatacombPieces.CORRIDOR_CENTER = register(CatacombPieces.CorridorCenter::new, CatacombPieces.CORRIDOR_CENTER_ID.getPath()); - CatacombPieces.CORRIDOR_DOOR = register(CatacombPieces.CorridorDoor::new, CatacombPieces.CORRIDOR_DOOR_ID.getPath()); - CatacombPieces.SMALL_ROOM = register(CatacombPieces.SmallRoom::new, CatacombPieces.SMALL_ROOM_ID.getPath()); - CatacombPieces.SHRINE = register(CatacombPieces.Shrine::new, CatacombPieces.SHRINE_ID.getPath()); - CatacombPieces.TRAP = register(CatacombPieces.Trap::new, CatacombPieces.TRAP_ID.getPath()); - CatacombPieces.SKULL = register(CatacombPieces.Skull::new, CatacombPieces.SKULL_ID.getPath()); - CatacombPieces.SPAWNER = register(CatacombPieces.Spawner::new, CatacombPieces.SPAWNER_ID.getPath()); - CatacombPieces.COFFIN = register(CatacombPieces.Coffin::new, CatacombPieces.COFFIN_ID.getPath()); - CatacombPieces.MEDIUM_ROOM = register(CatacombPieces.MediumRoom::new, CatacombPieces.MEDIUM_ROOM_ID.getPath()); - CatacombPieces.GRAVEYARD = register(CatacombPieces.Graveyard::new, CatacombPieces.GRAVEYARD_ID.getPath()); - CatacombPieces.TURNAROUND = register(CatacombPieces.Turnaround::new, CatacombPieces.TURNAROUND_ID.getPath()); - CatacombPieces.LAB = register(CatacombPieces.Lab::new, CatacombPieces.LAB_ID.getPath()); - CATACOMB_FEATURE = register(CATACOMB_STRUCTURE.get().withConfiguration(NoFeatureConfig.field_236559_b_), "catacomb"); - - for (Structure s : STRUCTURE_LIST) { - DimensionStructuresSettings.field_236191_b_ = // Default structures - ImmutableMap., StructureSeparationSettings>builder() - .putAll(DimensionStructuresSettings.field_236191_b_) + ConfiguredFeature LEAD_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_STONE, + Registry.LEAD_ORE.get().defaultBlockState(), Config.LEAD_VEIN_SIZE.get())), "lead_ore"); + LEAD_ORE_GEN = PlacementUtils.register("lead_ore", LEAD_ORE.placed( + InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.LEAD_VEIN_COUNT.get()), + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.LEAD_MIN_Y.get()), VerticalAnchor.absolute(Config.LEAD_MAX_Y.get())) + )); + ConfiguredFeature DEEP_LEAD_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_DEEPSLATE, + Registry.DEEP_LEAD_ORE.get().defaultBlockState(), Config.LEAD_VEIN_SIZE.get())), "deep_lead_ore"); + DEEP_LEAD_ORE_GEN = PlacementUtils.register("deep_lead_ore", DEEP_LEAD_ORE.placed( + InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.LEAD_VEIN_COUNT.get()), + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.LEAD_MIN_Y.get()), VerticalAnchor.absolute(Config.LEAD_MAX_Y.get())) + )); + if (Config.LEAD_ENABLED.get()) { + ORES.add(LEAD_ORE_GEN); + ORES.add(DEEP_LEAD_ORE_GEN); + } + + ConfiguredFeature SILVER_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_STONE, + Registry.SILVER_ORE.get().defaultBlockState(), Config.SILVER_VEIN_SIZE.get())), "silver_ore"); + SILVER_ORE_GEN = PlacementUtils.register("silver_ore", SILVER_ORE.placed( + InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.SILVER_VEIN_COUNT.get()), + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.SILVER_MIN_Y.get()), VerticalAnchor.absolute(Config.SILVER_MAX_Y.get())) + )); + ConfiguredFeature DEEP_SILVER_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_DEEPSLATE, + Registry.DEEP_SILVER_ORE.get().defaultBlockState(), Config.SILVER_VEIN_SIZE.get())), "deep_silver_ore"); + DEEP_SILVER_ORE_GEN = PlacementUtils.register("deep_silver_ore", DEEP_SILVER_ORE.placed( + InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.SILVER_VEIN_COUNT.get()), + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.SILVER_MIN_Y.get()), VerticalAnchor.absolute(Config.SILVER_MAX_Y.get())) + )); + if (Config.SILVER_ENABLED.get()) { + ORES.add(SILVER_ORE_GEN); + ORES.add(DEEP_SILVER_ORE_GEN); + } + + LAB_PIECE = register((ctx, tag) -> new RandomlyRotatedPiece(LAB_PIECE, tag, ctx.structureManager()), "lab"); + LAB_FEATURE = register(LAB_STRUCTURE.get().configured(NoneFeatureConfiguration.INSTANCE), "lab"); + + STRAY_TOWER_PIECE = register((ctx, tag) -> new RandomlyRotatedPiece(STRAY_TOWER_PIECE, tag, ctx.structureManager()), "stray_tower"); + STRAY_TOWER_FEATURE = register(STRAY_TOWER_STRUCTURE.get().configured(NoneFeatureConfiguration.INSTANCE), "stray_tower"); + + CatacombPieces.CORRIDOR_CENTER = register((ctx, tag) -> new CatacombPieces.CorridorCenter(ctx.structureManager(), tag), CatacombPieces.CORRIDOR_CENTER_ID.getPath()); + CatacombPieces.CORRIDOR_DOOR = register((ctx, tag) -> new CatacombPieces.CorridorDoor(ctx.structureManager(), tag), CatacombPieces.CORRIDOR_DOOR_ID.getPath()); + CatacombPieces.SMALL_ROOM = register((ctx, tag) -> new CatacombPieces.SmallRoom(ctx.structureManager(), tag), CatacombPieces.SMALL_ROOM_ID.getPath()); + CatacombPieces.SHRINE = register((ctx, tag) -> new CatacombPieces.Shrine(ctx.structureManager(), tag), CatacombPieces.SHRINE_ID.getPath()); + CatacombPieces.TRAP = register((ctx, tag) -> new CatacombPieces.Trap(ctx.structureManager(), tag), CatacombPieces.TRAP_ID.getPath()); + CatacombPieces.SKULL = register((ctx, tag) -> new CatacombPieces.Skull(ctx.structureManager(), tag), CatacombPieces.SKULL_ID.getPath()); + CatacombPieces.SPAWNER = register((ctx, tag) -> new CatacombPieces.Spawner(ctx.structureManager(), tag), CatacombPieces.SPAWNER_ID.getPath()); + CatacombPieces.COFFIN = register((ctx, tag) -> new CatacombPieces.Coffin(ctx.structureManager(), tag), CatacombPieces.COFFIN_ID.getPath()); + CatacombPieces.MEDIUM_ROOM = register((ctx, tag) -> new CatacombPieces.MediumRoom(ctx.structureManager(), tag), CatacombPieces.MEDIUM_ROOM_ID.getPath()); + CatacombPieces.GRAVEYARD = register((ctx, tag) -> new CatacombPieces.Graveyard(ctx.structureManager(), tag), CatacombPieces.GRAVEYARD_ID.getPath()); + CatacombPieces.TURNAROUND = register((ctx, tag) -> new CatacombPieces.Turnaround(ctx.structureManager(), tag), CatacombPieces.TURNAROUND_ID.getPath()); + CatacombPieces.LAB = register((ctx, tag) -> new CatacombPieces.Lab(ctx.structureManager(), tag), CatacombPieces.LAB_ID.getPath()); + CATACOMB_FEATURE = register(CATACOMB_STRUCTURE.get().configured(NoneFeatureConfiguration.INSTANCE), "catacomb"); + + for (StructureFeature s : STRUCTURE_LIST) { + StructureSettings.DEFAULTS = // Default structures + ImmutableMap., StructureFeatureConfiguration>builder() + .putAll(StructureSettings.DEFAULTS) .put(s, STRUCTURE_SETTINGS.get(s.getRegistryName())) .build(); - DimensionSettings.field_242740_q.getStructures().field_236193_d_.put(s, STRUCTURE_SETTINGS.get(s.getRegistryName())); + NoiseGeneratorSettings overworld = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.OVERWORLD); + overworld.structureSettings().structureConfig.put(s, STRUCTURE_SETTINGS.get(s.getRegistryName())); } } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load event) { +// if (event.getWorld() instanceof ServerLevel level) { +// StructureSettings settings = level.getChunkSource().getGenerator().getSettings(); +// +// ImmutableMap, ImmutableMultimap, ResourceKey>> +// if (Config.LAB_ENABLED.get()) +// Structure +// settings.structureConfig.computeIfAbsent(LAB_STRUCTURE.get(), ).addFeature(LAB_FEATURE); +// if (Config.CATACOMB_ENABLED.get()) +// event.getGeneration().addStructureStart(CATACOMB_FEATURE); +// if (event.getCategory() == Biome.BiomeCategory.ICY && Config.STRAY_TOWER_ENABLED.get()) +// event.getGeneration().addStructureStart(STRAY_TOWER_FEATURE); +// } + } @SubscribeEvent public void onBiomeLoad(BiomeLoadingEvent event) { - for (ConfiguredFeature feature : ORES) { - event.getGeneration().withFeature(GenerationStage.Decoration.UNDERGROUND_ORES, feature); + for (PlacedFeature feature : ORES) { + event.getGeneration().addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, feature); } - if (Config.LAB_ENABLED.get()) - event.getGeneration().withStructure(LAB_FEATURE); - if (Config.CATACOMB_ENABLED.get()) - event.getGeneration().withStructure(CATACOMB_FEATURE); - if (event.getCategory() == Biome.Category.ICY && Config.STRAY_TOWER_ENABLED.get()) - event.getGeneration().withStructure(STRAY_TOWER_FEATURE); } } diff --git a/src/main/java/elucent/eidolon/block/BlockBase.java b/src/main/java/elucent/eidolon/block/BlockBase.java index f1d312a..b5a946a 100644 --- a/src/main/java/elucent/eidolon/block/BlockBase.java +++ b/src/main/java/elucent/eidolon/block/BlockBase.java @@ -1,27 +1,27 @@ package elucent.eidolon.block; import elucent.eidolon.tile.TileEntityBase; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.Explosion; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; -import net.minecraftforge.fml.RegistryObject; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class BlockBase extends Block { VoxelShape shape = null; - TileEntityType tileEntityType = null; public BlockBase(Properties properties) { super(properties); @@ -32,65 +32,50 @@ public BlockBase setShape(VoxelShape shape) { return this; } - public BlockBase setTile(TileEntityType type) { - this.tileEntityType = type; - return this; - } - - @Override - public boolean hasTileEntity(BlockState state) { - return this.tileEntityType != null; - } - - @Override - public TileEntity createTileEntity(BlockState state, IBlockReader world) { - return tileEntityType.create(); - } - @Override - public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext ctx) { - return getRaytraceShape(state, world, pos); + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { + return getInteractionShape(state, world, pos); } @Override - public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext ctx) { - return getRaytraceShape(state, world, pos); + public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { + return getInteractionShape(state, world, pos); } @Override - public VoxelShape getRaytraceShape(BlockState state, IBlockReader world, BlockPos pos) { - return shape != null ? shape : VoxelShapes.fullCube(); + public VoxelShape getInteractionShape(BlockState state, BlockGetter world, BlockPos pos) { + return shape != null ? shape : Shapes.block(); } @Override - public void onBlockHarvested(World world, BlockPos pos, BlockState state, PlayerEntity player) { + public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { breakBlock(state, world, pos); - super.onBlockHarvested(world, pos, state, player); + super.playerWillDestroy(world, pos, state, player); } @Override - public void onBlockExploded(BlockState state, World world, BlockPos pos, Explosion explosion) { + public void onBlockExploded(BlockState state, Level world, BlockPos pos, Explosion explosion) { breakBlock(state, world, pos); super.onBlockExploded(state, world, pos, explosion); } - public void breakBlock(BlockState state, IBlockReader world, BlockPos pos) { - if (hasTileEntity(state)) { - TileEntity te = world.getTileEntity(pos); + public void breakBlock(BlockState state, Level world, BlockPos pos) { + if (this instanceof EntityBlock) { + BlockEntity te = world.getBlockEntity(pos); if (te instanceof TileEntityBase) { - ((TileEntityBase) world.getTileEntity(pos)).onDestroyed(state, pos); + ((TileEntityBase) world.getBlockEntity(pos)).onDestroyed(state, pos); } } } @Override - public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - if (hasTileEntity(state)) { - TileEntity te = world.getTileEntity(pos); + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) { + if (this instanceof EntityBlock) { + BlockEntity te = world.getBlockEntity(pos); if (te instanceof TileEntityBase) { - return ((TileEntityBase) world.getTileEntity(pos)).onActivated(state, pos, player, hand); + return ((TileEntityBase) world.getBlockEntity(pos)).onActivated(state, pos, player, hand); } } - return super.onBlockActivated(state, world, pos, player, hand, ray); + return super.use(state, world, pos, player, hand, ray); } } diff --git a/src/main/java/elucent/eidolon/block/BrazierBlock.java b/src/main/java/elucent/eidolon/block/BrazierBlock.java new file mode 100644 index 0000000..71ae9bf --- /dev/null +++ b/src/main/java/elucent/eidolon/block/BrazierBlock.java @@ -0,0 +1,47 @@ +package elucent.eidolon.block; + +import javax.annotation.Nullable; + +import elucent.eidolon.gui.SoulEnchanterContainer; +import elucent.eidolon.tile.BrazierTileEntity; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.HandTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class BrazierBlock extends BlockBase implements EntityBlock { + public BrazierBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new BrazierTileEntity(pos, state); + } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return new BlockEntityTicker() { + @Override + public void tick(Level level, BlockPos pos, BlockState state, T tile) { + ((BrazierTileEntity)tile).tick(); + } + }; + } +} diff --git a/src/main/java/elucent/eidolon/block/CandleBlock.java b/src/main/java/elucent/eidolon/block/CandleBlock.java index 29cef03..452a6ee 100644 --- a/src/main/java/elucent/eidolon/block/CandleBlock.java +++ b/src/main/java/elucent/eidolon/block/CandleBlock.java @@ -1,60 +1,56 @@ package elucent.eidolon.block; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.state.DirectionProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.Mirror; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.IWorldReader; -import net.minecraft.world.World; +import java.util.Random; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.Random; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class CandleBlock extends BlockBase { - protected static final VoxelShape SHAPE = Block.makeCuboidShape(6.0D, 0.0D, 6.0D, 10.0D, 9.0, 10.0D); + protected static final VoxelShape SHAPE = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 9.0, 10.0D); public CandleBlock(Properties properties) { super(properties); } @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return SHAPE; } @Override - public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return VoxelShapes.empty(); + public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return Shapes.empty(); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - BlockPos blockpos = pos.offset(Direction.DOWN); + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + BlockPos blockpos = pos.relative(Direction.DOWN); BlockState blockstate = worldIn.getBlockState(blockpos); - return blockstate.isSolidSide(worldIn, blockpos, Direction.UP); + return blockstate.isFaceSturdy(worldIn, blockpos, Direction.UP); } @Override - public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { - return facing == Direction.DOWN && !this.isValidPosition(state, worldIn, currentPos) ? Blocks.AIR.getDefaultState() : super.updatePostPlacement(state, facing, facingState, worldIn, currentPos, facingPos); + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { + return facing == Direction.DOWN && !this.canSurvive(state, worldIn, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, worldIn, currentPos, facingPos); } @OnlyIn(Dist.CLIENT) - public void animateTick(BlockState state, World worldIn, BlockPos pos, Random rand) { + public void animateTick(BlockState state, Level worldIn, BlockPos pos, Random rand) { double d0 = (double) pos.getX() + 0.5D; double d1 = (double) pos.getY() + 0.6D; double d2 = (double) pos.getZ() + 0.5D; diff --git a/src/main/java/elucent/eidolon/block/CandlestickBlock.java b/src/main/java/elucent/eidolon/block/CandlestickBlock.java index 022cd24..92b3120 100644 --- a/src/main/java/elucent/eidolon/block/CandlestickBlock.java +++ b/src/main/java/elucent/eidolon/block/CandlestickBlock.java @@ -1,39 +1,38 @@ package elucent.eidolon.block; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import net.minecraft.block.*; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.state.DirectionProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.Mirror; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.IWorldReader; -import net.minecraft.world.World; +import java.util.Random; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import javax.annotation.Nullable; -import java.util.Map; -import java.util.Random; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class CandlestickBlock extends BlockBase { public static final DirectionProperty FACING = DirectionProperty.create("facing", (d) -> d != Direction.DOWN); - protected static final VoxelShape UP_SHAPE = Block.makeCuboidShape(6.0D, 0.0D, 6.0D, 10.0D, 14.0D, 10.0D); + protected static final VoxelShape UP_SHAPE = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 14.0D, 10.0D); private static final VoxelShape[] SHAPES = new VoxelShape[]{ - Block.makeCuboidShape(5.5D, 3.0D, 11.0D, 10.5D, 16.0D, 16.0D), - Block.makeCuboidShape(5.5D, 3.0D, 0.0D, 10.5D, 16.0D, 5.0D), - Block.makeCuboidShape(11.0D, 3.0D, 5.5D, 16.0D, 16.0D, 10.5D), - Block.makeCuboidShape(0.0D, 3.0D, 5.5D, 5.0D, 16.0D, 10.5D) + Block.box(5.5D, 3.0D, 11.0D, 10.5D, 16.0D, 16.0D), + Block.box(5.5D, 3.0D, 0.0D, 10.5D, 16.0D, 5.0D), + Block.box(11.0D, 3.0D, 5.5D, 16.0D, 16.0D, 10.5D), + Block.box(0.0D, 3.0D, 5.5D, 5.0D, 16.0D, 10.5D) }; public CandlestickBlock(Properties properties) { @@ -41,48 +40,48 @@ public CandlestickBlock(Properties properties) { } public static VoxelShape getShapeForState(BlockState state) { - Direction dir = state.get(FACING); + Direction dir = state.getValue(FACING); if (dir == Direction.UP) return UP_SHAPE; else return SHAPES[dir.ordinal() - 2]; } @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return getShapeForState(state); } @Override - public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return VoxelShapes.empty(); + public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return Shapes.empty(); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - Direction direction = state.get(FACING); - BlockPos blockpos = pos.offset(direction.getOpposite()); + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos blockpos = pos.relative(direction.getOpposite()); BlockState blockstate = worldIn.getBlockState(blockpos); - return blockstate.isSolidSide(worldIn, blockpos, direction); + return blockstate.isFaceSturdy(worldIn, blockpos, direction); } @Override - public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { - Direction direction = state.get(FACING); - if (direction == Direction.UP) return facing == Direction.DOWN && !this.isValidPosition(state, worldIn, currentPos) ? Blocks.AIR.getDefaultState() : super.updatePostPlacement(state, facing, facingState, worldIn, currentPos, facingPos); - else return facing.getOpposite() == state.get(FACING) && !state.isValidPosition(worldIn, currentPos) ? Blocks.AIR.getDefaultState() : state; + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { + Direction direction = state.getValue(FACING); + if (direction == Direction.UP) return facing == Direction.DOWN && !this.canSurvive(state, worldIn, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, worldIn, currentPos, facingPos); + else return facing.getOpposite() == state.getValue(FACING) && !state.canSurvive(worldIn, currentPos) ? Blocks.AIR.defaultBlockState() : state; } @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - BlockState blockstate = this.getDefaultState(); - IWorldReader iworldreader = context.getWorld(); - BlockPos blockpos = context.getPos(); + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState blockstate = this.defaultBlockState(); + LevelReader iworldreader = context.getLevel(); + BlockPos blockpos = context.getClickedPos(); Direction[] adirection = context.getNearestLookingDirections(); for(Direction direction : adirection) { if (direction != Direction.UP) { Direction direction1 = direction.getOpposite(); - blockstate = blockstate.with(FACING, direction1); - if (blockstate.isValidPosition(iworldreader, blockpos)) { + blockstate = blockstate.setValue(FACING, direction1); + if (blockstate.canSurvive(iworldreader, blockpos)) { return blockstate; } } @@ -92,15 +91,15 @@ public BlockState getStateForPlacement(BlockItemUseContext context) { } @OnlyIn(Dist.CLIENT) - public void animateTick(BlockState state, World worldIn, BlockPos pos, Random rand) { - Direction direction = state.get(FACING); + public void animateTick(BlockState state, Level worldIn, BlockPos pos, Random rand) { + Direction direction = state.getValue(FACING); double d0 = (double) pos.getX() + 0.5D; double d1 = (double) pos.getY() + 0.925D; double d2 = (double) pos.getZ() + 0.5D; if (direction != Direction.UP) { - d0 -= 0.3 * direction.getXOffset(); + d0 -= 0.3 * direction.getStepX(); d1 += 0.125; - d2 -= 0.3 * direction.getZOffset(); + d2 -= 0.3 * direction.getStepZ(); } worldIn.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); worldIn.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); @@ -108,16 +107,16 @@ public void animateTick(BlockState state, World worldIn, BlockPos pos, Random ra @Override public BlockState rotate(BlockState state, Rotation rot) { - return state.get(FACING) != Direction.UP ? state.with(FACING, rot.rotate(state.get(FACING))) : state; + return state.getValue(FACING) != Direction.UP ? state.setValue(FACING, rot.rotate(state.getValue(FACING))) : state; } @Override public BlockState mirror(BlockState state, Mirror mirrorIn) { - return state.get(FACING) != Direction.UP ? state.rotate(mirrorIn.toRotation(state.get(FACING))) : state; + return state.getValue(FACING) != Direction.UP ? state.rotate(mirrorIn.getRotation(state.getValue(FACING))) : state; } @Override - protected void fillStateContainer(StateContainer.Builder builder) { + protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(FACING); } } diff --git a/src/main/java/elucent/eidolon/block/CisternBlock.java b/src/main/java/elucent/eidolon/block/CisternBlock.java new file mode 100644 index 0000000..4bf5735 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/CisternBlock.java @@ -0,0 +1,61 @@ +package elucent.eidolon.block; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.core.Direction; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import elucent.eidolon.tile.reagent.CisternTileEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.Level; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class CisternBlock extends BlockBase implements EntityBlock { + public static final BooleanProperty TOP = BooleanProperty.create("top"); + public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); + + public CisternBlock(Properties properties) { + super(properties); + } + + protected boolean canConnectTo(LevelAccessor world, BlockPos pos, Direction dir) { + BlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof CisternBlock && dir.getAxis() == Direction.Axis.Y) return true; + return false; + } + + protected BlockState getState(Level world, BlockPos pos) { + return this.defaultBlockState() + .setValue(TOP, canConnectTo(world, pos.above(), Direction.UP)) + .setValue(BOTTOM, canConnectTo(world, pos.below(), Direction.DOWN)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return getState(context.getLevel(), context.getClickedPos()); + } + + @Override + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { + if (facing == Direction.UP) state = state.setValue(TOP, canConnectTo(world, pos.above(), Direction.UP)); + if (facing == Direction.DOWN) state = state.setValue(BOTTOM, canConnectTo(world, pos.below(), Direction.DOWN)); + + return state; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(TOP, BOTTOM); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new CisternTileEntity(pos, state); + } +} diff --git a/src/main/java/elucent/eidolon/block/CrucibleBlock.java b/src/main/java/elucent/eidolon/block/CrucibleBlock.java new file mode 100644 index 0000000..548b1d9 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/CrucibleBlock.java @@ -0,0 +1,46 @@ +package elucent.eidolon.block; + +import javax.annotation.Nullable; + +import elucent.eidolon.gui.SoulEnchanterContainer; +import elucent.eidolon.tile.BrazierTileEntity; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class CrucibleBlock extends BlockBase implements EntityBlock { + public CrucibleBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new CrucibleTileEntity(pos, state); + } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return new BlockEntityTicker() { + @Override + public void tick(Level level, BlockPos pos, BlockState state, T tile) { + ((CrucibleTileEntity)tile).tick(); + } + }; + } +} diff --git a/src/main/java/elucent/eidolon/block/EffigyBlock.java b/src/main/java/elucent/eidolon/block/EffigyBlock.java new file mode 100644 index 0000000..f4a30b9 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/EffigyBlock.java @@ -0,0 +1,32 @@ +package elucent.eidolon.block; + +import elucent.eidolon.gui.SoulEnchanterContainer; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.EffigyTileEntity; +import elucent.eidolon.tile.HandTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class EffigyBlock extends HorizontalWaterloggableBlock implements EntityBlock { + public EffigyBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new EffigyTileEntity(pos, state); + } +} diff --git a/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java b/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java index ae746e9..68f8987 100644 --- a/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java +++ b/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java @@ -1,61 +1,62 @@ package elucent.eidolon.block; +import java.util.Map; +import java.util.Random; + import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; + import elucent.eidolon.Registry; -import net.minecraft.block.*; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ArrowEntity; -import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.entity.projectile.ProjectileHelper; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.EnumProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.state.properties.RedstoneSide; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Direction; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.IWorldReader; -import net.minecraft.world.World; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.RedStoneWireBlock; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.RedstoneSide; +import net.minecraft.world.InteractionResult; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.EntityCollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import javax.annotation.Nullable; -import java.util.Map; -import java.util.Random; -import java.util.Set; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class EnchantedAshBlock extends BlockBase { - public static final EnumProperty NORTH = BlockStateProperties.REDSTONE_NORTH; - public static final EnumProperty EAST = BlockStateProperties.REDSTONE_EAST; - public static final EnumProperty SOUTH = BlockStateProperties.REDSTONE_SOUTH; - public static final EnumProperty WEST = BlockStateProperties.REDSTONE_WEST; + public static final EnumProperty NORTH = BlockStateProperties.NORTH_REDSTONE; + public static final EnumProperty EAST = BlockStateProperties.EAST_REDSTONE; + public static final EnumProperty SOUTH = BlockStateProperties.SOUTH_REDSTONE; + public static final EnumProperty WEST = BlockStateProperties.WEST_REDSTONE; public static final Map> FACING_PROPERTY_MAP = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, NORTH, Direction.EAST, EAST, Direction.SOUTH, SOUTH, Direction.WEST, WEST)); - private static final VoxelShape BARRIER_SHAPE = VoxelShapes.create(0, -4, 0, 1, 5, 1); - private static final VoxelShape BASE_SHAPE = Block.makeCuboidShape(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D); - private static final Map SIDE_TO_SHAPE = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Block.makeCuboidShape(3.0D, 0.0D, 0.0D, 13.0D, 1.0D, 13.0D), Direction.SOUTH, Block.makeCuboidShape(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 16.0D), Direction.EAST, Block.makeCuboidShape(3.0D, 0.0D, 3.0D, 16.0D, 1.0D, 13.0D), Direction.WEST, Block.makeCuboidShape(0.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D))); - private static final Map SIDE_TO_ASCENDING_SHAPE = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, VoxelShapes.or(SIDE_TO_SHAPE.get(Direction.NORTH), Block.makeCuboidShape(3.0D, 0.0D, 0.0D, 13.0D, 16.0D, 1.0D)), Direction.SOUTH, VoxelShapes.or(SIDE_TO_SHAPE.get(Direction.SOUTH), Block.makeCuboidShape(3.0D, 0.0D, 15.0D, 13.0D, 16.0D, 16.0D)), Direction.EAST, VoxelShapes.or(SIDE_TO_SHAPE.get(Direction.EAST), Block.makeCuboidShape(15.0D, 0.0D, 3.0D, 16.0D, 16.0D, 13.0D)), Direction.WEST, VoxelShapes.or(SIDE_TO_SHAPE.get(Direction.WEST), Block.makeCuboidShape(0.0D, 0.0D, 3.0D, 1.0D, 16.0D, 13.0D)))); + private static final VoxelShape BARRIER_SHAPE = Shapes.box(0, -4, 0, 1, 5, 1); + private static final VoxelShape BASE_SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D); + private static final Map SIDE_TO_SHAPE = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Block.box(3.0D, 0.0D, 0.0D, 13.0D, 1.0D, 13.0D), Direction.SOUTH, Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 16.0D), Direction.EAST, Block.box(3.0D, 0.0D, 3.0D, 16.0D, 1.0D, 13.0D), Direction.WEST, Block.box(0.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D))); + private static final Map SIDE_TO_ASCENDING_SHAPE = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Shapes.or(SIDE_TO_SHAPE.get(Direction.NORTH), Block.box(3.0D, 0.0D, 0.0D, 13.0D, 16.0D, 1.0D)), Direction.SOUTH, Shapes.or(SIDE_TO_SHAPE.get(Direction.SOUTH), Block.box(3.0D, 0.0D, 15.0D, 13.0D, 16.0D, 16.0D)), Direction.EAST, Shapes.or(SIDE_TO_SHAPE.get(Direction.EAST), Block.box(15.0D, 0.0D, 3.0D, 16.0D, 16.0D, 13.0D)), Direction.WEST, Shapes.or(SIDE_TO_SHAPE.get(Direction.WEST), Block.box(0.0D, 0.0D, 3.0D, 1.0D, 16.0D, 13.0D)))); private final Map stateToShapeMap = Maps.newHashMap(); private final BlockState sideBaseState; public EnchantedAshBlock(Properties properties) { super(properties); - this.setDefaultState(this.stateContainer.getBaseState().with(NORTH, RedstoneSide.NONE).with(EAST, RedstoneSide.NONE).with(SOUTH, RedstoneSide.NONE).with(WEST, RedstoneSide.NONE)); - this.sideBaseState = this.getDefaultState().with(NORTH, RedstoneSide.SIDE).with(EAST, RedstoneSide.SIDE).with(SOUTH, RedstoneSide.SIDE).with(WEST, RedstoneSide.SIDE); + this.registerDefaultState(this.stateDefinition.any().setValue(NORTH, RedstoneSide.NONE).setValue(EAST, RedstoneSide.NONE).setValue(SOUTH, RedstoneSide.NONE).setValue(WEST, RedstoneSide.NONE)); + this.sideBaseState = this.defaultBlockState().setValue(NORTH, RedstoneSide.SIDE).setValue(EAST, RedstoneSide.SIDE).setValue(SOUTH, RedstoneSide.SIDE).setValue(WEST, RedstoneSide.SIDE); - for(BlockState blockstate : this.getStateContainer().getValidStates()) { + for(BlockState blockstate : this.getStateDefinition().getPossibleStates()) { this.stateToShapeMap.put(blockstate, this.getShapeForState(blockstate)); } } @@ -64,11 +65,11 @@ private VoxelShape getShapeForState(BlockState state) { VoxelShape voxelshape = BASE_SHAPE; for(Direction direction : Direction.Plane.HORIZONTAL) { - RedstoneSide redstoneside = state.get(FACING_PROPERTY_MAP.get(direction)); + RedstoneSide redstoneside = state.getValue(FACING_PROPERTY_MAP.get(direction)); if (redstoneside == RedstoneSide.SIDE) { - voxelshape = VoxelShapes.or(voxelshape, SIDE_TO_SHAPE.get(direction)); + voxelshape = Shapes.or(voxelshape, SIDE_TO_SHAPE.get(direction)); } else if (redstoneside == RedstoneSide.UP) { - voxelshape = VoxelShapes.or(voxelshape, SIDE_TO_ASCENDING_SHAPE.get(direction)); + voxelshape = Shapes.or(voxelshape, SIDE_TO_ASCENDING_SHAPE.get(direction)); } } @@ -76,51 +77,51 @@ private VoxelShape getShapeForState(BlockState state) { } private static boolean areAllSidesInvalid(BlockState state) { - return !state.get(NORTH).func_235921_b_() && !state.get(SOUTH).func_235921_b_() && !state.get(EAST).func_235921_b_() && !state.get(WEST).func_235921_b_(); + return !state.getValue(NORTH).isConnected() && !state.getValue(SOUTH).isConnected() && !state.getValue(EAST).isConnected() && !state.getValue(WEST).isConnected(); } private static boolean areAllSidesValid(BlockState state) { - return state.get(NORTH).func_235921_b_() && state.get(SOUTH).func_235921_b_() && state.get(EAST).func_235921_b_() && state.get(WEST).func_235921_b_(); + return state.getValue(NORTH).isConnected() && state.getValue(SOUTH).isConnected() && state.getValue(EAST).isConnected() && state.getValue(WEST).isConnected(); } - private BlockState recalculateFacingState(IBlockReader reader, BlockState state, BlockPos pos) { - boolean flag = !reader.getBlockState(pos.up()).isNormalCube(reader, pos); + private BlockState recalculateFacingState(BlockGetter reader, BlockState state, BlockPos pos) { + boolean flag = !reader.getBlockState(pos.above()).isRedstoneConductor(reader, pos); for(Direction direction : Direction.Plane.HORIZONTAL) { - if (!state.get(FACING_PROPERTY_MAP.get(direction)).func_235921_b_()) { + if (!state.getValue(FACING_PROPERTY_MAP.get(direction)).isConnected()) { RedstoneSide redstoneside = this.recalculateSide(reader, pos, direction, flag); - state = state.with(FACING_PROPERTY_MAP.get(direction), redstoneside); + state = state.setValue(FACING_PROPERTY_MAP.get(direction), redstoneside); } } return state; } - private RedstoneSide getSide(IBlockReader worldIn, BlockPos pos, Direction face) { - RedstoneWireBlock r; - return this.recalculateSide(worldIn, pos, face, !worldIn.getBlockState(pos.up()).isNormalCube(worldIn, pos)); + private RedstoneSide getSide(BlockGetter worldIn, BlockPos pos, Direction face) { + RedStoneWireBlock r; + return this.recalculateSide(worldIn, pos, face, !worldIn.getBlockState(pos.above()).isRedstoneConductor(worldIn, pos)); } - public void updateDiagonalNeighbors(BlockState state, IWorld worldIn, BlockPos pos, int flags, int recursionLeft) { - BlockPos.Mutable blockpos$mutable = new BlockPos.Mutable(); + public void updateIndirectNeighbourShapes(BlockState state, LevelAccessor worldIn, BlockPos pos, int flags, int recursionLeft) { + BlockPos.MutableBlockPos blockpos$mutable = new BlockPos.MutableBlockPos(); for(Direction direction : Direction.Plane.HORIZONTAL) { - RedstoneSide redstoneside = state.get(FACING_PROPERTY_MAP.get(direction)); - if (redstoneside != RedstoneSide.NONE && !worldIn.getBlockState(blockpos$mutable.setAndMove(pos, direction)).isIn(this)) { + RedstoneSide redstoneside = state.getValue(FACING_PROPERTY_MAP.get(direction)); + if (redstoneside != RedstoneSide.NONE && !worldIn.getBlockState(blockpos$mutable.setWithOffset(pos, direction)).is(this)) { blockpos$mutable.move(Direction.DOWN); BlockState blockstate = worldIn.getBlockState(blockpos$mutable); - if (!blockstate.isIn(Blocks.OBSERVER)) { - BlockPos blockpos = blockpos$mutable.offset(direction.getOpposite()); - BlockState blockstate1 = blockstate.updatePostPlacement(direction.getOpposite(), worldIn.getBlockState(blockpos), worldIn, blockpos$mutable, blockpos); - replaceBlockState(blockstate, blockstate1, worldIn, blockpos$mutable, flags, recursionLeft); + if (!blockstate.is(Blocks.OBSERVER)) { + BlockPos blockpos = blockpos$mutable.relative(direction.getOpposite()); + BlockState blockstate1 = blockstate.updateShape(direction.getOpposite(), worldIn.getBlockState(blockpos), worldIn, blockpos$mutable, blockpos); + updateOrDestroy(blockstate, blockstate1, worldIn, blockpos$mutable, flags, recursionLeft); } - blockpos$mutable.setAndMove(pos, direction).move(Direction.UP); + blockpos$mutable.setWithOffset(pos, direction).move(Direction.UP); BlockState blockstate3 = worldIn.getBlockState(blockpos$mutable); - if (!blockstate3.isIn(Blocks.OBSERVER)) { - BlockPos blockpos1 = blockpos$mutable.offset(direction.getOpposite()); - BlockState blockstate2 = blockstate3.updatePostPlacement(direction.getOpposite(), worldIn.getBlockState(blockpos1), worldIn, blockpos$mutable, blockpos1); - replaceBlockState(blockstate3, blockstate2, worldIn, blockpos$mutable, flags, recursionLeft); + if (!blockstate3.is(Blocks.OBSERVER)) { + BlockPos blockpos1 = blockpos$mutable.relative(direction.getOpposite()); + BlockState blockstate2 = blockstate3.updateShape(direction.getOpposite(), worldIn.getBlockState(blockpos1), worldIn, blockpos$mutable, blockpos1); + updateOrDestroy(blockstate3, blockstate2, worldIn, blockpos$mutable, flags, recursionLeft); } } } @@ -128,24 +129,24 @@ public void updateDiagonalNeighbors(BlockState state, IWorld worldIn, BlockPos p } @Override - public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { + public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { if (facing == Direction.DOWN) { return stateIn; } else if (facing == Direction.UP) { return this.getUpdatedState(worldIn, stateIn, currentPos); } else { RedstoneSide redstoneside = this.getSide(worldIn, currentPos, facing); - return redstoneside.func_235921_b_() == stateIn.get(FACING_PROPERTY_MAP.get(facing)).func_235921_b_() && !areAllSidesValid(stateIn) ? stateIn.with(FACING_PROPERTY_MAP.get(facing), redstoneside) : this.getUpdatedState(worldIn, this.sideBaseState.with(FACING_PROPERTY_MAP.get(facing), redstoneside), currentPos); + return redstoneside.isConnected() == stateIn.getValue(FACING_PROPERTY_MAP.get(facing)).isConnected() && !areAllSidesValid(stateIn) ? stateIn.setValue(FACING_PROPERTY_MAP.get(facing), redstoneside) : this.getUpdatedState(worldIn, this.sideBaseState.setValue(FACING_PROPERTY_MAP.get(facing), redstoneside), currentPos); } } - private RedstoneSide recalculateSide(IBlockReader reader, BlockPos pos, Direction direction, boolean nonNormalCubeAbove) { - BlockPos blockpos = pos.offset(direction); + private RedstoneSide recalculateSide(BlockGetter reader, BlockPos pos, Direction direction, boolean nonNormalCubeAbove) { + BlockPos blockpos = pos.relative(direction); BlockState blockstate = reader.getBlockState(blockpos); if (nonNormalCubeAbove) { boolean flag = this.canPlaceOnTopOf(reader, blockpos, blockstate); - if (flag && canConnectTo(reader.getBlockState(blockpos.up()), reader, blockpos.up(), null) ) { - if (blockstate.isSolidSide(reader, blockpos, direction.getOpposite())) { + if (flag && canConnectTo(reader.getBlockState(blockpos.above()), reader, blockpos.above(), null) ) { + if (blockstate.isFaceSturdy(reader, blockpos, direction.getOpposite())) { return RedstoneSide.UP; } @@ -153,39 +154,39 @@ private RedstoneSide recalculateSide(IBlockReader reader, BlockPos pos, Directio } } - return !canConnectTo(blockstate, reader, blockpos, direction) && (blockstate.isNormalCube(reader, blockpos) || !canConnectTo(reader.getBlockState(blockpos.down()), reader, blockpos.down(), null)) ? RedstoneSide.NONE : RedstoneSide.SIDE; + return !canConnectTo(blockstate, reader, blockpos, direction) && (blockstate.isRedstoneConductor(reader, blockpos) || !canConnectTo(reader.getBlockState(blockpos.below()), reader, blockpos.below(), null)) ? RedstoneSide.NONE : RedstoneSide.SIDE; } - private boolean canPlaceOnTopOf(IBlockReader reader, BlockPos pos, BlockState state) { - return state.isSolidSide(reader, pos, Direction.UP); + private boolean canPlaceOnTopOf(BlockGetter reader, BlockPos pos, BlockState state) { + return state.isFaceSturdy(reader, pos, Direction.UP); } - private BlockState getUpdatedState(IBlockReader reader, BlockState state, BlockPos pos) { + private BlockState getUpdatedState(BlockGetter reader, BlockState state, BlockPos pos) { boolean flag = areAllSidesInvalid(state); - state = this.recalculateFacingState(reader, this.getDefaultState(), pos); + state = this.recalculateFacingState(reader, this.defaultBlockState(), pos); if (flag && areAllSidesInvalid(state)) { return state; } else { - boolean flag1 = state.get(NORTH).func_235921_b_(); - boolean flag2 = state.get(SOUTH).func_235921_b_(); - boolean flag3 = state.get(EAST).func_235921_b_(); - boolean flag4 = state.get(WEST).func_235921_b_(); + boolean flag1 = state.getValue(NORTH).isConnected(); + boolean flag2 = state.getValue(SOUTH).isConnected(); + boolean flag3 = state.getValue(EAST).isConnected(); + boolean flag4 = state.getValue(WEST).isConnected(); boolean flag5 = !flag1 && !flag2; boolean flag6 = !flag3 && !flag4; if (!flag4 && flag5) { - state = state.with(WEST, RedstoneSide.SIDE); + state = state.setValue(WEST, RedstoneSide.SIDE); } if (!flag3 && flag5) { - state = state.with(EAST, RedstoneSide.SIDE); + state = state.setValue(EAST, RedstoneSide.SIDE); } if (!flag1 && flag6) { - state = state.with(NORTH, RedstoneSide.SIDE); + state = state.setValue(NORTH, RedstoneSide.SIDE); } if (!flag2 && flag6) { - state = state.with(SOUTH, RedstoneSide.SIDE); + state = state.setValue(SOUTH, RedstoneSide.SIDE); } return state; @@ -193,20 +194,20 @@ private BlockState getUpdatedState(IBlockReader reader, BlockState state, BlockP } @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return this.stateToShapeMap.get(state); } @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - return this.getUpdatedState(context.getWorld(), this.sideBaseState, context.getPos()); + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.getUpdatedState(context.getLevel(), this.sideBaseState, context.getClickedPos()); } @Override - public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - if (!oldState.isIn(state.getBlock()) && !worldIn.isRemote) { + public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + if (!oldState.is(state.getBlock()) && !worldIn.isClientSide) { for(Direction direction : Direction.Plane.VERTICAL) { - worldIn.notifyNeighborsOfStateChange(pos.offset(direction), this); + worldIn.updateNeighborsAt(pos.relative(direction), this); } this.updateNeighboursStateChange(worldIn, pos); @@ -214,41 +215,43 @@ public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockSta } @Override - public boolean collisionExtendsVertically(BlockState state, IBlockReader world, BlockPos pos, Entity entity) { - return entity instanceof LivingEntity && ((LivingEntity)entity).isEntityUndead(); + public boolean collisionExtendsVertically(BlockState state, BlockGetter world, BlockPos pos, Entity entity) { + return entity instanceof LivingEntity && ((LivingEntity)entity).isInvertedHealAndHarm(); } boolean isBlocked(Entity entity) { if (entity == null) return false; if (entity instanceof LivingEntity) { LivingEntity living = (LivingEntity)entity; - if (living.isEntityUndead()) return true; + if (living.isInvertedHealAndHarm()) return true; } - if (entity.getPassengers().stream().anyMatch((e) -> e instanceof LivingEntity && ((LivingEntity)e).isEntityUndead())) + if (entity.getPassengers().stream().anyMatch((e) -> e instanceof LivingEntity && ((LivingEntity)e).isInvertedHealAndHarm())) return true; return false; } @Override - public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext ctx) { - return isBlocked(ctx.getEntity()) ? BARRIER_SHAPE : super.getCollisionShape(state, world, pos, ctx); + public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { + return ctx instanceof EntityCollisionContext + && ((EntityCollisionContext)ctx).getEntity() != null + && isBlocked(((EntityCollisionContext)ctx).getEntity()) ? BARRIER_SHAPE : super.getCollisionShape(state, world, pos, ctx); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - BlockPos blockpos = pos.down(); + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + BlockPos blockpos = pos.below(); BlockState blockstate = worldIn.getBlockState(blockpos); return this.canPlaceOnTopOf(worldIn, blockpos, blockstate); } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!isMoving && !state.isIn(newState.getBlock())) { - super.onReplaced(state, worldIn, pos, newState, isMoving); - if (!worldIn.isRemote) { + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { + super.onRemove(state, worldIn, pos, newState, isMoving); + if (!worldIn.isClientSide) { for(Direction direction : Direction.values()) { - worldIn.notifyNeighborsOfStateChange(pos.offset(direction), this); + worldIn.updateNeighborsAt(pos.relative(direction), this); } this.updateNeighboursStateChange(worldIn, pos); @@ -256,76 +259,76 @@ public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState } } - private void updateChangedConnections(World world, BlockPos pos, BlockState prevState, BlockState newState) { + private void updateChangedConnections(Level world, BlockPos pos, BlockState prevState, BlockState newState) { for(Direction direction : Direction.Plane.HORIZONTAL) { - BlockPos blockpos = pos.offset(direction); - if (prevState.get(FACING_PROPERTY_MAP.get(direction)).func_235921_b_() != newState.get(FACING_PROPERTY_MAP.get(direction)).func_235921_b_() && world.getBlockState(blockpos).isNormalCube(world, blockpos)) { - world.notifyNeighborsOfStateExcept(blockpos, newState.getBlock(), direction.getOpposite()); + BlockPos blockpos = pos.relative(direction); + if (prevState.getValue(FACING_PROPERTY_MAP.get(direction)).isConnected() != newState.getValue(FACING_PROPERTY_MAP.get(direction)).isConnected() && world.getBlockState(blockpos).isRedstoneConductor(world, blockpos)) { + world.updateNeighborsAtExceptFromFacing(blockpos, newState.getBlock(), direction.getOpposite()); } } } - private void notifyWireNeighborsOfStateChange(World worldIn, BlockPos pos) { - if (worldIn.getBlockState(pos).isIn(this)) { - worldIn.notifyNeighborsOfStateChange(pos, this); + private void notifyWireNeighborsOfStateChange(Level worldIn, BlockPos pos) { + if (worldIn.getBlockState(pos).is(this)) { + worldIn.updateNeighborsAt(pos, this); for(Direction direction : Direction.values()) { - worldIn.notifyNeighborsOfStateChange(pos.offset(direction), this); + worldIn.updateNeighborsAt(pos.relative(direction), this); } } } - private void updateNeighboursStateChange(World world, BlockPos pos) { + private void updateNeighboursStateChange(Level world, BlockPos pos) { for(Direction direction : Direction.Plane.HORIZONTAL) { - this.notifyWireNeighborsOfStateChange(world, pos.offset(direction)); + this.notifyWireNeighborsOfStateChange(world, pos.relative(direction)); } for(Direction direction1 : Direction.Plane.HORIZONTAL) { - BlockPos blockpos = pos.offset(direction1); - if (world.getBlockState(blockpos).isNormalCube(world, blockpos)) { - this.notifyWireNeighborsOfStateChange(world, blockpos.up()); + BlockPos blockpos = pos.relative(direction1); + if (world.getBlockState(blockpos).isRedstoneConductor(world, blockpos)) { + this.notifyWireNeighborsOfStateChange(world, blockpos.above()); } else { - this.notifyWireNeighborsOfStateChange(world, blockpos.down()); + this.notifyWireNeighborsOfStateChange(world, blockpos.below()); } } } @Override - public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (!worldIn.isRemote) { - if (!state.isValidPosition(worldIn, pos)) { - spawnDrops(state, worldIn, pos); + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { + if (!worldIn.isClientSide) { + if (!state.canSurvive(worldIn, pos)) { + dropResources(state, worldIn, pos); worldIn.removeBlock(pos, false); } } } - protected static boolean canConnectTo(BlockState blockState, IBlockReader world, BlockPos pos, Direction side) { - if (blockState.isIn(Registry.ENCHANTED_ASH.get())) { + protected static boolean canConnectTo(BlockState blockState, BlockGetter world, BlockPos pos, Direction side) { + if (blockState.is(Registry.ENCHANTED_ASH.get())) { return true; } return false; } @Override - public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - return ActionResultType.PASS; + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { + return InteractionResult.PASS; } @OnlyIn(Dist.CLIENT) - public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { + public void animateTick(BlockState stateIn, Level worldIn, BlockPos pos, Random rand) { // } @Override - public boolean canProvidePower(BlockState state) { + public boolean isSignalSource(BlockState state) { return false; } @Override - protected void fillStateContainer(StateContainer.Builder builder) { + protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(NORTH, EAST, SOUTH, WEST); } } diff --git a/src/main/java/elucent/eidolon/block/HandBlock.java b/src/main/java/elucent/eidolon/block/HandBlock.java new file mode 100644 index 0000000..70efb1e --- /dev/null +++ b/src/main/java/elucent/eidolon/block/HandBlock.java @@ -0,0 +1,31 @@ +package elucent.eidolon.block; + +import elucent.eidolon.gui.SoulEnchanterContainer; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.HandTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class HandBlock extends HorizontalWaterloggableBlock implements EntityBlock { + public HandBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new HandTileEntity(pos, state); + } +} diff --git a/src/main/java/elucent/eidolon/block/HerbBlockBase.java b/src/main/java/elucent/eidolon/block/HerbBlockBase.java new file mode 100644 index 0000000..b71f98e --- /dev/null +++ b/src/main/java/elucent/eidolon/block/HerbBlockBase.java @@ -0,0 +1,70 @@ +package elucent.eidolon.block; + +import java.util.Random; + +import elucent.eidolon.Registry; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.BushBlock; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.common.IPlantable; + +public class HerbBlockBase extends BushBlock { + public static final IntegerProperty AGE = BlockStateProperties.AGE_1; + private static final VoxelShape[] SHAPES = new VoxelShape[]{Block.box(5, 0, 5, 11, 4, 11), Block.box(4, 0, 4, 12, 8, 12) }; + public HerbBlockBase(BlockBehaviour.Properties builder) { + super(builder); + this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return SHAPES[state.getValue(AGE)]; + } + + @Override + public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + + @Override + public boolean canSustainPlant(BlockState state, BlockGetter worldIn, BlockPos pos, Direction facing, IPlantable plantable) { + return state.is(Registry.PLANTER.get()); + } + + @Override + protected boolean mayPlaceOn(BlockState state, BlockGetter worldIn, BlockPos pos) { + return state.is(Registry.PLANTER.get()); + } + + @Override + public boolean isRandomlyTicking(BlockState state) { + return state.getValue(AGE) < 1; + } + + @Override + public void randomTick(BlockState state, ServerLevel worldIn, BlockPos pos, Random random) { + int i = state.getValue(AGE); + if (i < 1 && mayPlaceOn(worldIn.getBlockState(pos.below()), worldIn, pos.below()) + && net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, pos, state, random.nextInt(20) == 0)) { + state = state.setValue(AGE, i + 1); + worldIn.setBlock(pos, state, 2); + net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state); + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(AGE); + } +} diff --git a/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java b/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java index 0650285..7449e6f 100644 --- a/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java +++ b/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java @@ -1,26 +1,13 @@ package elucent.eidolon.block; -import elucent.eidolon.tile.TileEntityBase; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.HorizontalBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.DirectionProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.Explosion; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class HorizontalBlockBase extends BlockBase { public static final DirectionProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; @@ -30,12 +17,12 @@ public HorizontalBlockBase(Properties properties) { } @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - return this.getDefaultState().with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState().setValue(HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite()); } @Override - protected void fillStateContainer(StateContainer.Builder builder) { + protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(HORIZONTAL_FACING); } } diff --git a/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java b/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java index 103f634..7a8ae81 100644 --- a/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java +++ b/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java @@ -1,20 +1,24 @@ package elucent.eidolon.block; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.IWaterLoggable; -import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.Fluids; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.BooleanProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; - -public class HorizontalWaterloggableBlock extends HorizontalBlockBase implements IWaterLoggable { +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.ticks.ScheduledTick; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class HorizontalWaterloggableBlock extends HorizontalBlockBase implements SimpleWaterloggedBlock { public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public HorizontalWaterloggableBlock(Properties properties) { @@ -23,30 +27,30 @@ public HorizontalWaterloggableBlock(Properties properties) { @Override public FluidState getFluidState(BlockState state) { - return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state); + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); } @Override - public boolean propagatesSkylightDown(BlockState state, IBlockReader reader, BlockPos pos) { - return !state.get(WATERLOGGED); + public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) { + return !state.getValue(WATERLOGGED); } @Override - public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld world, BlockPos pos, BlockPos facingPos) { - if (state.get(WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { + if (state.getValue(WATERLOGGED)) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - return super.getStateForPlacement(context).with(WATERLOGGED, false); + public BlockState getStateForPlacement(BlockPlaceContext context) { + return super.getStateForPlacement(context).setValue(WATERLOGGED, false); } @Override - protected void fillStateContainer(StateContainer.Builder builder) { - super.fillStateContainer(builder); + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); builder.add(WATERLOGGED); } } diff --git a/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java b/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java index bac63ce..6d37099 100644 --- a/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java +++ b/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java @@ -1,31 +1,29 @@ package elucent.eidolon.block; -import elucent.eidolon.tile.TileEntityBase; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.DirectionProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.IBlockReader; - -public class NecroticFocusBlock extends HorizontalWaterloggableBlock { - VoxelShape SOUTH = VoxelShapes.create(0, 0, 0, 1, 1, 0.5), - NORTH = VoxelShapes.create(0, 0, 0.5, 1, 1, 1), - WEST = VoxelShapes.create(0.5, 0, 0, 1, 1, 1), - EAST = VoxelShapes.create(0, 0, 0, 0.5, 1, 1); +import net.minecraft.world.level.block.state.BlockState; +import elucent.eidolon.tile.NecroticFocusTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class NecroticFocusBlock extends HorizontalWaterloggableBlock implements EntityBlock { + VoxelShape SOUTH = Shapes.box(0, 0, 0, 1, 1, 0.5), + NORTH = Shapes.box(0, 0, 0.5, 1, 1, 1), + WEST = Shapes.box(0.5, 0, 0, 1, 1, 1), + EAST = Shapes.box(0, 0, 0, 0.5, 1, 1); public NecroticFocusBlock(Properties properties) { super(properties); } VoxelShape shapeForState(BlockState state) { - switch (state.get(HORIZONTAL_FACING)) { + switch (state.getValue(HORIZONTAL_FACING)) { case NORTH: return NORTH; case SOUTH: @@ -39,17 +37,22 @@ VoxelShape shapeForState(BlockState state) { } @Override - public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext ctx) { + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return shapeForState(state); } @Override - public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext ctx) { + public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return shapeForState(state); } @Override - public VoxelShape getRaytraceShape(BlockState state, IBlockReader world, BlockPos pos) { + public VoxelShape getInteractionShape(BlockState state, BlockGetter world, BlockPos pos) { return shapeForState(state); } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new NecroticFocusTileEntity(pos, state); + } } diff --git a/src/main/java/elucent/eidolon/block/PillarBlockBase.java b/src/main/java/elucent/eidolon/block/PillarBlockBase.java new file mode 100644 index 0000000..a8970f7 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/PillarBlockBase.java @@ -0,0 +1,75 @@ +package elucent.eidolon.block; + +import elucent.eidolon.Registry; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.Level; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class PillarBlockBase extends BlockBase implements SimpleWaterloggedBlock { + public static final BooleanProperty TOP = BooleanProperty.create("top"); + public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + + public PillarBlockBase(Properties properties) { + super(properties); + } + + protected boolean canConnectTo(LevelAccessor world, BlockPos pos, Direction dir) { + BlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof PillarBlockBase && dir.getAxis() == Direction.Axis.Y) return true; + if (dir == Direction.UP && state.getBlock() == Registry.STONE_HAND.get()) return true; + return false; + } + + protected BlockState getState(Level world, BlockPos pos) { + return this.defaultBlockState() + .setValue(TOP, canConnectTo(world, pos.above(), Direction.UP)) + .setValue(BOTTOM, canConnectTo(world, pos.below(), Direction.DOWN)) + .setValue(WATERLOGGED, Boolean.valueOf(world.getFluidState(pos).getType() == Fluids.WATER)); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override + public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) { + return !state.getValue(WATERLOGGED); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return getState(context.getLevel(), context.getClickedPos()); + } + + @Override + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { + if (state.getValue(WATERLOGGED)) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + + if (facing == Direction.UP) state = state.setValue(TOP, canConnectTo(world, pos.above(), Direction.UP)); + if (facing == Direction.DOWN) state = state.setValue(BOTTOM, canConnectTo(world, pos.below(), Direction.DOWN)); + + return state; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(TOP, BOTTOM, WATERLOGGED); + } +} diff --git a/src/main/java/elucent/eidolon/block/PipeBlock.java b/src/main/java/elucent/eidolon/block/PipeBlock.java new file mode 100644 index 0000000..69c01bd --- /dev/null +++ b/src/main/java/elucent/eidolon/block/PipeBlock.java @@ -0,0 +1,110 @@ +package elucent.eidolon.block; + +import com.google.common.base.Predicates; + +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import elucent.eidolon.tile.reagent.PipeTileEntity; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class PipeBlock extends BlockBase implements EntityBlock { + static final VoxelShape + UP = Shapes.box(0.375, 0.625, 0.375, 0.625, 1, 0.625), + DOWN = Shapes.box(0.375, 0, 0.375, 0.625, 0.375, 0.625), + EAST = Shapes.box(0.625, 0.375, 0.375, 1, 0.625, 0.625), + WEST = Shapes.box(0, 0.375, 0.375, 0.375, 0.625, 0.625), + NORTH = Shapes.box(0.375, 0.375, 0, 0.625, 0.625, 0.375), + SOUTH = Shapes.box(0.375, 0.375, 0.625, 0.625, 0.625, 1), + CENTER = Shapes.box(0.375, 0.375, 0.375, 0.625, 0.625, 0.625); + + static final VoxelShape[] SHAPES = new VoxelShape[36]; + static { + VoxelShape[] FACES = new VoxelShape[]{ DOWN, UP, NORTH, SOUTH, WEST, EAST }; + for (Direction in : Direction.values()) { + for (Direction out : Direction.values()) { + SHAPES[in.ordinal() * 6 + out.ordinal()] = Shapes.or(FACES[in.ordinal()], FACES[out.ordinal()], CENTER); + } + } + } + + public static final DirectionProperty + IN = DirectionProperty.create("in", Predicates.alwaysTrue()), + OUT = DirectionProperty.create("out", Predicates.alwaysTrue()); + public static final BooleanProperty + IN_ATTACHED = BooleanProperty.create("attachin"), + OUT_ATTACHED = BooleanProperty.create("attachout"); + + public PipeBlock(Properties properties) { + super(properties); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { + return getInteractionShape(state, world, pos); + } + + @Override + public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { + return getInteractionShape(state, world, pos); + } + + @Override + public VoxelShape getInteractionShape(BlockState state, BlockGetter world, BlockPos pos) { + return SHAPES[state.getValue(IN).ordinal() * 6 + state.getValue(OUT).ordinal()]; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return defaultBlockState() + .setValue(IN, context.getClickedFace().getOpposite()) + .setValue(OUT, context.getClickedFace()) + .setValue(IN_ATTACHED, + context.getLevel() + .getBlockState(context.getClickedPos().relative(context.getClickedFace().getOpposite())) + .getBlock() == this) + .setValue(OUT_ATTACHED, + context.getLevel() + .getBlockState(context.getClickedPos().relative(context.getClickedFace())) + .getBlock() == this && + context.getLevel().getBlockState(context.getClickedPos().relative(context.getClickedFace())) + .getValue(IN) == context.getClickedFace()); + } + + @Override + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { + if (facing == state.getValue(OUT)) + state = state.setValue(OUT_ATTACHED, facingState.getBlock() == this && facingState.getValue(IN) == facing.getOpposite()); + if (facing == state.getValue(IN)) + state = state.setValue(IN_ATTACHED, facingState.getBlock() == this && facingState.getValue(OUT) == facing.getOpposite()); + if (facingState.getBlock() == this && facingPos.relative(facingState.getValue(IN)).equals(pos) + && facing != state.getValue(IN)) { + state = state.setValue(OUT, facing).setValue(OUT_ATTACHED, true); + } + return state; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(IN).add(OUT).add(IN_ATTACHED).add(OUT_ATTACHED); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new PipeTileEntity(pos, state); + } +} diff --git a/src/main/java/elucent/eidolon/block/PlinthBlockBase.java b/src/main/java/elucent/eidolon/block/PlinthBlockBase.java deleted file mode 100644 index 519c936..0000000 --- a/src/main/java/elucent/eidolon/block/PlinthBlockBase.java +++ /dev/null @@ -1,74 +0,0 @@ -package elucent.eidolon.block; - -import elucent.eidolon.Registry; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.IWaterLoggable; -import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.Fluids; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.BooleanProperty; -import net.minecraft.state.DirectionProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.World; - -public class PlinthBlockBase extends BlockBase implements IWaterLoggable { - public static final BooleanProperty TOP = BooleanProperty.create("top"); - public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - - public PlinthBlockBase(Properties properties) { - super(properties); - } - - protected boolean canConnectTo(IWorld world, BlockPos pos, Direction dir) { - BlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof PlinthBlockBase && dir.getAxis() == Direction.Axis.Y) return true; - if (dir == Direction.UP && state.getBlock() == Registry.STONE_HAND.get()) return true; - return false; - } - - protected BlockState getState(World world, BlockPos pos) { - return this.getDefaultState() - .with(TOP, canConnectTo(world, pos.up(), Direction.UP)) - .with(BOTTOM, canConnectTo(world, pos.down(), Direction.DOWN)) - .with(WATERLOGGED, Boolean.valueOf(world.getFluidState(pos).getFluid() == Fluids.WATER)); - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state); - } - - @Override - public boolean propagatesSkylightDown(BlockState state, IBlockReader reader, BlockPos pos) { - return !state.get(WATERLOGGED); - } - - @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - return getState(context.getWorld(), context.getPos()); - } - - @Override - public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld world, BlockPos pos, BlockPos facingPos) { - if (state.get(WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); - } - - if (facing == Direction.UP) state = state.with(TOP, canConnectTo(world, pos.up(), Direction.UP)); - if (facing == Direction.DOWN) state = state.with(BOTTOM, canConnectTo(world, pos.down(), Direction.DOWN)); - - return state; - } - - @Override - protected void fillStateContainer(StateContainer.Builder builder) { - builder.add(TOP, BOTTOM, WATERLOGGED); - } -} diff --git a/src/main/java/elucent/eidolon/block/ShroomBlockBase.java b/src/main/java/elucent/eidolon/block/ShroomBlockBase.java deleted file mode 100644 index fcc5377..0000000 --- a/src/main/java/elucent/eidolon/block/ShroomBlockBase.java +++ /dev/null @@ -1,56 +0,0 @@ -package elucent.eidolon.block; - -import elucent.eidolon.Registry; -import net.minecraft.block.*; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.state.IntegerProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.server.ServerWorld; - -import java.util.Random; - -public class ShroomBlockBase extends BushBlock { - public static final IntegerProperty AGE = BlockStateProperties.AGE_0_3; - private static final VoxelShape[] SHAPES = new VoxelShape[]{Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 5.0D, 16.0D), Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 11.0D, 16.0D), Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D)}; - - public ShroomBlockBase(AbstractBlock.Properties builder) { - super(builder); - this.setDefaultState(this.stateContainer.getBaseState().with(AGE, Integer.valueOf(0))); - } - - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return SHAPES[state.get(AGE)]; - } - - @Override - protected boolean isValidGround(BlockState state, IBlockReader worldIn, BlockPos pos) { - return false; // return state.isIn(Registry.PLANTER.get()); - } - - @Override - public boolean ticksRandomly(BlockState state) { - return state.get(AGE) < 3; - } - - @Override - public void randomTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random random) { - int i = state.get(AGE); - if (i < 3 && !worldIn.canBlockSeeSky(pos) && net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, pos, state, random.nextInt(10) == 0)) { - state = state.with(AGE, i + 1); - worldIn.setBlockState(pos, state, 2); - net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state); - } - } - - @Override - protected void fillStateContainer(StateContainer.Builder builder) { - builder.add(AGE); - } -} diff --git a/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java b/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java index c88723c..d43b75b 100644 --- a/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java +++ b/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java @@ -1,35 +1,58 @@ package elucent.eidolon.block; +import javax.annotation.Nullable; + import elucent.eidolon.gui.SoulEnchanterContainer; -import elucent.eidolon.gui.WorktableContainer; -import net.minecraft.block.BlockState; -import net.minecraft.block.HorizontalBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.container.SimpleNamedContainerProvider; +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.SoulEnchanterTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; import net.minecraft.stats.Stats; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.IWorldPosCallable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.World; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; -public class SoulEnchanterBlock extends HorizontalBlockBase { +public class SoulEnchanterBlock extends HorizontalBlockBase implements EntityBlock { public SoulEnchanterBlock(Properties properties) { super(properties); } @Override - public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - if (world.isRemote) { - return ActionResultType.SUCCESS; + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) { + if (world.isClientSide) { + return InteractionResult.SUCCESS; } else { - player.openContainer(new SimpleNamedContainerProvider((id, inventory, p) -> { - return new SoulEnchanterContainer(id, inventory, IWorldPosCallable.of(world, pos)); - }, new StringTextComponent(""))); - player.addStat(Stats.INTERACT_WITH_CRAFTING_TABLE); - return ActionResultType.CONSUME; + player.openMenu(new SimpleMenuProvider((id, inventory, p) -> { + return new SoulEnchanterContainer(id, inventory, ContainerLevelAccess.create(world, pos)); + }, new TextComponent(""))); + player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE); + return InteractionResult.CONSUME; } } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new SoulEnchanterTileEntity(pos, state); + } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return new BlockEntityTicker() { + @Override + public void tick(Level level, BlockPos pos, BlockState state, T tile) { + ((SoulEnchanterTileEntity)tile).tick(); + } + }; + } } diff --git a/src/main/java/elucent/eidolon/block/TableBlockBase.java b/src/main/java/elucent/eidolon/block/TableBlockBase.java index f943f63..a94f271 100644 --- a/src/main/java/elucent/eidolon/block/TableBlockBase.java +++ b/src/main/java/elucent/eidolon/block/TableBlockBase.java @@ -1,39 +1,30 @@ package elucent.eidolon.block; -import elucent.eidolon.tile.TileEntityBase; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.FenceGateBlock; -import net.minecraft.block.IWaterLoggable; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.Fluids; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.state.BooleanProperty; -import net.minecraft.state.StateContainer; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Direction; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.shapes.IBooleanFunction; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.world.Explosion; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.World; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.core.Direction; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; -public class TableBlockBase extends BlockBase implements IWaterLoggable { - VoxelShape NORMAL = VoxelShapes.create(0, 0.75, 0, 1, 1, 1), - CORNER = VoxelShapes.combine( +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + +public class TableBlockBase extends BlockBase implements SimpleWaterloggedBlock { + VoxelShape NORMAL = Shapes.box(0, 0.75, 0, 1, 1, 1), + CORNER = Shapes.joinUnoptimized( NORMAL, - VoxelShapes.create(0.0625, 0, 0.0625, 0.9375, 0.75, 0.9375), - IBooleanFunction.OR + Shapes.box(0.0625, 0, 0.0625, 0.9375, 0.75, 0.9375), + BooleanOp.OR ); public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; @@ -44,31 +35,31 @@ public class TableBlockBase extends BlockBase implements IWaterLoggable { public TableBlockBase(Properties properties) { super(properties); - setDefaultState(super.getDefaultState() - .with(NX, false) - .with(PX, false) - .with(NZ, false) - .with(PZ, false)); + registerDefaultState(super.defaultBlockState() + .setValue(NX, false) + .setValue(PX, false) + .setValue(NZ, false) + .setValue(PZ, false)); } public TableBlockBase setMainShape(VoxelShape shape) { NORMAL = shape; - CORNER = VoxelShapes.combine( + CORNER = Shapes.joinUnoptimized( NORMAL, - VoxelShapes.create(0.0625, 0, 0.0625, 0.9375, 0.75, 0.9375), - IBooleanFunction.OR + Shapes.box(0.0625, 0, 0.0625, 0.9375, 0.75, 0.9375), + BooleanOp.OR ); return this; } @Override - public VoxelShape getRaytraceShape(BlockState state, IBlockReader world, BlockPos pos) { - boolean nx = state.get(NX), px = state.get(PX), nz = state.get(NZ), pz = state.get(PZ); + public VoxelShape getInteractionShape(BlockState state, BlockGetter world, BlockPos pos) { + boolean nx = state.getValue(NX), px = state.getValue(PX), nz = state.getValue(NZ), pz = state.getValue(PZ); if ((!nx && !nz) || (!nx && !pz) || (!px && !pz) || (!px && !nz)) return CORNER; return NORMAL; } - protected BlockState updateCorners(IBlockReader world, BlockPos pos, BlockState state) { + protected BlockState updateCorners(BlockGetter world, BlockPos pos, BlockState state) { BlockState blockstate = world.getBlockState(pos.north()); BlockState blockstate1 = world.getBlockState(pos.east()); BlockState blockstate2 = world.getBlockState(pos.south()); @@ -78,37 +69,37 @@ protected BlockState updateCorners(IBlockReader world, BlockPos pos, BlockState conn3 = blockstate2.getBlock() == this, conn4 = blockstate3.getBlock() == this; return state - .with(NZ, conn1).with(PX, conn2) - .with(PZ, conn3).with(NX, conn4); + .setValue(NZ, conn1).setValue(PX, conn2) + .setValue(PZ, conn3).setValue(NX, conn4); } @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - IBlockReader iblockreader = context.getWorld(); - BlockPos blockpos = context.getPos(); - return updateCorners(iblockreader, blockpos, super.getStateForPlacement(context)).with(WATERLOGGED, false); + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockGetter iblockreader = context.getLevel(); + BlockPos blockpos = context.getClickedPos(); + return updateCorners(iblockreader, blockpos, super.getStateForPlacement(context)).setValue(WATERLOGGED, false); } @Override - public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld world, BlockPos pos, BlockPos facingPos) { - if (state.get(WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { + if (state.getValue(WATERLOGGED)) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return updateCorners(world, pos, state); } @Override - protected void fillStateContainer(StateContainer.Builder builder) { + protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(NX, PX, NZ, PZ, WATERLOGGED); } @Override public FluidState getFluidState(BlockState state) { - return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state); + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); } @Override - public boolean propagatesSkylightDown(BlockState state, IBlockReader reader, BlockPos pos) { - return !state.get(WATERLOGGED); + public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) { + return !state.getValue(WATERLOGGED); } } diff --git a/src/main/java/elucent/eidolon/block/TwoHighBlockBase.java b/src/main/java/elucent/eidolon/block/TwoHighBlockBase.java new file mode 100644 index 0000000..aecefe0 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/TwoHighBlockBase.java @@ -0,0 +1,51 @@ +package elucent.eidolon.block; + +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.Level; + +public class TwoHighBlockBase extends BlockBase { + public static final EnumProperty HALF = BlockStateProperties.HALF; + + public TwoHighBlockBase(BlockBehaviour.Properties properties) { + super(properties); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return super.canSurvive(state, world, pos) && world.isEmptyBlock(pos.above()); + } + + @Override + public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity entity, ItemStack stack) { + world.setBlockAndUpdate(pos.above(), defaultBlockState().setValue(HALF, Half.TOP)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState().setValue(HALF, Half.BOTTOM); + } + + @Override + public void breakBlock(BlockState state, Level world, BlockPos pos) { + if (state.getValue(HALF) == Half.BOTTOM && world.getBlockState(pos.above()).getBlock() == this) + world.destroyBlock(pos.above(), false); + else if (state.getValue(HALF) == Half.TOP && world.getBlockState(pos.below()).getBlock() == this) + world.destroyBlock(pos.below(), false); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(HALF); + } +} diff --git a/src/main/java/elucent/eidolon/block/WoodenStandBlock.java b/src/main/java/elucent/eidolon/block/WoodenStandBlock.java index c4ffd6f..fa0a912 100644 --- a/src/main/java/elucent/eidolon/block/WoodenStandBlock.java +++ b/src/main/java/elucent/eidolon/block/WoodenStandBlock.java @@ -1,98 +1,109 @@ package elucent.eidolon.block; -import elucent.eidolon.gui.SoulEnchanterContainer; +import java.util.Random; + +import javax.annotation.Nullable; + import elucent.eidolon.gui.WoodenBrewingStandContainer; +import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.WoodenStandTileEntity; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.BrewingStandBlock; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.inventory.container.SimpleNamedContainerProvider; -import net.minecraft.item.ItemStack; -import net.minecraft.particles.ParticleTypes; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.BrewingStandBlock; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Containers; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.world.item.ItemStack; import net.minecraft.stats.Stats; -import net.minecraft.tileentity.BrewingStandTileEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Direction; -import net.minecraft.util.Hand; -import net.minecraft.util.IWorldPosCallable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.network.NetworkHooks; - -import java.util.Random; +import net.minecraftforge.network.NetworkHooks; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class WoodenStandBlock extends BrewingStandBlock { - protected static final VoxelShape SHAPE = VoxelShapes.or(Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.makeCuboidShape(7.0D, 0.0D, 7.0D, 9.0D, 14.0D, 9.0D)); + protected static final VoxelShape SHAPE = Shapes.or(Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 14.0D, 9.0D)); public WoodenStandBlock(Properties properties) { super(properties); } @Override - public TileEntity createNewTileEntity(IBlockReader worldIn) { - return new WoodenStandTileEntity(); + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new WoodenStandTileEntity(pos, state); } @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return SHAPE; } @Override - public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - if (worldIn.isRemote) { - return ActionResultType.SUCCESS; + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { + if (worldIn.isClientSide) { + return InteractionResult.SUCCESS; } else { - TileEntity tileentity = worldIn.getTileEntity(pos); + BlockEntity tileentity = worldIn.getBlockEntity(pos); if (tileentity instanceof WoodenStandTileEntity) { - NetworkHooks.openGui((ServerPlayerEntity)player, new SimpleNamedContainerProvider((id, inventory, p) -> { - return new WoodenBrewingStandContainer(id, inventory, ((WoodenStandTileEntity)tileentity), ((WoodenStandTileEntity)tileentity).field_213954_a); + NetworkHooks.openGui((ServerPlayer)player, new SimpleMenuProvider((id, inventory, p) -> { + return new WoodenBrewingStandContainer(id, inventory, ((WoodenStandTileEntity)tileentity), ((WoodenStandTileEntity)tileentity).dataAccess); }, ((WoodenStandTileEntity)tileentity).getDisplayName()), pos); - player.addStat(Stats.INTERACT_WITH_BREWINGSTAND); + player.awardStat(Stats.INTERACT_WITH_BREWINGSTAND); } - return ActionResultType.CONSUME; + return InteractionResult.CONSUME; } } @Override - public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - if (stack.hasDisplayName()) { - TileEntity tileentity = worldIn.getTileEntity(pos); + public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (stack.hasCustomHoverName()) { + BlockEntity tileentity = worldIn.getBlockEntity(pos); if (tileentity instanceof WoodenStandTileEntity) { - ((WoodenStandTileEntity)tileentity).setCustomName(stack.getDisplayName()); + ((WoodenStandTileEntity)tileentity).setCustomName(stack.getHoverName()); } } } @OnlyIn(Dist.CLIENT) @Override - public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { + public void animateTick(BlockState stateIn, Level worldIn, BlockPos pos, Random rand) { // no particles with this one } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!state.isIn(newState.getBlock())) { - TileEntity tileentity = worldIn.getTileEntity(pos); + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { + BlockEntity tileentity = worldIn.getBlockEntity(pos); if (tileentity instanceof WoodenStandTileEntity) { - InventoryHelper.dropInventoryItems(worldIn, pos, (WoodenStandTileEntity)tileentity); + Containers.dropContents(worldIn, pos, (WoodenStandTileEntity)tileentity); } - super.onReplaced(state, worldIn, pos, newState, isMoving); + super.onRemove(state, worldIn, pos, newState, isMoving); } } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return new BlockEntityTicker() { + @Override + public void tick(Level level, BlockPos pos, BlockState state, T tile) { + ((WoodenStandTileEntity)tile).tick(); + } + }; + } } diff --git a/src/main/java/elucent/eidolon/block/WorktableBlock.java b/src/main/java/elucent/eidolon/block/WorktableBlock.java index 9105d85..617d2c0 100644 --- a/src/main/java/elucent/eidolon/block/WorktableBlock.java +++ b/src/main/java/elucent/eidolon/block/WorktableBlock.java @@ -1,17 +1,19 @@ package elucent.eidolon.block; import elucent.eidolon.gui.WorktableContainer; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.container.SimpleNamedContainerProvider; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; import net.minecraft.stats.Stats; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.IWorldPosCallable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.World; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.level.Level; + +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class WorktableBlock extends BlockBase { public WorktableBlock(Properties properties) { @@ -19,15 +21,15 @@ public WorktableBlock(Properties properties) { } @Override - public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - if (world.isRemote) { - return ActionResultType.SUCCESS; + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) { + if (world.isClientSide) { + return InteractionResult.SUCCESS; } else { - player.openContainer(new SimpleNamedContainerProvider((id, inventory, p) -> { - return new WorktableContainer(id, inventory, IWorldPosCallable.of(world, pos)); - }, new StringTextComponent(""))); - player.addStat(Stats.INTERACT_WITH_CRAFTING_TABLE); - return ActionResultType.CONSUME; + player.openMenu(new SimpleMenuProvider((id, inventory, p) -> { + return new WorktableContainer(id, inventory, ContainerLevelAccess.create(world, pos)); + }, new TextComponent(""))); + player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE); + return InteractionResult.CONSUME; } } } diff --git a/src/main/java/elucent/eidolon/capability/Facts.java b/src/main/java/elucent/eidolon/capability/Facts.java index d55d398..13f3205 100644 --- a/src/main/java/elucent/eidolon/capability/Facts.java +++ b/src/main/java/elucent/eidolon/capability/Facts.java @@ -1,7 +1,7 @@ package elucent.eidolon.capability; import elucent.eidolon.Eidolon; -import net.minecraft.util.ResourceLocation; +import net.minecraft.resources.ResourceLocation; public class Facts { public static final ResourceLocation diff --git a/src/main/java/elucent/eidolon/capability/IKnowledge.java b/src/main/java/elucent/eidolon/capability/IKnowledge.java index 0ba94a5..8975852 100644 --- a/src/main/java/elucent/eidolon/capability/IKnowledge.java +++ b/src/main/java/elucent/eidolon/capability/IKnowledge.java @@ -1,14 +1,41 @@ package elucent.eidolon.capability; -import elucent.eidolon.spell.Sign; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; - -import java.util.Map; import java.util.Set; -import java.util.UUID; + +import elucent.eidolon.spell.Sign; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; public interface IKnowledge { + public static final Capability INSTANCE = CapabilityManager.get(new CapabilityToken<>(){}); + + public static class Provider implements ICapabilityProvider, INBTSerializable { + KnowledgeImpl impl = new KnowledgeImpl(); + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == INSTANCE) return (LazyOptional) LazyOptional.of(() -> impl); + else return LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT() { + return impl.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + impl.deserializeNBT(nbt); + } + } + boolean knowsSign(Sign sign); void addSign(Sign sign); Set getKnownSigns(); diff --git a/src/main/java/elucent/eidolon/capability/IReputation.java b/src/main/java/elucent/eidolon/capability/IReputation.java index be2ed18..a932aef 100644 --- a/src/main/java/elucent/eidolon/capability/IReputation.java +++ b/src/main/java/elucent/eidolon/capability/IReputation.java @@ -1,14 +1,46 @@ package elucent.eidolon.capability; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import elucent.eidolon.deity.Deities; +import elucent.eidolon.deity.Deity; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; + public interface IReputation { + public static final Capability INSTANCE = CapabilityManager.get(new CapabilityToken<>(){}); + + public static class Provider implements ICapabilityProvider, INBTSerializable { + ReputationImpl impl = new ReputationImpl(); + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == INSTANCE) return (LazyOptional) LazyOptional.of(() -> impl); + else return LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT() { + return impl.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + impl.deserializeNBT(nbt); + } + } + double getReputation(UUID player, ResourceLocation deity); void addReputation(UUID player, ResourceLocation deity, double amount); void subtractReputation(UUID player, ResourceLocation deity, double amount); @@ -16,42 +48,59 @@ public interface IReputation { boolean isLocked(UUID player, ResourceLocation deity); void lock(UUID player, ResourceLocation deity, ResourceLocation key); boolean unlock(UUID player, ResourceLocation deity, ResourceLocation key); - void pray(UUID player, long time); - boolean canPray(UUID player, long time); + void pray(UUID player, ResourceLocation spell, long time); + boolean canPray(UUID player, ResourceLocation spell, long time); + + default double getReputation(Player player, ResourceLocation deity) { + return getReputation(player.getUUID(), deity); + } - default double getReputation(PlayerEntity player, ResourceLocation deity) { - return getReputation(player.getUniqueID(), deity); + default void considerChange(Player player, ResourceLocation deity, double prev) { + double amount = getReputation(player, deity); + Deity d = Deities.find(deity); + if (d != null && amount != prev) d.onReputationChange(player, this, prev, amount); } - default void addReputation(PlayerEntity player, ResourceLocation deity, double amount) { - addReputation(player.getUniqueID(), deity, amount); + default void addReputation(Player player, ResourceLocation deity, double amount) { + double prev = getReputation(player.getUUID(), deity); + addReputation(player.getUUID(), deity, amount); + considerChange(player, deity, prev); } - default void subtractReputation(PlayerEntity player, ResourceLocation deity, double amount) { - subtractReputation(player.getUniqueID(), deity, amount); + default void subtractReputation(Player player, ResourceLocation deity, double amount) { + double prev = getReputation(player.getUUID(), deity); + subtractReputation(player.getUUID(), deity, amount); + considerChange(player, deity, prev); } - default void setReputation(PlayerEntity player, ResourceLocation deity, double amount) { - setReputation(player.getUniqueID(), deity, amount); + default void setReputation(Player player, ResourceLocation deity, double amount) { + double prev = getReputation(player.getUUID(), deity); + setReputation(player.getUUID(), deity, amount); + considerChange(player, deity, prev); } - default void lock(PlayerEntity player, ResourceLocation deity, ResourceLocation key) { - lock(player.getUniqueID(), deity, key); + default void lock(Player player, ResourceLocation deity, ResourceLocation key) { + lock(player.getUUID(), deity, key); } - default boolean unlock(PlayerEntity player, ResourceLocation deity, ResourceLocation key) { - return unlock(player.getUniqueID(), deity, key); + default boolean unlock(Player player, ResourceLocation deity, ResourceLocation key) { + if (unlock(player.getUUID(), deity, key)) { + Deity d = Deities.find(deity); + if (d != null) d.onReputationUnlock(player, this, key); + return true; + } + return false; } - default void pray(PlayerEntity player, long time) { - pray(player.getUniqueID(), time); + default void pray(Player player, ResourceLocation spell, long time) { + pray(player.getUUID(), spell, time); } - default boolean canPray(PlayerEntity player, long time) { - return player.isCreative() || canPray(player.getUniqueID(), time); + default boolean canPray(Player player, ResourceLocation spell, long time) { + return player.isCreative() || canPray(player.getUUID(), spell, time); } - Map getPrayerTimes(); + Map> getPrayerTimes(); Map> getReputationMap(); default Map getReputationMap(UUID player) { return getReputationMap().computeIfAbsent(player, (k) -> new HashMap<>()); diff --git a/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java b/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java index f078281..2c57987 100644 --- a/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java +++ b/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java @@ -1,11 +1,18 @@ package elucent.eidolon.capability; -import elucent.eidolon.spell.Sign; -import net.minecraft.util.ResourceLocation; +import java.util.HashSet; +import java.util.Set; -import java.util.*; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.util.INBTSerializable; -public class KnowledgeImpl implements IKnowledge { +public class KnowledgeImpl implements IKnowledge, INBTSerializable { Set signs = new HashSet<>(); Set facts = new HashSet<>(); @@ -38,4 +45,42 @@ public void addFact(ResourceLocation fact) { public Set getKnownFacts() { return facts; } + + @Override + public CompoundTag serializeNBT() { + ListTag signs = new ListTag(); + for (Sign s : getKnownSigns()) { + signs.add(StringTag.valueOf(s.getRegistryName().toString())); + } + ListTag facts = new ListTag(); + for (ResourceLocation s : getKnownFacts()) { + facts.add(StringTag.valueOf(s.toString())); + } + CompoundTag wrapper = new CompoundTag(); + wrapper.put("signs", signs); + wrapper.put("facts", facts); + return wrapper; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + getKnownSigns().clear(); + getKnownFacts().clear(); + + if (((CompoundTag)nbt).contains("signs")) { + ListTag signs = ((CompoundTag) nbt).getList("signs", Tag.TAG_STRING); + for (int i = 0; i < signs.size(); i++) { + ResourceLocation loc = new ResourceLocation(signs.getString(i)); + Sign s = Signs.find(loc); + if (s != null) addSign(s); + } + } + + if (((CompoundTag)nbt).contains("facts")) { + ListTag facts = ((CompoundTag) nbt).getList("facts", Tag.TAG_STRING); + for (int i = 0; i < facts.size(); i++) { + addFact(new ResourceLocation(facts.getString(i))); + } + } + } } diff --git a/src/main/java/elucent/eidolon/capability/KnowledgeProvider.java b/src/main/java/elucent/eidolon/capability/KnowledgeProvider.java deleted file mode 100644 index 423f22d..0000000 --- a/src/main/java/elucent/eidolon/capability/KnowledgeProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package elucent.eidolon.capability; - -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.util.Direction; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.CapabilityInject; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.capabilities.ICapabilitySerializable; -import net.minecraftforge.common.util.LazyOptional; - -public class KnowledgeProvider implements ICapabilityProvider, ICapabilitySerializable { - @CapabilityInject(IKnowledge.class) - public static Capability CAPABILITY = null; - - IKnowledge instance = new KnowledgeImpl(); - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - return cap == CAPABILITY ? LazyOptional.of(() -> (T)instance) : LazyOptional.empty(); - } - - @Override - public CompoundNBT serializeNBT() { - return (CompoundNBT)CAPABILITY.getStorage().writeNBT(CAPABILITY, instance, null); - } - - @Override - public void deserializeNBT(CompoundNBT nbt) { - CAPABILITY.getStorage().readNBT(CAPABILITY, instance, null, nbt); - } -} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/capability/KnowledgeStorage.java b/src/main/java/elucent/eidolon/capability/KnowledgeStorage.java deleted file mode 100644 index 4bb4f4c..0000000 --- a/src/main/java/elucent/eidolon/capability/KnowledgeStorage.java +++ /dev/null @@ -1,52 +0,0 @@ -package elucent.eidolon.capability; - -import elucent.eidolon.spell.Sign; -import elucent.eidolon.spell.Signs; -import net.minecraft.nbt.*; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.Constants; - -import java.util.Map; -import java.util.UUID; - -public class KnowledgeStorage implements Capability.IStorage { - @Override - public INBT writeNBT(Capability capability, IKnowledge instance, Direction side) { - ListNBT signs = new ListNBT(); - for (Sign s : instance.getKnownSigns()) { - signs.add(StringNBT.valueOf(s.getRegistryName().toString())); - } - ListNBT facts = new ListNBT(); - for (ResourceLocation s : instance.getKnownFacts()) { - facts.add(StringNBT.valueOf(s.toString())); - } - CompoundNBT wrapper = new CompoundNBT(); - wrapper.put("signs", signs); - wrapper.put("facts", facts); - return wrapper; - } - - @Override - public void readNBT(Capability capability, IKnowledge instance, Direction side, INBT nbt) { - instance.getKnownSigns().clear(); - instance.getKnownFacts().clear(); - - if (((CompoundNBT)nbt).contains("signs")) { - ListNBT signs = ((CompoundNBT) nbt).getList("signs", Constants.NBT.TAG_STRING); - for (int i = 0; i < signs.size(); i++) { - ResourceLocation loc = new ResourceLocation(signs.getString(i)); - Sign s = Signs.find(loc); - if (s != null) instance.addSign(s); - } - } - - if (((CompoundNBT)nbt).contains("facts")) { - ListNBT facts = ((CompoundNBT) nbt).getList("facts", Constants.NBT.TAG_STRING); - for (int i = 0; i < facts.size(); i++) { - instance.addFact(new ResourceLocation(facts.getString(i))); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/capability/ReputationEntry.java b/src/main/java/elucent/eidolon/capability/ReputationEntry.java index 6c4f5ab..d53ccef 100644 --- a/src/main/java/elucent/eidolon/capability/ReputationEntry.java +++ b/src/main/java/elucent/eidolon/capability/ReputationEntry.java @@ -1,7 +1,7 @@ package elucent.eidolon.capability; -import net.minecraft.util.ResourceLocation; +import net.minecraft.resources.ResourceLocation; public class ReputationEntry { double reputation; diff --git a/src/main/java/elucent/eidolon/capability/ReputationImpl.java b/src/main/java/elucent/eidolon/capability/ReputationImpl.java index 946db52..00d5e17 100644 --- a/src/main/java/elucent/eidolon/capability/ReputationImpl.java +++ b/src/main/java/elucent/eidolon/capability/ReputationImpl.java @@ -1,16 +1,17 @@ package elucent.eidolon.capability; -import elucent.eidolon.deity.Deities; -import elucent.eidolon.deity.Deity; -import net.minecraft.util.ResourceLocation; - import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.Map.Entry; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.util.INBTSerializable; -public class ReputationImpl implements IReputation { +public class ReputationImpl implements IReputation, INBTSerializable { Map> reputationMap = new HashMap<>(); - Map prayerTimes = new HashMap<>(); + Map> prayerTimes = new HashMap<>(); @Override public double getReputation(UUID player, ResourceLocation deity) { @@ -32,7 +33,10 @@ public void subtractReputation(UUID player, ResourceLocation deity, double amoun @Override public void setReputation(UUID player, ResourceLocation deity, double amount) { ReputationEntry entry = getReputationMap(player).computeIfAbsent(deity, (k) -> new ReputationEntry()); - if (entry.lock == null || amount < 0) entry.reputation = amount; + if (entry.lock == null || amount < 0) { + double prev = entry.reputation; + entry.reputation = amount; + } } @Override @@ -56,17 +60,18 @@ public boolean unlock(UUID player, ResourceLocation deity, ResourceLocation key) } @Override - public void pray(UUID player, long time) { - getPrayerTimes().put(player, time); + public void pray(UUID player, ResourceLocation spell, long time) { + getPrayerTimes().computeIfAbsent(player, (p) -> new HashMap<>()).put(spell, time); } @Override - public boolean canPray(UUID player, long time) { - return !getPrayerTimes().containsKey(player) || getPrayerTimes().get(player) < time - 21000; + public boolean canPray(UUID player, ResourceLocation spell, long time) { + Map times = getPrayerTimes().computeIfAbsent(player, (p) -> new HashMap<>()); + return !times.containsKey(player) || times.get(spell) < time - 21000; } @Override - public Map getPrayerTimes() { + public Map> getPrayerTimes() { return prayerTimes; } @@ -74,4 +79,58 @@ public Map getPrayerTimes() { public Map> getReputationMap() { return reputationMap; } + + @Override + public CompoundTag serializeNBT() { + CompoundTag data = new CompoundTag(); + CompoundTag reps = new CompoundTag(); + for (Entry> e : getReputationMap().entrySet()) { + CompoundTag tag = new CompoundTag(); + for (Entry e2 : e.getValue().entrySet()) { + CompoundTag entry = new CompoundTag(); + entry.putDouble("rep", e2.getValue().reputation); + if (e2.getValue().lock != null) entry.putString("lock", e2.getValue().lock.toString()); + tag.put(e2.getKey().toString(), entry); + } + reps.put(e.getKey().toString(), tag); + } + CompoundTag times = new CompoundTag(); + for (Entry> e : getPrayerTimes().entrySet()) { + CompoundTag nbt = new CompoundTag(); + for (Entry e2 : e.getValue().entrySet()) + nbt.putLong(e2.getKey().toString(), e2.getValue()); + times.put(e.getKey().toString(), nbt); + } + data.put("reps", reps); + data.put("times", times); + return data; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + CompoundTag data = (CompoundTag)nbt; + getReputationMap().clear(); + if (data.contains("reps")) { + CompoundTag reps = data.getCompound("reps"); + for (String uuidString : reps.getAllKeys()) { + UUID uuid = UUID.fromString(uuidString); + CompoundTag tag = reps.getCompound(uuidString); + for (String deity : tag.getAllKeys()) { + CompoundTag entry = tag.getCompound(deity); + setReputation(uuid, new ResourceLocation(deity), entry.getDouble("rep")); + if (entry.contains("lock")) + lock(uuid, new ResourceLocation(deity), new ResourceLocation(entry.getString("lock"))); + } + } + } + if (data.contains("times")) { + CompoundTag times = data.getCompound("times"); + for (String uuidString : times.getAllKeys()) { + UUID uuid = UUID.fromString(uuidString); + CompoundTag spelltimes = times.getCompound(uuidString); + for (String rl : spelltimes.getAllKeys()) + pray(uuid, new ResourceLocation(rl), spelltimes.getLong(rl)); + } + } + } } diff --git a/src/main/java/elucent/eidolon/capability/ReputationProvider.java b/src/main/java/elucent/eidolon/capability/ReputationProvider.java deleted file mode 100644 index cc33d73..0000000 --- a/src/main/java/elucent/eidolon/capability/ReputationProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package elucent.eidolon.capability; - -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.util.Direction; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.CapabilityInject; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.capabilities.ICapabilitySerializable; -import net.minecraftforge.common.util.LazyOptional; - -public class ReputationProvider implements ICapabilityProvider, ICapabilitySerializable { - @CapabilityInject(IReputation.class) - public static Capability CAPABILITY = null; - - IReputation instance = new ReputationImpl(); - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - return cap == CAPABILITY ? LazyOptional.of(() -> (T)instance) : LazyOptional.empty(); - } - - @Override - public CompoundNBT serializeNBT() { - return (CompoundNBT)CAPABILITY.getStorage().writeNBT(CAPABILITY, instance, null); - } - - @Override - public void deserializeNBT(CompoundNBT nbt) { - CAPABILITY.getStorage().readNBT(CAPABILITY, instance, null, nbt); - } -} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/capability/ReputationStorage.java b/src/main/java/elucent/eidolon/capability/ReputationStorage.java deleted file mode 100644 index eefda84..0000000 --- a/src/main/java/elucent/eidolon/capability/ReputationStorage.java +++ /dev/null @@ -1,63 +0,0 @@ -package elucent.eidolon.capability; - -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.INBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.capabilities.Capability; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -public class ReputationStorage implements Capability.IStorage { - @Override - public INBT writeNBT(Capability capability, IReputation instance, Direction side) { - CompoundNBT data = new CompoundNBT(); - CompoundNBT reps = new CompoundNBT(); - for (Entry> e : instance.getReputationMap().entrySet()) { - CompoundNBT tag = new CompoundNBT(); - for (Entry e2 : e.getValue().entrySet()) { - CompoundNBT entry = new CompoundNBT(); - entry.putDouble("rep", e2.getValue().reputation); - if (e2.getValue().lock != null) entry.putString("lock", e2.getValue().lock.toString()); - tag.put(e2.getKey().toString(), entry); - } - reps.put(e.getKey().toString(), tag); - } - CompoundNBT times = new CompoundNBT(); - for (Entry e : instance.getPrayerTimes().entrySet()) { - times.putLong(e.getKey().toString(), e.getValue()); - } - data.put("reps", reps); - data.put("times", times); - return data; - } - - @Override - public void readNBT(Capability capability, IReputation instance, Direction side, INBT nbt) { - CompoundNBT data = (CompoundNBT)nbt; - instance.getReputationMap().clear(); - if (data.contains("reps")) { - CompoundNBT reps = data.getCompound("reps"); - for (String uuidString : reps.keySet()) { - UUID uuid = UUID.fromString(uuidString); - CompoundNBT tag = reps.getCompound(uuidString); - for (String deity : tag.keySet()) { - CompoundNBT entry = tag.getCompound(deity); - instance.setReputation(uuid, new ResourceLocation(deity), entry.getDouble("rep")); - if (entry.contains("lock")) - instance.lock(uuid, new ResourceLocation(deity), new ResourceLocation(entry.getString("lock"))); - } - } - } - if (data.contains("times")) { - CompoundNBT times = data.getCompound("times"); - for (String uuidString : times.keySet()) { - UUID uuid = UUID.fromString(uuidString); - instance.pray(uuid, times.getLong(uuidString)); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/codex/Category.java b/src/main/java/elucent/eidolon/codex/Category.java index 5fa6ac5..96770c5 100644 --- a/src/main/java/elucent/eidolon/codex/Category.java +++ b/src/main/java/elucent/eidolon/codex/Category.java @@ -1,18 +1,21 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.util.ColorUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldVertexBufferUploader; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Mirror; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.client.renderer.GameRenderer; + +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.util.Mth; +import com.mojang.math.Matrix4f; +import net.minecraft.network.chat.TranslatableComponent; public class Category { ItemStack icon; @@ -32,23 +35,23 @@ protected void reset() { hoveramount = 0; } - static void colorBlit(MatrixStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { - Matrix4f matrix = mStack.getLast().getMatrix(); + static void colorBlit(PoseStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { + RenderSystem.setShader(GameRenderer::getPositionTexColorShader); + Matrix4f matrix = mStack.last().pose(); int maxX = x + width, maxY = y + height; float minU = (float)uOffset / textureWidth, minV = (float)vOffset / textureHeight; float maxU = minU + (float)width / textureWidth, maxV = minV + (float)height / textureHeight; int r = ColorUtil.getRed(color), g = ColorUtil.getGreen(color), b = ColorUtil.getBlue(color); - BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer(); - bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - bufferbuilder.pos(matrix, (float)x, (float)maxY, 0).tex(minU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)maxY, 0).tex(maxU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)y, 0).tex(maxU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)x, (float)y, 0).tex(minU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.finishDrawing(); - RenderSystem.enableAlphaTest(); - WorldVertexBufferUploader.draw(bufferbuilder); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + bufferbuilder.vertex(matrix, (float)x, (float)maxY, 0).uv(minU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)maxY, 0).uv(maxU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)y, 0).uv(maxU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)x, (float)y, 0).uv(minU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.end(); + BufferUploader.end(bufferbuilder); } public boolean click(CodexGui gui, int x, int y, boolean right, int mouseX, int mouseY) { @@ -67,34 +70,34 @@ public boolean click(CodexGui gui, int x, int y, boolean right, int mouseX, int return false; } - public void draw(CodexGui gui, MatrixStack mStack, int x, int y, boolean right, int mouseX, int mouseY) { + public void draw(CodexGui gui, PoseStack mStack, int x, int y, boolean right, int mouseX, int mouseY) { int w = 36; if (!right) x -= 36; w += hoveramount * 12; if (!right) x -= hoveramount * 12; boolean hover = mouseX >= x && mouseY >= y && mouseX <= x + w && mouseY <= y + 19; - if (hover && hoveramount < 1) hoveramount += Minecraft.getInstance().getRenderPartialTicks() / 4; - else if (!hover && hoveramount > 0) hoveramount -= Minecraft.getInstance().getRenderPartialTicks() / 4; - hoveramount = MathHelper.clamp(hoveramount, 0, 1); + if (hover && hoveramount < 1) hoveramount += Minecraft.getInstance().getFrameTime() / 4; + else if (!hover && hoveramount > 0) hoveramount -= Minecraft.getInstance().getFrameTime() / 4; + hoveramount = Mth.clamp(hoveramount, 0, 1); if (right) { x -= 12; x += hoveramount * 12; } - Minecraft.getInstance().getTextureManager().bindTexture(CodexGui.CODEX_BACKGROUND); + RenderSystem.setShaderTexture(0, CodexGui.CODEX_BACKGROUND); colorBlit(mStack, x, y, 208, right ? 208 : 227, 48, 19, 512, 512, color); - Minecraft.getInstance().getItemRenderer().renderItemAndEffectIntoGUI(icon, x + (right ? 23 : 9), y + 1); + Minecraft.getInstance().getItemRenderer().renderAndDecorateItem(icon, x + (right ? 23 : 9), y + 1); } - public void drawTooltip(CodexGui gui, MatrixStack mStack, int x, int y, boolean right, int mouseX, int mouseY) { + public void drawTooltip(CodexGui gui, PoseStack mStack, int x, int y, boolean right, int mouseX, int mouseY) { int w = 36; if (!right) x -= 36; w += hoveramount * 12; if (!right) x -= hoveramount * 12; boolean hover = mouseX >= x && mouseY >= y && mouseX <= x + w && mouseY <= y + 19; - if (hover) gui.renderTooltip(mStack, new TranslationTextComponent("eidolon.codex.category." + key), mouseX, mouseY); + if (hover) gui.renderTooltip(mStack, new TranslatableComponent("eidolon.codex.category." + key), mouseX, mouseY); } } diff --git a/src/main/java/elucent/eidolon/codex/ChantPage.java b/src/main/java/elucent/eidolon/codex/ChantPage.java index 3271009..e48a3a8 100644 --- a/src/main/java/elucent/eidolon/codex/ChantPage.java +++ b/src/main/java/elucent/eidolon/codex/ChantPage.java @@ -1,34 +1,31 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.KnowledgeProvider; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.ColorUtil; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldVertexBufferUploader; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.util.text.TranslationTextComponent; +import com.mojang.blaze3d.vertex.BufferBuilder; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import com.mojang.blaze3d.vertex.BufferUploader; +import net.minecraft.client.renderer.texture.TextureAtlas; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; +import com.mojang.math.Matrix4f; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; public class ChantPage extends Page { public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_chant_page.png"); @@ -43,66 +40,63 @@ public ChantPage(String textKey, Sign... chant) { } @OnlyIn(Dist.CLIENT) - static void colorBlit(MatrixStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { - Matrix4f matrix = mStack.getLast().getMatrix(); + static void colorBlit(PoseStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { + Matrix4f matrix = mStack.last().pose(); int maxX = x + width, maxY = y + height; float minU = (float)uOffset / textureWidth, minV = (float)vOffset / textureHeight; float maxU = minU + (float)width / textureWidth, maxV = minV + (float)height / textureHeight; int r = ColorUtil.getRed(color), g = ColorUtil.getGreen(color), b = ColorUtil.getBlue(color); - BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer(); - bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - bufferbuilder.pos(matrix, (float)x, (float)maxY, 0).tex(minU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)maxY, 0).tex(maxU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)y, 0).tex(maxU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)x, (float)y, 0).tex(minU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.finishDrawing(); - RenderSystem.enableAlphaTest(); - WorldVertexBufferUploader.draw(bufferbuilder); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + bufferbuilder.vertex(matrix, (float)x, (float)maxY, 0).uv(minU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)maxY, 0).uv(maxU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)y, 0).uv(maxU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)x, (float)y, 0).uv(minU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.end(); + BufferUploader.end(bufferbuilder); } @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - String title = I18n.format(this.title); - int titleWidth = Minecraft.getInstance().fontRenderer.getStringWidth(title); - drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + String title = I18n.get(this.title); + int titleWidth = Minecraft.getInstance().font.width(title); + drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().font.lineHeight); - Minecraft.getInstance().getTextureManager().bindTexture(CodexGui.CODEX_BACKGROUND); - PlayerEntity entity = Minecraft.getInstance().player; - IKnowledge knowledge = entity.getCapability(KnowledgeProvider.CAPABILITY, null).resolve().get(); + RenderSystem.setShaderTexture(0, CodexGui.CODEX_BACKGROUND); + Player entity = Minecraft.getInstance().player; + IKnowledge knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve().get(); int w = chant.length * 24; int baseX = x + 64 - w / 2; - gui.blit(mStack, baseX - 16, y + 28, 256, 208, 16, 32, 512, 512); + CodexGui.blit(mStack, baseX - 16, y + 28, 256, 208, 16, 32, 512, 512); for (int i = 0; i < chant.length; i ++) { - gui.blit(mStack, baseX + i * 24, y + 28, 272, 208, 24, 32, 512, 512); + CodexGui.blit(mStack, baseX + i * 24, y + 28, 272, 208, 24, 32, 512, 512); } - gui.blit(mStack, baseX + w, y + 28, 296, 208, 16, 32, 512, 512); + CodexGui.blit(mStack, baseX + w, y + 28, 296, 208, 16, 32, 512, 512); - Tessellator tess = Tessellator.getInstance(); + Tesselator tess = Tesselator.getInstance(); RenderSystem.enableBlend(); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); for (int i = 0; i < chant.length; i ++) { - Minecraft.getInstance().getTextureManager().bindTexture(CodexGui.CODEX_BACKGROUND); + RenderSystem.setShaderTexture(0, CodexGui.CODEX_BACKGROUND); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - gui.blit(mStack, baseX + i * 24, y + 28, 312, 208, 24, 24, 512, 512); + CodexGui.blit(mStack, baseX + i * 24, y + 28, 312, 208, 24, 24, 512, 512); - Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); Sign sign = chant[i]; float flicker = 0.875f + 0.125f * (float)Math.sin(Math.toRadians(12 * ClientEvents.getClientTicks())); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), baseX + i * 24 + 4, y + 32, 16, 16, - sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), baseX + i * 24 + 4, y + 32, 16, 16, - sign.getRed() * flicker, sign.getGreen() * flicker, sign.getBlue() * flicker, Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), baseX + i * 24 + 4, y + 32, 16, 16, + sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), baseX + i * 24 + 4, y + 32, 16, 16, + sign.getRed() * flicker, sign.getGreen() * flicker, sign.getBlue() * flicker, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); } - RenderSystem.defaultAlphaFunc(); RenderSystem.disableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - drawWrappingText(gui, mStack, I18n.format(text), x + 4, y + 72, 120); + drawWrappingText(gui, mStack, I18n.get(text), x + 4, y + 72, 120); } } diff --git a/src/main/java/elucent/eidolon/codex/Chapter.java b/src/main/java/elucent/eidolon/codex/Chapter.java index 900e128..d34a4aa 100644 --- a/src/main/java/elucent/eidolon/codex/Chapter.java +++ b/src/main/java/elucent/eidolon/codex/Chapter.java @@ -1,10 +1,9 @@ package elucent.eidolon.codex; -import com.google.common.collect.Lists; - -import java.util.ArrayList; import java.util.List; +import com.google.common.collect.Lists; + public class Chapter { String titleKey; List pages; diff --git a/src/main/java/elucent/eidolon/codex/CodexChapters.java b/src/main/java/elucent/eidolon/codex/CodexChapters.java index be8deb8..362ca5e 100644 --- a/src/main/java/elucent/eidolon/codex/CodexChapters.java +++ b/src/main/java/elucent/eidolon/codex/CodexChapters.java @@ -1,7 +1,8 @@ package elucent.eidolon.codex; -import com.sun.corba.se.spi.orbutil.threadpool.Work; -import elucent.eidolon.Eidolon; +import java.util.ArrayList; +import java.util.List; + import elucent.eidolon.Registry; import elucent.eidolon.capability.Facts; import elucent.eidolon.codex.CruciblePage.CrucibleStep; @@ -12,18 +13,13 @@ import elucent.eidolon.codex.RitualPage.RitualIngredient; import elucent.eidolon.codex.SignIndexPage.SignEntry; import elucent.eidolon.ritual.RitualRegistry; -import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; import elucent.eidolon.util.ColorUtil; -import net.minecraft.block.Blocks; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.potion.PotionUtils; -import net.minecraft.potion.Potions; - -import java.util.ArrayList; -import java.util.List; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; public class CodexChapters { static List categories = new ArrayList<>(); @@ -33,7 +29,7 @@ public class CodexChapters { RITUALS_INDEX, BRAZIER, ITEM_PROVIDERS, CRYSTAL_RITUAL, SUMMON_RITUAL, ALLURE_RITUAL, REPELLING_RITUAL, DECEIT_RITUAL, TIME_RITUALS, PURIFY_RITUAL, SANGUINE_RITUAL, ARTIFICE_INDEX, WOODEN_STAND, TALLOW, CRUCIBLE, ARCANE_GOLD, REAGENTS, SOUL_GEMS, SHADOW_GEM, WARPED_SPROUTS, BASIC_ALCHEMY, INLAYS, BASIC_BAUBLES, MAGIC_WORKBENCH, VOID_AMULET, WARDED_MAIL, SOULFIRE_WAND, BONECHILL_WAND, REAPER_SCYTHE, CLEAVING_AXE, SOUL_ENCHANTER, REVERSAL_PICK, WARLOCK_ARMOR, GRAVITY_BELT, PRESTIGIOUS_PALM, MIND_SHIELDING_PLATE, RESOLUTE_BELT, GLASS_HAND, THEURGY_INDEX, INTRO_SIGNS, EFFIGY, ALTARS, ALTAR_LIGHTS, ALTAR_SKULLS, ALTAR_HERBS, GOBLET, DARK_PRAYER, ANIMAL_SACRIFICE, DARK_TOUCH, STONE_ALTAR, UNHOLY_EFFIGY, VILLAGER_SACRIFICE, - SIGNS_INDEX, WICKED_SIGN, SACRED_SIGN, BLOOD_SIGN, SOUL_SIGN, MIND_SIGN; + SIGNS_INDEX, WICKED_SIGN, SACRED_SIGN, BLOOD_SIGN, SOUL_SIGN, MIND_SIGN, FLAME_SIGN; public static void init() { MONSTERS = new Chapter( @@ -215,7 +211,7 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY), new TitledRitualPage("eidolon.codex.page.purify_ritual", RitualRegistry.PURIFY_RITUAL, new ItemStack(Items.GLISTERING_MELON_SLICE), new RitualIngredient(new ItemStack(Registry.ENCHANTED_ASH.get()), false), new RitualIngredient(new ItemStack(Registry.ENCHANTED_ASH.get()), false), - new RitualIngredient(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HEALING), false), + new RitualIngredient(PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HEALING), false), new RitualIngredient(new ItemStack(Registry.SOUL_SHARD.get()), false), new RitualIngredient(new ItemStack(Registry.SOUL_SHARD.get()), false)), new TextPage("eidolon.codex.page.purify_ritual") @@ -223,7 +219,7 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY), SANGUINE_RITUAL = new Chapter( "eidolon.codex.chapter.sanguine_ritual", - new TitledRitualPage("eidolon.codex.page.sanguine_ritual.0", RitualRegistry.SANGUINE_SWORD, PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HARMING), + new TitledRitualPage("eidolon.codex.page.sanguine_ritual.0", RitualRegistry.SANGUINE_SWORD, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HARMING), new RitualIngredient(new ItemStack(Registry.SHADOW_GEM.get()), false), new RitualIngredient(new ItemStack(Registry.SOUL_SHARD.get()), false), new RitualIngredient(new ItemStack(Registry.SOUL_SHARD.get()), false), @@ -232,7 +228,7 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY), new RitualIngredient(new ItemStack(Items.NETHER_WART), false), new RitualIngredient(new ItemStack(Items.NETHER_WART), false)), new TextPage("eidolon.codex.page.sanguine_ritual.0"), - new TitledRitualPage("eidolon.codex.page.sanguine_ritual.1", RitualRegistry.SANGUINE_AMULET, PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HARMING), + new TitledRitualPage("eidolon.codex.page.sanguine_ritual.1", RitualRegistry.SANGUINE_AMULET, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HARMING), new RitualIngredient(new ItemStack(Items.REDSTONE), false), new RitualIngredient(new ItemStack(Items.REDSTONE), false), new RitualIngredient(new ItemStack(Items.DIAMOND), false), @@ -488,7 +484,7 @@ ItemStack.EMPTY, new ItemStack(Items.STICK), new ItemStack(Registry.PEWTER_INGOT new ItemStack(Registry.PEWTER_INGOT.get()), new ItemStack(Registry.PEWTER_INGOT.get()), ItemStack.EMPTY, ItemStack.EMPTY, new ItemStack(Items.STICK), new ItemStack(Registry.PEWTER_INGOT.get()), new ItemStack(Items.STICK), ItemStack.EMPTY, ItemStack.EMPTY, - new ItemStack(Registry.UNHOLY_SYMBOL.get()), new ItemStack(Registry.SOUL_SHARD.get()), new ItemStack(Registry.TATTERED_CLOTH.get()), new ItemStack(Registry.SOUL_SHARD.get())) + new ItemStack(Registry.UNHOLY_SYMBOL.get()), new ItemStack(Registry.TATTERED_CLOTH.get()), new ItemStack(Registry.SOUL_SHARD.get()), new ItemStack(Registry.TATTERED_CLOTH.get())) ); CLEAVING_AXE = new Chapter( @@ -808,6 +804,12 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY, new SignPage(Signs.MIND_SIGN) ); + FLAME_SIGN = new Chapter( + "eidolon.codex.chapter.flame_sign", + new TitlePage("eidolon.codex.page.flame_sign"), + new SignPage(Signs.FLAME_SIGN) + ); + SIGNS_INDEX = new Chapter( "eidolon.codex.chapter.signs_index", new SignIndexPage( @@ -815,7 +817,8 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY, new SignEntry(SACRED_SIGN, Signs.SACRED_SIGN), new SignEntry(BLOOD_SIGN, Signs.BLOOD_SIGN), new SignEntry(SOUL_SIGN, Signs.SOUL_SIGN), - new SignEntry(MIND_SIGN, Signs.MIND_SIGN) + new SignEntry(MIND_SIGN, Signs.MIND_SIGN), + new SignEntry(FLAME_SIGN, Signs.FLAME_SIGN) ) ); diff --git a/src/main/java/elucent/eidolon/codex/CodexGui.java b/src/main/java/elucent/eidolon/codex/CodexGui.java index 249e8e6..9152866 100644 --- a/src/main/java/elucent/eidolon/codex/CodexGui.java +++ b/src/main/java/elucent/eidolon/codex/CodexGui.java @@ -1,37 +1,37 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; import elucent.eidolon.network.AttemptCastPacket; import elucent.eidolon.network.Networking; -import elucent.eidolon.particle.SignParticleData; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.world.World; -import org.lwjgl.glfw.GLFW; -import org.lwjgl.opengl.GL11; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.math.Matrix4f; -import java.util.ArrayList; -import java.util.List; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.level.Level; public class CodexGui extends Screen { public static final CodexGui DUMMY = new CodexGui(); @@ -50,7 +50,7 @@ public static CodexGui getInstance() { } protected CodexGui() { - super(new TranslationTextComponent("gui.eidolon.codex.title")); + super(new TranslatableComponent("gui.eidolon.codex.title")); currentChapter = CodexChapters.NATURE_INDEX; } @@ -69,13 +69,12 @@ public void addToChant(Sign sign) { if (this.chant.size() < 9) this.chant.add(sign); } - protected void renderChant(MatrixStack mStack, int x, int y, int mouseX, int mouseY, float pticks) { + protected void renderChant(PoseStack mStack, int x, int y, int mouseX, int mouseY, float pticks) { int chantWidth = 32 + 24 * chant.size(); int baseX = x + this.xSize / 2 - chantWidth / 2, baseY = y + 180; RenderSystem.enableBlend(); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); - + int bgx = baseX; blit(mStack, bgx, baseY, 256, 208, 16, 32, 512, 512); bgx += 16; @@ -91,19 +90,18 @@ protected void renderChant(MatrixStack mStack, int x, int y, int mouseX, int mou bgx += 36; boolean cancelHover = mouseX >= bgx && mouseY >= baseY - 4 && mouseX <= bgx + 32 && mouseY <= baseY + 28; blit(mStack, bgx, baseY - 4, 368, cancelHover ? 240 : 208, 32, 32, 512, 512); - if (chantHover) renderTooltip(mStack, new TranslationTextComponent("eidolon.codex.chant_hover"), mouseX, mouseY); - if (cancelHover) renderTooltip(mStack, new TranslationTextComponent("eidolon.codex.cancel_hover"), mouseX, mouseY); + if (chantHover) renderTooltip(mStack, new TranslatableComponent("eidolon.codex.chant_hover"), mouseX, mouseY); + if (cancelHover) renderTooltip(mStack, new TranslatableComponent("eidolon.codex.cancel_hover"), mouseX, mouseY); RenderSystem.enableBlend(); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); - Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); bgx = baseX + 16; - Tessellator tess = Tessellator.getInstance(); + Tesselator tess = Tesselator.getInstance(); for (int i = 0; i < chant.size(); i ++) { Sign sign = chant.get(i); - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), bgx + 4, baseY + 4, 16, 16, - sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 4, baseY + 4, 16, 16, + sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); bgx += 24; } bgx = baseX + 16; @@ -111,25 +109,39 @@ protected void renderChant(MatrixStack mStack, int x, int y, int mouseX, int mou float flicker = 0.875f + 0.125f * (float)Math.sin(Math.toRadians(12 * ClientEvents.getClientTicks())); for (int i = 0; i < chant.size(); i ++) { Sign sign = chant.get(i); - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), bgx + 4, baseY + 4, 16, 16, - sign.getRed() * flicker, sign.getGreen() * flicker, sign.getBlue() * flicker, Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 4, baseY + 4, 16, 16, + sign.getRed() * flicker, sign.getGreen() * flicker, sign.getBlue() * flicker, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); bgx += 24; } - RenderSystem.defaultAlphaFunc(); RenderSystem.defaultBlendFunc(); RenderSystem.disableBlend(); - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND_LOCATION); + RenderSystem.setShaderTexture(0, BACKGROUND_LOCATION); } + + boolean hasTooltip = false; + Matrix4f tooltipMatrix = null; + Component tooltipText = null; + int tooltipX = 0, tooltipY = 0; @Override - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + public void renderTooltip(PoseStack poseStack, Component text, int x, int y) { + tooltipMatrix = poseStack.last().pose(); + tooltipText = text; + tooltipX = x; + tooltipY = y; + hasTooltip = true; + } + + @Override + public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { + hasTooltip = false; renderBackground(matrixStack); Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(CODEX_BACKGROUND); + RenderSystem.setShaderTexture(0, CODEX_BACKGROUND); - this.width = mc.getMainWindow().getScaledWidth(); - this.height = mc.getMainWindow().getScaledHeight(); + this.width = mc.getWindow().getGuiScaledWidth(); + this.height = mc.getWindow().getGuiScaledHeight(); int guiLeft = (width - xSize) / 2, guiTop = (height - ySize) / 2; blit(matrixStack, guiLeft, guiTop, 0, 256, xSize, ySize, 512, 512); @@ -138,13 +150,13 @@ public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partia CodexChapters.categories.get(i).draw(this, matrixStack, guiLeft + (i >= 8 ? 304 : 8), y, i >= 8, mouseX, mouseY); } - mc.getTextureManager().bindTexture(CODEX_BACKGROUND); + RenderSystem.setShaderTexture(0, CODEX_BACKGROUND); blit(matrixStack, guiLeft, guiTop, 0, 0, xSize, ySize, 512, 512); Page left = currentChapter.get(currentPage), right = currentChapter.get(currentPage + 1); if (left != null) left.fullRender(this, matrixStack, guiLeft + 14, guiTop + 24, mouseX, mouseY); if (right != null) right.fullRender(this, matrixStack, guiLeft + 170, guiTop + 24, mouseX, mouseY); - mc.getTextureManager().bindTexture(CODEX_BACKGROUND); + RenderSystem.setShaderTexture(0, CODEX_BACKGROUND); if (currentPage > 0) { // left arrow int x = 10, y = 169; int v = 208; @@ -165,6 +177,14 @@ public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partia int y = guiTop + 28 + (i % 8) * 20; CodexChapters.categories.get(i).drawTooltip(this, matrixStack, guiLeft + (i >= 8 ? 304 : 8), y, i >= 8, mouseX, mouseY); } + + if (hasTooltip) { + matrixStack.pushPose(); + matrixStack.setIdentity(); + matrixStack.mulPoseMatrix(tooltipMatrix); + super.renderTooltip(matrixStack, tooltipText, tooltipX, tooltipY); + matrixStack.popPose(); + } } protected boolean interactChant(int x, int y, int mouseX, int mouseY) { @@ -175,17 +195,17 @@ protected boolean interactChant(int x, int y, int mouseX, int mouseY) { bgx += 36; boolean cancelHover = mouseX >= bgx && mouseY >= baseY - 4 && mouseX <= bgx + 32 && mouseY <= baseY + 28; if (chantHover) { - PlayerEntity player = Minecraft.getInstance().player; - World world = Minecraft.getInstance().world; + Player player = Minecraft.getInstance().player; + Level world = Minecraft.getInstance().level; Networking.sendToServer(new AttemptCastPacket(player, chant)); chant.clear(); - player.playSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.NEUTRAL, 1.0f, 1.0f); - this.closeScreen(); + player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.NEUTRAL, 1.0f, 1.0f); + this.onClose(); return true; } if (cancelHover) { chant.clear(); - Minecraft.getInstance().player.playSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Minecraft.getInstance().player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.NEUTRAL, 1.0f, 1.0f); return true; } return false; @@ -200,15 +220,15 @@ public boolean isPauseScreen() { public boolean mouseClicked(double mouseX, double mouseY, int button) { if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { Minecraft mc = Minecraft.getInstance(); - this.width = mc.getMainWindow().getScaledWidth(); - this.height = mc.getMainWindow().getScaledHeight(); + this.width = mc.getWindow().getGuiScaledWidth(); + this.height = mc.getWindow().getGuiScaledHeight(); int guiLeft = (width - xSize) / 2, guiTop = (height - ySize) / 2; if (currentPage > 0) { // left arrow int x = guiLeft + 10, y = guiTop + 169; if (mouseX >= x && mouseY >= y && mouseX <= x + 32 && mouseY <= y + 16) { currentPage -= 2; - Minecraft.getInstance().player.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Minecraft.getInstance().player.playNotifySound(SoundEvents.BOOK_PAGE_TURN, SoundSource.NEUTRAL, 1.0f, 1.0f); resetPages(); return true; } @@ -217,7 +237,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { int x = guiLeft + 270, y = guiTop + 169; if (mouseX >= x && mouseY >= y && mouseX <= x + 32 && mouseY <= y + 16) { currentPage += 2; - Minecraft.getInstance().player.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Minecraft.getInstance().player.playNotifySound(SoundEvents.BOOK_PAGE_TURN, SoundSource.NEUTRAL, 1.0f, 1.0f); resetPages(); return true; } @@ -238,7 +258,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } @Override - public void renderTooltip(MatrixStack mStack, ItemStack stack, int x, int y) { + public void renderTooltip(PoseStack mStack, ItemStack stack, int x, int y) { if (!stack.isEmpty()) super.renderTooltip(mStack, stack, x, y); } } diff --git a/src/main/java/elucent/eidolon/codex/CraftingPage.java b/src/main/java/elucent/eidolon/codex/CraftingPage.java index 307cda9..56426fa 100644 --- a/src/main/java/elucent/eidolon/codex/CraftingPage.java +++ b/src/main/java/elucent/eidolon/codex/CraftingPage.java @@ -1,11 +1,10 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -22,7 +21,7 @@ public CraftingPage(ItemStack result, ItemStack... inputs) { @Override @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { for (int i = 0; i < 3; i ++) { for (int j = 0; j < 3; j ++) { int index = i * 3 + j; diff --git a/src/main/java/elucent/eidolon/codex/CruciblePage.java b/src/main/java/elucent/eidolon/codex/CruciblePage.java index b3052b4..1450fa7 100644 --- a/src/main/java/elucent/eidolon/codex/CruciblePage.java +++ b/src/main/java/elucent/eidolon/codex/CruciblePage.java @@ -1,14 +1,14 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import elucent.eidolon.recipe.CrucibleRecipe; import elucent.eidolon.recipe.CrucibleRegistry; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.gui.Font; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -43,7 +43,7 @@ public CruciblePage(ItemStack result, CrucibleStep... steps) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { int h = steps.length * 20 + 32; int yoff = 80 - h / 2; for (int i = 0; i < steps.length; i ++) { @@ -63,10 +63,10 @@ public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, i } gui.blit(mStack, x, y + yoff + steps.length * 20, 128, 64, 128, 32); - FontRenderer font = Minecraft.getInstance().fontRenderer; + Font font = Minecraft.getInstance().font; for (int i = 0; i < steps.length; i ++) { int tx = x, ty = y + yoff + i * 20; - drawText(gui, mStack, I18n.format("enchantment.level." + (i + 1)) + ".", tx + 7, ty + 17 - font.FONT_HEIGHT); + drawText(gui, mStack, I18n.get("enchantment.level." + (i + 1)) + ".", tx + 7, ty + 17 - font.lineHeight); tx += 24; } } @@ -74,7 +74,7 @@ public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, i @Override @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { int h = steps.length * 20 + 32; int yoff = 80 - h / 2; for (int i = 0; i < steps.length; i ++) { diff --git a/src/main/java/elucent/eidolon/codex/EntityPage.java b/src/main/java/elucent/eidolon/codex/EntityPage.java index 39a3bea..b8aad10 100644 --- a/src/main/java/elucent/eidolon/codex/EntityPage.java +++ b/src/main/java/elucent/eidolon/codex/EntityPage.java @@ -1,25 +1,20 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.resources.ResourceLocation; +import com.mojang.math.Vector3f; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; - -import java.util.function.Supplier; public class EntityPage extends Page { public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_entity_page.png"); @@ -33,27 +28,27 @@ public EntityPage(EntityType type) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Entity e = type.create(Minecraft.getInstance().world); - EntityRenderer renderer = Minecraft.getInstance().getRenderManager().getRenderer(e); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + Entity e = type.create(Minecraft.getInstance().level); + EntityRenderer renderer = Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(e); RenderSystem.disableCull(); RenderSystem.enableDepthTest(); RenderSystem.enableBlend(); - RenderSystem.enableLighting(); - Tessellator tess = Tessellator.getInstance(); - mStack.push(); + Tesselator tess = Tesselator.getInstance(); + mStack.pushPose(); mStack.translate(x + 64, y + 136, 64); - mStack.rotate(Vector3f.XP.rotationDegrees(-15)); - mStack.rotate(Vector3f.YP.rotationDegrees(-30)); - float scale = 112 / e.getHeight(); + mStack.mulPose(Vector3f.XP.rotationDegrees(-15)); + mStack.mulPose(Vector3f.YP.rotationDegrees(-30)); + float scale = 112 / e.getBbHeight(); mStack.scale(scale, -scale, scale); - Minecraft.getInstance().getTextureManager().bindTexture(renderer.getEntityTexture(e)); - renderer.render(e, e.rotationYaw, 0, mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), 0xf000f0); - tess.draw(); - mStack.pop(); + RenderSystem.setShader(GameRenderer::getRendertypeEntityAlphaShader); + RenderSystem.setupShaderLights(RenderSystem.getShader()); + RenderSystem.setShaderTexture(0, renderer.getTextureLocation(e)); + renderer.render(e, e.getYRot(), 0, mStack, MultiBufferSource.immediate(tess.getBuilder()), 0xf000f0); + tess.end(); + mStack.popPose(); RenderSystem.enableCull(); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); - RenderSystem.disableLighting(); } } diff --git a/src/main/java/elucent/eidolon/codex/IndexPage.java b/src/main/java/elucent/eidolon/codex/IndexPage.java index 4471464..3fd8108 100644 --- a/src/main/java/elucent/eidolon/codex/IndexPage.java +++ b/src/main/java/elucent/eidolon/codex/IndexPage.java @@ -1,15 +1,17 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Sign; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -71,7 +73,7 @@ public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { for (int i = 0; i < entries.length; i ++) if (entries[i].isUnlocked()) { if (mouseX >= x + 2 && mouseX <= x + 124 && mouseY >= y + 8 + i * 20 && mouseY <= y + 26 + i * 20) { gui.changeChapter(entries[i].chapter); - Minecraft.getInstance().player.playSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Minecraft.getInstance().player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.NEUTRAL, 1.0f, 1.0f); return true; } } @@ -80,15 +82,15 @@ public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); for (int i = 0; i < entries.length; i ++) { gui.blit(mStack, x + 1, y + 7 + i * 20, 128, entries[i].isUnlocked() ? 0 : 96, 122, 18); } for (int i = 0; i < entries.length; i ++) if (entries[i].isUnlocked()) { - Minecraft.getInstance().getItemRenderer().renderItemAndEffectIntoGUI(entries[i].icon, x + 2, y + 8 + i * 20); - drawText(gui, mStack, I18n.format(entries[i].chapter.titleKey), x + 24, y + 20 + i * 20 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); + Minecraft.getInstance().getItemRenderer().renderAndDecorateItem(entries[i].icon, x + 2, y + 8 + i * 20); + drawText(gui, mStack, I18n.get(entries[i].chapter.titleKey), x + 24, y + 20 + i * 20 - Minecraft.getInstance().font.lineHeight); } } } diff --git a/src/main/java/elucent/eidolon/codex/ListPage.java b/src/main/java/elucent/eidolon/codex/ListPage.java index 7ca340c..00398a8 100644 --- a/src/main/java/elucent/eidolon/codex/ListPage.java +++ b/src/main/java/elucent/eidolon/codex/ListPage.java @@ -1,15 +1,13 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import elucent.eidolon.spell.KnowledgeUtil; -import elucent.eidolon.spell.Sign; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -37,15 +35,15 @@ public ListPage(String key, ListEntry... pages) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); for (int i = 0; i < entries.length; i ++) { gui.blit(mStack, x + 1, y + 7 + i * 20, 128, 0, 122, 18); } for (int i = 0; i < entries.length; i ++) { drawItem(gui, mStack, entries[i].icon, x + 2, y + 8 + i * 20, mouseX, mouseY); - drawText(gui, mStack, I18n.format(key + "." + entries[i].key), x + 24, y + 20 + i * 20 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); + drawText(gui, mStack, I18n.get(key + "." + entries[i].key), x + 24, y + 20 + i * 20 - Minecraft.getInstance().font.lineHeight); } } } diff --git a/src/main/java/elucent/eidolon/codex/Page.java b/src/main/java/elucent/eidolon/codex/Page.java index 0ed46de..9f91d5a 100644 --- a/src/main/java/elucent/eidolon/codex/Page.java +++ b/src/main/java/elucent/eidolon/codex/Page.java @@ -1,20 +1,19 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.util.ColorUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.AbstractGui; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; - -import java.util.ArrayList; -import java.util.List; public abstract class Page { ResourceLocation bg; @@ -28,33 +27,33 @@ public void reset() { } @OnlyIn(Dist.CLIENT) - public static void drawItem(CodexGui gui, MatrixStack mStack, ItemStack stack, int x, int y, int mouseX, int mouseY) { + public static void drawItem(CodexGui gui, PoseStack mStack, ItemStack stack, int x, int y, int mouseX, int mouseY) { ItemRenderer ir = Minecraft.getInstance().getItemRenderer(); - ir.renderItemAndEffectIntoGUI(stack, x, y); - ir.renderItemOverlayIntoGUI(Minecraft.getInstance().fontRenderer, stack, x, y, null); + ir.renderAndDecorateItem(stack, x, y); + ir.renderGuiItemDecorations(Minecraft.getInstance().font, stack, x, y, null); if (mouseX >= x && mouseY >= y && mouseX <= x + 16 && mouseY <= y + 16) { gui.renderTooltip(mStack, stack, mouseX, mouseY); } } @OnlyIn(Dist.CLIENT) - public static void drawText(CodexGui gui, MatrixStack mStack, String text, int x, int y) { - FontRenderer font = Minecraft.getInstance().fontRenderer; - font.drawString(mStack, text, x, y - 1, ColorUtil.packColor(128, 255, 255, 255)); - font.drawString(mStack, text, x - 1, y, ColorUtil.packColor(128, 219, 212, 184)); - font.drawString(mStack, text, x + 1, y, ColorUtil.packColor(128, 219, 212, 184)); - font.drawString(mStack, text, x, y + 1, ColorUtil.packColor(128, 191, 179, 138)); - font.drawString(mStack, text, x, y, ColorUtil.packColor(255, 79, 59, 47)); + public static void drawText(CodexGui gui, PoseStack mStack, String text, int x, int y) { + Font font = Minecraft.getInstance().font; + font.draw(mStack, text, x, y - 1, ColorUtil.packColor(128, 255, 255, 255)); + font.draw(mStack, text, x - 1, y, ColorUtil.packColor(128, 219, 212, 184)); + font.draw(mStack, text, x + 1, y, ColorUtil.packColor(128, 219, 212, 184)); + font.draw(mStack, text, x, y + 1, ColorUtil.packColor(128, 191, 179, 138)); + font.draw(mStack, text, x, y, ColorUtil.packColor(255, 79, 59, 47)); } @OnlyIn(Dist.CLIENT) - public static void drawWrappingText(CodexGui gui, MatrixStack mStack, String text, int x, int y, int w) { - FontRenderer font = Minecraft.getInstance().fontRenderer; + public static void drawWrappingText(CodexGui gui, PoseStack mStack, String text, int x, int y, int w) { + Font font = Minecraft.getInstance().font; List lines = new ArrayList<>(); String[] words = text.split(" "); String line = ""; for (String s : words) { - if (font.getStringWidth(line) + font.getStringWidth(s) > w) { + if (font.width(line) + font.width(s) > w) { lines.add(line); line = s + " "; } @@ -62,21 +61,21 @@ public static void drawWrappingText(CodexGui gui, MatrixStack mStack, String tex } if (!line.isEmpty()) lines.add(line); for (int i = 0; i < lines.size(); i ++) { - drawText(gui, mStack, lines.get(i), x, y + i * (font.FONT_HEIGHT + 1)); + drawText(gui, mStack, lines.get(i), x, y + i * (font.lineHeight + 1)); } } @OnlyIn(Dist.CLIENT) - public void fullRender(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(bg); + public void fullRender(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, bg); renderBackground(gui, mStack, x, y, mouseX, mouseY); render(gui, mStack, x, y, mouseX, mouseY); renderIngredients(gui, mStack, x, y, mouseX, mouseY); } @OnlyIn(Dist.CLIENT) - public void renderBackground(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(bg); + public void renderBackground(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, bg); gui.blit(mStack, x, y, 0, 0, 128, 160); } @@ -86,8 +85,8 @@ public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { } @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) {} + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) {} @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) {} + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) {} } diff --git a/src/main/java/elucent/eidolon/codex/RitualPage.java b/src/main/java/elucent/eidolon/codex/RitualPage.java index 1600c3c..eae77e9 100644 --- a/src/main/java/elucent/eidolon/codex/RitualPage.java +++ b/src/main/java/elucent/eidolon/codex/RitualPage.java @@ -1,22 +1,24 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; import elucent.eidolon.ritual.Ritual; -import elucent.eidolon.spell.Sign; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; public class RitualPage extends Page { public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_ritual_page.png"); @@ -43,7 +45,7 @@ public RitualPage(Ritual ritual, ItemStack center, RitualIngredient... inputs) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { float angleStep = Math.min(30, 180 / inputs.length); double rootAngle = 90 - (inputs.length - 1) * angleStep / 2; for (int i = 0; i < inputs.length; i ++) { @@ -55,31 +57,30 @@ public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, i } RenderSystem.enableBlend(); - RenderSystem.shadeModel(GL11.GL_SMOOTH); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - Tessellator tess = Tessellator.getInstance(); + Tesselator tess = Tesselator.getInstance(); RenderSystem.disableTexture(); RenderSystem.depthMask(false); - RenderUtil.dragon(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), x + 64, y + 48, 20, 20, ritual.getRed(), ritual.getGreen(), ritual.getBlue()); - tess.draw(); + RenderSystem.setShader(Registry::getGlowingShader); + RenderUtil.dragon(mStack, MultiBufferSource.immediate(tess.getBuilder()), x + 64, y + 48, 20, 20, ritual.getRed(), ritual.getGreen(), ritual.getBlue()); + tess.end(); RenderSystem.enableTexture(); - Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); for (int j = 0; j < 2; j++) { - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), x + 52, y + 36, 24, 24, - ritual.getRed(), ritual.getGreen(), ritual.getBlue(), Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(ritual.getSymbol())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), x + 52, y + 36, 24, 24, + ritual.getRed(), ritual.getGreen(), ritual.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ritual.getSymbol())); + tess.end(); } - RenderSystem.defaultAlphaFunc(); RenderSystem.disableBlend(); - RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.depthMask(true); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShader(GameRenderer::getPositionTexShader); } @Override @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { float angleStep = Math.min(30, 180 / inputs.length); double rootAngle = 90 - (inputs.length - 1) * angleStep / 2; for (int i = 0; i < inputs.length; i ++) { diff --git a/src/main/java/elucent/eidolon/codex/SignIndexPage.java b/src/main/java/elucent/eidolon/codex/SignIndexPage.java index afb89de..ce40acd 100644 --- a/src/main/java/elucent/eidolon/codex/SignIndexPage.java +++ b/src/main/java/elucent/eidolon/codex/SignIndexPage.java @@ -1,36 +1,37 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; import elucent.eidolon.Registry; import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.KnowledgeProvider; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.ColorUtil; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldVertexBufferUploader; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.util.text.TranslationTextComponent; +import com.mojang.blaze3d.vertex.BufferBuilder; + +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import com.mojang.blaze3d.vertex.BufferUploader; +import net.minecraft.client.renderer.texture.TextureAtlas; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; public class SignIndexPage extends Page { public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_sign_index_page.png"); @@ -54,18 +55,18 @@ public SignIndexPage(SignEntry... pages) { @Override @OnlyIn(Dist.CLIENT) public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { - PlayerEntity entity = Minecraft.getInstance().player; - IKnowledge knowledge = entity.getCapability(KnowledgeProvider.CAPABILITY, null).resolve().get(); + Player entity = Minecraft.getInstance().player; + IKnowledge knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve().get(); for (int i = 0; i < entries.length; i ++) { int xx = x + 8 + (i % 2) * 56, yy = y + 4 + (i / 2) * 52; - if (mouseX >= xx + 38 && mouseY >= yy + 38 && mouseX <= xx + 50 && mouseY <= yy + 50) { + if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx + 38 && mouseY >= yy + 38 && mouseX <= xx + 50 && mouseY <= yy + 50) { gui.changeChapter(entries[i].chapter); - Minecraft.getInstance().player.playSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Minecraft.getInstance().player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.NEUTRAL, 1.0f, 1.0f); return true; } else if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx && mouseX <= xx + 48 && mouseY >= yy && mouseY <= yy + 48) { gui.addToChant(entries[i].sign); - entity.playSound(Registry.SELECT_SIGN.get(), SoundCategory.NEUTRAL, 0.5f, entity.world.rand.nextFloat() * 0.25f + 0.75f); + entity.playNotifySound(Registry.SELECT_SIGN.get(), SoundSource.NEUTRAL, 0.5f, entity.level.random.nextFloat() * 0.25f + 0.75f); return true; } } @@ -73,65 +74,64 @@ else if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx && mouseX <= xx + } @OnlyIn(Dist.CLIENT) - static void colorBlit(MatrixStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { - Matrix4f matrix = mStack.getLast().getMatrix(); + static void colorBlit(PoseStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { + Matrix4f matrix = mStack.last().pose(); int maxX = x + width, maxY = y + height; float minU = (float)uOffset / textureWidth, minV = (float)vOffset / textureHeight; float maxU = minU + (float)width / textureWidth, maxV = minV + (float)height / textureHeight; int r = ColorUtil.getRed(color), g = ColorUtil.getGreen(color), b = ColorUtil.getBlue(color); - BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer(); - bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - bufferbuilder.pos(matrix, (float)x, (float)maxY, 0).tex(minU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)maxY, 0).tex(maxU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)y, 0).tex(maxU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)x, (float)y, 0).tex(minU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.finishDrawing(); - RenderSystem.enableAlphaTest(); - WorldVertexBufferUploader.draw(bufferbuilder); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + bufferbuilder.vertex(matrix, (float)x, (float)maxY, 0).uv(minU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)maxY, 0).uv(maxU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)y, 0).uv(maxU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)x, (float)y, 0).uv(minU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.end(); + BufferUploader.end(bufferbuilder); } @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - PlayerEntity entity = Minecraft.getInstance().player; - IKnowledge knowledge = entity.getCapability(KnowledgeProvider.CAPABILITY, null).resolve().get(); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + Player entity = Minecraft.getInstance().player; + IKnowledge knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve().get(); for (int i = 0; i < entries.length; i ++) { - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + RenderSystem.setShaderTexture(0, BACKGROUND); int xx = x + 8 + (i % 2) * 56, yy = y + 4 + (i / 2) * 52; Sign sign = entries[i].sign; boolean hover = knowledge.knowsSign(sign) && mouseX >= xx && mouseX <= xx + 48 && mouseY >= yy && mouseY <= yy + 48; - boolean infoHover = mouseX >= xx + 38 && mouseY >= yy + 38 && mouseX <= xx + 50 && mouseY <= yy + 50; + boolean infoHover = knowledge.knowsSign(sign) && mouseX >= xx + 38 && mouseY >= yy + 38 && mouseX <= xx + 50 && mouseY <= yy + 50; gui.blit(mStack, xx, yy, knowledge.knowsSign(entries[i].sign) ? 128 : 176, 0, 48, 48); if (knowledge.knowsSign(sign)) { - Tessellator tess = Tessellator.getInstance(); + Tesselator tess = Tesselator.getInstance(); RenderSystem.enableBlend(); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); + RenderSystem.setShader(Registry::getGlowingSpriteShader); if (hover && !infoHover) { - mStack.push(); + mStack.pushPose(); mStack.translate(xx + 24, yy + 24, 0); - mStack.rotate(Vector3f.ZP.rotationDegrees(ClientEvents.getClientTicks() * 1.5f)); + mStack.mulPose(Vector3f.ZP.rotationDegrees(ClientEvents.getClientTicks() * 1.5f)); colorBlit(mStack, -18, -18, 128, 48, 36, 36, 256, 256, sign.getColor()); - mStack.pop(); + mStack.popPose(); } - Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); for (int j = 0; j < (hover && !infoHover ? 2 : 1); j++) { - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), xx + 12, yy + 12, 24, 24, - sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), xx + 12, yy + 12, 24, 24, + sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); } - RenderSystem.defaultAlphaFunc(); RenderSystem.disableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, BACKGROUND); gui.blit(mStack, xx + 38, yy + 38, infoHover ? 188 : 176, 48, 12, 14); - + if (infoHover) { - gui.renderTooltip(mStack, new TranslationTextComponent("eidolon.codex.sign_suffix", new TranslationTextComponent(sign.getRegistryName().getNamespace() + ".sign." + sign.getRegistryName().getPath())), mouseX, mouseY); + gui.renderTooltip(mStack, new TranslatableComponent("eidolon.codex.sign_suffix", new TranslatableComponent(sign.getRegistryName().getNamespace() + ".sign." + sign.getRegistryName().getPath())), mouseX, mouseY); } } } diff --git a/src/main/java/elucent/eidolon/codex/SignPage.java b/src/main/java/elucent/eidolon/codex/SignPage.java index 528622d..6525f7f 100644 --- a/src/main/java/elucent/eidolon/codex/SignPage.java +++ b/src/main/java/elucent/eidolon/codex/SignPage.java @@ -1,29 +1,30 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; +import elucent.eidolon.Registry; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.ColorUtil; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldVertexBufferUploader; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; +import com.mojang.blaze3d.vertex.BufferBuilder; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import com.mojang.blaze3d.vertex.BufferUploader; +import net.minecraft.client.renderer.texture.TextureAtlas; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.resources.ResourceLocation; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; public class SignPage extends Page { public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_sign_page.png"); @@ -35,46 +36,44 @@ public SignPage(Sign sign) { } @OnlyIn(Dist.CLIENT) - static void colorBlit(MatrixStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { - Matrix4f matrix = mStack.getLast().getMatrix(); + static void colorBlit(PoseStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { + Matrix4f matrix = mStack.last().pose(); int maxX = x + width, maxY = y + height; float minU = (float)uOffset / textureWidth, minV = (float)vOffset / textureHeight; float maxU = minU + (float)width / textureWidth, maxV = minV + (float)height / textureHeight; int r = ColorUtil.getRed(color), g = ColorUtil.getGreen(color), b = ColorUtil.getBlue(color); - BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer(); - bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - bufferbuilder.pos(matrix, (float)x, (float)maxY, 0).tex(minU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)maxY, 0).tex(maxU, maxV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)maxX, (float)y, 0).tex(maxU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.pos(matrix, (float)x, (float)y, 0).tex(minU, minV).color(r, g, b, 255).endVertex(); - bufferbuilder.finishDrawing(); - RenderSystem.enableAlphaTest(); - WorldVertexBufferUploader.draw(bufferbuilder); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + bufferbuilder.vertex(matrix, (float)x, (float)maxY, 0).uv(minU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)maxY, 0).uv(maxU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)y, 0).uv(maxU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)x, (float)y, 0).uv(minU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.end(); + BufferUploader.end(bufferbuilder); } @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); - Tessellator tess = Tessellator.getInstance(); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); + Tesselator tess = Tesselator.getInstance(); RenderSystem.enableBlend(); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 1f / 256f); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - mStack.push(); + RenderSystem.setShader(Registry::getGlowingSpriteShader); + mStack.pushPose(); mStack.translate(x + 64, y + 80, 0); // mStack.scale(0.9f, 0.9f, 0.9f); - mStack.rotate(Vector3f.ZP.rotationDegrees(ClientEvents.getClientTicks() * 1.5f)); + mStack.mulPose(Vector3f.ZP.rotationDegrees(ClientEvents.getClientTicks() * 1.5f)); colorBlit(mStack, -40, -40, 128, 96, 80, 80, 256, 256, sign.getColor()); - mStack.pop(); - Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + mStack.popPose(); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); for (int i = 0; i < 2; i ++) { - RenderUtil.litQuad(mStack, IRenderTypeBuffer.getImpl(tess.getBuffer()), x + 44, y + 60, 40, 40, - sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(sign.getSprite())); - tess.draw(); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), x + 44, y + 60, 40, 40, + sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + tess.end(); } - RenderSystem.defaultAlphaFunc(); RenderSystem.disableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); } diff --git a/src/main/java/elucent/eidolon/codex/SmeltingPage.java b/src/main/java/elucent/eidolon/codex/SmeltingPage.java index cf9b5e9..17a7d91 100644 --- a/src/main/java/elucent/eidolon/codex/SmeltingPage.java +++ b/src/main/java/elucent/eidolon/codex/SmeltingPage.java @@ -1,9 +1,10 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -20,7 +21,7 @@ public SmeltingPage(ItemStack result, ItemStack input) { @Override @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { drawItem(gui, mStack, input, x + 56, y + 34, mouseX, mouseY); drawItem(gui, mStack, result,x + 56, y + 107, mouseX, mouseY); } diff --git a/src/main/java/elucent/eidolon/codex/TextPage.java b/src/main/java/elucent/eidolon/codex/TextPage.java index b60267c..149b308 100644 --- a/src/main/java/elucent/eidolon/codex/TextPage.java +++ b/src/main/java/elucent/eidolon/codex/TextPage.java @@ -1,9 +1,10 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -18,7 +19,7 @@ public TextPage(String textKey) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - drawWrappingText(gui, mStack, I18n.format(text), x + 4, y + 4, 120); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + drawWrappingText(gui, mStack, I18n.get(text), x + 4, y + 4, 120); } } diff --git a/src/main/java/elucent/eidolon/codex/TitlePage.java b/src/main/java/elucent/eidolon/codex/TitlePage.java index 0635146..6da1109 100644 --- a/src/main/java/elucent/eidolon/codex/TitlePage.java +++ b/src/main/java/elucent/eidolon/codex/TitlePage.java @@ -1,10 +1,11 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -20,10 +21,10 @@ public TitlePage(String textKey) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - String title = I18n.format(this.title); - int titleWidth = Minecraft.getInstance().fontRenderer.getStringWidth(title); - drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); - drawWrappingText(gui, mStack, I18n.format(text), x + 4, y + 24, 120); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + String title = I18n.get(this.title); + int titleWidth = Minecraft.getInstance().font.width(title); + drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().font.lineHeight); + drawWrappingText(gui, mStack, I18n.get(text), x + 4, y + 24, 120); } } diff --git a/src/main/java/elucent/eidolon/codex/TitledIndexPage.java b/src/main/java/elucent/eidolon/codex/TitledIndexPage.java index 7fbe7d8..ae0d0d0 100644 --- a/src/main/java/elucent/eidolon/codex/TitledIndexPage.java +++ b/src/main/java/elucent/eidolon/codex/TitledIndexPage.java @@ -1,11 +1,10 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; -import elucent.eidolon.Eidolon; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.client.resources.language.I18n; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -25,13 +24,13 @@ public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { gui.blit(mStack, x, y, 128, 64, 128, 32); - String title = I18n.format(this.title); - int titleWidth = Minecraft.getInstance().fontRenderer.getStringWidth(title); - drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); + String title = I18n.get(this.title); + int titleWidth = Minecraft.getInstance().font.width(title); + drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().font.lineHeight); - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + RenderSystem.setShaderTexture(0, BACKGROUND); super.render(gui, mStack, x, y + 16, mouseX, mouseY); } } diff --git a/src/main/java/elucent/eidolon/codex/TitledRitualPage.java b/src/main/java/elucent/eidolon/codex/TitledRitualPage.java index a34240d..3151093 100644 --- a/src/main/java/elucent/eidolon/codex/TitledRitualPage.java +++ b/src/main/java/elucent/eidolon/codex/TitledRitualPage.java @@ -1,10 +1,12 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.ritual.Ritual; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -18,14 +20,14 @@ public TitledRitualPage(String textKey, Ritual ritual, ItemStack center, RitualI @Override @OnlyIn(Dist.CLIENT) - public void render(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); gui.blit(mStack, x, y, 128, 64, 128, 24); - String title = I18n.format(this.title); - int titleWidth = Minecraft.getInstance().fontRenderer.getStringWidth(title); - drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().fontRenderer.FONT_HEIGHT); + String title = I18n.get(this.title); + int titleWidth = Minecraft.getInstance().font.width(title); + drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().font.lineHeight); - Minecraft.getInstance().getTextureManager().bindTexture(BACKGROUND); + RenderSystem.setShaderTexture(0, BACKGROUND); super.render(gui, mStack, x, y, mouseX, mouseY); } } diff --git a/src/main/java/elucent/eidolon/codex/WorktablePage.java b/src/main/java/elucent/eidolon/codex/WorktablePage.java index 27daa28..1fc0a3b 100644 --- a/src/main/java/elucent/eidolon/codex/WorktablePage.java +++ b/src/main/java/elucent/eidolon/codex/WorktablePage.java @@ -1,9 +1,10 @@ package elucent.eidolon.codex; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -20,7 +21,7 @@ public WorktablePage(ItemStack result, ItemStack... inputs) { @Override @OnlyIn(Dist.CLIENT) - public void renderIngredients(CodexGui gui, MatrixStack mStack, int x, int y, int mouseX, int mouseY) { + public void renderIngredients(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { for (int i = 0; i < 3; i ++) { for (int j = 0; j < 3; j ++) { int index = i * 3 + j; diff --git a/src/main/java/elucent/eidolon/deity/DarkDeity.java b/src/main/java/elucent/eidolon/deity/DarkDeity.java index a214281..4988ced 100644 --- a/src/main/java/elucent/eidolon/deity/DarkDeity.java +++ b/src/main/java/elucent/eidolon/deity/DarkDeity.java @@ -4,8 +4,8 @@ import elucent.eidolon.capability.IReputation; import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Signs; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; public class DarkDeity extends Deity { public DarkDeity(ResourceLocation id, int red, int green, int blue) { @@ -13,7 +13,7 @@ public DarkDeity(ResourceLocation id, int red, int green, int blue) { } @Override - public void onReputationUnlock(PlayerEntity player, IReputation rep, ResourceLocation lock) { + public void onReputationUnlock(Player player, IReputation rep, ResourceLocation lock) { if (lock.equals(DeityLocks.SACRIFICE_MOB)) { KnowledgeUtil.grantSign(player, Signs.SOUL_SIGN); } @@ -23,7 +23,7 @@ else if (lock.equals(DeityLocks.SACRIFICE_VILLAGER)) { } @Override - public void onReputationChange(PlayerEntity player, IReputation rep, double prev, double current) { + public void onReputationChange(Player player, IReputation rep, double prev, double current) { if (!KnowledgeUtil.knowsSign(player, Signs.BLOOD_SIGN) && current >= 3) { rep.setReputation(player, id, 3); rep.lock(player, id, DeityLocks.SACRIFICE_MOB); diff --git a/src/main/java/elucent/eidolon/deity/Deities.java b/src/main/java/elucent/eidolon/deity/Deities.java index df295b6..6539911 100644 --- a/src/main/java/elucent/eidolon/deity/Deities.java +++ b/src/main/java/elucent/eidolon/deity/Deities.java @@ -1,12 +1,11 @@ package elucent.eidolon.deity; -import elucent.eidolon.Eidolon; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; + public class Deities { static Map deities = new HashMap<>(); @@ -20,6 +19,6 @@ public static Deity find(ResourceLocation deity) { } public static final Deity - DARK_DEITY = register(new DarkDeity(new ResourceLocation(Eidolon.MODID, "dark"), 154, 77, 255)); - // LIGHT = new new ResourceLocation(Eidolon.MODID, "light"); + DARK_DEITY = register(new DarkDeity(new ResourceLocation(Eidolon.MODID, "dark"), 154, 77, 255)), + LIGHT_DEITY = register(new LightDeity(new ResourceLocation(Eidolon.MODID, "light"), 255, 230, 117)); } diff --git a/src/main/java/elucent/eidolon/deity/Deity.java b/src/main/java/elucent/eidolon/deity/Deity.java index 0e3afa0..1fac850 100644 --- a/src/main/java/elucent/eidolon/deity/Deity.java +++ b/src/main/java/elucent/eidolon/deity/Deity.java @@ -1,12 +1,8 @@ package elucent.eidolon.deity; import elucent.eidolon.capability.IReputation; -import elucent.eidolon.capability.ReputationEntry; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Resource; -import java.util.UUID; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; public abstract class Deity { ResourceLocation id; @@ -35,6 +31,6 @@ public ResourceLocation getId() { return id; } - public abstract void onReputationUnlock(PlayerEntity player, IReputation rep, ResourceLocation lock); - public abstract void onReputationChange(PlayerEntity player, IReputation rep, double prev, double current); + public abstract void onReputationUnlock(Player player, IReputation rep, ResourceLocation lock); + public abstract void onReputationChange(Player player, IReputation rep, double prev, double current); } diff --git a/src/main/java/elucent/eidolon/deity/DeityLocks.java b/src/main/java/elucent/eidolon/deity/DeityLocks.java index 5dfe806..46b913c 100644 --- a/src/main/java/elucent/eidolon/deity/DeityLocks.java +++ b/src/main/java/elucent/eidolon/deity/DeityLocks.java @@ -1,10 +1,12 @@ package elucent.eidolon.deity; import elucent.eidolon.Eidolon; -import net.minecraft.util.ResourceLocation; +import net.minecraft.resources.ResourceLocation; public class DeityLocks { public static final ResourceLocation SACRIFICE_MOB = new ResourceLocation(Eidolon.MODID, "sacrifice_mob"), - SACRIFICE_VILLAGER = new ResourceLocation(Eidolon.MODID, "sacrifice_villager"); + SACRIFICE_VILLAGER = new ResourceLocation(Eidolon.MODID, "sacrifice_villager"), + BASIC_INCENSE_PRAYER = new ResourceLocation(Eidolon.MODID, "basic_incense"), + SMITE_UNDEAD = new ResourceLocation(Eidolon.MODID, "smite_undead"); } diff --git a/src/main/java/elucent/eidolon/deity/LightDeity.java b/src/main/java/elucent/eidolon/deity/LightDeity.java new file mode 100644 index 0000000..4d8a340 --- /dev/null +++ b/src/main/java/elucent/eidolon/deity/LightDeity.java @@ -0,0 +1,29 @@ +package elucent.eidolon.deity; + +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.spell.KnowledgeUtil; +import elucent.eidolon.spell.Signs; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; + +public class LightDeity extends Deity { + public LightDeity(ResourceLocation id, int red, int green, int blue) { + super(id, red, green, blue); + } + + @Override + public void onReputationUnlock(Player player, IReputation rep, ResourceLocation lock) { + if (lock.equals(DeityLocks.BASIC_INCENSE_PRAYER)) { + KnowledgeUtil.grantSign(player, Signs.SOUL_SIGN); + } + } + + @Override + public void onReputationChange(Player player, IReputation rep, double prev, double current) { + if (!KnowledgeUtil.knowsSign(player, Signs.FLAME_SIGN) && current >= 3) { + rep.setReputation(player, id, 3); + rep.lock(player, id, DeityLocks.BASIC_INCENSE_PRAYER); + KnowledgeUtil.grantSign(player, Signs.FLAME_SIGN); + } + } +} diff --git a/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java b/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java new file mode 100644 index 0000000..bc5c0a4 --- /dev/null +++ b/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java @@ -0,0 +1,7 @@ +package elucent.eidolon.deity; + +import net.minecraftforge.eventbus.api.Event; + +public class RegisterDeitiesEvent extends Event { + +} diff --git a/src/main/java/elucent/eidolon/entity/AngelArrowEntity.java b/src/main/java/elucent/eidolon/entity/AngelArrowEntity.java new file mode 100644 index 0000000..9b01713 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/AngelArrowEntity.java @@ -0,0 +1,137 @@ +package elucent.eidolon.entity; + +import java.util.Comparator; +import java.util.List; + +import elucent.eidolon.Registry; +import elucent.eidolon.mixin.AbstractArrowMixin; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; +import net.minecraftforge.entity.IEntityAdditionalSpawnData; +import net.minecraftforge.network.NetworkHooks; +import net.minecraftforge.registries.ForgeRegistries; + +public class AngelArrowEntity extends AbstractArrow implements IEntityAdditionalSpawnData { + AbstractArrow internal = null; + + public AngelArrowEntity(EntityType type, Level worldIn) { + super(type, worldIn); + } + public AngelArrowEntity(Level worldIn, LivingEntity shooter) { + super(Registry.ANGEL_ARROW.get(), shooter, worldIn); + } + + public void setArrow(AbstractArrow entity) { + this.internal = entity; + internal.copyPosition(this); + } + + public static float lerpDegrees(float a, float b, float t) { + float d1 = Math.abs(b - a), d2 = Math.abs((b - 360) - a), d3 = Math.abs((b + 360) - a); + if (d2 > d3 && d2 > d1) { + b -= 360; + d1 = d2; + } + if (d3 > d2 && d3 > d1) { + b += 360; + d1 = d3; + } + return a + d1 * t; + } + + @Override + public void tick() { + if (internal == null) { + removeAfterChangingDimensions(); + return; + } + super.tick(); + internal.tick(); + internal.xo = xo; + internal.yo = yo; + internal.zo = zo; + internal.xRotO = xRotO; + internal.yRotO = yRotO; + internal.copyPosition(this); + internal.setDeltaMovement(getDeltaMovement()); + if (!inGround) { + List entities = level.getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(12), (e) -> { + return e != getOwner() && e.isAlive() && (!level.isClientSide || e != Minecraft.getInstance().player); + }); + if (!entities.isEmpty()) { + for (Entity e : entities) System.out.println(e); + LivingEntity nearest = entities.stream().min(Comparator.comparingDouble((e) -> e.distanceToSqr(this))).get(); + Vec3 diff = nearest.position().add(0, nearest.getBbHeight() / 2, 0).subtract(position()); + double speed = getDeltaMovement().length(); + Vec3 newmotion = getDeltaMovement().add(diff.normalize().scale(speed)).scale(0.5); + if (newmotion.length() == 0) newmotion = newmotion.add(0.01, 0, 0); // avoid divide by zero + setDeltaMovement(newmotion.scale(speed / newmotion.length())); + } + } + } + + @Override + protected ItemStack getPickupItem() { + return internal == null ? ItemStack.EMPTY : + ((AbstractArrowMixin)(Object)internal).callGetPickupItem(); + } + + @Override + public void onHitEntity(EntityHitResult result) { + ((AbstractArrowMixin)(Object)internal).callOnHitEntity(result); + if (internal.isRemoved()) remove(RemovalReason.DISCARDED); + } + + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); + nbt.putString("type", internal.getType().getRegistryName().toString()); + nbt.put("data", internal.serializeNBT()); + } + + @Override + public void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); + ResourceLocation rl = new ResourceLocation(nbt.getString("type")); + EntityType type = ForgeRegistries.ENTITIES.getValue(rl); + if (type == null) removeAfterChangingDimensions(); + + internal = (AbstractArrow)type.create(level); + internal.deserializeNBT(nbt.getCompound("data")); + } + + @Override + public Packet getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public void writeSpawnData(FriendlyByteBuf buffer) { + CompoundTag extra = new CompoundTag(); + extra.putString("type", internal.getType().getRegistryName().toString()); + extra.put("data", internal.serializeNBT()); + buffer.writeNbt(extra); + } + + @Override + public void readSpawnData(FriendlyByteBuf additionalData) { + CompoundTag extra = additionalData.readNbt(); + ResourceLocation rl = new ResourceLocation(extra.getString("type")); + EntityType type = ForgeRegistries.ENTITIES.getValue(rl); + if (type == null) removeAfterChangingDimensions(); + + internal = (AbstractArrow)type.create(level); + internal.deserializeNBT(extra.getCompound("data")); + } +} diff --git a/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java b/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java new file mode 100644 index 0000000..f00971f --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java @@ -0,0 +1,25 @@ +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.resources.ResourceLocation; + +public class AngelArrowRenderer extends EntityRenderer { + public AngelArrowRenderer(Context erm) { + super(erm); + } + + @Override + public void render(AngelArrowEntity entityIn, float entityYaw, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn) { + if (entityIn.internal != null) entityRenderDispatcher.getRenderer(entityIn.internal).render(entityIn.internal, entityYaw, partialTicks, matrixStackIn, bufferIn, packedLightIn); + } + + @Override + public ResourceLocation getTextureLocation(AngelArrowEntity entity) { + return entity.internal == null ? new ResourceLocation("unknown") : entityRenderDispatcher.getRenderer(entity.internal).getTextureLocation(entity.internal); + } +} diff --git a/src/main/java/elucent/eidolon/entity/BonechillProjectileEntity.java b/src/main/java/elucent/eidolon/entity/BonechillProjectileEntity.java index 0ffaa34..d7e641c 100644 --- a/src/main/java/elucent/eidolon/entity/BonechillProjectileEntity.java +++ b/src/main/java/elucent/eidolon/entity/BonechillProjectileEntity.java @@ -5,20 +5,19 @@ import elucent.eidolon.network.Networking; import elucent.eidolon.particle.Particles; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.potion.EffectInstance; -import net.minecraft.util.DamageSource; -import net.minecraft.util.IndirectEntityDamageSource; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.damagesource.IndirectEntityDamageSource; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; public class BonechillProjectileEntity extends SpellProjectileEntity { - public BonechillProjectileEntity(EntityType entityTypeIn, World worldIn) { + public BonechillProjectileEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); } @@ -26,43 +25,43 @@ public BonechillProjectileEntity(EntityType entityTypeIn, World worldIn) { public void tick() { super.tick(); - Vector3d motion = getMotion(); - Vector3d pos = getPositionVec(); - Vector3d norm = motion.normalize().scale(0.025f); + Vec3 motion = getDeltaMovement(); + Vec3 pos = position(); + Vec3 norm = motion.normalize().scale(0.025f); for (int i = 0; i < 8; i ++) { - double lerpX = MathHelper.lerp(i / 8.0f, prevPosX, pos.x); - double lerpY = MathHelper.lerp(i / 8.0f, prevPosY, pos.y); - double lerpZ = MathHelper.lerp(i / 8.0f, prevPosZ, pos.z); + double lerpX = Mth.lerp(i / 8.0f, xOld, pos.x); + double lerpY = Mth.lerp(i / 8.0f, yOld, pos.y); + double lerpZ = Mth.lerp(i / 8.0f, zOld, pos.z); Particles.create(Registry.WISP_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.0625f, 0).setScale(0.625f, 0) .setColor(0.875f, 1, 1, 0.375f, 0.5f, 0.75f) .setLifetime(5) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); Particles.create(Registry.WISP_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.125f, 0).setScale(0.25f, 0.125f) .setColor(1, 0.75f, 0.875f, 0.375f, 0.5f, 0.75f) .setLifetime(20) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); } } @Override - protected void onImpact(RayTraceResult ray, Entity target) { - target.attackEntityFrom(new IndirectEntityDamageSource(Registry.FROST_DAMAGE.getDamageType(), this, world.getPlayerByUuid(casterId)), 4.0f); + protected void onImpact(HitResult ray, Entity target) { + target.hurt(new IndirectEntityDamageSource(Registry.FROST_DAMAGE.getMsgId(), this, level.getPlayerByUUID(casterId)), 4.0f); if (target instanceof LivingEntity) - ((LivingEntity)target).addPotionEffect(new EffectInstance(Registry.CHILLED_EFFECT.get(), 300, 0)); + ((LivingEntity)target).addEffect(new MobEffectInstance(Registry.CHILLED_EFFECT.get(), 300, 0)); onImpact(ray); } @Override - protected void onImpact(RayTraceResult ray) { - setDead(); - if (!world.isRemote) { - Vector3d pos = ray.getHitVec(); - world.playSound(null, pos.x, pos.y, pos.z, Registry.SPLASH_BONECHILL_EVENT.get(), SoundCategory.NEUTRAL, 0.5f, rand.nextFloat() * 0.2f + 0.9f); - Networking.sendToTracking(world, getPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 192, 224, 255), ColorUtil.packColor(255, 96, 128, 192))); + protected void onImpact(HitResult ray) { + kill(); + if (!level.isClientSide) { + Vec3 pos = ray.getLocation(); + level.playSound(null, pos.x, pos.y, pos.z, Registry.SPLASH_BONECHILL_EVENT.get(), SoundSource.NEUTRAL, 0.5f, random.nextFloat() * 0.2f + 0.9f); + Networking.sendToTracking(level, blockPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 192, 224, 255), ColorUtil.packColor(255, 96, 128, 192))); } } } diff --git a/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java b/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java index 5c5c296..2ff82b9 100644 --- a/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java +++ b/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java @@ -1,5 +1,10 @@ package elucent.eidolon.entity; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + import elucent.eidolon.Registry; import elucent.eidolon.network.Networking; import elucent.eidolon.network.SpellCastPacket; @@ -8,50 +13,51 @@ import elucent.eidolon.spell.Signs; import elucent.eidolon.spell.Spell; import elucent.eidolon.spell.Spells; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.nbt.StringNBT; -import net.minecraft.network.IPacket; -import net.minecraft.network.datasync.DataParameter; -import net.minecraft.network.datasync.DataSerializers; -import net.minecraft.network.datasync.EntityDataManager; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.world.World; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.network.NetworkHooks; - -import java.util.*; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagTypes; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.Tags; +import net.minecraftforge.event.TagsUpdatedEvent; +import net.minecraftforge.network.NetworkHooks; public class ChantCasterEntity extends Entity { - public static final DataParameter SIGNS = EntityDataManager.createKey(ChantCasterEntity.class, DataSerializers.COMPOUND_NBT); - public static final DataParameter INDEX = EntityDataManager.createKey(ChantCasterEntity.class, DataSerializers.VARINT); - public static final DataParameter> CASTER_ID = EntityDataManager.>createKey(ChantCasterEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID); + public static final EntityDataAccessor SIGNS = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.COMPOUND_TAG); + public static final EntityDataAccessor INDEX = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.INT); + public static final EntityDataAccessor> CASTER_ID = SynchedEntityData.>defineId(ChantCasterEntity.class, EntityDataSerializers.OPTIONAL_UUID); int timer = 0; - public ChantCasterEntity(World world, PlayerEntity caster, List signs) { + public ChantCasterEntity(Level world, Player caster, List signs) { super(Registry.CHANT_CASTER.get(), world); - ListNBT list = new ListNBT(); - for (Sign sign : signs) list.add(StringNBT.valueOf(sign.getRegistryName().toString())); - CompoundNBT nbt = new CompoundNBT(); + ListTag list = new ListTag(); + for (Sign sign : signs) list.add(StringTag.valueOf(sign.getRegistryName().toString())); + CompoundTag nbt = new CompoundTag(); nbt.put("signs", list); - getDataManager().set(SIGNS, nbt); - getDataManager().set(CASTER_ID, Optional.of(caster.getUniqueID())); + getEntityData().set(SIGNS, nbt); + getEntityData().set(CASTER_ID, Optional.of(caster.getUUID())); } - public ChantCasterEntity(EntityType entityTypeIn, World worldIn) { + public ChantCasterEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); } @Override - protected void registerData() { - getDataManager().register(SIGNS, new CompoundNBT()); - getDataManager().register(INDEX, 0); - getDataManager().register(CASTER_ID, Optional.empty()); + protected void defineSynchedData() { + getEntityData().define(SIGNS, new CompoundTag()); + getEntityData().define(INDEX, 0); + getEntityData().define(CASTER_ID, Optional.empty()); } @Override @@ -61,62 +67,62 @@ public void tick() { if (timer > 0) { timer --; if (timer == 0) { - ListNBT signData = getDataManager().get(SIGNS).getList("signs", Constants.NBT.TAG_STRING); - Optional optuuid = getDataManager().get(CASTER_ID); - if (!world.isRemote && optuuid.isPresent()) { + ListTag signData = getEntityData().get(SIGNS).getList("signs", Tag.TAG_STRING); + Optional optuuid = getEntityData().get(CASTER_ID); + if (!level.isClientSide && optuuid.isPresent()) { List signs = new ArrayList<>(); for (int i = 0; i < signData.size(); i++) signs.add(Signs.find(new ResourceLocation(signData.getString(i)))); Spell spell = Spells.find(signs); - PlayerEntity player = world.getPlayerByUuid(optuuid.get()); - if (spell != null && player != null && spell.canCast(world, getPosition(), player, signs)) { - spell.cast(world, getPosition(), player, signs); - Networking.sendToTracking(world, getPosition(), new SpellCastPacket(player, getPosition(), spell, signs)); + Player player = level.getPlayerByUUID(optuuid.get()); + if (spell != null && player != null && spell.canCast(level, blockPosition(), player, signs)) { + spell.cast(level, blockPosition(), player, signs); + Networking.sendToTracking(level, blockPosition(), new SpellCastPacket(player, blockPosition(), spell, signs)); } - else world.playSound(null, getPosition(), SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.NEUTRAL, 1.0f, 1.0f); + else level.playSound(null, blockPosition(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 1.0f, 1.0f); } - if (!world.isRemote) setDead(); + if (!level.isClientSide) removeAfterChangingDimensions(); return; } } - if (ticksExisted % 5 == 0) { - ListNBT signs = getDataManager().get(SIGNS).getList("signs", Constants.NBT.TAG_STRING); - int index = getDataManager().get(INDEX); + if (tickCount % 5 == 0) { + ListTag signs = getEntityData().get(SIGNS).getList("signs", Tag.TAG_STRING); + int index = getEntityData().get(INDEX); if (index >= signs.size()) return; Sign sign = Signs.find(new ResourceLocation(signs.getString(index))); - double x = getPosX() + 0.2 * rand.nextGaussian(), - y = getPosY() + 0.2 * rand.nextGaussian(), - z = getPosZ() + 0.2 * rand.nextGaussian(); + double x = getX() + 0.2 * random.nextGaussian(), + y = getY() + 0.2 * random.nextGaussian(), + z = getZ() + 0.2 * random.nextGaussian(); for (int i = 0; i < 2; i ++) { - world.addParticle(new SignParticleData(sign), x, y, z, 0, 0, 0); + level.addParticle(new SignParticleData(sign), x, y, z, 0, 0, 0); } - world.playSound(null, getPosition(), Registry.CHANT_WORD.get(), SoundCategory.NEUTRAL, 0.7f, rand.nextFloat() * 0.375f + 0.625f); + level.playSound(null, blockPosition(), Registry.CHANT_WORD.get(), SoundSource.NEUTRAL, 0.7f, random.nextFloat() * 0.375f + 0.625f); if (index + 1 >= signs.size()) { timer = 40; } - if (!world.isRemote) getDataManager().set(INDEX, index + 1); + if (!level.isClientSide) getEntityData().set(INDEX, index + 1); } } @Override - protected void readAdditional(CompoundNBT compound) { - getDataManager().set(SIGNS, compound.getCompound("signs_tag")); - getDataManager().set(INDEX, compound.getInt("index")); - getDataManager().set(CASTER_ID, Optional.of(compound.getUniqueId("caster_id"))); + protected void readAdditionalSaveData(CompoundTag compound) { + getEntityData().set(SIGNS, compound.getCompound("signs_tag")); + getEntityData().set(INDEX, compound.getInt("index")); + getEntityData().set(CASTER_ID, Optional.of(compound.getUUID("caster_id"))); timer = compound.getInt("timer"); } @Override - protected void writeAdditional(CompoundNBT compound) { - compound.put("signs_tag", getDataManager().get(SIGNS)); - compound.putInt("index", getDataManager().get(INDEX)); + protected void addAdditionalSaveData(CompoundTag compound) { + compound.put("signs_tag", getEntityData().get(SIGNS)); + compound.putInt("index", getEntityData().get(INDEX)); compound.putInt("timer", timer); - compound.putUniqueId("caster_id", getDataManager().get(CASTER_ID).get()); + compound.putUUID("caster_id", getEntityData().get(CASTER_ID).get()); } @Override - public IPacket createSpawnPacket() { + public Packet getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } } diff --git a/src/main/java/elucent/eidolon/entity/EmptyRenderer.java b/src/main/java/elucent/eidolon/entity/EmptyRenderer.java deleted file mode 100644 index 977beba..0000000 --- a/src/main/java/elucent/eidolon/entity/EmptyRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package elucent.eidolon.entity; - -import elucent.eidolon.Eidolon; -import net.minecraft.client.renderer.culling.ClippingHelper; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; - -public class EmptyRenderer extends EntityRenderer { - public EmptyRenderer(EntityRendererManager rendererManager) { - super(rendererManager); - } - - @Override - public boolean shouldRender(T livingEntityIn, ClippingHelper camera, double camX, double camY, double camZ) { - return false; - } - - @Override - public ResourceLocation getEntityTexture(T entity) { - return null; - } -} diff --git a/src/main/java/elucent/eidolon/entity/NecromancerEntity.java b/src/main/java/elucent/eidolon/entity/NecromancerEntity.java index 68db005..1d56d99 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerEntity.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerEntity.java @@ -1,52 +1,60 @@ package elucent.eidolon.entity; +import java.util.UUID; + import elucent.eidolon.Registry; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.deity.Deities; -import elucent.eidolon.capability.ReputationProvider; import elucent.eidolon.network.MagicBurstEffectPacket; import elucent.eidolon.network.Networking; import elucent.eidolon.particle.Particles; import elucent.eidolon.util.ColorUtil; import elucent.eidolon.util.EntityUtil; -import net.minecraft.entity.CreatureAttribute; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.MobEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.goal.*; -import net.minecraft.entity.monster.*; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.*; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; -import net.minecraft.world.biome.Biome; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.registries.ForgeRegistries; -import java.util.UUID; - -public class NecromancerEntity extends SpellcastingIllagerEntity { - public NecromancerEntity(EntityType type, World worldIn) { +public class NecromancerEntity extends SpellcasterIllager { + public NecromancerEntity(EntityType type, Level worldIn) { super(type, worldIn); } @Override - public CreatureAttribute getCreatureAttribute() { - return CreatureAttribute.UNDEAD; + public MobType getMobType() { + return MobType.UNDEAD; } @Override - public boolean canDespawn(double dist) { + public boolean removeWhenFarAway(double dist) { return false; } boolean hack = false; @Override - public boolean isSpellcasting() { - return world.isRemote && hack ? false : super.isSpellcasting(); + public boolean isCastingSpell() { + return level.isClientSide && hack ? false : super.isCastingSpell(); } @Override @@ -54,47 +62,47 @@ public void tick() { hack = true; // Used to avoid the default spell particles from SpellcastingIllagerEntity super.tick(); hack = false; - if (this.world.isRemote && this.isSpellcasting()) { - SpellType spelltype = getSpellType(); - float f = this.renderYawOffset * ((float)Math.PI / 180F) + MathHelper.cos((float)this.ticksExisted * 0.6662F) * 0.25F; - float f1 = MathHelper.cos(f); - float f2 = MathHelper.sin(f); - if (spelltype == SpellType.FANGS) { + if (this.level.isClientSide && this.isCastingSpell()) { + IllagerSpell spelltype = getCurrentSpell(); + float f = this.yBodyRot * ((float)Math.PI / 180F) + Mth.cos((float)this.tickCount * 0.6662F) * 0.25F; + float f1 = Mth.cos(f); + float f2 = Mth.sin(f); + if (spelltype == IllagerSpell.FANGS) { Particles.create(Registry.SPARKLE_PARTICLE) .setColor(1, 0.3125f, 0.375f, 0.75f, 0.375f, 1) .randomVelocity(0.05f).randomOffset(0.025f) .setScale(0.25f, 0.125f).setAlpha(0.25f, 0) .setSpin(0.4f) - .spawn(world, getPosX() + f1 * 0.875, getPosY() + 2.0, getPosZ() + f2 * 0.875) - .spawn(world, getPosX() - f1 * 0.875, getPosY() + 2.0, getPosZ() - f2 * 0.875); + .spawn(level, getX() + f1 * 0.875, getY() + 2.0, getZ() + f2 * 0.875) + .spawn(level, getX() - f1 * 0.875, getY() + 2.0, getZ() - f2 * 0.875); } - else if (spelltype == SpellType.SUMMON_VEX) { + else if (spelltype == IllagerSpell.SUMMON_VEX) { Particles.create(Registry.WISP_PARTICLE) .setColor(0.75f, 1, 1, 0.125f, 0.125f, 0.875f) .randomVelocity(0.05f).randomOffset(0.025f) .setScale(0.25f, 0.125f).setAlpha(0.25f, 0) - .spawn(world, getPosX() + f1 * 0.875, getPosY() + 2.0, getPosZ() + f2 * 0.875) - .spawn(world, getPosX() - f1 * 0.875, getPosY() + 2.0, getPosZ() - f2 * 0.875); + .spawn(level, getX() + f1 * 0.875, getY() + 2.0, getZ() + f2 * 0.875) + .spawn(level, getX() - f1 * 0.875, getY() + 2.0, getZ() - f2 * 0.875); } } } @Override - public boolean isEntityUndead() { + public boolean isInvertedHealAndHarm() { return true; } - class AttackSpellGoal extends SpellcastingIllagerEntity.UseSpellGoal { + class AttackSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { private AttackSpellGoal() { } - public boolean shouldExecute() { - LivingEntity livingentity = NecromancerEntity.this.getAttackTarget(); + public boolean canUse() { + LivingEntity livingentity = NecromancerEntity.this.getTarget(); if (livingentity != null && livingentity.isAlive()) { - if (NecromancerEntity.this.isSpellcasting()) { + if (NecromancerEntity.this.isCastingSpell()) { return false; } else { - if (NecromancerEntity.this.ticksExisted >= this.spellCooldown) { + if (NecromancerEntity.this.tickCount >= this.nextAttackTickCount) { return true; } } @@ -114,30 +122,30 @@ protected int getCastingInterval() { @Override protected SoundEvent getSpellPrepareSound() { - return SoundEvents.ENTITY_EVOKER_PREPARE_SUMMON; + return SoundEvents.EVOKER_PREPARE_SUMMON; } @Override - protected SpellType getSpellType() { - return SpellType.FANGS; + protected IllagerSpell getSpell() { + return IllagerSpell.FANGS; } @Override - protected void castSpell() { - LivingEntity target = NecromancerEntity.this.getAttackTarget(); - Vector3d diff = target.getPositionVec().subtract(NecromancerEntity.this.getPositionVec()); - Vector3d norm = diff.normalize(); - if (!world.isRemote) { + protected void performSpellCasting() { + LivingEntity target = NecromancerEntity.this.getTarget(); + Vec3 diff = target.position().subtract(NecromancerEntity.this.position()); + Vec3 norm = diff.normalize(); + if (!level.isClientSide) { for (int i = 0; i < 3; i ++) { - NecromancerSpellEntity spell = new NecromancerSpellEntity(world, getPosX(), getPosYEye(), getPosZ(), norm.x + rand.nextFloat() * 0.1 - 0.05, norm.y + 0.04 * diff.length() / 2 + rand.nextFloat() * 0.1 - 0.05, norm.z + rand.nextFloat() * 0.1 - 0.05, i * 5); - spell.casterId = new UUID(0, getEntityId()); - world.addEntity(spell); + NecromancerSpellEntity spell = new NecromancerSpellEntity(level, getX(), getEyeY(), getZ(), norm.x + random.nextFloat() * 0.1 - 0.05, norm.y + 0.04 * diff.length() / 2 + random.nextFloat() * 0.1 - 0.05, norm.z + random.nextFloat() * 0.1 - 0.05, i * 5); + spell.casterId = new UUID(0, getId()); + level.addFreshEntity(spell); } } } } - class SummonSpellGoal extends SpellcastingIllagerEntity.UseSpellGoal { + class SummonSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { private SummonSpellGoal() { } @@ -153,78 +161,78 @@ protected int getCastingInterval() { @Override protected SoundEvent getSpellPrepareSound() { - return SoundEvents.ENTITY_EVOKER_PREPARE_SUMMON; + return SoundEvents.EVOKER_PREPARE_SUMMON; } @Override - protected SpellType getSpellType() { - return SpellType.SUMMON_VEX; + protected IllagerSpell getSpell() { + return IllagerSpell.SUMMON_VEX; } @Override - protected void castSpell() { - if (!world.isRemote) { - EntityType type = rand.nextBoolean() ? EntityType.SKELETON : EntityType.ZOMBIE; - ResourceLocation biomeKey = ForgeRegistries.BIOMES.getKey(world.getBiome(getPosition())); - RegistryKey biomeEntry = RegistryKey.getOrCreateKey(ForgeRegistries.Keys.BIOMES, biomeKey); + protected void performSpellCasting() { + if (!level.isClientSide) { + EntityType type = random.nextBoolean() ? EntityType.SKELETON : EntityType.ZOMBIE; + ResourceLocation biomeKey = ForgeRegistries.BIOMES.getKey(level.getBiome(blockPosition())); + ResourceKey biomeEntry = ResourceKey.create(ForgeRegistries.Keys.BIOMES, biomeKey); if (type == EntityType.SKELETON && BiomeDictionary.hasType(biomeEntry, BiomeDictionary.Type.SNOWY)) type = EntityType.STRAY; if (type == EntityType.ZOMBIE && BiomeDictionary.hasType(biomeEntry, BiomeDictionary.Type.SANDY)) type = EntityType.HUSK; if (type == EntityType.ZOMBIE && BiomeDictionary.hasType(biomeEntry, BiomeDictionary.Type.OCEAN)) type = EntityType.DROWNED; - MonsterEntity entity = (MonsterEntity)type.create(world); - entity.setPosition(getPosX(), getPosY(), getPosZ()); - world.addEntity(entity); - entity.setAttackTarget(getAttackTarget()); + Monster entity = (Monster)type.create(level); + entity.setPos(getX(), getY(), getZ()); + level.addFreshEntity(entity); + entity.setTarget(getTarget()); EntityUtil.enthrall(NecromancerEntity.this, entity); - Networking.sendToTracking(world, getPosition(), new MagicBurstEffectPacket(getPosX(), getPosY() + 1, getPosZ(), ColorUtil.packColor(255, 181, 255, 255), ColorUtil.packColor(255, 28, 31, 212))); + Networking.sendToTracking(level, blockPosition(), new MagicBurstEffectPacket(getX(), getY() + 1, getZ(), ColorUtil.packColor(255, 181, 255, 255), ColorUtil.packColor(255, 28, 31, 212))); } } } - class CastingSpellGoal extends SpellcastingIllagerEntity.CastingASpellGoal { + class CastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { private CastingSpellGoal() { } public void tick() { - if (NecromancerEntity.this.getAttackTarget() != null) { - NecromancerEntity.this.getLookController().setLookPositionWithEntity(NecromancerEntity.this.getAttackTarget(), (float)NecromancerEntity.this.getHorizontalFaceSpeed(), (float)NecromancerEntity.this.getVerticalFaceSpeed()); + if (NecromancerEntity.this.getTarget() != null) { + NecromancerEntity.this.getLookControl().setLookAt(NecromancerEntity.this.getTarget(), (float)NecromancerEntity.this.getMaxHeadYRot(), (float)NecromancerEntity.this.getMaxHeadXRot()); } } } protected void registerGoals() { - this.goalSelector.addGoal(0, new SwimGoal(this)); + this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(1, new CastingSpellGoal()); this.goalSelector.addGoal(5, new AttackSpellGoal()); this.goalSelector.addGoal(4, new SummonSpellGoal()); this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); - this.goalSelector.addGoal(9, new LookAtGoal(this, PlayerEntity.class, 3.0F, 1.0F)); - this.goalSelector.addGoal(10, new LookAtGoal(this, MobEntity.class, 8.0F)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomWalkingGoal(this, 1.0D)); - this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, PlayerEntity.class, 10, false, false, (e) -> e.getEntityWorld().getCapability(ReputationProvider.CAPABILITY).isPresent() && e.getEntityWorld().getCapability(ReputationProvider.CAPABILITY).resolve().get().getReputation((PlayerEntity)e, Deities.DARK_DEITY.getId()) >= 50)).setUnseenMemoryTicks(300)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, 10, false, false, (e) -> e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).isPresent() && e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).resolve().get().getReputation((Player)e, Deities.DARK_DEITY.getId()) >= 50)).setUnseenMemoryTicks(300)); } - protected SoundEvent getSpellSound() { - return SoundEvents.ENTITY_EVOKER_CAST_SPELL; + protected SoundEvent getCastingSoundEvent() { + return SoundEvents.EVOKER_CAST_SPELL; } - public static AttributeModifierMap createAttributes() { - return MonsterEntity.func_234295_eP_() - .createMutableAttribute(Attributes.MAX_HEALTH, 100.0D) - .createMutableAttribute(Attributes.MOVEMENT_SPEED, 0.25D) - .createMutableAttribute(Attributes.FOLLOW_RANGE, 12.0D) - .create(); + public static AttributeSupplier createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 100.0D) + .add(Attributes.MOVEMENT_SPEED, 0.25D) + .add(Attributes.FOLLOW_RANGE, 12.0D) + .build(); } @Override - public void applyWaveBonus(int wave, boolean p_213660_2_) { + public void applyRaidBuffs(int wave, boolean p_213660_2_) { return; } @Override - public SoundEvent getRaidLossSound() { - return SoundEvents.ENTITY_EVOKER_CELEBRATE; + public SoundEvent getCelebrateSound() { + return SoundEvents.EVOKER_CELEBRATE; } } diff --git a/src/main/java/elucent/eidolon/entity/NecromancerModel.java b/src/main/java/elucent/eidolon/entity/NecromancerModel.java index 018cec4..fbe2bed 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerModel.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerModel.java @@ -1,166 +1,152 @@ -package elucent.eidolon.entity; -// Made with Blockbench 3.7.4 -// Exported for Minecraft version 1.15 -// Paste this class into your mod and generate all required imports - - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.renderer.entity.model.EntityModel; -import net.minecraft.client.renderer.model.ModelHelper; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.monster.AbstractIllagerEntity; -import net.minecraft.util.math.MathHelper; - -public class NecromancerModel extends EntityModel { - private final ModelRenderer body; - private final ModelRenderer clothing; - private final ModelRenderer leftLeg; - private final ModelRenderer rightLeg; - private final ModelRenderer head; - private final ModelRenderer arms; - private final ModelRenderer rightArm; - private final ModelRenderer leftArm; - - public NecromancerModel(float delta) { - textureWidth = 64; - textureHeight = 64; - - body = new ModelRenderer(this); - body.setRotationPoint(0.0F, 24.0F, 0.0F); - body.setTextureOffset(16, 20).addBox(-4.0F, -24.0F, -3.0F, 8.0F, 12.0F, 6.0F, delta, false); - - clothing = new ModelRenderer(this); - clothing.setRotationPoint(0.0F, -24.0F, 0.0F); - body.addChild(clothing); - clothing.setTextureOffset(0, 38).addBox(-4.0F, 0.0F, -3.0F, 8.0F, 20.0F, 6.0F, delta + 0.5F, false); - // clothing.setTextureOffset(64, 0).addBox(-4.5F, 17.0F, -3.5F, 9.0F, 4.0F, 7.0F, delta + 0.5F, false); - - leftLeg = new ModelRenderer(this); - leftLeg.setRotationPoint(2.0F, -12.0F, 0.0F); - body.addChild(leftLeg); - leftLeg.setTextureOffset(0, 22).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, delta, true); - - rightLeg = new ModelRenderer(this); - rightLeg.setRotationPoint(-2.0F, -12.0F, 0.0F); - body.addChild(rightLeg); - rightLeg.setTextureOffset(0, 22).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, delta, false); - - head = new ModelRenderer(this); - head.setRotationPoint(0.0F, -24.0F, 0.0F); - body.addChild(head); - head.setTextureOffset(0, 0).addBox(-4.0F, -10.0F, -4.0F, 8.0F, 10.0F, 8.0F, delta, false); - head.setTextureOffset(32, 0).addBox(-4.0F, -12.0F, -4.0F, 8.0F, 12.0F, 8.0F, delta + 0.45F, false); - head.setTextureOffset(24, 0).addBox(-1.0F, -3.0F, -6.0F, 2.0F, 4.0F, 2.0F, delta, false); - - arms = new ModelRenderer(this); - arms.setRotationPoint(0.0F, -20.0F, -2.0F); - body.addChild(arms); - setRotationAngle(arms, -0.7854F, 0.0F, 0.0F); - arms.setTextureOffset(40, 38).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 4.0F, 4.0F, delta, false); - arms.setTextureOffset(44, 22).addBox(4.0F, -4.0F, -2.0F, 4.0F, 8.0F, 4.0F, delta, true); - arms.setTextureOffset(44, 22).addBox(-8.0F, -4.0F, -2.0F, 4.0F, 8.0F, 4.0F, delta, false); - - rightArm = new ModelRenderer(this); - rightArm.setRotationPoint(-6.0F, -24.0F, 0.0F); - body.addChild(rightArm); - rightArm.setTextureOffset(40, 46).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, delta, false); - - leftArm = new ModelRenderer(this); - leftArm.setRotationPoint(6.0F, -24.0F, 0.0F); - body.addChild(leftArm); - leftArm.setTextureOffset(40, 46).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, delta, true); - } - - @Override - public void setRotationAngles(NecromancerEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - this.head.rotateAngleY = netHeadYaw * ((float)Math.PI / 180F); - this.head.rotateAngleX = headPitch * ((float)Math.PI / 180F); - this.arms.rotateAngleX = -0.75F; - if (this.isSitting) { - this.rightArm.rotateAngleX = (-(float)Math.PI / 5F); - this.rightArm.rotateAngleY = 0.0F; - this.rightArm.rotateAngleZ = 0.0F; - this.leftArm.rotateAngleX = (-(float)Math.PI / 5F); - this.leftArm.rotateAngleY = 0.0F; - this.leftArm.rotateAngleZ = 0.0F; - this.rightLeg.rotateAngleX = -1.4137167F; - this.rightLeg.rotateAngleY = ((float)Math.PI / 10F); - this.rightLeg.rotateAngleZ = 0.07853982F; - this.leftLeg.rotateAngleX = -1.4137167F; - this.leftLeg.rotateAngleY = (-(float)Math.PI / 10F); - this.leftLeg.rotateAngleZ = -0.07853982F; - } else { - this.rightArm.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 2.0F * limbSwingAmount * 0.5F; - this.rightArm.rotateAngleY = 0.0F; - this.rightArm.rotateAngleZ = 0.0F; - this.leftArm.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F) * 2.0F * limbSwingAmount * 0.5F; - this.leftArm.rotateAngleY = 0.0F; - this.leftArm.rotateAngleZ = 0.0F; - this.rightLeg.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount * 0.5F; - this.rightLeg.rotateAngleY = 0.0F; - this.rightLeg.rotateAngleZ = 0.0F; - this.leftLeg.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount * 0.5F; - this.leftLeg.rotateAngleY = 0.0F; - this.leftLeg.rotateAngleZ = 0.0F; - } - - AbstractIllagerEntity.ArmPose armpose = entity.getArmPose(); - if (armpose == AbstractIllagerEntity.ArmPose.ATTACKING) { - if (entity.getHeldItemMainhand().isEmpty()) { - ModelHelper.func_239105_a_(this.leftArm, this.rightArm, true, this.swingProgress, ageInTicks); - } else { - ModelHelper.func_239103_a_(this.rightArm, this.leftArm, entity, this.swingProgress, ageInTicks); - } - } else if (armpose == AbstractIllagerEntity.ArmPose.SPELLCASTING) { - this.rightArm.rotationPointZ = 0.0F; - this.rightArm.rotationPointX = -5.0F; - this.leftArm.rotationPointZ = 0.0F; - this.leftArm.rotationPointX = 5.0F; - this.rightArm.rotateAngleX = MathHelper.cos(ageInTicks * 0.6662F) * 0.25F; - this.leftArm.rotateAngleX = MathHelper.cos(ageInTicks * 0.6662F) * 0.25F; - this.rightArm.rotateAngleZ = 2.3561945F; - this.leftArm.rotateAngleZ = -2.3561945F; - this.rightArm.rotateAngleY = 0.0F; - this.leftArm.rotateAngleY = 0.0F; - } else if (armpose == AbstractIllagerEntity.ArmPose.BOW_AND_ARROW) { - this.rightArm.rotateAngleY = -0.1F + this.head.rotateAngleY; - this.rightArm.rotateAngleX = (-(float)Math.PI / 2F) + this.head.rotateAngleX; - this.leftArm.rotateAngleX = -0.9424779F + this.head.rotateAngleX; - this.leftArm.rotateAngleY = this.head.rotateAngleY - 0.4F; - this.leftArm.rotateAngleZ = ((float)Math.PI / 2F); - } else if (armpose == AbstractIllagerEntity.ArmPose.CROSSBOW_HOLD) { - ModelHelper.func_239104_a_(this.rightArm, this.leftArm, this.head, true); - } else if (armpose == AbstractIllagerEntity.ArmPose.CROSSBOW_CHARGE) { - ModelHelper.func_239102_a_(this.rightArm, this.leftArm, entity, true); - } else if (armpose == AbstractIllagerEntity.ArmPose.CELEBRATING) { - this.rightArm.rotationPointZ = 0.0F; - this.rightArm.rotationPointX = -5.0F; - this.rightArm.rotateAngleX = MathHelper.cos(ageInTicks * 0.6662F) * 0.05F; - this.rightArm.rotateAngleZ = 2.670354F; - this.rightArm.rotateAngleY = 0.0F; - this.leftArm.rotationPointZ = 0.0F; - this.leftArm.rotationPointX = 5.0F; - this.leftArm.rotateAngleX = MathHelper.cos(ageInTicks * 0.6662F) * 0.05F; - this.leftArm.rotateAngleZ = -2.3561945F; - this.leftArm.rotateAngleY = 0.0F; - } - - boolean flag = armpose == AbstractIllagerEntity.ArmPose.CROSSED; - this.arms.showModel = flag; - this.leftArm.showModel = !flag; - this.rightArm.showModel = !flag; - } - - @Override - public void render(MatrixStack matrixStack, IVertexBuilder buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ - body.render(matrixStack, buffer, packedLight, packedOverlay); - } - - public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) { - modelRenderer.rotateAngleX = x; - modelRenderer.rotateAngleY = y; - modelRenderer.rotateAngleZ = z; - } +package elucent.eidolon.entity; +// Made with Blockbench 3.7.4 +// Exported for Minecraft version 1.15 +// Paste this class into your mod and generate all required imports + + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.AnimationUtils; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.monster.AbstractIllager; +import net.minecraft.util.Mth; + +public class NecromancerModel extends EntityModel { + private final ModelPart body, head, arms, leftArm, rightArm, leftLeg, rightLeg; + + public NecromancerModel(ModelPart root) { + this.body = root.getChild("body"); + this.head = body.getChild("head"); + this.arms = body.getChild("arms"); + this.leftArm = body.getChild("left_arm"); + this.rightArm = body.getChild("right_arm"); + this.leftLeg = body.getChild("left_leg"); + this.rightLeg = body.getChild("right_leg"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(16, 20).addBox(-4.0F, -24.0F, -3.0F, 8.0F, 12.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 24.0F, 0.0F)); + + PartDefinition clothing = body.addOrReplaceChild("clothing", CubeListBuilder.create().texOffs(0, 38).addBox(-4.0F, 0.0F, -3.0F, 8.0F, 20.0F, 6.0F, new CubeDeformation(0.5F)), PartPose.offset(0.0F, -24.0F, 0.0F)); + + PartDefinition left_leg = body.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(0, 22).mirror().addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offset(2.0F, -12.0F, 0.0F)); + + PartDefinition right_leg = body.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 22).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(-2.0F, -12.0F, 0.0F)); + + PartDefinition head = body.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -10.0F, -4.0F, 8.0F, 10.0F, 8.0F, new CubeDeformation(0.0F)) + .texOffs(32, 0).addBox(-4.0F, -12.0F, -4.0F, 8.0F, 12.0F, 8.0F, new CubeDeformation(0.45F)) + .texOffs(24, 0).addBox(-1.0F, -3.0F, -6.0F, 2.0F, 4.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -24.0F, 0.0F)); + + PartDefinition arms = body.addOrReplaceChild("arms", CubeListBuilder.create().texOffs(40, 38).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 4.0F, 4.0F, new CubeDeformation(0.0F)) + .texOffs(44, 22).mirror().addBox(4.0F, -4.0F, -2.0F, 4.0F, 8.0F, 4.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(44, 22).addBox(-8.0F, -4.0F, -2.0F, 4.0F, 8.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -20.0F, -2.0F, -0.7854F, 0.0F, 0.0F)); + + PartDefinition right_arm = body.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(40, 46).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(-6.0F, -24.0F, 0.0F)); + + PartDefinition left_arm = body.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(40, 46).mirror().addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offset(6.0F, -24.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 64, 64); + } + + @Override + public void setupAnim(NecromancerEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ + this.head.yRot = netHeadYaw * ((float)Math.PI / 180F); + this.head.xRot = headPitch * ((float)Math.PI / 180F); + this.arms.xRot = -0.75F; + if (this.riding) { + this.rightArm.xRot = (-(float)Math.PI / 5F); + this.rightArm.yRot = 0.0F; + this.rightArm.zRot = 0.0F; + this.leftArm.xRot = (-(float)Math.PI / 5F); + this.leftArm.yRot = 0.0F; + this.leftArm.zRot = 0.0F; + this.rightLeg.xRot = -1.4137167F; + this.rightLeg.yRot = ((float)Math.PI / 10F); + this.rightLeg.zRot = 0.07853982F; + this.leftLeg.xRot = -1.4137167F; + this.leftLeg.yRot = (-(float)Math.PI / 10F); + this.leftLeg.zRot = -0.07853982F; + } else { + this.rightArm.xRot = Mth.cos(limbSwing * 0.6662F + (float)Math.PI) * 2.0F * limbSwingAmount * 0.5F; + this.rightArm.yRot = 0.0F; + this.rightArm.zRot = 0.0F; + this.leftArm.xRot = Mth.cos(limbSwing * 0.6662F) * 2.0F * limbSwingAmount * 0.5F; + this.leftArm.yRot = 0.0F; + this.leftArm.zRot = 0.0F; + this.rightLeg.xRot = Mth.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount * 0.5F; + this.rightLeg.yRot = 0.0F; + this.rightLeg.zRot = 0.0F; + this.leftLeg.xRot = Mth.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount * 0.5F; + this.leftLeg.yRot = 0.0F; + this.leftLeg.zRot = 0.0F; + } + + AbstractIllager.IllagerArmPose armpose = entity.getArmPose(); + if (armpose == AbstractIllager.IllagerArmPose.ATTACKING) { + if (entity.getMainHandItem().isEmpty()) { + AnimationUtils.animateZombieArms(this.leftArm, this.rightArm, true, this.attackTime, ageInTicks); + } else { + AnimationUtils.swingWeaponDown(this.rightArm, this.leftArm, entity, this.attackTime, ageInTicks); + } + } else if (armpose == AbstractIllager.IllagerArmPose.SPELLCASTING) { + this.rightArm.z = 0.0F; + this.rightArm.x = -5.0F; + this.leftArm.z = 0.0F; + this.leftArm.x = 5.0F; + this.rightArm.xRot = Mth.cos(ageInTicks * 0.6662F) * 0.25F; + this.leftArm.xRot = Mth.cos(ageInTicks * 0.6662F) * 0.25F; + this.rightArm.zRot = 2.3561945F; + this.leftArm.zRot = -2.3561945F; + this.rightArm.yRot = 0.0F; + this.leftArm.yRot = 0.0F; + } else if (armpose == AbstractIllager.IllagerArmPose.BOW_AND_ARROW) { + this.rightArm.yRot = -0.1F + this.head.yRot; + this.rightArm.xRot = (-(float)Math.PI / 2F) + this.head.xRot; + this.leftArm.xRot = -0.9424779F + this.head.xRot; + this.leftArm.yRot = this.head.yRot - 0.4F; + this.leftArm.zRot = ((float)Math.PI / 2F); + } else if (armpose == AbstractIllager.IllagerArmPose.CROSSBOW_HOLD) { + AnimationUtils.animateCrossbowHold(this.rightArm, this.leftArm, this.head, true); + } else if (armpose == AbstractIllager.IllagerArmPose.CROSSBOW_CHARGE) { + AnimationUtils.animateCrossbowCharge(this.rightArm, this.leftArm, entity, true); + } else if (armpose == AbstractIllager.IllagerArmPose.CELEBRATING) { + this.rightArm.z = 0.0F; + this.rightArm.x = -5.0F; + this.rightArm.xRot = Mth.cos(ageInTicks * 0.6662F) * 0.05F; + this.rightArm.zRot = 2.670354F; + this.rightArm.yRot = 0.0F; + this.leftArm.z = 0.0F; + this.leftArm.x = 5.0F; + this.leftArm.xRot = Mth.cos(ageInTicks * 0.6662F) * 0.05F; + this.leftArm.zRot = -2.3561945F; + this.leftArm.yRot = 0.0F; + } + + boolean flag = armpose == AbstractIllager.IllagerArmPose.CROSSED; + this.arms.visible = flag; + this.leftArm.visible = !flag; + this.rightArm.visible = !flag; + } + + @Override + public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ + body.render(matrixStack, buffer, packedLight, packedOverlay); + } + + public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { + modelRenderer.xRot = x; + modelRenderer.yRot = y; + modelRenderer.zRot = z; + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java b/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java index 7295dcc..b5d78f4 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java @@ -1,55 +1,53 @@ package elucent.eidolon.entity; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderState; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.client.renderer.entity.IEntityRenderer; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.layers.AbstractEyesLayer; -import net.minecraft.client.renderer.entity.layers.LayerRenderer; -import net.minecraft.client.renderer.entity.layers.SpiderEyesLayer; -import net.minecraft.client.renderer.entity.model.SpiderModel; +import net.minecraft.client.renderer.entity.layers.RenderLayer; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import org.lwjgl.opengl.GL11; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.resources.ResourceLocation; public class NecromancerRenderer extends MobRenderer { - public NecromancerRenderer(EntityRendererManager rendererManager, NecromancerModel model, float shadowSizeIn) { - super(rendererManager, model, shadowSizeIn); + public NecromancerRenderer(Context erm) { + super(erm, new NecromancerModel(erm.bakeLayer(Registry.NECROMANCER_LAYER)), 0.6f); this.addLayer(new NecromancerEyesLayer(this)); } - public static class NecromancerEyesLayer extends LayerRenderer { + public static class NecromancerEyesLayer extends RenderLayer { NecromancerModel model; - private static final RenderType RENDER_TYPE = RenderType.makeType( + private static final RenderType RENDER_TYPE = RenderType.create( Eidolon.MODID+":necromancer_eyes", - DefaultVertexFormats.ENTITY, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(true)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(RenderUtil.ADDITIVE_TRANSPARENCY) - .texture(new RenderState.TextureState(new ResourceLocation(Eidolon.MODID,"textures/entity/necromancer_eyes.png"), false, false)) - .build(false) + DefaultVertexFormat.NEW_ENTITY, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setShaderState(new ShaderStateShard(Registry::getGlowingEntityShader)) + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(RenderUtil.ADDITIVE_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(new ResourceLocation(Eidolon.MODID,"textures/entity/necromancer_eyes.png"), false, false)) + .createCompositeState(false) ); - public NecromancerEyesLayer(IEntityRenderer entityRendererIn) { + public NecromancerEyesLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - this.model = new NecromancerModel(0.5f); + this.model = entityRendererIn.getModel(); } public RenderType getRenderType() { @@ -57,15 +55,15 @@ public RenderType getRenderType() { } @Override - public void render(MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn, NecromancerEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { - IVertexBuilder ivertexbuilder = bufferIn.getBuffer(this.getRenderType()); - this.model.setRotationAngles(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - model.render(matrixStackIn, ivertexbuilder, 15728640, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); + public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, NecromancerEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + VertexConsumer ivertexbuilder = bufferIn.getBuffer(this.getRenderType()); + this.model.setupAnim(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + model.renderToBuffer(matrixStackIn, ivertexbuilder, 15728640, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); } } @Override - public ResourceLocation getEntityTexture(NecromancerEntity entity) { + public ResourceLocation getTextureLocation(NecromancerEntity entity) { return new ResourceLocation(Eidolon.MODID, "textures/entity/necromancer.png"); } } diff --git a/src/main/java/elucent/eidolon/entity/NecromancerSpellEntity.java b/src/main/java/elucent/eidolon/entity/NecromancerSpellEntity.java index 02e2823..d419b59 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerSpellEntity.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerSpellEntity.java @@ -5,81 +5,79 @@ import elucent.eidolon.network.Networking; import elucent.eidolon.particle.Particles; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.network.datasync.DataParameter; -import net.minecraft.network.datasync.DataSerializers; -import net.minecraft.network.datasync.EntityDataManager; -import net.minecraft.potion.EffectInstance; -import net.minecraft.util.DamageSource; -import net.minecraft.util.IndirectEntityDamageSource; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.IndirectEntityDamageSource; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; public class NecromancerSpellEntity extends SpellProjectileEntity { - public static final DataParameter DELAY = EntityDataManager.createKey(NecromancerEntity.class, DataSerializers.VARINT); + public static final EntityDataAccessor DELAY = SynchedEntityData.defineId(NecromancerEntity.class, EntityDataSerializers.INT); - public NecromancerSpellEntity(EntityType entityTypeIn, World worldIn) { + public NecromancerSpellEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); - getDataManager().register(DELAY, 0); + getEntityData().define(DELAY, 0); } - public NecromancerSpellEntity(World worldIn, double x, double y, double z, double vx, double vy, double vz, int delay) { + public NecromancerSpellEntity(Level worldIn, double x, double y, double z, double vx, double vy, double vz, int delay) { super(Registry.NECROMANCER_SPELL.get(), worldIn); - setPosition(x, y, z); - setMotion(vx, vy, vz); - getDataManager().register(DELAY, delay); + setPos(x, y, z); + setDeltaMovement(vx, vy, vz); + getEntityData().define(DELAY, delay); } @Override public void tick() { - if (getDataManager().get(DELAY) > 0) { - getDataManager().set(DELAY, getDataManager().get(DELAY) - 1); + if (getEntityData().get(DELAY) > 0) { + getEntityData().set(DELAY, getEntityData().get(DELAY) - 1); return; } super.tick(); - Vector3d motion = getMotion(); - Vector3d pos = getPositionVec(); - Vector3d norm = motion.normalize().scale(0.025f); + Vec3 motion = getDeltaMovement(); + Vec3 pos = position(); + Vec3 norm = motion.normalize().scale(0.025f); for (int i = 0; i < 8; i ++) { - double lerpX = MathHelper.lerp(i / 8.0f, prevPosX, pos.x); - double lerpY = MathHelper.lerp(i / 8.0f, prevPosY, pos.y); - double lerpZ = MathHelper.lerp(i / 8.0f, prevPosZ, pos.z); + double lerpX = Mth.lerp(i / 8.0f, xo, pos.x); + double lerpY = Mth.lerp(i / 8.0f, yo, pos.y); + double lerpZ = Mth.lerp(i / 8.0f, zo, pos.z); Particles.create(Registry.WISP_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.375f, 0).setScale(0.25f, 0) .setColor(1, 0.3125f, 0.375f, 0.75f, 0.375f, 1) .setLifetime(5) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); Particles.create(Registry.SMOKE_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.0625f, 0).setScale(0.3125f, 0.125f) .setColor(0.625f, 0.375f, 1, 0.25f, 0.25f, 0.75f) .randomVelocity(0.025f, 0.025f) .setLifetime(20) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); } } @Override - protected void onImpact(RayTraceResult ray, Entity target) { - target.attackEntityFrom(new IndirectEntityDamageSource(DamageSource.WITHER.getDamageType(), this, world.getEntityByID((int)casterId.getLeastSignificantBits())), 3.0f + world.getDifficulty().getId()); + protected void onImpact(HitResult ray, Entity target) { + target.hurt(new IndirectEntityDamageSource(DamageSource.WITHER.getMsgId(), this, level.getEntity((int)casterId.getLeastSignificantBits())), 3.0f + level.getDifficulty().getId()); onImpact(ray); } @Override - protected void onImpact(RayTraceResult ray) { - setDead(); - if (!world.isRemote) { - Vector3d pos = ray.getHitVec(); - world.playSound(null, pos.x, pos.y, pos.z, SoundEvents.ENTITY_WITHER_SHOOT, SoundCategory.HOSTILE, 0.5f, rand.nextFloat() * 0.2f + 0.9f); - Networking.sendToTracking(world, getPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 158, 92, 255), ColorUtil.packColor(255, 60, 62, 186))); + protected void onImpact(HitResult ray) { + removeAfterChangingDimensions(); + if (!level.isClientSide) { + Vec3 pos = ray.getLocation(); + level.playSound(null, pos.x, pos.y, pos.z, SoundEvents.WITHER_SHOOT, SoundSource.HOSTILE, 0.5f, random.nextFloat() * 0.2f + 0.9f); + Networking.sendToTracking(level, blockPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 158, 92, 255), ColorUtil.packColor(255, 60, 62, 186))); } } } diff --git a/src/main/java/elucent/eidolon/entity/RavenEntity.java b/src/main/java/elucent/eidolon/entity/RavenEntity.java new file mode 100644 index 0000000..c950cc5 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/RavenEntity.java @@ -0,0 +1,163 @@ +package elucent.eidolon.entity; + +import elucent.eidolon.Registry; +import net.minecraft.world.entity.AgeableMob; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.goal.BreedGoal; +import net.minecraft.world.entity.ai.goal.FollowOwnerGoal; +import net.minecraft.world.entity.ai.goal.FollowParentGoal; +import net.minecraft.world.entity.ai.goal.LandOnOwnersShoulderGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +import net.minecraft.world.entity.ai.goal.PanicGoal; +import net.minecraft.world.entity.ai.goal.SitWhenOrderedToGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.TemptGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.animal.FlyingAnimal; +import net.minecraft.world.entity.animal.ShoulderRidingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; + +public class RavenEntity extends ShoulderRidingEntity implements FlyingAnimal { + private static final Ingredient TEMPTATION_ITEMS = Ingredient.of(Items.RABBIT, Items.BEETROOT_SEEDS); + + public RavenEntity(EntityType type, Level worldIn) { + super(type, worldIn); + registerGoals(); + this.moveControl = new FlyingMoveControl(this, 10, false); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.LEAVES, 4.0F); + } + + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, TEMPTATION_ITEMS, false)); + this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1D)); + this.goalSelector.addGoal(4, new WaterAvoidingRandomFlyingGoal(this, 1.0D)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LandOnOwnersShoulderGoal(this)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + } + + @Override + protected PathNavigation createNavigation(Level worldIn) { + FlyingPathNavigation flyingpathnavigator = new FlyingPathNavigation(this, worldIn); + flyingpathnavigator.setCanOpenDoors(false); + flyingpathnavigator.setCanFloat(true); + flyingpathnavigator.setCanPassDoors(true); + return flyingpathnavigator; + } + + public static AttributeSupplier createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 8.0D) + .add(Attributes.FLYING_SPEED, (double)0.4F) + .add(Attributes.MOVEMENT_SPEED, (double)0.2F) + .add(Attributes.ARMOR, 0.0D) + .build(); + } + + public void aiStep() { + super.aiStep(); + Vec3 motion = this.getDeltaMovement(); + if (!this.onGround && motion.y < 0.0D) { + this.setDeltaMovement(motion.multiply(1.0D, 0.6D, 1.0D)); + } + } + + public boolean causeFallDamage(float distance, float damageMultiplier) { + return false; + } + + @Override + public boolean isFood(ItemStack stack) { + return stack.getItem() == Items.BEETROOT_SEEDS; + } + + @Override + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { + return Registry.RAVEN.get().create(world); + } + + @Override + public boolean setEntityOnShoulder(ServerPlayer player) { + if (player.getShoulderEntityLeft().contains("UUID") + && player.getShoulderEntityLeft().getUUID("UUID").equals(getUUID())) + return false; + if (player.getShoulderEntityRight().contains("UUID") + && player.getShoulderEntityRight().getUUID("UUID").equals(getUUID())) + return false; + CompoundTag compoundnbt = new CompoundTag(); + compoundnbt.putString("id", this.getEncodeId()); + this.saveWithoutId(compoundnbt); + if (player.setEntityOnShoulder(compoundnbt)) { + this.remove(RemovalReason.DISCARDED); + return true; + } else { + return false; + } + } + + @Override + public InteractionResult mobInteract(Player player, InteractionHand hand) { + ItemStack itemstack = player.getItemInHand(hand); + if (!this.isTame() && itemstack.getItem() == Items.BEETROOT_SEEDS) { + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } + if (!this.level.isClientSide) { + if (this.random.nextInt(10) == 0 && !net.minecraftforge.event.ForgeEventFactory.onAnimalTame(this, player)) { + this.tame(player); + this.level.broadcastEntityEvent(this, (byte)7); + } else { + this.level.broadcastEntityEvent(this, (byte)6); + } + } + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else if (onGround && this.isTame() && this.isOwnedBy(player)) { + if (!this.level.isClientSide) { + this.setOrderedToSit(!this.isOrderedToSit()); + } + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else { + return super.mobInteract(player, hand); + } + } + + @Override + public boolean isFlying() { + return !onGround; + } + + @Override + protected void doPush(Entity entityIn) { + if (!(entityIn instanceof Player)) { + super.doPush(entityIn); + } + } +} diff --git a/src/main/java/elucent/eidolon/entity/RavenModel.java b/src/main/java/elucent/eidolon/entity/RavenModel.java new file mode 100644 index 0000000..5fdb1a5 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/RavenModel.java @@ -0,0 +1,116 @@ +package elucent.eidolon.entity;// Made with Blockbench 3.7.4 +// Exported for Minecraft version 1.15 +// Paste this class into your mod and generate all required imports + + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.ClientEvents; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.util.Mth; + +public class RavenModel extends EntityModel { + private final ModelPart body; + + public RavenModel(ModelPart root) { + this.body = root.getChild("body"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.offset(0.0F, 24.0F, -0.5F)); + + PartDefinition head = body.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-1.5F, -3.0F, -3.0F, 3.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)) + .texOffs(0, 6).addBox(-0.5F, -2.0F, -5.0F, 1.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -5.0F, -1.5F)); + + PartDefinition wings = body.addOrReplaceChild("wings", CubeListBuilder.create().texOffs(0, 14).addBox(-2.0F, -3.5F, -0.5F, 4.0F, 4.0F, 7.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -4.0F, -2.5F, -0.5236F, 0.0F, 0.0F)); + + PartDefinition tailMid = body.addOrReplaceChild("tailMid", CubeListBuilder.create().texOffs(13, 0).addBox(-1.0F, 0.0F, 0.0F, 2.0F, 0.0F, 7.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -3.5F, 3.0F, -0.2618F, 0.0F, 0.0F)); + + PartDefinition leftTail = body.addOrReplaceChild("leftTail", CubeListBuilder.create().texOffs(16, 14).mirror().addBox(-1.0F, 0.0F, 0.0F, 2.0F, 0.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(0.75F, -3.0F, 2.5F, -0.2618F, 0.2618F, 0.0F)); + + PartDefinition rightTail = body.addOrReplaceChild("rightTail", CubeListBuilder.create().texOffs(16, 14).addBox(-1.0F, 0.0F, 0.0F, 2.0F, 0.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.75F, -3.0F, 2.5F, -0.2618F, -0.2618F, 0.0F)); + + PartDefinition leftWing = body.addOrReplaceChild("leftWing", CubeListBuilder.create().texOffs(0, 25).addBox(0.0F, 0.0F, 0.0F, 10.0F, 0.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(1.0F, -5.5F, -1.5F)); + + PartDefinition rightWing = body.addOrReplaceChild("rightWing", CubeListBuilder.create().texOffs(0, 25).mirror().addBox(-10.0F, 0.0F, 0.0F, 10.0F, 0.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offset(-1.0F, -5.5F, -1.5F)); + + PartDefinition leftLeg = body.addOrReplaceChild("leftLeg", CubeListBuilder.create().texOffs(12, 7).addBox(-0.5F, 0.0F, -1.0F, 1.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offset(1.0F, -3.0F, 0.5F)); + + PartDefinition rightLeg = body.addOrReplaceChild("rightLeg", CubeListBuilder.create().texOffs(12, 7).addBox(-0.5F, 0.0F, -1.0F, 1.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offset(-1.0F, -3.0F, 0.5F)); + + PartDefinition chest = body.addOrReplaceChild("chest", CubeListBuilder.create().texOffs(1, 6).addBox(-1.5F, -3.0F, 0.0F, 3.0F, 3.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -4.0F, -2.5F, -0.5236F, 0.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 32, 32); + } + + public void renderOnShoulder(PoseStack matrixStackIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn, float p_228284_5_, float p_228284_6_, float p_228284_7_, float p_228284_8_, int p_228284_9_) { + body.getChild("leftWing").visible = false; + body.getChild("rightWing").visible = false; + body.getChild("wings").visible = true; + body.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn); + } + + @Override + public void setupAnim(RavenEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ + ModelPart leftWing = body.getChild("leftWing"), rightWing = body.getChild("rightWing"), + wings = body.getChild("wings"), rightLeg = body.getChild("rightLeg"), leftLeg = body.getChild("leftLeg"), + head = body.getChild("head"); + body.y = 24.0f; + if (entity.isOnGround()) { + leftWing.visible = false; + rightWing.visible = false; + wings.visible = true; + + if (entity.isTame() && entity.isInSittingPose()) { + rightLeg.xRot = -(float)Math.PI / 3; + leftLeg.xRot = -(float)Math.PI / 3; + body.y = 25.5f; + } + else { + rightLeg.xRot = Mth.cos(limbSwing * 2F + (float)Math.PI) * 2F * limbSwingAmount; + leftLeg.xRot = Mth.cos(limbSwing * 2F) * 2F * limbSwingAmount; + } + } + else { + leftWing.visible = true; + rightWing.visible = true; + wings.visible = false; + rightLeg.xRot = 0; + leftLeg.xRot = 0; + + if (entity.getDeltaMovement().y < 0) { + rightWing.zRot = Mth.sin(ClientEvents.getClientTicks()) * 0.1f; + leftWing.zRot = -Mth.sin(0.97f + ClientEvents.getClientTicks()) * 0.1f; + } + else { + rightWing.zRot = (float)Math.sin(ClientEvents.getClientTicks()) * 0.4f; + leftWing.zRot = -(float)Math.sin(ClientEvents.getClientTicks()) * 0.4f; + } + } + + head.xRot = (float)Math.toRadians(headPitch); + head.yRot = (float)Math.toRadians(netHeadYaw); + } + + @Override + public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ + body.render(matrixStack, buffer, packedLight, packedOverlay); + } + + public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { + modelRenderer.xRot = x; + modelRenderer.yRot = y; + modelRenderer.zRot = z; + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/entity/RavenRenderer.java b/src/main/java/elucent/eidolon/entity/RavenRenderer.java new file mode 100644 index 0000000..42ddc3a --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/RavenRenderer.java @@ -0,0 +1,35 @@ +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; + +public class RavenRenderer extends MobRenderer { + protected static final ResourceLocation TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/raven.png"); + public RavenRenderer(Context erm) { + super(erm, new RavenModel(erm.bakeLayer(Registry.RAVEN_LAYER)), 0.25f); + } + + @Override + public ResourceLocation getTextureLocation(RavenEntity entity) { + return TEXTURE; + } + + @Override + protected void scale(RavenEntity entitylivingbaseIn, PoseStack matrixStackIn, float partialTickTime) { + float f = 1; + if (entitylivingbaseIn.isBaby()) { + f *= 0.5f; + this.shadowRadius = 0.125F; + } else { + this.shadowRadius = 0.25F; + } + + matrixStackIn.scale(f, f, f); + } +} diff --git a/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java b/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java new file mode 100644 index 0000000..60e8573 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java @@ -0,0 +1,40 @@ +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.nbt.CompoundTag; + +public class RavenVariantLayer extends RenderLayer> { + private final RavenModel model; + + public RavenVariantLayer(RenderLayerParent> rendererIn) { + super(rendererIn); + this.model = new RavenModel(Minecraft.getInstance().getEntityModels().bakeLayer(Registry.RAVEN_LAYER)); + } + + public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, T entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + this.renderRaven(matrixStackIn, bufferIn, packedLightIn, entitylivingbaseIn, limbSwing, limbSwingAmount, netHeadYaw, headPitch, true); + this.renderRaven(matrixStackIn, bufferIn, packedLightIn, entitylivingbaseIn, limbSwing, limbSwingAmount, netHeadYaw, headPitch, false); + } + + private void renderRaven(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, T entitylivingbaseIn, float limbSwing, float limbSwingAmount, float netHeadYaw, float headPitch, boolean leftShoulderIn) { + CompoundTag compoundnbt = leftShoulderIn ? entitylivingbaseIn.getShoulderEntityLeft() : entitylivingbaseIn.getShoulderEntityRight(); + EntityType.byString(compoundnbt.getString("id")).filter((p_215344_0_) -> p_215344_0_ == Registry.RAVEN.get()).ifPresent((p_229137_11_) -> { + matrixStackIn.pushPose(); + matrixStackIn.translate(leftShoulderIn ? (double)0.4F : (double)-0.4F, entitylivingbaseIn.isCrouching() ? (double)-1.3F : -1.5D, 0.0D); + VertexConsumer ivertexbuilder = bufferIn.getBuffer(model.renderType(RavenRenderer.TEXTURE)); + model.renderOnShoulder(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY, limbSwing, limbSwingAmount, netHeadYaw, headPitch, entitylivingbaseIn.tickCount); + matrixStackIn.popPose(); + }); + } +} diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java b/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java new file mode 100644 index 0000000..8d35735 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java @@ -0,0 +1,74 @@ +package elucent.eidolon.entity; + +import elucent.eidolon.Registry; +import net.minecraft.world.entity.AgeableMob; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.goal.BreedGoal; +import net.minecraft.world.entity.ai.goal.FollowOwnerGoal; +import net.minecraft.world.entity.ai.goal.FollowParentGoal; +import net.minecraft.world.entity.ai.goal.LandOnOwnersShoulderGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +import net.minecraft.world.entity.ai.goal.PanicGoal; +import net.minecraft.world.entity.ai.goal.SitWhenOrderedToGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.TemptGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.animal.FlyingAnimal; +import net.minecraft.world.entity.animal.ShoulderRidingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; + +public class SlimySlugEntity extends PathfinderMob { + private static final Ingredient TEMPTATION_ITEMS = Ingredient.of(Items.PUMPKIN_SEEDS); + float yRotTrail = 0.0f; + float squishAmount = 1.0f; + + public SlimySlugEntity(EntityType type, Level worldIn) { + super(type, worldIn); + registerGoals(); + yRotTrail = this.getYRot(); + } + + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, TEMPTATION_ITEMS, false)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + } + + public static AttributeSupplier createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 8.0D) + .add(Attributes.MOVEMENT_SPEED, (double)0.1F) + .add(Attributes.ARMOR, 0.0D) + .build(); + } + + public void tick() { + super.tick(); + yRotTrail = Mth.rotLerp(yRotTrail, getYRot(), 0.2f); + } +} diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugModel.java b/src/main/java/elucent/eidolon/entity/SlimySlugModel.java new file mode 100644 index 0000000..501c308 --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/SlimySlugModel.java @@ -0,0 +1,57 @@ +package elucent.eidolon.entity; +// Made with Blockbench 4.0.5 +// Exported for Minecraft version 1.17 with Mojang mappings +// Paste this class into your mod and generate all required imports + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; + +public class SlimySlugModel extends EntityModel { + private final ModelPart body; + + public SlimySlugModel(ModelPart root) { + this.body = root.getChild("body"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 0).addBox(-2.0F, -4.0F, -4.0F, 4.0F, 4.0F, 8.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 24.0F, 0.0F)); + + PartDefinition tail = body.addOrReplaceChild("tail", CubeListBuilder.create().texOffs(16, 0).addBox(-1.0F, -2.0F, 0.0F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 0.0F, 4.0F)); + + PartDefinition left_eye = body.addOrReplaceChild("left_eye", CubeListBuilder.create(), PartPose.offsetAndRotation(1.0F, -4.0F, -3.0F, 0.2618F, 0.0F, 0.2618F)); + + PartDefinition cube_r1 = left_eye.addOrReplaceChild("cube_r1", CubeListBuilder.create().texOffs(0, 0).addBox(0.0F, -3.0F, -1.0F, 1.0F, 4.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); + + PartDefinition right_eye = body.addOrReplaceChild("right_eye", CubeListBuilder.create(), PartPose.offsetAndRotation(-1.0F, -4.0F, -3.0F, 0.2618F, 0.0F, -0.2618F)); + + PartDefinition cube_r2 = right_eye.addOrReplaceChild("cube_r2", CubeListBuilder.create().texOffs(0, 0).addBox(-3.0F, -3.0F, -1.0F, 1.0F, 4.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(2.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 32, 16); + } + + @Override + public void setupAnim(SlimySlugEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + entity.squishAmount = 1 + Mth.cos(limbSwing * 4.0F + (float)Math.PI) * 0.1f; + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + body.render(poseStack, buffer, packedLight, packedOverlay); + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java b/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java new file mode 100644 index 0000000..6cb4cef --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java @@ -0,0 +1,27 @@ +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; + +public class SlimySlugRenderer extends MobRenderer { + protected static final ResourceLocation TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/slimy_slug.png"); + public SlimySlugRenderer(Context erm) { + super(erm, new SlimySlugModel(erm.bakeLayer(Registry.SLUG_LAYER)), 0.4f); + } + + @Override + public ResourceLocation getTextureLocation(SlimySlugEntity entity) { + return TEXTURE; + } + + @Override + protected void scale(SlimySlugEntity e, PoseStack matrixStackIn, float partialTickTime) { + matrixStackIn.scale(2 / (1 + e.squishAmount), 2 / (1 + e.squishAmount), e.squishAmount); + } +} diff --git a/src/main/java/elucent/eidolon/entity/SoulfireProjectileEntity.java b/src/main/java/elucent/eidolon/entity/SoulfireProjectileEntity.java index 4b2df8f..3f6b99f 100644 --- a/src/main/java/elucent/eidolon/entity/SoulfireProjectileEntity.java +++ b/src/main/java/elucent/eidolon/entity/SoulfireProjectileEntity.java @@ -5,24 +5,17 @@ import elucent.eidolon.network.Networking; import elucent.eidolon.particle.Particles; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.network.IPacket; -import net.minecraft.util.DamageSource; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkHooks; - -import java.util.List; -import java.util.UUID; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; public class SoulfireProjectileEntity extends SpellProjectileEntity { - public SoulfireProjectileEntity(EntityType entityTypeIn, World worldIn) { + public SoulfireProjectileEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); } @@ -30,41 +23,41 @@ public SoulfireProjectileEntity(EntityType entityTypeIn, World worldIn) { public void tick() { super.tick(); - Vector3d motion = getMotion(); - Vector3d pos = getPositionVec(); - Vector3d norm = motion.normalize().scale(0.025f); + Vec3 motion = getDeltaMovement(); + Vec3 pos = position(); + Vec3 norm = motion.normalize().scale(0.025f); for (int i = 0; i < 8; i ++) { - double lerpX = MathHelper.lerp(i / 8.0f, prevPosX, pos.x); - double lerpY = MathHelper.lerp(i / 8.0f, prevPosY, pos.y); - double lerpZ = MathHelper.lerp(i / 8.0f, prevPosZ, pos.z); + double lerpX = Mth.lerp(i / 8.0f, xo, pos.x); + double lerpY = Mth.lerp(i / 8.0f, yo, pos.y); + double lerpZ = Mth.lerp(i / 8.0f, zo, pos.z); Particles.create(Registry.SPARKLE_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.375f, 0).setScale(0.375f, 0) .setColor(1, 0.875f, 0.5f, 0.5f, 0.25f, 1) .setLifetime(5) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); Particles.create(Registry.WISP_PARTICLE) .addVelocity(-norm.x, -norm.y, -norm.z) .setAlpha(0.125f, 0).setScale(0.25f, 0.125f) .setColor(1, 0.5f, 0.625f, 0.5f, 0.25f, 1) .setLifetime(20) - .spawn(world, lerpX, lerpY, lerpZ); + .spawn(level, lerpX, lerpY, lerpZ); } } @Override - protected void onImpact(RayTraceResult ray, Entity target) { - target.attackEntityFrom(DamageSource.causeIndirectMagicDamage(this, world.getPlayerByUuid(casterId)), 7.0f); + protected void onImpact(HitResult ray, Entity target) { + target.hurt(DamageSource.indirectMagic(this, level.getPlayerByUUID(casterId)), 7.0f); onImpact(ray); } @Override - protected void onImpact(RayTraceResult ray) { - setDead(); - if (!world.isRemote) { - Vector3d pos = ray.getHitVec(); - world.playSound(null, pos.x, pos.y, pos.z, Registry.SPLASH_SOULFIRE_EVENT.get(), SoundCategory.NEUTRAL, 0.6f, rand.nextFloat() * 0.2f + 0.9f); - Networking.sendToTracking(world, getPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 255, 229, 125), ColorUtil.packColor(255, 124, 57, 247))); + protected void onImpact(HitResult ray) { + removeAfterChangingDimensions(); + if (!level.isClientSide) { + Vec3 pos = ray.getLocation(); + level.playSound(null, pos.x, pos.y, pos.z, Registry.SPLASH_SOULFIRE_EVENT.get(), SoundSource.NEUTRAL, 0.6f, random.nextFloat() * 0.2f + 0.9f); + Networking.sendToTracking(level, blockPosition(), new MagicBurstEffectPacket(pos.x, pos.y, pos.z, ColorUtil.packColor(255, 255, 229, 125), ColorUtil.packColor(255, 124, 57, 247))); } } } diff --git a/src/main/java/elucent/eidolon/entity/SpellProjectileEntity.java b/src/main/java/elucent/eidolon/entity/SpellProjectileEntity.java index d39cf4f..110ea7c 100644 --- a/src/main/java/elucent/eidolon/entity/SpellProjectileEntity.java +++ b/src/main/java/elucent/eidolon/entity/SpellProjectileEntity.java @@ -1,93 +1,77 @@ package elucent.eidolon.entity; -import elucent.eidolon.Registry; -import elucent.eidolon.particle.Particles; -import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.goal.*; -import net.minecraft.entity.item.BoatEntity; -import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; -import net.minecraft.entity.monster.MonsterEntity; -import net.minecraft.entity.passive.IronGolemEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.entity.projectile.ProjectileHelper; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.network.IPacket; -import net.minecraft.network.play.server.SSpawnObjectPacket; -import net.minecraft.util.DamageSource; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.EntityRayTraceResult; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkHooks; - -import java.util.List; import java.util.UUID; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ProjectileUtil; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkHooks; +import net.minecraft.world.level.Level; + public abstract class SpellProjectileEntity extends Entity { UUID casterId = null; - public SpellProjectileEntity(EntityType entityTypeIn, World worldIn) { + public SpellProjectileEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); } public Entity shoot(double x, double y, double z, double vx, double vy, double vz, UUID caster) { - setPosition(x, y, z); - setMotion(vx, vy, vz); + setPos(x, y, z); + setDeltaMovement(vx, vy, vz); casterId = caster; - velocityChanged = true; + hurtMarked = true; return this; } @Override public void tick() { - Vector3d motion = getMotion(); - setMotion(motion.x * 0.96, (motion.y > 0 ? motion.y * 0.96 : motion.y) - 0.03f, motion.z * 0.96); + Vec3 motion = getDeltaMovement(); + setDeltaMovement(motion.x * 0.96, (motion.y > 0 ? motion.y * 0.96 : motion.y) - 0.03f, motion.z * 0.96); super.tick(); - if (!world.isRemote) { - RayTraceResult ray = ProjectileHelper.func_234618_a_(this, (e) -> !e.isSpectator() && e.canBeCollidedWith() && !e.getUniqueID().equals(casterId)); - if (ray.getType() == RayTraceResult.Type.ENTITY) { - onImpact(ray, ((EntityRayTraceResult)ray).getEntity()); + if (!level.isClientSide) { + HitResult ray = ProjectileUtil.getHitResult(this, (e) -> !e.isSpectator() && e.isPickable() && !e.getUUID().equals(casterId)); + if (ray.getType() == HitResult.Type.ENTITY) { + onImpact(ray, ((EntityHitResult)ray).getEntity()); } - else if (ray.getType() == RayTraceResult.Type.BLOCK) { + else if (ray.getType() == HitResult.Type.BLOCK) { onImpact(ray); } } - Vector3d pos = getPositionVec(); - prevPosX = pos.x; - prevPosY = pos.y; - prevPosZ = pos.z; - setPosition(pos.x + motion.x, pos.y + motion.y, pos.z + motion.z); + Vec3 pos = position(); + xo = pos.x; + yo = pos.y; + zo = pos.z; + setPos(pos.x + motion.x, pos.y + motion.y, pos.z + motion.z); } - protected abstract void onImpact(RayTraceResult ray, Entity target); - protected abstract void onImpact(RayTraceResult ray); + protected abstract void onImpact(HitResult ray, Entity target); + protected abstract void onImpact(HitResult ray); @Override - protected void registerData() { + protected void defineSynchedData() { // } @Override - protected void readAdditional(CompoundNBT compound) { - casterId = compound.contains("caster") ? compound.getUniqueId("caster") : null; + protected void readAdditionalSaveData(CompoundTag compound) { + casterId = compound.contains("caster") ? compound.getUUID("caster") : null; } @Override - protected void writeAdditional(CompoundNBT compound) { - if (casterId != null) compound.putUniqueId("caster", casterId); + protected void addAdditionalSaveData(CompoundTag compound) { + if (casterId != null) compound.putUUID("caster", casterId); } @Override - public IPacket createSpawnPacket() { + public Packet getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } } diff --git a/src/main/java/elucent/eidolon/entity/WraithEntity.java b/src/main/java/elucent/eidolon/entity/WraithEntity.java index 82ad104..9b68a03 100644 --- a/src/main/java/elucent/eidolon/entity/WraithEntity.java +++ b/src/main/java/elucent/eidolon/entity/WraithEntity.java @@ -1,132 +1,126 @@ package elucent.eidolon.entity; import elucent.eidolon.Registry; -import net.minecraft.enchantment.Enchantments; -import net.minecraft.entity.CreatureAttribute; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.goal.*; -import net.minecraft.entity.item.BoatEntity; -import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; -import net.minecraft.entity.monster.CreeperEntity; -import net.minecraft.entity.monster.MonsterEntity; -import net.minecraft.entity.monster.SpiderEntity; -import net.minecraft.entity.monster.ZombieEntity; -import net.minecraft.entity.passive.ChickenEntity; -import net.minecraft.entity.passive.IronGolemEntity; -import net.minecraft.entity.passive.TurtleEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.fluid.FluidState; -import net.minecraft.pathfinding.PathNavigator; -import net.minecraft.pathfinding.SwimmerPathNavigator; -import net.minecraft.potion.EffectInstance; -import net.minecraft.util.DamageSource; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; - -public class WraithEntity extends MonsterEntity { - public WraithEntity(EntityType type, World worldIn) { +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; + +public class WraithEntity extends Monster { + public WraithEntity(EntityType type, Level worldIn) { super(type, worldIn); registerGoals(); } @Override - public CreatureAttribute getCreatureAttribute() { - return CreatureAttribute.UNDEAD; + public MobType getMobType() { + return MobType.UNDEAD; } @Override - public boolean isEntityUndead() { + public boolean isInvertedHealAndHarm() { return true; } @Override - public boolean attackEntityAsMob(Entity entityIn) { - boolean flag = super.attackEntityAsMob(entityIn); + public boolean doHurtTarget(Entity entityIn) { + boolean flag = super.doHurtTarget(entityIn); if (flag && entityIn instanceof LivingEntity) { - float f = this.world.getDifficultyForLocation(this.getPosition()).getAdditionalDifficulty(); - ((LivingEntity)entityIn).addPotionEffect(new EffectInstance(Registry.CHILLED_EFFECT.get(), 100 + (int)(100 * world.getDifficulty().getId()))); + float f = this.level.getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + ((LivingEntity)entityIn).addEffect(new MobEffectInstance(Registry.CHILLED_EFFECT.get(), 100 + (int)(100 * level.getDifficulty().getId()))); } return flag; } protected void registerGoals() { - this.goalSelector.addGoal(0, new SwimGoal(this)); + this.goalSelector.addGoal(0, new FloatGoal(this)); this.applyEntityAI(); } - public static AttributeModifierMap createAttributes() { - return MonsterEntity.func_234295_eP_() - .createMutableAttribute(Attributes.MAX_HEALTH, 20.0D) - .createMutableAttribute(Attributes.MOVEMENT_SPEED, (double)0.2F) - .createMutableAttribute(Attributes.ATTACK_DAMAGE, 4.0D) - .createMutableAttribute(Attributes.ARMOR, 0.0D) - .create(); + public static AttributeSupplier createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 20.0D) + .add(Attributes.MOVEMENT_SPEED, (double)0.2F) + .add(Attributes.ATTACK_DAMAGE, 4.0D) + .add(Attributes.ARMOR, 0.0D) + .build(); } protected void applyEntityAI() { this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.5D, false)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomWalkingGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); } @Override - public int getExperiencePoints(PlayerEntity player) { + public int getExperienceReward(Player player) { return 5; } @Override - public void livingTick() { - if (this.world.isDaytime() && !this.world.isRemote) { + public void aiStep() { + if (this.level.isDay() && !this.level.isClientSide) { float f = this.getBrightness(); - BlockPos blockpos = this.getRidingEntity() instanceof BoatEntity ? (new BlockPos(this.getPosX(), (double) Math.round(this.getPosY()), this.getPosZ())).up() : new BlockPos(this.getPosX(), (double) Math.round(this.getPosY()), this.getPosZ()); - if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(blockpos)) { - this.setFire(8); + BlockPos blockpos = this.getVehicle() instanceof Boat ? (new BlockPos(this.getX(), (double) Math.round(this.getY()), this.getZ())).above() : new BlockPos(this.getX(), (double) Math.round(this.getY()), this.getZ()); + if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.level.canSeeSky(blockpos)) { + this.setSecondsOnFire(8); } } // hover over water - FluidState below = world.getBlockState(getPositionUnderneath()).getFluidState(); + FluidState below = level.getBlockState(getBlockPosBelowThatAffectsMyMovement()).getFluidState(); if (!below.isEmpty()) { - Vector3d motion = getMotion(); + Vec3 motion = getDeltaMovement(); this.setOnGround(true); - if (getPosY() + motion.y < getPositionUnderneath().getY() + below.getHeight()) { + if (getY() + motion.y < getBlockPosBelowThatAffectsMyMovement().getY() + below.getOwnHeight()) { setNoGravity(true); - if (motion.y < 0) setMotion(motion.mul(1, 0, 1)); - setPosition(getPosX(), getPositionUnderneath().getY() + below.getHeight(), getPosZ()); + if (motion.y < 0) setDeltaMovement(motion.multiply(1, 0, 1)); + setPos(getX(), getBlockPosBelowThatAffectsMyMovement().getY() + below.getOwnHeight(), getZ()); } } else setNoGravity(false); // slow fall this.fallDistance = 0; - Vector3d vector3d = this.getMotion(); + Vec3 vector3d = this.getDeltaMovement(); if (!this.onGround && vector3d.y < 0.0D) { - this.setMotion(vector3d.mul(1.0D, 0.6D, 1.0D)); + this.setDeltaMovement(vector3d.multiply(1.0D, 0.6D, 1.0D)); } - super.livingTick(); + super.aiStep(); } @Override public SoundEvent getDeathSound() { - return SoundEvents.ENTITY_STRAY_DEATH; + return SoundEvents.STRAY_DEATH; } @Override public SoundEvent getAmbientSound() { - return SoundEvents.ENTITY_STRAY_AMBIENT; + return SoundEvents.STRAY_AMBIENT; } @Override public SoundEvent getHurtSound(DamageSource source) { - return SoundEvents.ENTITY_STRAY_HURT; + return SoundEvents.STRAY_HURT; } } diff --git a/src/main/java/elucent/eidolon/entity/WraithModel.java b/src/main/java/elucent/eidolon/entity/WraithModel.java index ad10f57..d932165 100644 --- a/src/main/java/elucent/eidolon/entity/WraithModel.java +++ b/src/main/java/elucent/eidolon/entity/WraithModel.java @@ -1,93 +1,64 @@ -package elucent.eidolon.entity; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.entity.model.EntityModel; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3d; - -public class WraithModel extends EntityModel { - private final ModelRenderer body; - private final ModelRenderer tail; - private final ModelRenderer right_arm; - private final ModelRenderer lower_right_arm; - private final ModelRenderer right_hand; - private final ModelRenderer left_arm; - private final ModelRenderer lower_left_arm; - private final ModelRenderer left_hand; - - public WraithModel() { - textureWidth = 64; - textureHeight = 64; - - body = new ModelRenderer(this); - body.setRotationPoint(0.0F, 8.0F, 0.0F); - body.setTextureOffset(0, 0).addBox(-4.0F, -16.0F, -4.0F, 8.0F, 16.0F, 8.0F, 0.0F, false); - body.setTextureOffset(32, 2).addBox(-3.0F, -15.0F, -3.0F, 6.0F, 15.0F, 6.0F, 0.0F, false); - - tail = new ModelRenderer(this); - tail.setRotationPoint(0.0F, 0.0F, -4.0F); - body.addChild(tail); - setRotationAngle(tail, 0.2618F, 0.0F, 0.0F); - tail.setTextureOffset(0, 24).addBox(-4.0F, 0.0F, 0.0F, 8.0F, 16.0F, 8.0F, 0.0F, false); - tail.setTextureOffset(32, 26).addBox(-3.0F, 0.2588F, 0.9659F, 6.0F, 15.0F, 6.0F, 0.0F, false); - - right_arm = new ModelRenderer(this); - right_arm.setRotationPoint(-5.5F, -6.5F, 0.0F); - body.addChild(right_arm); - setRotationAngle(right_arm, -1.0472F, 0.0F, -0.1745F); - right_arm.setTextureOffset(0, 48).addBox(-1.5F, -1.5F, -1.0F, 3.0F, 6.0F, 3.0F, 0.0F, false); - - lower_right_arm = new ModelRenderer(this); - lower_right_arm.setRotationPoint(0.0F, 6.0F, 0.0F); - right_arm.addChild(lower_right_arm); - setRotationAngle(lower_right_arm, -0.7854F, 0.0F, 0.0F); - lower_right_arm.setTextureOffset(12, 48).addBox(-1.5F, -2.4749F, -2.6464F, 3.0F, 6.0F, 3.0F, 0.0F, false); - - right_hand = new ModelRenderer(this); - right_hand.setRotationPoint(0.0F, 2.5F, 0.0F); - lower_right_arm.addChild(right_hand); - setRotationAngle(right_hand, 0.3927F, 0.0F, 0.0F); - right_hand.setTextureOffset(25, 48).addBox(-1.5F, -1.0F, -1.5F, 3.0F, 3.0F, 3.0F, 0.0F, false); - - left_arm = new ModelRenderer(this); - left_arm.setRotationPoint(5.5F, -6.5F, 0.0F); - body.addChild(left_arm); - setRotationAngle(left_arm, -1.0472F, 0.0F, 0.1745F); - left_arm.setTextureOffset(0, 48).addBox(-1.5F, -1.5F, -1.0F, 3.0F, 6.0F, 3.0F, 0.0F, true); - - lower_left_arm = new ModelRenderer(this); - lower_left_arm.setRotationPoint(-11.0F, 6.0F, 0.0F); - left_arm.addChild(lower_left_arm); - setRotationAngle(lower_left_arm, -0.7854F, 0.0F, 0.0F); - lower_left_arm.setTextureOffset(12, 48).addBox(9.5F, -2.4749F, -2.6464F, 3.0F, 6.0F, 3.0F, 0.0F, true); - - left_hand = new ModelRenderer(this); - left_hand.setRotationPoint(0.0F, 2.5F, 0.0F); - lower_left_arm.addChild(left_hand); - setRotationAngle(left_hand, 0.3927F, 0.0F, 0.0F); - left_hand.setTextureOffset(25, 48).addBox(9.5F, -1.0F, -1.5F, 3.0F, 3.0F, 3.0F, 0.0F, true); - } - - @Override - public void setRotationAngles(WraithEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - body.rotationPointY = 8.0f + 1.5f * MathHelper.sin(ageInTicks / 20.0f * (float)Math.PI); - body.rotateAngleX = (float)Math.toRadians(MathHelper.clamp( - 10.0f * (float)entity.getMotion().mul(1, 0, 1).length() / 0.3f, - -10.0f, 10.0f - )); - } - - @Override - public void render(MatrixStack matrixStack, IVertexBuilder buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ - body.render(matrixStack, buffer, packedLight, packedOverlay); - } - - public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) { - modelRenderer.rotateAngleX = x; - modelRenderer.rotateAngleY = y; - modelRenderer.rotateAngleZ = z; - } +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix3f; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.util.Mth; + +public class WraithModel extends EntityModel { + private final ModelPart body; + + public WraithModel(ModelPart root) { + this.body = root.getChild("body"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -16.0F, -4.0F, 8.0F, 16.0F, 8.0F, new CubeDeformation(0.0F)) + .texOffs(32, 2).addBox(-3.0F, -15.0F, -3.0F, 6.0F, 15.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 8.0F, 0.0F)); + + PartDefinition tail = body.addOrReplaceChild("tail", CubeListBuilder.create().texOffs(0, 24).addBox(-4.0F, 0.0F, 0.0F, 8.0F, 16.0F, 8.0F, new CubeDeformation(0.0F)) + .texOffs(32, 26).addBox(-3.0F, 0.2588F, 0.9659F, 6.0F, 15.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, -4.0F, 0.2618F, 0.0F, 0.0F)); + + PartDefinition right_arm = body.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(0, 48).addBox(-1.5F, -1.5F, -1.0F, 3.0F, 6.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-5.5F, -6.5F, 0.0F, -1.0472F, 0.0F, -0.1745F)); + + PartDefinition lower_right_arm = right_arm.addOrReplaceChild("lower_right_arm", CubeListBuilder.create().texOffs(12, 48).addBox(-1.5F, -2.4749F, -2.6464F, 3.0F, 6.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 6.0F, 0.0F, -0.7854F, 0.0F, 0.0F)); + + PartDefinition right_hand = lower_right_arm.addOrReplaceChild("right_hand", CubeListBuilder.create().texOffs(25, 48).addBox(-1.5F, -1.0F, -1.5F, 3.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 2.5F, 0.0F, 0.3927F, 0.0F, 0.0F)); + + PartDefinition left_arm = body.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(0, 48).mirror().addBox(-1.5F, -1.5F, -1.0F, 3.0F, 6.0F, 3.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(5.5F, -6.5F, 0.0F, -1.0472F, 0.0F, 0.1745F)); + + PartDefinition lower_left_arm = left_arm.addOrReplaceChild("lower_left_arm", CubeListBuilder.create().texOffs(12, 48).mirror().addBox(9.5F, -2.4749F, -2.6464F, 3.0F, 6.0F, 3.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-11.0F, 6.0F, 0.0F, -0.7854F, 0.0F, 0.0F)); + + PartDefinition left_hand = lower_left_arm.addOrReplaceChild("left_hand", CubeListBuilder.create().texOffs(25, 48).mirror().addBox(9.5F, -1.0F, -1.5F, 3.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(0.0F, 2.5F, 0.0F, 0.3927F, 0.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 64, 64); + } + + @Override + public void setupAnim(WraithEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + body.y = 8.0f + 1.5f * (float)Mth.sin(ageInTicks / 20.0f * (float)Math.PI); + body.xRot = (float)Math.toRadians(Mth.clamp( + 15.0f * (float)entity.getDeltaMovement().multiply(1, 0, 1).length() / 0.3f, + -15.0f, 15.0f + )); + body.getChild("right_arm").xRot = -1.0472F + Mth.cos(limbSwing * 0.666F + (float)Math.PI) * 0.25F * limbSwingAmount; + body.getChild("left_arm").xRot = -1.0472F + Mth.cos(limbSwing * 0.666F) * 0.25F * limbSwingAmount; + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + body.render(poseStack, buffer, packedLight, packedOverlay); + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/entity/WraithRenderer.java b/src/main/java/elucent/eidolon/entity/WraithRenderer.java index 97600a7..e01ce43 100644 --- a/src/main/java/elucent/eidolon/entity/WraithRenderer.java +++ b/src/main/java/elucent/eidolon/entity/WraithRenderer.java @@ -1,17 +1,19 @@ package elucent.eidolon.entity; import elucent.eidolon.Eidolon; -import net.minecraft.client.renderer.entity.EntityRendererManager; +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.util.ResourceLocation; +import net.minecraft.resources.ResourceLocation; public class WraithRenderer extends MobRenderer { - public WraithRenderer(EntityRendererManager rendererManager, WraithModel entityModelIn, float shadowSizeIn) { - super(rendererManager, entityModelIn, shadowSizeIn); + public WraithRenderer(Context erm) { + super(erm, new WraithModel(erm.bakeLayer(Registry.WRAITH_LAYER)), 0.45f); } @Override - public ResourceLocation getEntityTexture(WraithEntity entity) { + public ResourceLocation getTextureLocation(WraithEntity entity) { return new ResourceLocation(Eidolon.MODID, "textures/entity/wraith.png"); } } diff --git a/src/main/java/elucent/eidolon/entity/ZombieBruteEntity.java b/src/main/java/elucent/eidolon/entity/ZombieBruteEntity.java index 0ee3db1..877f186 100644 --- a/src/main/java/elucent/eidolon/entity/ZombieBruteEntity.java +++ b/src/main/java/elucent/eidolon/entity/ZombieBruteEntity.java @@ -1,100 +1,98 @@ package elucent.eidolon.entity; -import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; -import net.minecraft.entity.CreatureAttribute; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.MobEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.GlobalEntityTypeAttributes; -import net.minecraft.entity.ai.goal.*; -import net.minecraft.entity.item.BoatEntity; -import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; -import net.minecraft.entity.monster.MonsterEntity; -import net.minecraft.entity.monster.ZombieEntity; -import net.minecraft.entity.monster.ZombifiedPiglinEntity; -import net.minecraft.entity.passive.IronGolemEntity; -import net.minecraft.entity.passive.TurtleEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; -public class ZombieBruteEntity extends MonsterEntity { - public ZombieBruteEntity(EntityType type, World worldIn) { +public class ZombieBruteEntity extends Monster { + public ZombieBruteEntity(EntityType type, Level worldIn) { super(type, worldIn); registerGoals(); } @Override - public CreatureAttribute getCreatureAttribute() { - return CreatureAttribute.UNDEAD; + public MobType getMobType() { + return MobType.UNDEAD; } @Override - public boolean isEntityUndead() { + public boolean isInvertedHealAndHarm() { return true; } protected void registerGoals() { - this.goalSelector.addGoal(0, new SwimGoal(this)); + this.goalSelector.addGoal(0, new FloatGoal(this)); this.applyEntityAI(); } - public static AttributeModifierMap createAttributes() { - return MonsterEntity.func_234295_eP_() - .createMutableAttribute(Attributes.MAX_HEALTH, 40.0D) - .createMutableAttribute(Attributes.MOVEMENT_SPEED, (double)0.28F) - .createMutableAttribute(Attributes.ATTACK_DAMAGE, 5.0D) - .createMutableAttribute(Attributes.ARMOR, 6.0D) - .create(); + public static AttributeSupplier createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 40.0D) + .add(Attributes.MOVEMENT_SPEED, (double)0.28F) + .add(Attributes.ATTACK_DAMAGE, 5.0D) + .add(Attributes.ARMOR, 6.0D) + .build(); } protected void applyEntityAI() { - this.goalSelector.addGoal(8, new LookAtGoal(this, PlayerEntity.class, 8.0F)); - this.goalSelector.addGoal(8, new LookRandomlyGoal(this)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomWalkingGoal(this, 1.0D)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillagerEntity.class, false)); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolemEntity.class, true)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); } @Override - public int getExperiencePoints(PlayerEntity player) { + public int getExperienceReward(Player player) { return 8; } @Override - public void livingTick() { - if (this.world.isDaytime() && !this.world.isRemote) { + public void aiStep() { + if (this.level.isDay() && !this.level.isClientSide) { float f = this.getBrightness(); - BlockPos blockpos = this.getRidingEntity() instanceof BoatEntity ? (new BlockPos(this.getPosX(), (double) Math.round(this.getPosY()), this.getPosZ())).up() : new BlockPos(this.getPosX(), (double) Math.round(this.getPosY()), this.getPosZ()); - if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(blockpos)) { - this.setFire(8); + BlockPos blockpos = this.getVehicle() instanceof Boat ? (new BlockPos(this.getX(), (double) Math.round(this.getY()), this.getZ())).above() : new BlockPos(this.getX(), (double) Math.round(this.getY()), this.getZ()); + if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.level.canSeeSky(blockpos)) { + this.setSecondsOnFire(8); } } - super.livingTick(); + super.aiStep(); } @Override public SoundEvent getDeathSound() { - return SoundEvents.ENTITY_ZOMBIE_DEATH; + return SoundEvents.ZOMBIE_DEATH; } @Override public SoundEvent getAmbientSound() { - return SoundEvents.ENTITY_ZOMBIE_AMBIENT; + return SoundEvents.ZOMBIE_AMBIENT; } @Override public SoundEvent getHurtSound(DamageSource source) { - return SoundEvents.ENTITY_ZOMBIE_HURT; + return SoundEvents.ZOMBIE_HURT; } } diff --git a/src/main/java/elucent/eidolon/entity/ZombieBruteModel.java b/src/main/java/elucent/eidolon/entity/ZombieBruteModel.java index d927741..2f8bc80 100644 --- a/src/main/java/elucent/eidolon/entity/ZombieBruteModel.java +++ b/src/main/java/elucent/eidolon/entity/ZombieBruteModel.java @@ -1,76 +1,61 @@ -package elucent.eidolon.entity; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.renderer.entity.model.EntityModel; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.util.math.MathHelper; - -public class ZombieBruteModel extends EntityModel { - private final ModelRenderer chest; - private final ModelRenderer right_leg; - private final ModelRenderer head; - private final ModelRenderer left_arm; - private final ModelRenderer right_arm; - private final ModelRenderer left_leg; - - public ZombieBruteModel() { - textureWidth = 96; - textureHeight = 96; - - chest = new ModelRenderer(this); - chest.setRotationPoint(0.0F, 9.0F, 0.0F); - chest.setTextureOffset(20, 16).addBox(-6.0F, -15.0F, -3.0F, 12.0F, 15.0F, 6.0F, 0.0F, false); - - right_leg = new ModelRenderer(this); - right_leg.setRotationPoint(-3.0F, 0.0F, 0.0F); - chest.addChild(right_leg); - right_leg.setTextureOffset(0, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 15.0F, 5.0F, 0.0F, false); - - head = new ModelRenderer(this); - head.setRotationPoint(0.0F, -15.0F, 0.0F); - chest.addChild(head); - head.setTextureOffset(0, 37).addBox(-5.0F, -10.0F, -5.0F, 10.0F, 10.0F, 10.0F, 0.0F, false); - - left_arm = new ModelRenderer(this); - left_arm.setRotationPoint(9.0F, -12.0F, 0.0F); - chest.addChild(left_arm); - left_arm.setTextureOffset(56, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 13.0F, 5.0F, 0.0F, true); - left_arm.setTextureOffset(48, 4).addBox(-3.0F, -3.0F, -3.0F, 6.0F, 6.0F, 6.0F, 0.0F, false); - - right_arm = new ModelRenderer(this); - right_arm.setRotationPoint(-9.0F, -12.0F, 0.0F); - chest.addChild(right_arm); - right_arm.setTextureOffset(48, 4).addBox(-3.0F, -3.0F, -3.0F, 6.0F, 6.0F, 6.0F, 0.0F, false); - right_arm.setTextureOffset(56, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 13.0F, 5.0F, 0.0F, false); - - left_leg = new ModelRenderer(this); - left_leg.setRotationPoint(3.0F, 0.0F, 0.0F); - chest.addChild(left_leg); - left_leg.setTextureOffset(0, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 15.0F, 5.0F, 0.0F, true); - } - - @Override - public void setRotationAngles(ZombieBruteEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - right_leg.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount; - left_leg.rotateAngleX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; - right_arm.rotateAngleX = (float)Math.toRadians(-80); - left_arm.rotateAngleX = (float)Math.toRadians(-80); - right_arm.rotateAngleZ = (float)Math.toRadians(5); - left_arm.rotateAngleZ = (float)Math.toRadians(-5); - - head.rotateAngleX = (float)Math.toRadians(headPitch); - head.rotateAngleY = (float)Math.toRadians(netHeadYaw); - } - - @Override - public void render(MatrixStack matrixStack, IVertexBuilder buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ - chest.render(matrixStack, buffer, packedLight, packedOverlay); - } - - public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) { - modelRenderer.rotateAngleX = x; - modelRenderer.rotateAngleY = y; - modelRenderer.rotateAngleZ = z; - } +package elucent.eidolon.entity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.util.Mth; + +public class ZombieBruteModel extends EntityModel { + private final ModelPart chest; + + public ZombieBruteModel(ModelPart root) { + this.chest = root.getChild("chest"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition chest = partdefinition.addOrReplaceChild("chest", CubeListBuilder.create().texOffs(20, 16).addBox(-6.0F, -15.0F, -3.0F, 12.0F, 15.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 9.0F, 0.0F)); + + PartDefinition right_leg = chest.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 15.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offset(-3.0F, 0.0F, 0.0F)); + + PartDefinition head = chest.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 37).addBox(-5.0F, -10.0F, -5.0F, 10.0F, 10.0F, 10.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -15.0F, 0.0F)); + + PartDefinition left_arm = chest.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(56, 16).mirror().addBox(-2.5F, 0.0F, -2.5F, 5.0F, 13.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(48, 4).addBox(-3.0F, -3.0F, -3.0F, 6.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(9.0F, -12.0F, 0.0F)); + + PartDefinition right_arm = chest.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(48, 4).addBox(-3.0F, -3.0F, -3.0F, 6.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)) + .texOffs(56, 16).addBox(-2.5F, 0.0F, -2.5F, 5.0F, 13.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offset(-9.0F, -12.0F, 0.0F)); + + PartDefinition left_leg = chest.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(0, 16).mirror().addBox(-2.5F, 0.0F, -2.5F, 5.0F, 15.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offset(3.0F, 0.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 96, 64); + } + + @Override + public void setupAnim(ZombieBruteEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + chest.getChild("right_leg").xRot = Mth.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount; + chest.getChild("left_leg").xRot = Mth.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + chest.getChild("right_arm").xRot = (float)Math.toRadians(-80); + chest.getChild("left_arm").xRot = (float)Math.toRadians(-80); + chest.getChild("right_arm").zRot = (float)Math.toRadians(5); + chest.getChild("left_arm").zRot = (float)Math.toRadians(-5); + + chest.getChild("head").xRot = (float)Math.toRadians(headPitch); + chest.getChild("head").yRot = (float)Math.toRadians(netHeadYaw); + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + chest.render(poseStack, buffer, packedLight, packedOverlay); + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java b/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java index 1f22b32..48a55a3 100644 --- a/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java +++ b/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java @@ -1,20 +1,19 @@ package elucent.eidolon.entity; import elucent.eidolon.Eidolon; -import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.client.renderer.entity.LivingRenderer; +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.model.EntityModel; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; +import net.minecraft.resources.ResourceLocation; public class ZombieBruteRenderer extends MobRenderer { - public ZombieBruteRenderer(EntityRendererManager rendererManager, ZombieBruteModel entityModelIn, float shadowSizeIn) { - super(rendererManager, entityModelIn, shadowSizeIn); + public ZombieBruteRenderer(Context erm) { + super(erm, new ZombieBruteModel(erm.bakeLayer(Registry.ZOMBIE_BRUTE_LAYER)), 0.6f); } @Override - public ResourceLocation getEntityTexture(ZombieBruteEntity entity) { + public ResourceLocation getTextureLocation(ZombieBruteEntity entity) { return new ResourceLocation(Eidolon.MODID, "textures/entity/zombie_brute.png"); } } diff --git a/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java b/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java index 3c96345..fc7f70f 100644 --- a/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java +++ b/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java @@ -1,24 +1,25 @@ package elucent.eidolon.entity.ai; -import net.minecraft.entity.CreatureEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; -import net.minecraft.entity.ai.brain.memory.MemoryModuleType; -import net.minecraft.entity.ai.brain.task.Task; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Hand; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; - -import java.util.*; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; import java.util.function.Function; import java.util.function.Predicate; -public class GenericBarterGoal extends Goal { +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.Entity.RemovalReason; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionHand; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; + +import net.minecraft.world.entity.ai.goal.Goal.Flag; + +public class GenericBarterGoal extends Goal { static Random rand = new Random(); Predicate valid; Function result; @@ -30,11 +31,11 @@ public GenericBarterGoal(E entity, Predicate valid, Function 0) return; if (progress > 0 && !backupHack.isEmpty()) - entity.setHeldItem(Hand.MAIN_HAND, backupHack); + entity.setItemInHand(InteractionHand.MAIN_HAND, backupHack); - entity.setAttackTarget(null); + entity.setTarget(null); if (progress > 0) { progress --; - entity.getNavigator().clearPath(); + entity.getNavigation().stop(); if (progress == 0) { - if (!entity.world.isRemote) { - entity.world.addEntity(new ItemEntity(entity.world, entity.getPosX(), entity.getPosY() + 0.1, entity.getPosZ(), result.apply(entity.getHeldItemMainhand().copy()))); + if (!entity.level.isClientSide) { + entity.level.addFreshEntity(new ItemEntity(entity.level, entity.getX(), entity.getY() + 0.1, entity.getZ(), result.apply(entity.getMainHandItem().copy()))); } - entity.setHeldItem(Hand.MAIN_HAND, ItemStack.EMPTY); + entity.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); cooldown = 600; } } else { - List items = entity.world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(entity.getPosition().add(-8, -8, -8), entity.getPosition().add(8, 8, 8)), (item) -> valid.test(item.getItem())); - ItemEntity nearest = items.stream().min(Comparator.comparingDouble(a -> a.getDistanceSq(entity))).get(); - if (nearest.getDistanceSq(entity) < 2.25) { + List items = entity.level.getEntitiesOfClass(ItemEntity.class, new AABB(entity.blockPosition().offset(-8, -8, -8), entity.blockPosition().offset(8, 8, 8)), (item) -> valid.test(item.getItem())); + ItemEntity nearest = items.stream().min(Comparator.comparingDouble(a -> a.distanceToSqr(entity))).get(); + if (nearest.distanceToSqr(entity) < 2.25) { progress = 100; - entity.setHeldItem(Hand.MAIN_HAND, nearest.getItem()); - nearest.remove(); - entity.world.playSound(null, entity.getPosition(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.HOSTILE, 0.2F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F); + entity.setItemInHand(InteractionHand.MAIN_HAND, nearest.getItem()); + nearest.remove(RemovalReason.DISCARDED); + entity.level.playSound(null, entity.blockPosition(), SoundEvents.ITEM_PICKUP, SoundSource.HOSTILE, 0.2F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F); } - entity.getNavigator().tryMoveToXYZ(nearest.getPosX(), nearest.getPosY(), nearest.getPosZ(), 1.0f); + entity.getNavigation().moveTo(nearest.getX(), nearest.getY(), nearest.getZ(), 1.0f); } - if (!entity.getHeldItemMainhand().isEmpty()) - backupHack = entity.getHeldItemMainhand(); + if (!entity.getMainHandItem().isEmpty()) + backupHack = entity.getMainHandItem(); } @Override - public boolean shouldExecute() { + public boolean canUse() { if (-- cooldown > 0) return false; - if (progress > 0 || entity.ticksExisted < lastTick + 20) return false; - lastTick = entity.ticksExisted; - List items = entity.world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(entity.getPosition().add(-8, -8, -8), entity.getPosition().add(8, 8, 8)), (item) -> valid.test(item.getItem())); + if (progress > 0 || entity.tickCount < lastTick + 20) return false; + lastTick = entity.tickCount; + List items = entity.level.getEntitiesOfClass(ItemEntity.class, new AABB(entity.blockPosition().offset(-8, -8, -8), entity.blockPosition().offset(8, 8, 8)), (item) -> valid.test(item.getItem())); return items.size() > 0; } @Override - public boolean shouldContinueExecuting() { + public boolean canContinueToUse() { if (progress > 0) return true; else { // walking towards item - List items = entity.world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(entity.getPosition().add(-8, -8, -8), entity.getPosition().add(8, 8, 8)), (item) -> valid.test(item.getItem())); + List items = entity.level.getEntitiesOfClass(ItemEntity.class, new AABB(entity.blockPosition().offset(-8, -8, -8), entity.blockPosition().offset(8, 8, 8)), (item) -> valid.test(item.getItem())); return items.size() > 0; } } diff --git a/src/main/java/elucent/eidolon/entity/ai/GoToPositionGoal.java b/src/main/java/elucent/eidolon/entity/ai/GoToPositionGoal.java index 2b9a910..1ba40c6 100644 --- a/src/main/java/elucent/eidolon/entity/ai/GoToPositionGoal.java +++ b/src/main/java/elucent/eidolon/entity/ai/GoToPositionGoal.java @@ -1,21 +1,18 @@ package elucent.eidolon.entity.ai; -import net.minecraft.entity.CreatureAttribute; -import net.minecraft.entity.CreatureEntity; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.ai.goal.MoveToBlockGoal; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorldReader; - import java.util.Random; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.core.BlockPos; + public class GoToPositionGoal extends Goal { Random random = new Random(); BlockPos dest; - CreatureEntity creature; + PathfinderMob creature; double speed; boolean running; - public GoToPositionGoal(CreatureEntity creature, BlockPos pos, double speedIn) { + public GoToPositionGoal(PathfinderMob creature, BlockPos pos, double speedIn) { this.creature = creature; this.dest = pos; this.speed = speedIn; @@ -25,13 +22,13 @@ public GoToPositionGoal(CreatureEntity creature, BlockPos pos, double speedIn) { @Override public void tick() { if (running) { - creature.getNavigator().tryMoveToXYZ(dest.getX(), dest.getY(), dest.getZ(), speed); - if (creature.getDistanceSq(dest.getX(), dest.getY(), dest.getZ()) < 8 * 8) running = false; + creature.getNavigation().moveTo(dest.getX(), dest.getY(), dest.getZ(), speed); + if (creature.distanceToSqr(dest.getX(), dest.getY(), dest.getZ()) < 8 * 8) running = false; } } @Override - public boolean shouldExecute() { + public boolean canUse() { return running; } } diff --git a/src/main/java/elucent/eidolon/entity/ai/PriestBarterGoal.java b/src/main/java/elucent/eidolon/entity/ai/PriestBarterGoal.java index ec32342..ed53358 100644 --- a/src/main/java/elucent/eidolon/entity/ai/PriestBarterGoal.java +++ b/src/main/java/elucent/eidolon/entity/ai/PriestBarterGoal.java @@ -1,25 +1,21 @@ package elucent.eidolon.entity.ai; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.merchant.villager.VillagerEntity; -import net.minecraft.entity.merchant.villager.VillagerProfession; -import net.minecraft.entity.monster.WitchEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.AxisAlignedBB; - -import java.util.List; import java.util.function.Function; import java.util.function.Predicate; -public class PriestBarterGoal extends GenericBarterGoal { - public PriestBarterGoal(VillagerEntity entity, Predicate valid, Function result) { +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.item.ItemStack; + +public class PriestBarterGoal extends GenericBarterGoal { + public PriestBarterGoal(Villager entity, Predicate valid, Function result) { super(entity, valid, result); } @Override - public boolean shouldExecute() { + public boolean canUse() { if (entity.getVillagerData().getProfession() != VillagerProfession.CLERIC) return false; - return super.shouldExecute(); + return super.canUse(); } @Override diff --git a/src/main/java/elucent/eidolon/entity/ai/WitchBarterGoal.java b/src/main/java/elucent/eidolon/entity/ai/WitchBarterGoal.java index 8ff9bab..adb733a 100644 --- a/src/main/java/elucent/eidolon/entity/ai/WitchBarterGoal.java +++ b/src/main/java/elucent/eidolon/entity/ai/WitchBarterGoal.java @@ -1,24 +1,13 @@ package elucent.eidolon.entity.ai; -import net.minecraft.entity.CreatureEntity; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.monster.WitchEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Hand; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; - -import java.util.Comparator; -import java.util.EnumSet; -import java.util.List; -import java.util.Random; import java.util.function.Function; import java.util.function.Predicate; -public class WitchBarterGoal extends GenericBarterGoal { - public WitchBarterGoal(WitchEntity entity, Predicate valid, Function result) { +import net.minecraft.world.entity.monster.Witch; +import net.minecraft.world.item.ItemStack; + +public class WitchBarterGoal extends GenericBarterGoal { + public WitchBarterGoal(Witch entity, Predicate valid, Function result) { super(entity, valid, result); } diff --git a/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java b/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java index 3083d9c..8d34a98 100644 --- a/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java +++ b/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java @@ -1,6 +1,6 @@ package elucent.eidolon.event; -import net.minecraft.entity.Entity; +import net.minecraft.world.entity.Entity; public class SpeedFactorEvent extends net.minecraftforge.eventbus.api.Event { Entity entity; diff --git a/src/main/java/elucent/eidolon/gui/SoulEnchanterContainer.java b/src/main/java/elucent/eidolon/gui/SoulEnchanterContainer.java index 1efdab5..759be86 100644 --- a/src/main/java/elucent/eidolon/gui/SoulEnchanterContainer.java +++ b/src/main/java/elucent/eidolon/gui/SoulEnchanterContainer.java @@ -1,68 +1,75 @@ package elucent.eidolon.gui; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + import com.google.common.collect.Lists; + import elucent.eidolon.Registry; import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.block.Blocks; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentData; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.container.Container; -import net.minecraft.inventory.container.ContainerType; -import net.minecraft.inventory.container.EnchantmentContainer; -import net.minecraft.inventory.container.Slot; -import net.minecraft.item.EnchantedBookItem; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.EnchantedBookItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.stats.Stats; -import net.minecraft.util.*; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.World; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.DataSlot; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.registries.ForgeRegistries; -import java.util.*; - -public class SoulEnchanterContainer extends Container { - private final IInventory tableInventory = new Inventory(2) { - public void markDirty() { - super.markDirty(); - SoulEnchanterContainer.this.onCraftMatrixChanged(this); +public class SoulEnchanterContainer extends AbstractContainerMenu { + private final Container tableInventory = new SimpleContainer(2) { + public void setChanged() { + super.setChanged(); + SoulEnchanterContainer.this.slotsChanged(this); } }; - private final IWorldPosCallable worldPosCallable; + private final ContainerLevelAccess worldPosCallable; private final Random rand = new Random(); - private final IntReferenceHolder xpSeed = IntReferenceHolder.single(); + private final DataSlot xpSeed = DataSlot.standalone(); public final int[] enchantClue = new int[]{-1, -1, -1}; public final int[] worldClue = new int[]{-1, -1, -1}; - public SoulEnchanterContainer(int id, PlayerInventory playerInventory) { - this(id, playerInventory, IWorldPosCallable.DUMMY); + public SoulEnchanterContainer(int id, Inventory playerInventory) { + this(id, playerInventory, ContainerLevelAccess.NULL); } - public SoulEnchanterContainer(int id, PlayerInventory playerInventory, IWorldPosCallable worldPosCallable) { + public SoulEnchanterContainer(int id, Inventory playerInventory, ContainerLevelAccess worldPosCallable) { super(Registry.SOUL_ENCHANTER_CONTAINER.get(), id); this.worldPosCallable = worldPosCallable; this.addSlot(new Slot(this.tableInventory, 0, 15, 47) { - public boolean isItemValid(ItemStack stack) { + public boolean mayPlace(ItemStack stack) { return true; } - public int getSlotStackLimit() { + public int getMaxStackSize() { return 1; } }); this.addSlot(new Slot(this.tableInventory, 1, 35, 47) { - public boolean isItemValid(ItemStack stack) { + public boolean mayPlace(ItemStack stack) { return stack.getItem() == Registry.SOUL_SHARD.get(); } }); @@ -77,40 +84,40 @@ public boolean isItemValid(ItemStack stack) { this.addSlot(new Slot(playerInventory, k, 8 + k * 18, 142)); } - this.trackInt(this.xpSeed).set(playerInventory.player.getXPSeed()); - this.trackInt(IntReferenceHolder.create(this.enchantClue, 0)); - this.trackInt(IntReferenceHolder.create(this.enchantClue, 1)); - this.trackInt(IntReferenceHolder.create(this.enchantClue, 2)); - this.trackInt(IntReferenceHolder.create(this.worldClue, 0)); - this.trackInt(IntReferenceHolder.create(this.worldClue, 1)); - this.trackInt(IntReferenceHolder.create(this.worldClue, 2)); + this.addDataSlot(this.xpSeed).set(playerInventory.player.getEnchantmentSeed()); + this.addDataSlot(DataSlot.shared(this.enchantClue, 0)); + this.addDataSlot(DataSlot.shared(this.enchantClue, 1)); + this.addDataSlot(DataSlot.shared(this.enchantClue, 2)); + this.addDataSlot(DataSlot.shared(this.worldClue, 0)); + this.addDataSlot(DataSlot.shared(this.worldClue, 1)); + this.addDataSlot(DataSlot.shared(this.worldClue, 2)); } - private float getPower(World world, BlockPos pos) { + private float getPower(Level world, BlockPos pos) { return world.getBlockState(pos).getEnchantPowerBonus(world, pos); } /** * Callback for when the crafting matrix is changed. */ - public void onCraftMatrixChanged(IInventory inventoryIn) { + public void slotsChanged(Container inventoryIn) { if (inventoryIn == this.tableInventory) { - ItemStack itemstack = inventoryIn.getStackInSlot(0); + ItemStack itemstack = inventoryIn.getItem(0); if (!itemstack.isEmpty() && (itemstack.isEnchantable() || itemstack.isEnchanted() || itemstack.getItem() == Items.ENCHANTED_BOOK)) { - this.worldPosCallable.consume((world, pos) -> { + this.worldPosCallable.execute((world, pos) -> { int power = 0; for(int k = -1; k <= 1; ++k) { for(int l = -1; l <= 1; ++l) { - if ((k != 0 || l != 0) && world.isAirBlock(pos.add(l, 0, k)) && world.isAirBlock(pos.add(l, 1, k))) { - power += getPower(world, pos.add(l * 2, 0, k * 2)); - power += getPower(world, pos.add(l * 2, 1, k * 2)); + if ((k != 0 || l != 0) && world.isEmptyBlock(pos.offset(l, 0, k)) && world.isEmptyBlock(pos.offset(l, 1, k))) { + power += getPower(world, pos.offset(l * 2, 0, k * 2)); + power += getPower(world, pos.offset(l * 2, 1, k * 2)); if (l != 0 && k != 0) { - power += getPower(world, pos.add(l * 2, 0, k)); - power += getPower(world, pos.add(l * 2, 1, k)); - power += getPower(world, pos.add(l, 0, k * 2)); - power += getPower(world, pos.add(l, 1, k * 2)); + power += getPower(world, pos.offset(l * 2, 0, k)); + power += getPower(world, pos.offset(l * 2, 1, k)); + power += getPower(world, pos.offset(l, 0, k * 2)); + power += getPower(world, pos.offset(l, 1, k * 2)); } } } @@ -124,15 +131,15 @@ public void onCraftMatrixChanged(IInventory inventoryIn) { } for(int j1 = 0; j1 < 3; ++j1) { - List list = getEnchantmentList(itemstack, j1); + List list = getEnchantmentList(itemstack, j1); if (list != null && !list.isEmpty()) { - EnchantmentData enchantmentdata = list.get(rand.nextInt(list.size())); - enchantClue[j1] = net.minecraft.util.registry.Registry.ENCHANTMENT.getId(enchantmentdata.enchantment); - worldClue[j1] = enchantmentdata.enchantmentLevel; + EnchantmentInstance enchantmentdata = list.get(rand.nextInt(list.size())); + enchantClue[j1] = net.minecraft.core.Registry.ENCHANTMENT.getId(enchantmentdata.enchantment); + worldClue[j1] = enchantmentdata.level; } } - this.detectAndSendChanges(); + this.broadcastChanges(); }); } else { for(int i = 0; i < 3; ++i) { @@ -147,65 +154,65 @@ public void onCraftMatrixChanged(IInventory inventoryIn) { /** * Handles the given Button-click on the server, currently only used by enchanting. Name is for legacy. */ - public boolean enchantItem(PlayerEntity playerIn, int id) { - ItemStack itemstack = this.tableInventory.getStackInSlot(0); - ItemStack itemstack1 = this.tableInventory.getStackInSlot(1); + public boolean clickMenuButton(Player playerIn, int id) { + ItemStack itemstack = this.tableInventory.getItem(0); + ItemStack itemstack1 = this.tableInventory.getItem(1); int i = id + 1; - if ((itemstack1.isEmpty() || itemstack1.getCount() < 1) && !playerIn.abilities.isCreativeMode) { + if ((itemstack1.isEmpty() || itemstack1.getCount() < 1) && !playerIn.getAbilities().instabuild) { return false; - } else if (itemstack.isEmpty() || playerIn.experienceLevel < this.worldClue[id] && !playerIn.abilities.isCreativeMode) { + } else if (itemstack.isEmpty() || playerIn.experienceLevel < this.worldClue[id] && !playerIn.getAbilities().instabuild) { return false; } else { - this.worldPosCallable.consume((p_217003_6_, p_217003_7_) -> { + this.worldPosCallable.execute((p_217003_6_, p_217003_7_) -> { ItemStack itemstack2 = itemstack; - List list = this.getEnchantmentList(itemstack, id); + List list = this.getEnchantmentList(itemstack, id); if (!list.isEmpty()) { - playerIn.onEnchant(itemstack, worldClue[id]); + playerIn.onEnchantmentPerformed(itemstack, worldClue[id]); boolean flag = itemstack.getItem() == Items.BOOK; if (flag) { itemstack2 = new ItemStack(Items.ENCHANTED_BOOK); - CompoundNBT compoundnbt = itemstack.getTag(); + CompoundTag compoundnbt = itemstack.getTag(); if (compoundnbt != null) { itemstack2.setTag(compoundnbt.copy()); } - this.tableInventory.setInventorySlotContents(0, itemstack2); + this.tableInventory.setItem(0, itemstack2); } Map enchants = EnchantmentHelper.getEnchantments(itemstack2); if (enchants.size() > 0) { for (int j = 0; j < list.size(); ++ j) { - EnchantmentData data = list.get(j); - if (enchants.containsKey(data.enchantment)) enchants.replace(data.enchantment, data.enchantmentLevel); - else enchants.put(data.enchantment, data.enchantmentLevel); + EnchantmentInstance data = list.get(j); + if (enchants.containsKey(data.enchantment)) enchants.replace(data.enchantment, data.level); + else enchants.put(data.enchantment, data.level); } EnchantmentHelper.setEnchantments(enchants, itemstack2); } else for(int j = 0; j < list.size(); ++j) { - EnchantmentData data = list.get(j); + EnchantmentInstance data = list.get(j); if (flag) { EnchantedBookItem.addEnchantment(itemstack2, data); } else { - itemstack2.addEnchantment(data.enchantment, data.enchantmentLevel); + itemstack2.enchant(data.enchantment, data.level); } } - if (!playerIn.abilities.isCreativeMode) { + if (!playerIn.getAbilities().instabuild) { itemstack1.shrink(1); if (itemstack1.isEmpty()) { - this.tableInventory.setInventorySlotContents(1, ItemStack.EMPTY); + this.tableInventory.setItem(1, ItemStack.EMPTY); } } - playerIn.addStat(Stats.ENCHANT_ITEM); - if (playerIn instanceof ServerPlayerEntity) { - CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayerEntity)playerIn, itemstack2, i); + playerIn.awardStat(Stats.ENCHANT_ITEM); + if (playerIn instanceof ServerPlayer) { + CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayer)playerIn, itemstack2, i); } - this.tableInventory.markDirty(); - this.xpSeed.set(playerIn.getXPSeed()); - this.onCraftMatrixChanged(this.tableInventory); - p_217003_6_.playSound((PlayerEntity)null, p_217003_7_, SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE, SoundCategory.BLOCKS, 1.0F, p_217003_6_.rand.nextFloat() * 0.1F + 0.7F); + this.tableInventory.setChanged(); + this.xpSeed.set(playerIn.getEnchantmentSeed()); + this.slotsChanged(this.tableInventory); + p_217003_6_.playSound((Player)null, p_217003_7_, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, p_217003_6_.random.nextFloat() * 0.1F + 0.7F); } }); return true; @@ -216,14 +223,14 @@ public static int getEnchantmentLevel(Enchantment enchID, ItemStack stack) { if (stack.isEmpty()) { return 0; } else { - ResourceLocation resourcelocation = net.minecraft.util.registry.Registry.ENCHANTMENT.getKey(enchID); - ListNBT listnbt = stack.getItem() == Items.ENCHANTED_BOOK ? EnchantedBookItem.getEnchantments(stack) : stack.getEnchantmentTagList(); + ResourceLocation resourcelocation = net.minecraft.core.Registry.ENCHANTMENT.getKey(enchID); + ListTag listnbt = stack.getItem() == Items.ENCHANTED_BOOK ? EnchantedBookItem.getEnchantments(stack) : stack.getEnchantmentTags(); for(int i = 0; i < listnbt.size(); ++i) { - CompoundNBT compoundnbt = listnbt.getCompound(i); - ResourceLocation resourcelocation1 = ResourceLocation.tryCreate(compoundnbt.getString("id")); + CompoundTag compoundnbt = listnbt.getCompound(i); + ResourceLocation resourcelocation1 = ResourceLocation.tryParse(compoundnbt.getString("id")); if (resourcelocation1 != null && resourcelocation1.equals(resourcelocation)) { - return MathHelper.clamp(compoundnbt.getInt("lvl"), 0, 255); + return Mth.clamp(compoundnbt.getInt("lvl"), 0, 255); } } @@ -231,7 +238,7 @@ public static int getEnchantmentLevel(Enchantment enchID, ItemStack stack) { } } - private List getEnchantmentList(ItemStack stack, int enchantSlot) { + private List getEnchantmentList(ItemStack stack, int enchantSlot) { this.rand.setSeed((long)(this.xpSeed.get() + enchantSlot)); ItemStack test = stack.copy(); EnchantmentHelper.setEnchantments(new HashMap<>(), test); @@ -241,9 +248,12 @@ private List getEnchantmentList(ItemStack stack, int enchantSlo Map existing = EnchantmentHelper.getEnchantments(stack); List valid = Lists.newArrayList(ForgeRegistries.ENCHANTMENTS.getValues()); valid.removeIf((ench) -> { - boolean canApply = ench.canApplyAtEnchantingTable(finalTest) || + boolean canApply = ench.canEnchant(finalTest) || finalTest.getItem() == Items.BOOK && ench.isAllowedOnBooks(); - return !canApply || ench.isTreasureEnchantment() || existing.containsKey(ench) && existing.get(ench) >= ench.getMaxLevel(); + return !canApply + || ench.isTreasureOnly() + || existing.containsKey(ench) && existing.get(ench) >= ench.getMaxLevel() + || ench.isCurse(); }); for (Map.Entry e : existing.entrySet()) { @@ -257,21 +267,21 @@ private List getEnchantmentList(ItemStack stack, int enchantSlo } } - List enchants = new ArrayList<>(); + List enchants = new ArrayList<>(); if (valid.isEmpty()) return enchants; // System.out.println("" + enchantSlot + ": " + valid.stream().reduce("", (a, b) -> "" + a + ", " + b, (a, b) -> "" + a + ", " + b)); for (int i = 0; i < enchantSlot; i ++) rand.nextInt(valid.size()); Enchantment enchant = valid.get(this.rand.nextInt(valid.size())); int level = getEnchantmentLevel(enchant, stack); - if (level > 0) enchants.add(new EnchantmentData(enchant, level + 1)); - else enchants.add(new EnchantmentData(enchant, 1)); + if (level > 0) enchants.add(new EnchantmentInstance(enchant, level + 1)); + else enchants.add(new EnchantmentInstance(enchant, 1)); return enchants; } @OnlyIn(Dist.CLIENT) public int getSoulShardAmount() { - ItemStack itemstack = this.tableInventory.getStackInSlot(1); + ItemStack itemstack = this.tableInventory.getItem(1); return itemstack.isEmpty() ? 0 : itemstack.getCount(); } @@ -283,57 +293,57 @@ public int getXPSeed() { /** * Called when the container is closed. */ - public void onContainerClosed(PlayerEntity playerIn) { - super.onContainerClosed(playerIn); - this.worldPosCallable.consume((world, pos) -> { - this.clearContainer(playerIn, playerIn.world, this.tableInventory); + public void removed(Player playerIn) { + super.removed(playerIn); + this.worldPosCallable.execute((world, pos) -> { + this.clearContainer(playerIn, this.tableInventory); }); } /** * Determines whether supplied player can use this container */ - public boolean canInteractWith(PlayerEntity playerIn) { - return isWithinUsableDistance(this.worldPosCallable, playerIn, Registry.SOUL_ENCHANTER.get()); + public boolean stillValid(Player playerIn) { + return stillValid(this.worldPosCallable, playerIn, Registry.SOUL_ENCHANTER.get()); } /** * Handle when the stack in slot {@code index} is shift-clicked. Normally this moves the stack between the player * inventory and the other inventory(s). */ - public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + public ItemStack quickMoveStack(Player playerIn, int index) { ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.inventorySlots.get(index); - if (slot != null && slot.getHasStack()) { - ItemStack itemstack1 = slot.getStack(); + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); itemstack = itemstack1.copy(); if (index == 0) { - if (!this.mergeItemStack(itemstack1, 2, 38, true)) { + if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { return ItemStack.EMPTY; } } else if (index == 1) { - if (!this.mergeItemStack(itemstack1, 2, 38, true)) { + if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { return ItemStack.EMPTY; } } else if (itemstack1.getItem() == Registry.SOUL_SHARD.get()) { - if (!this.mergeItemStack(itemstack1, 1, 2, true)) { + if (!this.moveItemStackTo(itemstack1, 1, 2, true)) { return ItemStack.EMPTY; } } else { - if (this.inventorySlots.get(0).getHasStack() || !this.inventorySlots.get(0).isItemValid(itemstack1)) { + if (this.slots.get(0).hasItem() || !this.slots.get(0).mayPlace(itemstack1)) { return ItemStack.EMPTY; } ItemStack itemstack2 = itemstack1.copy(); itemstack2.setCount(1); itemstack1.shrink(1); - this.inventorySlots.get(0).putStack(itemstack2); + this.slots.get(0).set(itemstack2); } if (itemstack1.isEmpty()) { - slot.putStack(ItemStack.EMPTY); + slot.set(ItemStack.EMPTY); } else { - slot.onSlotChanged(); + slot.setChanged(); } if (itemstack1.getCount() == itemstack.getCount()) { diff --git a/src/main/java/elucent/eidolon/gui/SoulEnchanterScreen.java b/src/main/java/elucent/eidolon/gui/SoulEnchanterScreen.java index 8a6becf..62f3c44 100644 --- a/src/main/java/elucent/eidolon/gui/SoulEnchanterScreen.java +++ b/src/main/java/elucent/eidolon/gui/SoulEnchanterScreen.java @@ -1,35 +1,42 @@ package elucent.eidolon.gui; +import java.util.List; +import java.util.Random; + import com.google.common.collect.Lists; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.Eidolon; -import net.minecraft.client.gui.screen.inventory.ContainerScreen; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.entity.model.BookModel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.vertex.Tesselator; +import net.minecraft.client.model.BookModel; +import net.minecraft.client.model.geom.ModelLayers; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.container.EnchantmentContainer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnchantmentNameParts; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.util.text.*; - -import java.util.List; -import java.util.Random; - -public class SoulEnchanterScreen extends ContainerScreen { +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.client.gui.screens.inventory.EnchantmentNames; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.TranslatableComponent; + +public class SoulEnchanterScreen extends AbstractContainerScreen { private static final ResourceLocation ENCHANTMENT_TABLE_GUI_TEXTURE = new ResourceLocation(Eidolon.MODID,"textures/gui/soul_enchanter.png"); private static final ResourceLocation ENCHANTMENT_TABLE_BOOK_TEXTURE = new ResourceLocation(Eidolon.MODID,"textures/entity/enchanter_book.png"); - private static final BookModel MODEL_BOOK = new BookModel(); + private static BookModel MODEL_BOOK = null; private final Random random = new Random(); public int ticks; public float flip; @@ -40,24 +47,25 @@ public class SoulEnchanterScreen extends ContainerScreen public float oOpen; private ItemStack last = ItemStack.EMPTY; - public SoulEnchanterScreen(SoulEnchanterContainer container, PlayerInventory playerInventory, ITextComponent textComponent) { + public SoulEnchanterScreen(SoulEnchanterContainer container, Inventory playerInventory, Component textComponent) { super(container, playerInventory, textComponent); + if (MODEL_BOOK == null) MODEL_BOOK = new BookModel(Minecraft.getInstance().getEntityModels().bakeLayer(ModelLayers.BOOK)); } - public void tick() { - super.tick(); + public void containerTick() { + super.containerTick(); this.tickBook(); } public boolean mouseClicked(double mouseX, double mouseY, int button) { - int i = (this.width - this.xSize) / 2; - int j = (this.height - this.ySize) / 2; + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; for(int k = 0; k < 3; ++k) { double d0 = mouseX - (double)(i + 60); double d1 = mouseY - (double)(j + 14 + 19 * k); - if (d0 >= 0.0D && d1 >= 0.0D && d0 < 108.0D && d1 < 19.0D && this.container.enchantItem(this.minecraft.player, k)) { - this.minecraft.playerController.sendEnchantPacket((this.container).windowId, k); + if (d0 >= 0.0D && d1 >= 0.0D && d0 < 108.0D && d1 < 19.0D && this.menu.clickMenuButton(this.minecraft.player, k)) { + this.minecraft.gameMode.handleInventoryButtonClick((this.menu).containerId, k); return true; } } @@ -65,88 +73,83 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return super.mouseClicked(mouseX, mouseY, button); } - protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) { - RenderHelper.setupGuiFlatDiffuseLighting(); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - this.minecraft.getTextureManager().bindTexture(ENCHANTMENT_TABLE_GUI_TEXTURE); - int i = (this.width - this.xSize) / 2; - int j = (this.height - this.ySize) / 2; - this.blit(matrixStack, i, j, 0, 0, this.xSize, this.ySize); - RenderSystem.matrixMode(5889); - RenderSystem.pushMatrix(); - RenderSystem.loadIdentity(); - int k = (int)this.minecraft.getMainWindow().getGuiScaleFactor(); - RenderSystem.viewport((this.width - 320) / 2 * k, (this.height - 240) / 2 * k, 320 * k, 240 * k); - RenderSystem.translatef(-0.34F, 0.23F, 0.0F); - RenderSystem.multMatrix(Matrix4f.perspective(90.0D, 1.3333334F, 9.0F, 80.0F)); - RenderSystem.matrixMode(5888); - matrixStack.push(); - MatrixStack.Entry matrixstack$entry = matrixStack.getLast(); - matrixstack$entry.getMatrix().setIdentity(); - matrixstack$entry.getNormal().setIdentity(); - matrixStack.translate(0.0D, (double)3.3F, 1984.0D); - float f = 5.0F; - matrixStack.scale(5.0F, 5.0F, 5.0F); - matrixStack.rotate(Vector3f.ZP.rotationDegrees(180.0F)); - matrixStack.rotate(Vector3f.XP.rotationDegrees(20.0F)); - float f1 = MathHelper.lerp(partialTicks, this.oOpen, this.open); - matrixStack.translate((double)((1.0F - f1) * 0.2F), (double)((1.0F - f1) * 0.1F), (double)((1.0F - f1) * 0.25F)); - float f2 = -(1.0F - f1) * 90.0F - 90.0F; - matrixStack.rotate(Vector3f.YP.rotationDegrees(f2)); - matrixStack.rotate(Vector3f.XP.rotationDegrees(180.0F)); - float f3 = MathHelper.lerp(partialTicks, this.oFlip, this.flip) + 0.25F; - float f4 = MathHelper.lerp(partialTicks, this.oFlip, this.flip) + 0.75F; - f3 = (f3 - (float)MathHelper.fastFloor((double)f3)) * 1.6F - 0.3F; - f4 = (f4 - (float)MathHelper.fastFloor((double)f4)) * 1.6F - 0.3F; - if (f3 < 0.0F) { - f3 = 0.0F; - } - - if (f4 < 0.0F) { - f4 = 0.0F; - } - - if (f3 > 1.0F) { - f3 = 1.0F; - } - - if (f4 > 1.0F) { - f4 = 1.0F; - } - - RenderSystem.enableRescaleNormal(); - MODEL_BOOK.setBookState(0.0F, f3, f4, f1); - IRenderTypeBuffer.Impl irendertypebuffer$impl = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer()); - IVertexBuilder ivertexbuilder = irendertypebuffer$impl.getBuffer(MODEL_BOOK.getRenderType(ENCHANTMENT_TABLE_BOOK_TEXTURE)); - MODEL_BOOK.render(matrixStack, ivertexbuilder, 15728880, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); - irendertypebuffer$impl.finish(); - matrixStack.pop(); - RenderSystem.matrixMode(5889); - RenderSystem.viewport(0, 0, this.minecraft.getMainWindow().getFramebufferWidth(), this.minecraft.getMainWindow().getFramebufferHeight()); - RenderSystem.popMatrix(); - RenderSystem.matrixMode(5888); - RenderHelper.setupGui3DDiffuseLighting(); - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - EnchantmentNameParts.getInstance().reseedRandomGenerator((long)this.container.getXPSeed()); - int l = this.container.getSoulShardAmount(); + protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) {Lighting.setupForFlatItems(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, ENCHANTMENT_TABLE_GUI_TEXTURE); + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + this.blit(matrixStack, i, j, 0, 0, this.imageWidth, this.imageHeight); + int k = (int)this.minecraft.getWindow().getGuiScale(); + RenderSystem.viewport((this.width - 320) / 2 * k, (this.height - 240) / 2 * k, 320 * k, 240 * k); + Matrix4f matrix4f = Matrix4f.createTranslateMatrix(-0.34F, 0.23F, 0.0F); + matrix4f.multiply(Matrix4f.perspective(90.0D, 1.3333334F, 9.0F, 80.0F)); + RenderSystem.backupProjectionMatrix(); + RenderSystem.setProjectionMatrix(matrix4f); + matrixStack.pushPose(); + PoseStack.Pose posestack$pose = matrixStack.last(); + posestack$pose.pose().setIdentity(); + posestack$pose.normal().setIdentity(); + matrixStack.translate(0.0D, (double)3.3F, 1984.0D); + float f = 5.0F; + matrixStack.scale(5.0F, 5.0F, 5.0F); + matrixStack.mulPose(Vector3f.ZP.rotationDegrees(180.0F)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(20.0F)); + float f1 = Mth.lerp(partialTicks, this.oOpen, this.open); + matrixStack.translate((double)((1.0F - f1) * 0.2F), (double)((1.0F - f1) * 0.1F), (double)((1.0F - f1) * 0.25F)); + float f2 = -(1.0F - f1) * 90.0F - 90.0F; + matrixStack.mulPose(Vector3f.YP.rotationDegrees(f2)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(180.0F)); + float f3 = Mth.lerp(partialTicks, this.oFlip, this.flip) + 0.25F; + float f4 = Mth.lerp(partialTicks, this.oFlip, this.flip) + 0.75F; + f3 = (f3 - (float)Mth.fastFloor((double)f3)) * 1.6F - 0.3F; + f4 = (f4 - (float)Mth.fastFloor((double)f4)) * 1.6F - 0.3F; + if (f3 < 0.0F) { + f3 = 0.0F; + } + + if (f4 < 0.0F) { + f4 = 0.0F; + } + + if (f3 > 1.0F) { + f3 = 1.0F; + } + + if (f4 > 1.0F) { + f4 = 1.0F; + } + + MODEL_BOOK.setupAnim(0.0F, f3, f4, f1); + MultiBufferSource.BufferSource multibuffersource$buffersource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + VertexConsumer vertexconsumer = multibuffersource$buffersource.getBuffer(MODEL_BOOK.renderType(ENCHANTMENT_TABLE_BOOK_TEXTURE)); + MODEL_BOOK.renderToBuffer(matrixStack, vertexconsumer, 15728880, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); + multibuffersource$buffersource.endBatch(); + matrixStack.popPose(); + RenderSystem.viewport(0, 0, this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight()); + RenderSystem.restoreProjectionMatrix(); + Lighting.setupFor3DItems(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + EnchantmentNames.getInstance().initSeed((long)this.menu.getXPSeed()); + int l = this.menu.getSoulShardAmount(); for(int i1 = 0; i1 < 3; ++i1) { int j1 = i + 60; int k1 = j1 + 20; this.setBlitOffset(0); - this.minecraft.getTextureManager().bindTexture(ENCHANTMENT_TABLE_GUI_TEXTURE); - int l1 = container.worldClue[i1]; - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, ENCHANTMENT_TABLE_GUI_TEXTURE); + int l1 = menu.worldClue[i1]; + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); int i2 = 86; - ITextProperties itextproperties = EnchantmentNameParts.getInstance().getGalacticEnchantmentName(this.font, i2); + FormattedText itextproperties = EnchantmentNames.getInstance().getRandomName(this.font, i2); int j2 = 6839882; if (l1 < 1) { this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 185, 108, 19); } else { - if (((l == 0 || this.minecraft.player.experienceLevel < l1) && !this.minecraft.player.abilities.isCreativeMode) || this.container.enchantClue[i1] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels + if (((l == 0 || this.minecraft.player.experienceLevel < l1) && !this.minecraft.player.getAbilities().instabuild) || this.menu.enchantClue[i1] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 185, 108, 19); - this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * (container.worldClue[i1] - 1), 239, 16, 16); - this.font.func_238418_a_(itextproperties, k1, j + 16 + 19 * i1, i2, (j2 & 16711422) >> 1); + this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * (menu.worldClue[i1] - 1), 239, 16, 16); + this.font.drawWordWrap(itextproperties, k1, j + 16 + 19 * i1, i2, (j2 & 16711422) >> 1); j2 = 4226832; } else { int k2 = x - (i + 60); @@ -158,52 +161,52 @@ protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float pa this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 166, 108, 19); } - this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * (container.worldClue[i1] - 1), 223, 16, 16); - this.font.func_238418_a_(itextproperties, k1, j + 16 + 19 * i1, i2, j2); + this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * (menu.worldClue[i1] - 1), 223, 16, 16); + this.font.drawWordWrap(itextproperties, k1, j + 16 + 19 * i1, i2, j2); j2 = 8453920; } } } } - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - partialTicks = this.minecraft.getRenderPartialTicks(); + public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { + partialTicks = this.minecraft.getFrameTime(); this.renderBackground(matrixStack); super.render(matrixStack, mouseX, mouseY, partialTicks); - this.renderHoveredTooltip(matrixStack, mouseX, mouseY); - boolean flag = this.minecraft.player.abilities.isCreativeMode; - int i = this.container.getSoulShardAmount(); + this.renderTooltip(matrixStack, mouseX, mouseY); + boolean flag = this.minecraft.player.getAbilities().instabuild; + int i = this.menu.getSoulShardAmount(); for(int j = 0; j < 3; ++j) { - Enchantment enchantment = Enchantment.getEnchantmentByID((this.container).enchantClue[j]); - int l = (this.container).worldClue[j]; + Enchantment enchantment = Enchantment.byId((this.menu).enchantClue[j]); + int l = (this.menu).worldClue[j]; int i1 = j + 1; - if (this.isPointInRegion(60, 14 + 19 * j, 108, 17, (double)mouseX, (double)mouseY) && l > 0) { - List list = Lists.newArrayList(); - list.add(enchantment == null ? new StringTextComponent("") : enchantment.getDisplayName(l)); + if (this.isHovering(60, 14 + 19 * j, 108, 17, (double)mouseX, (double)mouseY) && l > 0) { + List list = Lists.newArrayList(); + list.add(enchantment == null ? new TextComponent("") : enchantment.getFullname(l)); if(enchantment == null) { - list.add(new StringTextComponent("")); - list.add(new TranslationTextComponent("forge.container.enchant.limitedEnchantability").mergeStyle(TextFormatting.RED)); + list.add(new TextComponent("")); + list.add(new TranslatableComponent("forge.container.enchant.limitedEnchantability").withStyle(ChatFormatting.RED)); } else if (!flag) { - list.add(StringTextComponent.EMPTY); + list.add(TextComponent.EMPTY); if (this.minecraft.player.experienceLevel < l) { - list.add((new TranslationTextComponent("container.enchant.level.requirement", l)).mergeStyle(TextFormatting.RED)); + list.add((new TranslatableComponent("container.enchant.level.requirement", l)).withStyle(ChatFormatting.RED)); } else { - IFormattableTextComponent iformattabletextcomponent = new TranslationTextComponent("container.eidolon.enchant.shard.one", 1); + MutableComponent iformattabletextcomponent = new TranslatableComponent("container.eidolon.enchant.shard.one", 1); - list.add(iformattabletextcomponent.mergeStyle(minecraft.player.experienceLevel >= l ? TextFormatting.GRAY : TextFormatting.RED)); - IFormattableTextComponent iformattabletextcomponent1; + list.add(iformattabletextcomponent.withStyle(minecraft.player.experienceLevel >= l ? ChatFormatting.GRAY : ChatFormatting.RED)); + MutableComponent iformattabletextcomponent1; if (l == 1) { - iformattabletextcomponent1 = new TranslationTextComponent("container.enchant.level.one"); + iformattabletextcomponent1 = new TranslatableComponent("container.enchant.level.one"); } else { - iformattabletextcomponent1 = new TranslationTextComponent("container.enchant.level.many", container.worldClue[i1 - 1]); + iformattabletextcomponent1 = new TranslatableComponent("container.enchant.level.many", menu.worldClue[i1 - 1]); } - list.add(iformattabletextcomponent1.mergeStyle(TextFormatting.GRAY)); + list.add(iformattabletextcomponent1.withStyle(ChatFormatting.GRAY)); } } - this.func_243308_b(matrixStack, list, mouseX, mouseY); + this.renderComponentTooltip(matrixStack, list, mouseX, mouseY); break; } } @@ -211,8 +214,8 @@ public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partia } public void tickBook() { - ItemStack itemstack = this.container.getSlot(0).getStack(); - if (!ItemStack.areItemStacksEqual(itemstack, this.last)) { + ItemStack itemstack = this.menu.getSlot(0).getItem(); + if (!ItemStack.matches(itemstack, this.last)) { this.last = itemstack; do { @@ -226,7 +229,7 @@ public void tickBook() { boolean flag = false; for(int i = 0; i < 3; ++i) { - if ((this.container).worldClue[i] != 0) { + if ((this.menu).worldClue[i] != 0) { flag = true; } } @@ -237,10 +240,10 @@ public void tickBook() { this.open -= 0.2F; } - this.open = MathHelper.clamp(this.open, 0.0F, 1.0F); + this.open = Mth.clamp(this.open, 0.0F, 1.0F); float f1 = (this.flipT - this.flip) * 0.4F; float f = 0.2F; - f1 = MathHelper.clamp(f1, -0.2F, 0.2F); + f1 = Mth.clamp(f1, -0.2F, 0.2F); this.flipA += (f1 - this.flipA) * 0.9F; this.flip += this.flipA; } diff --git a/src/main/java/elucent/eidolon/gui/WoodenBrewingStandContainer.java b/src/main/java/elucent/eidolon/gui/WoodenBrewingStandContainer.java index c71d39f..71bac05 100644 --- a/src/main/java/elucent/eidolon/gui/WoodenBrewingStandContainer.java +++ b/src/main/java/elucent/eidolon/gui/WoodenBrewingStandContainer.java @@ -2,47 +2,44 @@ import elucent.eidolon.Registry; import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.container.BrewingStandContainer; -import net.minecraft.inventory.container.Container; -import net.minecraft.inventory.container.ContainerType; -import net.minecraft.inventory.container.Slot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.potion.Potion; -import net.minecraft.potion.PotionUtils; -import net.minecraft.util.IIntArray; -import net.minecraft.util.IntArray; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.SimpleContainerData; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.Tags; import net.minecraftforge.common.brewing.BrewingRecipeRegistry; import net.minecraftforge.event.ForgeEventFactory; -public class WoodenBrewingStandContainer extends Container { - private final IInventory tileBrewingStand; - private final IIntArray intArray; +public class WoodenBrewingStandContainer extends AbstractContainerMenu { + private final Container tileBrewingStand; + private final ContainerData intArray; private final Slot slot; - public WoodenBrewingStandContainer(int id, PlayerInventory playerInventory) { - this(id, playerInventory, new Inventory(4), new IntArray(2)); + public WoodenBrewingStandContainer(int id, Inventory playerInventory) { + this(id, playerInventory, new SimpleContainer(4), new SimpleContainerData(2)); } - public WoodenBrewingStandContainer(int id, PlayerInventory playerInventory, IInventory inventory, IIntArray p_i50096_4_) { + public WoodenBrewingStandContainer(int id, Inventory playerInventory, Container inventory, ContainerData p_i50096_4_) { super(Registry.WOODEN_STAND_CONTAINER.get(), id); - assertInventorySize(inventory, 4); - assertIntArraySize(p_i50096_4_, 2); + checkContainerSize(inventory, 4); + checkContainerDataCount(p_i50096_4_, 2); this.tileBrewingStand = inventory; this.intArray = p_i50096_4_; this.addSlot(new PotionSlot(inventory, 0, 56, 51)); this.addSlot(new PotionSlot(inventory, 1, 79, 58)); this.addSlot(new PotionSlot(inventory, 2, 102, 51)); this.slot = this.addSlot(new IngredientSlot(inventory, 3, 79, 17)); - this.trackIntArray(p_i50096_4_); + this.addDataSlots(p_i50096_4_); for(int i = 0; i < 3; ++i) { for(int j = 0; j < 9; ++j) { @@ -55,48 +52,48 @@ public WoodenBrewingStandContainer(int id, PlayerInventory playerInventory, IInv } } - public boolean canInteractWith(PlayerEntity playerIn) { - return this.tileBrewingStand.isUsableByPlayer(playerIn); + public boolean stillValid(Player playerIn) { + return this.tileBrewingStand.stillValid(playerIn); } - public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + public ItemStack quickMoveStack(Player playerIn, int index) { ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.inventorySlots.get(index); - if (slot != null && slot.getHasStack()) { - ItemStack itemstack1 = slot.getStack(); + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); itemstack = itemstack1.copy(); if ((index < 0 || index > 2) && index != 3) { - if (this.slot.isItemValid(itemstack1)) { - if (!this.mergeItemStack(itemstack1, 3, 4, false)) { + if (this.slot.mayPlace(itemstack1)) { + if (!this.moveItemStackTo(itemstack1, 3, 4, false)) { return ItemStack.EMPTY; } } else if (PotionSlot.canHoldPotion(itemstack) && itemstack.getCount() == 1) { - if (!this.mergeItemStack(itemstack1, 0, 3, false)) { + if (!this.moveItemStackTo(itemstack1, 0, 3, false)) { return ItemStack.EMPTY; } } else if (index >= 4 && index < 31) { - if (!this.mergeItemStack(itemstack1, 31, 40, false)) { + if (!this.moveItemStackTo(itemstack1, 31, 40, false)) { return ItemStack.EMPTY; } } else if (index >= 31 && index < 40) { - if (!this.mergeItemStack(itemstack1, 4, 31, false)) { + if (!this.moveItemStackTo(itemstack1, 4, 31, false)) { return ItemStack.EMPTY; } - } else if (!this.mergeItemStack(itemstack1, 4, 40, false)) { + } else if (!this.moveItemStackTo(itemstack1, 4, 40, false)) { return ItemStack.EMPTY; } } else { - if (!this.mergeItemStack(itemstack1, 4, 40, true)) { + if (!this.moveItemStackTo(itemstack1, 4, 40, true)) { return ItemStack.EMPTY; } - slot.onSlotChange(itemstack1, itemstack); + slot.onQuickCraft(itemstack1, itemstack); } if (itemstack1.isEmpty()) { - slot.putStack(ItemStack.EMPTY); + slot.set(ItemStack.EMPTY); } else { - slot.onSlotChanged(); + slot.setChanged(); } if (itemstack1.getCount() == itemstack.getCount()) { @@ -120,43 +117,42 @@ public int getTime() { } static class IngredientSlot extends Slot { - public IngredientSlot(IInventory iInventoryIn, int index, int xPosition, int yPosition) { + public IngredientSlot(Container iInventoryIn, int index, int xPosition, int yPosition) { super(iInventoryIn, index, xPosition, yPosition); } - public boolean isItemValid(ItemStack stack) { + public boolean mayPlace(ItemStack stack) { return BrewingRecipeRegistry.isValidIngredient(stack) && !Tags.Items.DUSTS_REDSTONE.contains(stack.getItem()) && !Tags.Items.DUSTS_GLOWSTONE.contains(stack.getItem()); } - public int getSlotStackLimit() { + public int getMaxStackSize() { return 64; } } static class PotionSlot extends Slot { - public PotionSlot(IInventory p_i47598_1_, int p_i47598_2_, int p_i47598_3_, int p_i47598_4_) { + public PotionSlot(Container p_i47598_1_, int p_i47598_2_, int p_i47598_3_, int p_i47598_4_) { super(p_i47598_1_, p_i47598_2_, p_i47598_3_, p_i47598_4_); } - public boolean isItemValid(ItemStack stack) { + public boolean mayPlace(ItemStack stack) { return canHoldPotion(stack); } - public int getSlotStackLimit() { + public int getMaxStackSize() { return 1; } - public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) { - Potion potion = PotionUtils.getPotionFromItem(stack); - if (thePlayer instanceof ServerPlayerEntity) { + public void onTake(Player thePlayer, ItemStack stack) { + Potion potion = PotionUtils.getPotion(stack); + if (thePlayer instanceof ServerPlayer) { ForgeEventFactory.onPlayerBrewedPotion(thePlayer, stack); - CriteriaTriggers.BREWED_POTION.trigger((ServerPlayerEntity)thePlayer, potion); + CriteriaTriggers.BREWED_POTION.trigger((ServerPlayer)thePlayer, potion); } super.onTake(thePlayer, stack); - return stack; } public static boolean canHoldPotion(ItemStack stack) { diff --git a/src/main/java/elucent/eidolon/gui/WoodenBrewingStandScreen.java b/src/main/java/elucent/eidolon/gui/WoodenBrewingStandScreen.java index cce24c9..85d39f0 100644 --- a/src/main/java/elucent/eidolon/gui/WoodenBrewingStandScreen.java +++ b/src/main/java/elucent/eidolon/gui/WoodenBrewingStandScreen.java @@ -1,48 +1,47 @@ package elucent.eidolon.gui; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.Eidolon; -import net.minecraft.client.gui.screen.inventory.ContainerScreen; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.container.BrewingStandContainer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.chat.Component; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) -public class WoodenBrewingStandScreen extends ContainerScreen { +public class WoodenBrewingStandScreen extends AbstractContainerScreen { private static final ResourceLocation BREWING_STAND_GUI_TEXTURES = new ResourceLocation(Eidolon.MODID, "textures/gui/wooden_brewing_stand.png"); private static final int[] BUBBLELENGTHS = new int[]{29, 24, 20, 16, 11, 6, 0}; - public WoodenBrewingStandScreen(WoodenBrewingStandContainer p_i51097_1_, PlayerInventory p_i51097_2_, ITextComponent p_i51097_3_) { + public WoodenBrewingStandScreen(WoodenBrewingStandContainer p_i51097_1_, Inventory p_i51097_2_, Component p_i51097_3_) { super(p_i51097_1_, p_i51097_2_, p_i51097_3_); } protected void init() { super.init(); - this.titleX = (this.xSize - this.font.getStringPropertyWidth(this.title)) / 2; + this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2; } - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { this.renderBackground(matrixStack); super.render(matrixStack, mouseX, mouseY, partialTicks); - this.renderHoveredTooltip(matrixStack, mouseX, mouseY); + this.renderTooltip(matrixStack, mouseX, mouseY); } - protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) { - RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - this.minecraft.getTextureManager().bindTexture(BREWING_STAND_GUI_TEXTURES); - int i = (this.width - this.xSize) / 2; - int j = (this.height - this.ySize) / 2; - this.blit(matrixStack, i, j, 0, 0, this.xSize, this.ySize); - if (container.getHeat() > 0) { + protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, BREWING_STAND_GUI_TEXTURES); + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + this.blit(matrixStack, i, j, 0, 0, this.imageWidth, this.imageHeight); + if (menu.getHeat() > 0) { this.blit(matrixStack, i + 32, j + 52, 197, 0, 14, 14); } - int i1 = this.container.getTime(); + int i1 = this.menu.getTime(); if (i1 > 0) { int j1 = (int)(28.0F * (1.0F - (float)i1 / 800)); if (j1 > 0) { diff --git a/src/main/java/elucent/eidolon/gui/WorktableContainer.java b/src/main/java/elucent/eidolon/gui/WorktableContainer.java index 3ba7963..bcd148a 100644 --- a/src/main/java/elucent/eidolon/gui/WorktableContainer.java +++ b/src/main/java/elucent/eidolon/gui/WorktableContainer.java @@ -1,41 +1,38 @@ package elucent.eidolon.gui; +import java.util.Optional; + import elucent.eidolon.Registry; import elucent.eidolon.recipe.WorktableRecipe; import elucent.eidolon.recipe.WorktableRegistry; -import net.minecraft.block.Blocks; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.inventory.CraftResultInventory; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.container.Container; -import net.minecraft.inventory.container.ContainerType; -import net.minecraft.inventory.container.CraftingResultSlot; -import net.minecraft.inventory.container.Slot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.ICraftingRecipe; -import net.minecraft.item.crafting.IRecipeType; -import net.minecraft.network.play.server.SSetSlotPacket; -import net.minecraft.util.IWorldPosCallable; -import net.minecraft.world.World; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.inventory.ResultContainer; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.Optional; - -public class WorktableContainer extends Container { - CraftingInventory core = new CraftingInventory(this, 3, 3), extras = new CraftingInventory(this, 2, 2); - CraftResultInventory result = new CraftResultInventory(); - PlayerEntity player; - IWorldPosCallable callable; +public class WorktableContainer extends AbstractContainerMenu { + CraftingContainer core = new CraftingContainer(this, 3, 3), extras = new CraftingContainer(this, 2, 2); + ResultContainer result = new ResultContainer(); + Player player; + ContainerLevelAccess callable; - public WorktableContainer(int id, PlayerInventory inventory) { - this(id, inventory, IWorldPosCallable.DUMMY); + public WorktableContainer(int id, Inventory inventory) { + this(id, inventory, ContainerLevelAccess.NULL); } - public WorktableContainer(int id, PlayerInventory inventory, IWorldPosCallable callable) { + public WorktableContainer(int id, Inventory inventory, ContainerLevelAccess callable) { super(Registry.WORKTABLE_CONTAINER.get(), id); this.player = inventory.player; this.callable = callable; @@ -62,94 +59,91 @@ public WorktableContainer(int id, PlayerInventory inventory, IWorldPosCallable c } } - protected void updateCraftingResult(int id, World world, PlayerEntity player, CraftingInventory inventory, CraftResultInventory inventoryResult) { - if (!world.isRemote) { - ServerPlayerEntity serverplayerentity = (ServerPlayerEntity)player; + protected void updateCraftingResult(int id, Level world, Player player, CraftingContainer inventory, ResultContainer inventoryResult) { + if (!world.isClientSide) { + ServerPlayer serverplayerentity = (ServerPlayer)player; ItemStack itemstack = ItemStack.EMPTY; WorktableRecipe recipe = WorktableRegistry.find(core, extras); if (recipe != null) { itemstack = recipe.getResult(); } else { - Optional optional = world.getServer().getRecipeManager().getRecipe(IRecipeType.CRAFTING, inventory, world); + Optional optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inventory, world); if (optional.isPresent()) { - ICraftingRecipe icraftingrecipe = optional.get(); - if (inventoryResult.canUseRecipe(world, serverplayerentity, icraftingrecipe)) { - itemstack = icraftingrecipe.getCraftingResult(inventory); + CraftingRecipe icraftingrecipe = optional.get(); + if (inventoryResult.setRecipeUsed(world, serverplayerentity, icraftingrecipe)) { + itemstack = icraftingrecipe.assemble(inventory); } } } - inventoryResult.setInventorySlotContents(0, itemstack); - serverplayerentity.connection.sendPacket(new SSetSlotPacket(id, 0, itemstack)); + inventoryResult.setItem(0, itemstack); + serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(id, incrementStateId(), 0, itemstack)); } } @Override - public void onCraftMatrixChanged(IInventory inventoryIn) { - callable.consume((p_217069_1_, p_217069_2_) -> { - updateCraftingResult(this.windowId, p_217069_1_, player, core, result); + public void slotsChanged(Container inventoryIn) { + callable.execute((p_217069_1_, p_217069_2_) -> { + updateCraftingResult(this.containerId, p_217069_1_, player, core, result); }); } @Override - public void onContainerClosed(PlayerEntity playerIn) { - super.onContainerClosed(playerIn); - callable.consume((p_217068_2_, p_217068_3_) -> { - this.clearContainer(playerIn, p_217068_2_, this.core); - this.clearContainer(playerIn, p_217068_2_, this.extras); + public void removed(Player playerIn) { + super.removed(playerIn); + callable.execute((p_217068_2_, p_217068_3_) -> { + this.clearContainer(playerIn, this.core); + this.clearContainer(playerIn, this.extras); }); } @Override - public boolean canInteractWith(PlayerEntity playerIn) { - return isWithinUsableDistance(this.callable, playerIn, Registry.WORKTABLE.get()); + public boolean stillValid(Player playerIn) { + return stillValid(this.callable, playerIn, Registry.WORKTABLE.get()); } @Override - public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + public ItemStack quickMoveStack(Player playerIn, int index) { ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.inventorySlots.get(index); - if (slot != null && slot.getHasStack()) { - ItemStack itemstack1 = slot.getStack(); + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); itemstack = itemstack1.copy(); if (index == 0) { - callable.consume((p_217067_2_, p_217067_3_) -> { - itemstack1.getItem().onCreated(itemstack1, p_217067_2_, playerIn); + callable.execute((p_217067_2_, p_217067_3_) -> { + itemstack1.getItem().onCraftedBy(itemstack1, p_217067_2_, playerIn); }); - if (!this.mergeItemStack(itemstack1, 14, 50, true)) { + if (!this.moveItemStackTo(itemstack1, 14, 50, true)) { return ItemStack.EMPTY; } - slot.onSlotChange(itemstack1, itemstack); + slot.onQuickCraft(itemstack1, itemstack); } else if (index >= 14 && index < 50) { - if (!this.mergeItemStack(itemstack1, 1, 14, false)) { + if (!this.moveItemStackTo(itemstack1, 1, 14, false)) { if (index < 41) { - if (!this.mergeItemStack(itemstack1, 41, 50, false)) { + if (!this.moveItemStackTo(itemstack1, 41, 50, false)) { return ItemStack.EMPTY; } - } else if (!this.mergeItemStack(itemstack1, 14, 41, false)) { + } else if (!this.moveItemStackTo(itemstack1, 14, 41, false)) { return ItemStack.EMPTY; } } - } else if (!this.mergeItemStack(itemstack1, 14, 50, false)) { + } else if (!this.moveItemStackTo(itemstack1, 14, 50, false)) { return ItemStack.EMPTY; } if (itemstack1.isEmpty()) { - slot.putStack(ItemStack.EMPTY); + slot.set(ItemStack.EMPTY); } else { - slot.onSlotChanged(); + slot.setChanged(); } if (itemstack1.getCount() == itemstack.getCount()) { return ItemStack.EMPTY; } - ItemStack itemstack2 = slot.onTake(playerIn, itemstack1); - if (index == 0) { - playerIn.dropItem(itemstack2, false); - } + slot.onTake(playerIn, itemstack1); } return itemstack; @@ -161,8 +155,8 @@ public int getSize() { } @Override - public boolean canMergeSlot(ItemStack stack, Slot slotIn) { - return slotIn.inventory != result && super.canMergeSlot(stack, slotIn); + public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { + return slotIn.container != result && super.canTakeItemForPickAll(stack, slotIn); } public int getOutputSlot() { diff --git a/src/main/java/elucent/eidolon/gui/WorktableResultSlot.java b/src/main/java/elucent/eidolon/gui/WorktableResultSlot.java index 40e51fd..399c61b 100644 --- a/src/main/java/elucent/eidolon/gui/WorktableResultSlot.java +++ b/src/main/java/elucent/eidolon/gui/WorktableResultSlot.java @@ -2,25 +2,23 @@ import elucent.eidolon.recipe.WorktableRecipe; import elucent.eidolon.recipe.WorktableRegistry; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.IRecipeHolder; -import net.minecraft.inventory.container.Slot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.ICraftingRecipe; -import net.minecraft.item.crafting.IRecipeType; -import net.minecraft.util.NonNullList; -import net.minecraft.util.SoundEvents; - -import java.util.Optional; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.RecipeHolder; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraft.core.NonNullList; +import net.minecraft.sounds.SoundEvents; public class WorktableResultSlot extends Slot { - private final CraftingInventory core, extras; - private final PlayerEntity player; + private final CraftingContainer core, extras; + private final Player player; private int amountCrafted; - public WorktableResultSlot(PlayerEntity player, CraftingInventory core, CraftingInventory extras, IInventory inventory, int index, int x, int y) { + public WorktableResultSlot(Player player, CraftingContainer core, CraftingContainer extras, Container inventory, int index, int x, int y) { super(inventory, index, x, y); this.player = player; this.core = core; @@ -28,23 +26,23 @@ public WorktableResultSlot(PlayerEntity player, CraftingInventory core, Crafting } @Override - public boolean isItemValid(ItemStack stack) { + public boolean mayPlace(ItemStack stack) { return false; } @Override - public ItemStack decrStackSize(int amount) { - if (this.getHasStack()) { - this.amountCrafted += Math.min(amount, this.getStack().getCount()); + public ItemStack remove(int amount) { + if (this.hasItem()) { + this.amountCrafted += Math.min(amount, this.getItem().getCount()); } - return super.decrStackSize(amount); + return super.remove(amount); } @Override - protected void onCrafting(ItemStack stack, int amount) { + protected void onQuickCraft(ItemStack stack, int amount) { this.amountCrafted += amount; - this.onCrafting(stack); + this.checkTakeAchievements(stack); } protected void onSwapCraft(int numItemsCrafted) { @@ -52,24 +50,24 @@ protected void onSwapCraft(int numItemsCrafted) { } @Override - protected void onCrafting(ItemStack stack) { + protected void checkTakeAchievements(ItemStack stack) { if (this.amountCrafted > 0) { - stack.onCrafting(this.player.world, this.player, this.amountCrafted); - net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerCraftingEvent(this.player, stack, core); + stack.onCraftedBy(this.player.level, this.player, this.amountCrafted); + ForgeEventFactory.firePlayerCraftingEvent(this.player, stack, core); } - if (this.inventory instanceof IRecipeHolder) { - ((IRecipeHolder)this.inventory).onCrafting(this.player); + if (this.container instanceof RecipeHolder) { + ((RecipeHolder)this.container).awardUsedRecipes(this.player); } - player.playSound(SoundEvents.BLOCK_SMITHING_TABLE_USE, 1.0f, 1.0f); + player.playSound(SoundEvents.SMITHING_TABLE_USE, 1.0f, 1.0f); this.amountCrafted = 0; } @Override - public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) { - this.onCrafting(stack); + public void onTake(Player thePlayer, ItemStack stack) { + this.checkTakeAchievements(stack); net.minecraftforge.common.ForgeHooks.setCraftingPlayer(thePlayer); WorktableRecipe recipe = WorktableRegistry.find(core, extras); NonNullList items = null; @@ -78,34 +76,33 @@ public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) { } else { items = NonNullList.create(); - items.addAll(thePlayer.world.getRecipeManager().getRecipeNonNull(IRecipeType.CRAFTING, core, thePlayer.world)); - for (int i = 0; i < 4; i ++) items.add(extras.getStackInSlot(i)); + items.addAll(thePlayer.level.getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, core, thePlayer.level)); + for (int i = 0; i < 4; i ++) items.add(extras.getItem(i)); } net.minecraftforge.common.ForgeHooks.setCraftingPlayer(null); assert items != null; - for(int i = 0; i < items.size(); ++i) { - IInventory inv = i < 9 ? core : extras; + int n = recipe == null ? Math.min(9, items.size()) : items.size(); + for(int i = 0; i < n; ++i) { + Container inv = i < 9 ? core : extras; int index = i < 9 ? i : i - 9; - ItemStack item = inv.getStackInSlot(index); + ItemStack item = inv.getItem(index); ItemStack remaining = items.get(i); if (!item.isEmpty()) { - inv.decrStackSize(index, 1); - item = inv.getStackInSlot(index); + inv.removeItem(index, 1); + item = inv.getItem(index); } if (!remaining.isEmpty()) { if (item.isEmpty()) { - inv.setInventorySlotContents(index, remaining); - } else if (ItemStack.areItemsEqual(item, remaining) && ItemStack.areItemStackTagsEqual(item, remaining)) { + inv.setItem(index, remaining); + } else if (ItemStack.isSame(item, remaining) && ItemStack.tagMatches(item, remaining)) { remaining.grow(item.getCount()); - inv.setInventorySlotContents(index, remaining); - } else if (!this.player.inventory.addItemStackToInventory(remaining)) { - this.player.dropItem(remaining, false); + inv.setItem(index, remaining); + } else if (!this.player.getInventory().add(remaining)) { + this.player.drop(remaining, false); } } } - - return stack; } } diff --git a/src/main/java/elucent/eidolon/gui/WorktableScreen.java b/src/main/java/elucent/eidolon/gui/WorktableScreen.java index 3521cf0..6fb8bcb 100644 --- a/src/main/java/elucent/eidolon/gui/WorktableScreen.java +++ b/src/main/java/elucent/eidolon/gui/WorktableScreen.java @@ -1,38 +1,40 @@ package elucent.eidolon.gui; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; -import net.minecraft.client.gui.screen.inventory.ContainerScreen; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.chat.Component; -public class WorktableScreen extends ContainerScreen { +public class WorktableScreen extends AbstractContainerScreen { private static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID,"textures/gui/worktable.png"); - public WorktableScreen(WorktableContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { + public WorktableScreen(WorktableContainer screenContainer, Inventory inv, Component titleIn) { super(screenContainer, inv, titleIn); - this.ySize = 224; - this.xSize = 192; + this.imageHeight = 224; + this.imageWidth = 192; } @Override - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { this.renderBackground(matrixStack); super.render(matrixStack, mouseX, mouseY, partialTicks); - this.renderHoveredTooltip(matrixStack, mouseX, mouseY); + this.renderTooltip(matrixStack, mouseX, mouseY); } @Override - protected void drawGuiContainerForegroundLayer(MatrixStack matrixStack, int x, int y) { + protected void renderLabels(PoseStack matrixStack, int x, int y) { } @Override - protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) { - this.minecraft.getTextureManager().bindTexture(BACKGROUND); - int i = this.guiLeft; - int j = (this.height - this.ySize) / 2; - this.blit(matrixStack, i, j, 0, 0, this.xSize, this.ySize); + protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) { + RenderSystem.setShaderTexture(0, BACKGROUND); + int i = this.leftPos; + int j = (this.height - this.imageHeight) / 2; + this.blit(matrixStack, i, j, 0, 0, this.imageWidth, this.imageHeight); } } diff --git a/src/main/java/elucent/eidolon/gui/jei/CrucibleCategory.java b/src/main/java/elucent/eidolon/gui/jei/CrucibleCategory.java index 68d579b..d9595bf 100644 --- a/src/main/java/elucent/eidolon/gui/jei/CrucibleCategory.java +++ b/src/main/java/elucent/eidolon/gui/jei/CrucibleCategory.java @@ -1,12 +1,18 @@ package elucent.eidolon.gui.jei; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.codex.CodexGui; import elucent.eidolon.recipe.CrucibleRecipe; import elucent.eidolon.recipe.CrucibleRegistry; -import elucent.eidolon.util.StackUtil; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.drawable.IDrawable; @@ -14,12 +20,12 @@ import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; - -import java.util.*; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.resources.ResourceLocation; public class CrucibleCategory implements IRecipeCategory { static final ResourceLocation UID = new ResourceLocation(Eidolon.MODID, "crucible"); @@ -36,13 +42,13 @@ public ResourceLocation getUid() { } @Override - public Class getRecipeClass() { + public Class getRecipeClass() { return RecipeWrappers.Crucible.class; } @Override - public String getTitle() { - return I18n.format("jei." + Eidolon.MODID + ".crucible"); + public Component getTitle() { + return new TranslatableComponent(I18n.get("jei." + Eidolon.MODID + ".crucible")); } @Override @@ -70,7 +76,7 @@ public static void condense(List stacks) { StackIngredient last = new StackIngredient(ItemStack.EMPTY, Ingredient.EMPTY); while (iter.hasNext()) { StackIngredient i = iter.next(); - if (!ItemStack.areItemsEqual(i.stack, last.stack) || !ItemStack.areItemStackTagsEqual(i.stack, last.stack) || last.stack.getCount() + i.stack.getCount() > last.stack.getMaxStackSize()) { + if (!ItemStack.isSame(i.stack, last.stack) || !ItemStack.tagMatches(i.stack, last.stack) || last.stack.getCount() + i.stack.getCount() > last.stack.getMaxStackSize()) { last = i; } else { @@ -87,15 +93,15 @@ public void setIngredients(RecipeWrappers.Crucible wrapper, IIngredients ingredi List> inputs = new ArrayList<>(); for (CrucibleRecipe.Step step : wrapper.recipe.getSteps()) { List stepInputs = new ArrayList<>(); - for (Object o : step.matches) { - ItemStack stack = StackUtil.stackFromObject(o); - if (!stack.isEmpty()) stepInputs.add(new StackIngredient(stack, StackUtil.ingredientFromObject(o))); + for (Ingredient o : step.matches) { + ItemStack stack = o.getItems().length > 0 ? o.getItems()[0].copy() : ItemStack.EMPTY.copy(); + if (!stack.isEmpty()) stepInputs.add(new StackIngredient(stack, o)); } condense(stepInputs); for (StackIngredient i : stepInputs) { - ItemStack[] valid = i.ingredient.getMatchingStacks(); + List valid = Arrays.stream(i.ingredient.getItems()).map((s) -> s.copy()).collect(Collectors.toList()); for (ItemStack stack : valid) stack.setCount(i.stack.getCount()); - inputs.add(Arrays.asList(valid)); + inputs.add(valid); } } ingredients.setInputLists(VanillaTypes.ITEM, inputs); @@ -115,8 +121,8 @@ public void setRecipe(IRecipeLayout layout, RecipeWrappers.Crucible recipe, IIng tx += 24; List stepInputs = new ArrayList<>(); - for (Object o : steps.get(i).matches) { - ItemStack stack = StackUtil.stackFromObject(o); + for (Ingredient o : steps.get(i).matches) { + ItemStack stack = o.getItems().length > 0 ? o.getItems()[0].copy() : ItemStack.EMPTY.copy(); if (!stack.isEmpty()) stepInputs.add(new StackIngredient(stack, Ingredient.EMPTY)); } condense(stepInputs); @@ -132,7 +138,7 @@ public void setRecipe(IRecipeLayout layout, RecipeWrappers.Crucible recipe, IIng } @Override - public void draw(RecipeWrappers.Crucible recipe, MatrixStack mStack, double mouseX, double mouseY) { + public void draw(RecipeWrappers.Crucible recipe, PoseStack mStack, double mouseX, double mouseY) { recipe.page.renderBackground(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); recipe.page.render(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); } diff --git a/src/main/java/elucent/eidolon/gui/jei/JEIRegistry.java b/src/main/java/elucent/eidolon/gui/jei/JEIRegistry.java index 6d793e5..e5cbe0a 100644 --- a/src/main/java/elucent/eidolon/gui/jei/JEIRegistry.java +++ b/src/main/java/elucent/eidolon/gui/jei/JEIRegistry.java @@ -9,14 +9,11 @@ import mezz.jei.api.JeiPlugin; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.category.IRecipeCategory; -import mezz.jei.api.registration.IAdvancedRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCategoryRegistration; import mezz.jei.api.registration.IRecipeRegistration; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; @JeiPlugin public class JEIRegistry implements IModPlugin { diff --git a/src/main/java/elucent/eidolon/gui/jei/RecipeWrappers.java b/src/main/java/elucent/eidolon/gui/jei/RecipeWrappers.java index cb254e6..6e01daa 100644 --- a/src/main/java/elucent/eidolon/gui/jei/RecipeWrappers.java +++ b/src/main/java/elucent/eidolon/gui/jei/RecipeWrappers.java @@ -4,9 +4,6 @@ import elucent.eidolon.recipe.CrucibleRecipe; import elucent.eidolon.recipe.WorktableRecipe; import elucent.eidolon.ritual.Ritual; -import net.minecraft.item.ItemStack; - -import java.util.List; public class RecipeWrappers { public static class Crucible { diff --git a/src/main/java/elucent/eidolon/gui/jei/RitualCategory.java b/src/main/java/elucent/eidolon/gui/jei/RitualCategory.java index 73aace5..b2cb723 100644 --- a/src/main/java/elucent/eidolon/gui/jei/RitualCategory.java +++ b/src/main/java/elucent/eidolon/gui/jei/RitualCategory.java @@ -1,6 +1,10 @@ package elucent.eidolon.gui.jei; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.codex.CodexGui; @@ -8,7 +12,7 @@ import elucent.eidolon.ritual.ItemRequirement; import elucent.eidolon.ritual.MultiItemSacrifice; import elucent.eidolon.ritual.RitualRegistry; -import elucent.eidolon.util.StackUtil; +import elucent.eidolon.util.RecipeUtil; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.drawable.IDrawable; @@ -16,13 +20,12 @@ import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; - -import java.util.ArrayList; -import java.util.List; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.resources.ResourceLocation; public class RitualCategory implements IRecipeCategory { static final ResourceLocation UID = new ResourceLocation(Eidolon.MODID, "ritual"); @@ -39,13 +42,13 @@ public ResourceLocation getUid() { } @Override - public Class getRecipeClass() { + public Class getRecipeClass() { return RecipeWrappers.RitualRecipe.class; } @Override - public String getTitle() { - return I18n.format("jei." + Eidolon.MODID + ".ritual"); + public Component getTitle() { + return new TranslatableComponent(I18n.get("jei." + Eidolon.MODID + ".ritual")); } @Override @@ -66,10 +69,10 @@ public void setIngredients(RecipeWrappers.RitualRecipe wrapper, IIngredients ing int slot = 0; for (IRequirement r : wrapper.ritual.getRequirements()) { if (r instanceof ItemRequirement) - inputs.add(StackUtil.ingredientFromObject(((ItemRequirement)r).getMatch())); + inputs.add(RecipeUtil.ingredientFromObject(((ItemRequirement)r).getMatch())); slot ++; } - inputs.add(StackUtil.ingredientFromObject(sacrifice instanceof MultiItemSacrifice ? ((MultiItemSacrifice)sacrifice).main : sacrifice)); + inputs.add(RecipeUtil.ingredientFromObject(sacrifice instanceof MultiItemSacrifice ? ((MultiItemSacrifice)sacrifice).main : sacrifice)); ingredients.setInputIngredients(inputs); } @@ -92,7 +95,7 @@ public void setRecipe(IRecipeLayout layout, RecipeWrappers.RitualRecipe recipe, } @Override - public void draw(RecipeWrappers.RitualRecipe recipe, MatrixStack mStack, double mouseX, double mouseY) { + public void draw(RecipeWrappers.RitualRecipe recipe, PoseStack mStack, double mouseX, double mouseY) { recipe.page.renderBackground(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); recipe.page.render(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); } diff --git a/src/main/java/elucent/eidolon/gui/jei/WorktableCategory.java b/src/main/java/elucent/eidolon/gui/jei/WorktableCategory.java index 024bcde..6732508 100644 --- a/src/main/java/elucent/eidolon/gui/jei/WorktableCategory.java +++ b/src/main/java/elucent/eidolon/gui/jei/WorktableCategory.java @@ -1,13 +1,14 @@ package elucent.eidolon.gui.jei; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.codex.CodexGui; -import elucent.eidolon.recipe.CrucibleRecipe; -import elucent.eidolon.recipe.WorktableRecipe; import elucent.eidolon.recipe.WorktableRegistry; -import elucent.eidolon.util.StackUtil; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.drawable.IDrawable; @@ -15,15 +16,12 @@ import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.resources.ResourceLocation; public class WorktableCategory implements IRecipeCategory { static final ResourceLocation UID = new ResourceLocation(Eidolon.MODID, "worktable"); @@ -40,13 +38,13 @@ public ResourceLocation getUid() { } @Override - public Class getRecipeClass() { + public Class getRecipeClass() { return RecipeWrappers.Worktable.class; } @Override - public String getTitle() { - return I18n.format("jei." + Eidolon.MODID + ".worktable"); + public Component getTitle() { + return new TranslatableComponent(I18n.get("jei." + Eidolon.MODID + ".worktable")); } @Override @@ -64,8 +62,8 @@ public void setIngredients(RecipeWrappers.Worktable wrapper, IIngredients ingred if (wrapper.page == null) wrapper.page = WorktableRegistry.getDefaultPage(wrapper.recipe); List inputs = new ArrayList<>(); - for (Object o : wrapper.recipe.getCore()) inputs.add(StackUtil.ingredientFromObject(o)); - for (Object o : wrapper.recipe.getOuter()) inputs.add(StackUtil.ingredientFromObject(o)); + for (Ingredient i : wrapper.recipe.getCore()) inputs.add(i); + for (Ingredient i : wrapper.recipe.getOuter()) inputs.add(i); ingredients.setInputIngredients(inputs); ingredients.setOutput(VanillaTypes.ITEM, wrapper.recipe.getResult()); } @@ -89,7 +87,7 @@ public void setRecipe(IRecipeLayout layout, RecipeWrappers.Worktable recipe, IIn } @Override - public void draw(RecipeWrappers.Worktable recipe, MatrixStack mStack, double mouseX, double mouseY) { + public void draw(RecipeWrappers.Worktable recipe, PoseStack mStack, double mouseX, double mouseY) { recipe.page.renderBackground(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); recipe.page.render(CodexGui.DUMMY, mStack, 5, 4, (int)mouseX, (int)mouseY); } diff --git a/src/main/java/elucent/eidolon/item/AthameItem.java b/src/main/java/elucent/eidolon/item/AthameItem.java new file mode 100644 index 0000000..022ebd3 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/AthameItem.java @@ -0,0 +1,128 @@ +package elucent.eidolon.item; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import elucent.eidolon.Registry; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DoublePlantBlock; +import net.minecraft.world.level.material.Material; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Endermite; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.item.SwordItem; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.InteractionResult; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.Vec3; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.living.LootingLevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import net.minecraft.world.item.Item.Properties; +import java.util.Random; + +public class AthameItem extends SwordItem { + private Random random = new Random(); + + public AthameItem(Properties builderIn) { + super(Tiers.PewterTier.INSTANCE, 1, -1.6f, builderIn); + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onLooting(LootingLevelEvent event) { + if (event.getEntityLiving().getMainHandItem().getItem() instanceof AthameItem) + event.setLootingLevel(event.getLootingLevel() * 2 + 1); + } + + @SubscribeEvent + public void onHurt(LivingHurtEvent event) { + if (event.getSource().getEntity() instanceof LivingEntity + && ((LivingEntity)event.getSource().getEntity()).getMainHandItem().getItem() instanceof AthameItem + && (event.getEntity() instanceof EnderMan || event.getEntity() instanceof Endermite || event.getEntity() instanceof EnderDragon)) { + event.setAmount(event.getAmount() * 4); + } + } + + String loreTag = null; + + public Item setLore(String tag) { + this.loreTag = tag; + return this; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + if (this.loreTag != null) { + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); + } + } + + @Override + public InteractionResult useOn(UseOnContext ctx) { + BlockState state = ctx.getLevel().getBlockState(ctx.getClickedPos()); + float hardness = state.getDestroySpeed(ctx.getLevel(), ctx.getClickedPos()); + if ((state.getMaterial() == Material.PLANT || state.getMaterial() == Material.REPLACEABLE_PLANT || state.getMaterial() == Material.LEAVES || state.getMaterial() == Material.WATER_PLANT || state.getMaterial() == Material.REPLACEABLE_FIREPROOF_PLANT) + && hardness < 5.0f && hardness >= 0) { + if (!ctx.getLevel().isClientSide) { + Vec3 hit = ctx.getClickLocation(); + ((ServerLevel)ctx.getLevel()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, state), hit.x, hit.y, hit.z, 3, ((double)random.nextFloat() - 0.5D) * 0.08D, ((double)random.nextFloat() - 0.5D) * 0.08D, ((double)random.nextFloat() - 0.5D) * 0.08D, (double)0.05F); + ctx.getLevel().playSound(null, ctx.getClickedPos(), SoundEvents.SHEEP_SHEAR, SoundSource.PLAYERS, 0.5f, 0.9f + random.nextFloat() * 0.2f); + if (random.nextInt(5) == 0) { + if (state.getBlock() instanceof DoublePlantBlock && state.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER) + ctx.getLevel().destroyBlock(ctx.getClickedPos().below(), false); + else ctx.getLevel().destroyBlock(ctx.getClickedPos(), false); + if (random.nextInt(10) == 0) { + ItemStack drop = getHarvestable(state); + if (!drop.isEmpty() && !ctx.getLevel().isClientSide) { + ctx.getLevel().playSound(null, ctx.getClickedPos(), SoundEvents.EXPERIENCE_ORB_PICKUP, SoundSource.PLAYERS, 0.5f, 0.9f + random.nextFloat() * 0.2f); + ctx.getLevel().addFreshEntity(new ItemEntity(ctx.getLevel(), ctx.getClickedPos().getX() + 0.5, ctx.getClickedPos().getY() + 0.5, ctx.getClickedPos().getZ() + 0.5, drop.copy())); + } + if (!ctx.getPlayer().isCreative()) ctx.getItemInHand().hurtAndBreak(1, ctx.getPlayer(), (player) -> { + player.broadcastBreakEvent(ctx.getHand()); + }); + } + } + } + return InteractionResult.SUCCESS; + } + return super.useOn(ctx); + } + + public static Map harvestables = new HashMap<>(); + + public static void initHarvestables() { + harvestables.put(Blocks.JUNGLE_LEAVES.getRegistryName(), new ItemStack(Registry.SILDRIAN_SEED.get())); + harvestables.put(Blocks.LILY_PAD.getRegistryName(), new ItemStack(Registry.OANNA_BLOOM.get())); + harvestables.put(Blocks.OXEYE_DAISY.getRegistryName(), new ItemStack(Registry.MERAMMER_ROOT.get())); + harvestables.put(Blocks.FERN.getRegistryName(), new ItemStack(Registry.AVENNIAN_SPRIG.get())); + } + + public static ItemStack getHarvestable(BlockState state) { + return harvestables.getOrDefault(state.getBlock().getRegistryName(), ItemStack.EMPTY); + } +} diff --git a/src/main/java/elucent/eidolon/item/BonechillWandItem.java b/src/main/java/elucent/eidolon/item/BonechillWandItem.java index 45556f0..47b2e77 100644 --- a/src/main/java/elucent/eidolon/item/BonechillWandItem.java +++ b/src/main/java/elucent/eidolon/item/BonechillWandItem.java @@ -1,58 +1,61 @@ package elucent.eidolon.item; +import java.util.List; +import java.util.Random; + import elucent.eidolon.Registry; -import elucent.eidolon.capability.ReputationProvider; import elucent.eidolon.entity.BonechillProjectileEntity; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionHand; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.phys.Vec3; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class BonechillWandItem extends WandItem { + private Random random = new Random(); + public BonechillWandItem(Properties builderIn) { super(builderIn); } @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } @Override - public ActionResult onItemRightClick(World world, PlayerEntity entity, Hand hand) { - ItemStack stack = entity.getHeldItem(hand); - if (!entity.isSwingInProgress) { - if (!world.isRemote) { - Vector3d pos = entity.getPositionVec().add(entity.getLookVec().scale(0.5)).add(0.5 * Math.sin(Math.toRadians(225 - entity.rotationYawHead)), entity.getHeight() * 2 / 3, 0.5 * Math.cos(Math.toRadians(225 - entity.rotationYawHead))); - Vector3d vel = entity.getEyePosition(0).add(entity.getLookVec().scale(40)).subtract(pos).scale(1.0 / 20); - world.addEntity(new BonechillProjectileEntity(Registry.BONECHILL_PROJECTILE.get(), world).shoot( - pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, entity.getUniqueID() + public InteractionResultHolder use(Level world, Player entity, InteractionHand hand) { + ItemStack stack = entity.getItemInHand(hand); + if (!entity.swinging) { + if (!world.isClientSide) { + Vec3 pos = entity.position().add(entity.getLookAngle().scale(0.5)).add(0.5 * Math.sin(Math.toRadians(225 - entity.yHeadRot)), entity.getBbHeight() * 2 / 3, 0.5 * Math.cos(Math.toRadians(225 - entity.yHeadRot))); + Vec3 vel = entity.getEyePosition(0).add(entity.getLookAngle().scale(40)).subtract(pos).scale(1.0 / 20); + world.addFreshEntity(new BonechillProjectileEntity(Registry.BONECHILL_PROJECTILE.get(), world).shoot( + pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, entity.getUUID() )); - world.playSound(null, pos.x, pos.y, pos.z, Registry.CAST_BONECHILL_EVENT.get(), SoundCategory.NEUTRAL, 0.75f, random.nextFloat() * 0.2f + 0.9f); - stack.damageItem(1, entity, (player) -> { - player.sendBreakAnimation(hand); + world.playSound(null, pos.x, pos.y, pos.z, Registry.CAST_BONECHILL_EVENT.get(), SoundSource.NEUTRAL, 0.75f, random.nextFloat() * 0.2f + 0.9f); + stack.hurtAndBreak(1, entity, (player) -> { + player.broadcastBreakEvent(hand); }); } - entity.swingArm(hand); - return ActionResult.resultSuccess(stack); + entity.swing(hand); + return InteractionResultHolder.success(stack); } - return ActionResult.resultPass(stack); + return InteractionResultHolder.pass(stack); } } diff --git a/src/main/java/elucent/eidolon/item/CleavingAxeItem.java b/src/main/java/elucent/eidolon/item/CleavingAxeItem.java index de98e4a..1c58234 100644 --- a/src/main/java/elucent/eidolon/item/CleavingAxeItem.java +++ b/src/main/java/elucent/eidolon/item/CleavingAxeItem.java @@ -1,18 +1,20 @@ package elucent.eidolon.item; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.AxeItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import java.util.List; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.AxeItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class CleavingAxeItem extends AxeItem { public CleavingAxeItem(Properties builderIn) { @@ -28,10 +30,10 @@ public Item setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } } diff --git a/src/main/java/elucent/eidolon/item/CodexItem.java b/src/main/java/elucent/eidolon/item/CodexItem.java index f9163ac..f6f983e 100644 --- a/src/main/java/elucent/eidolon/item/CodexItem.java +++ b/src/main/java/elucent/eidolon/item/CodexItem.java @@ -1,14 +1,20 @@ package elucent.eidolon.item; import elucent.eidolon.Eidolon; -import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.KnowledgeUtil; +import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.*; -import net.minecraft.world.World; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionHand; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; + +import net.minecraft.world.item.Item.Properties; public class CodexItem extends ItemBase { public CodexItem(Properties properties) { @@ -16,18 +22,18 @@ public CodexItem(Properties properties) { } @Override - public ActionResult onItemRightClick(World world, PlayerEntity entity, Hand hand) { - if (world.isRemote) { - entity.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, SoundCategory.PLAYERS, 1.0f, 1.0f); + public InteractionResultHolder use(Level world, Player entity, InteractionHand hand) { + if (world.isClientSide) { + entity.playNotifySound(SoundEvents.BOOK_PAGE_TURN, SoundSource.PLAYERS, 1.0f, 1.0f); Eidolon.proxy.openCodexGui(); } - return ActionResult.resultPass(entity.getHeldItem(hand)); + return InteractionResultHolder.pass(entity.getItemInHand(hand)); } @Override - public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) { + public void inventoryTick(ItemStack stack, Level world, Entity entity, int slot, boolean selected) { super.inventoryTick(stack, world, entity, slot, selected); - if (!world.isRemote && stack.hasTag() && stack.getTag().contains("sign")) { + if (!world.isClientSide && stack.hasTag() && stack.getTag().contains("sign")) { ResourceLocation loc = new ResourceLocation(stack.getTag().getString("sign")); stack.getTag().remove("sign"); Sign sign = Signs.find(loc); diff --git a/src/main/java/elucent/eidolon/item/ItemBase.java b/src/main/java/elucent/eidolon/item/ItemBase.java index f441151..ac28ac6 100644 --- a/src/main/java/elucent/eidolon/item/ItemBase.java +++ b/src/main/java/elucent/eidolon/item/ItemBase.java @@ -1,18 +1,19 @@ package elucent.eidolon.item; -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.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import java.util.List; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import javax.annotation.Nullable; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class ItemBase extends Item { String loreTag = null; @@ -28,10 +29,10 @@ public ItemBase setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } } diff --git a/src/main/java/elucent/eidolon/item/ReaperScytheItem.java b/src/main/java/elucent/eidolon/item/ReaperScytheItem.java index 7cf0f89..9f4d7c6 100644 --- a/src/main/java/elucent/eidolon/item/ReaperScytheItem.java +++ b/src/main/java/elucent/eidolon/item/ReaperScytheItem.java @@ -1,17 +1,20 @@ package elucent.eidolon.item; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.*; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import java.util.List; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SwordItem; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class ReaperScytheItem extends SwordItem { public ReaperScytheItem(Properties builderIn) { @@ -27,10 +30,10 @@ public Item setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } } diff --git a/src/main/java/elucent/eidolon/item/ReversalPickItem.java b/src/main/java/elucent/eidolon/item/ReversalPickItem.java index 33ba533..b66a041 100644 --- a/src/main/java/elucent/eidolon/item/ReversalPickItem.java +++ b/src/main/java/elucent/eidolon/item/ReversalPickItem.java @@ -1,25 +1,24 @@ package elucent.eidolon.item; -import com.google.common.eventbus.Subscribe; -import net.minecraft.block.Blocks; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.AxeItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.PickaxeItem; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import java.util.List; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.PickaxeItem; +import net.minecraft.util.Mth; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class ReversalPickItem extends PickaxeItem { public ReversalPickItem(Properties builderIn) { @@ -36,19 +35,19 @@ public Item setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } @SubscribeEvent public static void onStartBreak(PlayerEvent.BreakSpeed event) { - if (event.getPlayer().getHeldItemMainhand().getItem() instanceof ReversalPickItem) { - float hardness = event.getState().getBlockHardness(event.getEntity().world, event.getPos()); - float adjHardness = 1 / (hardness / 1.5f + event.getState().getHarvestLevel()); - float newSpeed = MathHelper.sqrt(event.getOriginalSpeed() * 0.25f) * MathHelper.sqrt(hardness / adjHardness); + if (event.getPlayer().getMainHandItem().getItem() instanceof ReversalPickItem) { + float hardness = event.getState().getDestroySpeed(event.getEntity().level, event.getPos()); + float adjHardness = 1 / (hardness / 2.0f); + float newSpeed = Mth.sqrt(event.getOriginalSpeed() * 0.25f) * Mth.sqrt(hardness / adjHardness); event.setNewSpeed(newSpeed * newSpeed); } } diff --git a/src/main/java/elucent/eidolon/item/SappingSwordItem.java b/src/main/java/elucent/eidolon/item/SappingSwordItem.java index 24c6031..fc7f46f 100644 --- a/src/main/java/elucent/eidolon/item/SappingSwordItem.java +++ b/src/main/java/elucent/eidolon/item/SappingSwordItem.java @@ -1,20 +1,24 @@ package elucent.eidolon.item; +import java.util.List; + import elucent.eidolon.network.LifestealEffectPacket; import elucent.eidolon.network.Networking; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.*; -import net.minecraft.util.EntityDamageSource; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SwordItem; +import net.minecraft.world.damagesource.EntityDamageSource; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class SappingSwordItem extends SwordItem { public SappingSwordItem(Properties builderIn) { @@ -30,25 +34,25 @@ public Item setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } @Override - public boolean hitEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) { - if (target.hurtResistantTime > 0) { - target.hurtResistantTime = 0; + public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { + if (target.invulnerableTime > 0) { + target.invulnerableTime = 0; float before = target.getHealth(); - target.attackEntityFrom(new EntityDamageSource("wither", attacker).setDamageBypassesArmor(), 2.0f); + target.hurt(new EntityDamageSource("wither", attacker).bypassArmor(), 2.0f); float healing = before - target.getHealth(); if (healing > 0) { attacker.heal(healing); - if (!attacker.world.isRemote) Networking.sendToTracking(attacker.world, attacker.getPosition(), new LifestealEffectPacket(target.getPosition(), attacker.getPosition(), 1.0f, 0.125f, 0.1875f)); + if (!attacker.level.isClientSide) Networking.sendToTracking(attacker.level, attacker.blockPosition(), new LifestealEffectPacket(target.blockPosition(), attacker.blockPosition(), 1.0f, 0.125f, 0.1875f)); } } - return super.hitEntity(stack, target, attacker); + return super.hurtEnemy(stack, target, attacker); } } diff --git a/src/main/java/elucent/eidolon/item/SilverArmorItem.java b/src/main/java/elucent/eidolon/item/SilverArmorItem.java new file mode 100644 index 0000000..c459e8f --- /dev/null +++ b/src/main/java/elucent/eidolon/item/SilverArmorItem.java @@ -0,0 +1,110 @@ +package elucent.eidolon.item; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.item.model.SilverArmorModel; +import elucent.eidolon.item.model.WarlockArmorModel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterials; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.IItemRenderProperties; +import net.minecraft.world.item.Item.Properties; + +public class SilverArmorItem extends ArmorItem { + private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; + + public static class Material implements ArmorMaterial { + @Override + public int getDurabilityForSlot(EquipmentSlot slot) { + return MAX_DAMAGE_ARRAY[slot.getIndex()] * 17; + } + + @Override + public int getDefenseForSlot(EquipmentSlot slot) { + switch (slot) { + case CHEST: + return 6; + case HEAD: + return 2; + case LEGS: + return 4; + case FEET: + return 2; + default: + return 0; + } + } + + @Override + public int getEnchantmentValue() { + return 20; + } + + @Override + public SoundEvent getEquipSound() { + return ArmorMaterials.GOLD.getEquipSound(); + } + + @Override + public Ingredient getRepairIngredient() { + return Ingredient.of(Registry.INGOTS_SILVER); + } + + @Override + public String getName() { + return Eidolon.MODID + ":silver_armor"; + } + + @Override + public float getToughness() { + return 0; + } + + @Override + public float getKnockbackResistance() { + return 0; + } + + public static final Material INSTANCE = new Material(); + } + + public SilverArmorItem(EquipmentSlot slot, Properties builderIn) { + super(Material.INSTANCE, slot, builderIn); + } + + @OnlyIn(Dist.CLIENT) + @Override + public void initializeClient(java.util.function.Consumer consumer) { + consumer.accept(new IItemRenderProperties() { + @Override + public SilverArmorModel getArmorModel(LivingEntity entity, ItemStack itemStack, EquipmentSlot armorSlot, HumanoidModel _default) { + float pticks = Minecraft.getInstance().getFrameTime(); + float f = Mth.rotLerp(pticks, entity.yBodyRotO, entity.yBodyRot); + float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); + float netHeadYaw = f1 - f; + float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); + Registry.SILVER_ARMOR_MODEL.slot = slot; + Registry.SILVER_ARMOR_MODEL.copyFromDefault(_default); + Registry.SILVER_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return Registry.SILVER_ARMOR_MODEL; + } + }); + } + + @OnlyIn(Dist.CLIENT) + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { + return Eidolon.MODID + ":textures/entity/silver_armor.png"; + } +} diff --git a/src/main/java/elucent/eidolon/item/SoulfireWandItem.java b/src/main/java/elucent/eidolon/item/SoulfireWandItem.java index a6816d4..c609922 100644 --- a/src/main/java/elucent/eidolon/item/SoulfireWandItem.java +++ b/src/main/java/elucent/eidolon/item/SoulfireWandItem.java @@ -1,68 +1,50 @@ package elucent.eidolon.item; -import elucent.eidolon.Eidolon; +import java.util.Random; + import elucent.eidolon.Registry; -import elucent.eidolon.capability.KnowledgeProvider; -import elucent.eidolon.capability.ReputationProvider; -import elucent.eidolon.deity.Deities; -import elucent.eidolon.deity.DeityLocks; import elucent.eidolon.entity.SoulfireProjectileEntity; -import elucent.eidolon.network.KnowledgeUpdatePacket; -import elucent.eidolon.network.Networking; -import elucent.eidolon.spell.Sign; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.*; -import net.minecraft.util.*; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionHand; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.server.level.ServerLevel; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class SoulfireWandItem extends WandItem { + static Random random = new Random(); + public SoulfireWandItem(Properties builderIn) { super(builderIn); } @Override - public ActionResult onItemRightClick(World world, PlayerEntity entity, Hand hand) { - ItemStack stack = entity.getHeldItem(hand); - if (!entity.isSwingInProgress) { - if (!world.isRemote) { - Vector3d pos = entity.getPositionVec().add(entity.getLookVec().scale(0.5)).add(0.5 * Math.sin(Math.toRadians(225 - entity.rotationYawHead)), entity.getHeight() * 2 / 3, 0.5 * Math.cos(Math.toRadians(225 - entity.rotationYawHead))); - Vector3d vel = entity.getEyePosition(0).add(entity.getLookVec().scale(40)).subtract(pos).scale(1.0 / 20); - world.addEntity(new SoulfireProjectileEntity(Registry.SOULFIRE_PROJECTILE.get(), world).shoot( - pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, entity.getUniqueID() + public InteractionResultHolder use(Level world, Player entity, InteractionHand hand) { + ItemStack stack = entity.getItemInHand(hand); + if (!entity.swinging) { + if (!world.isClientSide) { + Vec3 pos = entity.position().add(entity.getLookAngle().scale(0.5)).add(0.5 * Math.sin(Math.toRadians(225 - entity.yHeadRot)), entity.getBbHeight() * 2 / 3, 0.5 * Math.cos(Math.toRadians(225 - entity.yHeadRot))); + Vec3 vel = entity.getEyePosition(0).add(entity.getLookAngle().scale(40)).subtract(pos).scale(1.0 / 20); + world.addFreshEntity(new SoulfireProjectileEntity(Registry.SOULFIRE_PROJECTILE.get(), world).shoot( + pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, entity.getUUID() )); - world.playSound(null, pos.x, pos.y, pos.z, Registry.CAST_SOULFIRE_EVENT.get(), SoundCategory.NEUTRAL, 0.75f, random.nextFloat() * 0.2f + 0.9f); - stack.damageItem(1, entity, (player) -> { - player.sendBreakAnimation(hand); + world.playSound(null, pos.x, pos.y, pos.z, Registry.CAST_SOULFIRE_EVENT.get(), SoundSource.NEUTRAL, 0.75f, random.nextFloat() * 0.2f + 0.9f); + stack.hurtAndBreak(1, entity, (player) -> { + player.broadcastBreakEvent(hand); }); - - try { - Template t = ((ServerWorld)world).getStructureTemplateManager().getTemplate(new ResourceLocation("eidolon", "corridor")); - BlockPos d = t.getSize(); - Rotation r = Rotation.values()[entity.getHorizontalFacing().getHorizontalIndex()]; - BlockPos o = new BlockPos(-d.getX() / 2, -d.getY() / 2, -d.getZ() / 2); - BlockPos s = new BlockPos(Math.max(o.getX(), o.getZ()), o.getY(), Math.max(o.getX(), o.getZ())); - t.func_237152_b_((ServerWorld)world, entity.getPosition().down(8).add(o.rotate(r)).subtract(s), new PlacementSettings().setRotation(r), random); - } catch (Exception e) { - // - } } - entity.swingArm(hand); - return ActionResult.resultSuccess(stack); + entity.swing(hand); + return InteractionResultHolder.success(stack); } - return ActionResult.resultPass(stack); + return InteractionResultHolder.pass(stack); } } diff --git a/src/main/java/elucent/eidolon/item/Tiers.java b/src/main/java/elucent/eidolon/item/Tiers.java index 309a9d4..1d27089 100644 --- a/src/main/java/elucent/eidolon/item/Tiers.java +++ b/src/main/java/elucent/eidolon/item/Tiers.java @@ -1,107 +1,141 @@ package elucent.eidolon.item; import elucent.eidolon.Registry; -import net.minecraft.item.IItemTier; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; +import net.minecraft.world.item.Tier; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; public class Tiers { - public static class PewterTier implements IItemTier { + public static class PewterTier implements Tier { @Override - public int getMaxUses() { + public int getUses() { return 325; } @Override - public float getEfficiency() { + public float getSpeed() { return 6.5f; } @Override - public float getAttackDamage() { + public float getAttackDamageBonus() { return 2; } @Override - public int getHarvestLevel() { + public int getLevel() { return 2; } @Override - public int getEnchantability() { + public int getEnchantmentValue() { return 8; } @Override - public Ingredient getRepairMaterial() { - return Ingredient.fromStacks(new ItemStack(Registry.PEWTER_INGOT.get())); + public Ingredient getRepairIngredient() { + return Ingredient.of(new ItemStack(Registry.PEWTER_INGOT.get())); } public static PewterTier INSTANCE = new PewterTier(); } - public static class MagicToolTier implements IItemTier { + public static class MagicToolTier implements Tier { @Override - public int getMaxUses() { + public int getUses() { return 1170; } @Override - public float getEfficiency() { + public float getSpeed() { return 7.0f; } @Override - public float getAttackDamage() { + public float getAttackDamageBonus() { return 3; } @Override - public int getHarvestLevel() { + public int getLevel() { return 3; } @Override - public int getEnchantability() { + public int getEnchantmentValue() { return 30; } @Override - public Ingredient getRepairMaterial() { + public Ingredient getRepairIngredient() { return Ingredient.EMPTY; } public static MagicToolTier INSTANCE = new MagicToolTier(); } - public static class SanguineTier implements IItemTier { + public static class SilverTier implements Tier { @Override - public int getMaxUses() { + public int getUses() { + return 193; + } + + @Override + public float getSpeed() { + return 7.0f; + } + + @Override + public float getAttackDamageBonus() { + return 2; + } + + @Override + public int getLevel() { + return 2; + } + + @Override + public int getEnchantmentValue() { + return 20; + } + + @Override + public Ingredient getRepairIngredient() { + return Ingredient.of(new ItemStack(Registry.SILVER_INGOT.get())); + } + + public static SilverTier INSTANCE = new SilverTier(); + } + + public static class SanguineTier implements Tier { + @Override + public int getUses() { return 507; } @Override - public float getEfficiency() { + public float getSpeed() { return 8.0f; } @Override - public float getAttackDamage() { + public float getAttackDamageBonus() { return 3; } @Override - public int getHarvestLevel() { + public int getLevel() { return 3; } @Override - public int getEnchantability() { + public int getEnchantmentValue() { return 20; } @Override - public Ingredient getRepairMaterial() { + public Ingredient getRepairIngredient() { return Ingredient.EMPTY; } diff --git a/src/main/java/elucent/eidolon/item/TongsItem.java b/src/main/java/elucent/eidolon/item/TongsItem.java new file mode 100644 index 0000000..0d1ca32 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/TongsItem.java @@ -0,0 +1,31 @@ +package elucent.eidolon.item; + +import elucent.eidolon.block.PipeBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.InteractionResult; + +import net.minecraft.world.item.Item.Properties; + +public class TongsItem extends ItemBase { + public TongsItem(Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext ctx) { + BlockState state = ctx.getLevel().getBlockState(ctx.getClickedPos()); + if (state.getBlock() instanceof PipeBlock && ctx.getClickedFace() != state.getValue(PipeBlock.IN)) { + BlockState newState = state.setValue(PipeBlock.OUT, ctx.getClickedFace()); + BlockState off = ctx.getLevel().getBlockState(ctx.getClickedPos().relative(ctx.getClickedFace())); + if (off.getBlock() == state.getBlock() && + off.getValue(PipeBlock.OUT) == ctx.getClickedFace().getOpposite()) + return InteractionResult.FAIL; + if (off.getBlock() != state.getBlock() || off.getValue(PipeBlock.IN) != ctx.getClickedFace()) + newState = newState.setValue(PipeBlock.OUT_ATTACHED, false); + ctx.getLevel().setBlock(ctx.getClickedPos(), newState, 3); + return InteractionResult.SUCCESS; + } + return super.useOn(ctx); + } +} diff --git a/src/main/java/elucent/eidolon/item/TopHatItem.java b/src/main/java/elucent/eidolon/item/TopHatItem.java index c83c570..a0c2845 100644 --- a/src/main/java/elucent/eidolon/item/TopHatItem.java +++ b/src/main/java/elucent/eidolon/item/TopHatItem.java @@ -1,56 +1,63 @@ package elucent.eidolon.item; +import java.util.List; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.model.TopHatModel; import elucent.eidolon.item.model.WarlockArmorModel; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.entity.model.BipedModel; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.item.*; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterials; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.List; +import net.minecraftforge.client.IItemRenderProperties; +import net.minecraft.world.item.Item.Properties; public class TopHatItem extends ArmorItem { private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; - public static class Material implements IArmorMaterial { + public static class Material implements ArmorMaterial { @Override - public int getDurability(EquipmentSlotType slot) { + public int getDurabilityForSlot(EquipmentSlot slot) { return MAX_DAMAGE_ARRAY[slot.getIndex()] * 7; } @Override - public int getDamageReductionAmount(EquipmentSlotType slot) { + public int getDefenseForSlot(EquipmentSlot slot) { return 1; } @Override - public int getEnchantability() { + public int getEnchantmentValue() { return 12; } @Override - public SoundEvent getSoundEvent() { - return ArmorMaterial.LEATHER.getSoundEvent(); + public SoundEvent getEquipSound() { + return ArmorMaterials.LEATHER.getEquipSound(); } @Override - public Ingredient getRepairMaterial() { - return Ingredient.fromStacks(new ItemStack(Items.BLACK_WOOL)); + public Ingredient getRepairIngredient() { + return Ingredient.of(new ItemStack(Items.BLACK_WOOL)); } @Override @@ -80,29 +87,39 @@ public Item setLore(String tag) { @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new StringTextComponent("")); - tooltip.add(new StringTextComponent("" + TextFormatting.DARK_PURPLE + TextFormatting.ITALIC + I18n.format(this.loreTag))); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } public TopHatItem(Properties builderIn) { - super(Material.INSTANCE, EquipmentSlotType.HEAD, builderIn); + super(Material.INSTANCE, EquipmentSlot.HEAD, builderIn); } - TopHatModel model = null; - @OnlyIn(Dist.CLIENT) - @Override - public TopHatModel getArmorModel(LivingEntity entity, ItemStack stack, EquipmentSlotType slot, BipedModel defaultModel) { - if (model == null) model = new TopHatModel(); - return model; + @Override + public void initializeClient(java.util.function.Consumer consumer) { + consumer.accept(new IItemRenderProperties() { + @Override + public TopHatModel getArmorModel(LivingEntity entity, ItemStack itemStack, EquipmentSlot armorSlot, HumanoidModel _default) { + float pticks = Minecraft.getInstance().getFrameTime(); + float f = Mth.rotLerp(pticks, entity.yBodyRotO, entity.yBodyRot); + float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); + float netHeadYaw = f1 - f; + float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); + Registry.TOP_HAT_MODEL.slot = slot; + Registry.TOP_HAT_MODEL.copyFromDefault(_default); + Registry.TOP_HAT_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return Registry.TOP_HAT_MODEL; + } + }); } @OnlyIn(Dist.CLIENT) @Override - public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlotType slot, String type) { + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { return Eidolon.MODID + ":textures/entity/hat.png"; } } diff --git a/src/main/java/elucent/eidolon/item/UnholySymbolItem.java b/src/main/java/elucent/eidolon/item/UnholySymbolItem.java index fdb161c..3482fd7 100644 --- a/src/main/java/elucent/eidolon/item/UnholySymbolItem.java +++ b/src/main/java/elucent/eidolon/item/UnholySymbolItem.java @@ -1,18 +1,21 @@ package elucent.eidolon.item; -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.item.SwordItem; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.World; +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.item.model.UnholySymbolModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import java.util.List; +import net.minecraft.world.item.Item.Properties; public class UnholySymbolItem extends ItemBase { public UnholySymbolItem(Properties builderIn) { @@ -28,4 +31,22 @@ public boolean hasContainerItem(ItemStack stack) { public ItemStack getContainerItem(ItemStack stack) { return stack.copy(); } + + @OnlyIn(Dist.CLIENT) + public static class UnholySymbolItemRenderer extends BlockEntityWithoutLevelRenderer { + static final UnholySymbolModel MODEL = new UnholySymbolModel(); + + public UnholySymbolItemRenderer(BlockEntityRenderDispatcher berd, EntityModelSet ems) { + super(berd, ems); + } + + @Override + public void renderByItem(ItemStack stack, ItemTransforms.TransformType type, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay) { + RenderType rendertype = RenderType.entityCutoutNoCullZOffset(new ResourceLocation(Eidolon.MODID, "textures/item/unholy_symbol_base.png")); + matrixStack.pushPose(); + matrixStack.scale(1.0F, -1.0F, -1.0F); + MODEL.renderToBuffer(matrixStack, buffer.getBuffer(rendertype), combinedLight, combinedOverlay, 1, 1, 1, 1); + matrixStack.popPose(); + } + } } diff --git a/src/main/java/elucent/eidolon/item/WandItem.java b/src/main/java/elucent/eidolon/item/WandItem.java index 0b6d35c..02f64a5 100644 --- a/src/main/java/elucent/eidolon/item/WandItem.java +++ b/src/main/java/elucent/eidolon/item/WandItem.java @@ -1,9 +1,10 @@ package elucent.eidolon.item; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.Enchantments; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.item.ItemStack; + +import net.minecraft.world.item.Item.Properties; public class WandItem extends ItemBase { public WandItem(Properties properties) { @@ -11,7 +12,7 @@ public WandItem(Properties properties) { } @Override - public int getItemEnchantability() { + public int getEnchantmentValue() { return 20; } diff --git a/src/main/java/elucent/eidolon/item/WarlockRobesItem.java b/src/main/java/elucent/eidolon/item/WarlockRobesItem.java index 29eb501..7df0523 100644 --- a/src/main/java/elucent/eidolon/item/WarlockRobesItem.java +++ b/src/main/java/elucent/eidolon/item/WarlockRobesItem.java @@ -4,31 +4,34 @@ import elucent.eidolon.Registry; import elucent.eidolon.item.model.WarlockArmorModel; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.entity.model.BipedModel; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.item.ArmorItem; -import net.minecraft.item.ArmorMaterial; -import net.minecraft.item.IArmorMaterial; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.MathHelper; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterials; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.IItemRenderProperties; +import net.minecraftforge.common.extensions.IForgeItem; +import net.minecraft.world.item.Item.Properties; -public class WarlockRobesItem extends ArmorItem { +public class WarlockRobesItem extends ArmorItem implements IForgeItem { private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; - public static class Material implements IArmorMaterial { + public static class Material implements ArmorMaterial { @Override - public int getDurability(EquipmentSlotType slot) { + public int getDurabilityForSlot(EquipmentSlot slot) { return MAX_DAMAGE_ARRAY[slot.getIndex()] * 21; } @Override - public int getDamageReductionAmount(EquipmentSlotType slot) { + public int getDefenseForSlot(EquipmentSlot slot) { switch (slot) { case CHEST: return 7; @@ -42,18 +45,18 @@ public int getDamageReductionAmount(EquipmentSlotType slot) { } @Override - public int getEnchantability() { + public int getEnchantmentValue() { return 25; } @Override - public SoundEvent getSoundEvent() { - return ArmorMaterial.LEATHER.getSoundEvent(); + public SoundEvent getEquipSound() { + return ArmorMaterials.LEATHER.getEquipSound(); } @Override - public Ingredient getRepairMaterial() { - return Ingredient.fromStacks(new ItemStack(Registry.WICKED_WEAVE.get())); + public Ingredient getRepairIngredient() { + return Ingredient.of(new ItemStack(Registry.WICKED_WEAVE.get())); } @Override @@ -74,28 +77,32 @@ public float getKnockbackResistance() { public static final Material INSTANCE = new Material(); } - public WarlockRobesItem(EquipmentSlotType slot, Properties builderIn) { + public WarlockRobesItem(EquipmentSlot slot, Properties builderIn) { super(Material.INSTANCE, slot, builderIn); - } - - WarlockArmorModel model = null; + } @OnlyIn(Dist.CLIENT) - @Override - public WarlockArmorModel getArmorModel(LivingEntity entity, ItemStack stack, EquipmentSlotType slot, BipedModel defaultModel) { - if (model == null) model = new WarlockArmorModel(slot); - float pticks = Minecraft.getInstance().getRenderPartialTicks(); - float f = MathHelper.interpolateAngle(pticks, entity.prevRenderYawOffset, entity.renderYawOffset); - float f1 = MathHelper.interpolateAngle(pticks, entity.prevRotationYawHead, entity.rotationYawHead); - float netHeadYaw = f1 - f; - float netHeadPitch = MathHelper.lerp(pticks, entity.prevRotationPitch, entity.rotationPitch); - model.setRotationAngles(entity, entity.limbSwing, entity.limbSwingAmount, entity.ticksExisted + pticks, netHeadYaw, netHeadPitch); - return model; - } + @Override + public void initializeClient(java.util.function.Consumer consumer) { + consumer.accept(new IItemRenderProperties() { + @Override + public WarlockArmorModel getArmorModel(LivingEntity entity, ItemStack itemStack, EquipmentSlot armorSlot, HumanoidModel _default) { + float pticks = Minecraft.getInstance().getFrameTime(); + float f = Mth.rotLerp(pticks, entity.yBodyRotO, entity.yBodyRot); + float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); + float netHeadYaw = f1 - f; + float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); + Registry.WARLOCK_ARMOR_MODEL.slot = slot; + Registry.WARLOCK_ARMOR_MODEL.copyFromDefault(_default); + Registry.WARLOCK_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return Registry.WARLOCK_ARMOR_MODEL; + } + }); + } @OnlyIn(Dist.CLIENT) @Override - public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlotType slot, String type) { + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { return Eidolon.MODID + ":textures/entity/warlock_robes.png"; } } diff --git a/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java b/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java new file mode 100644 index 0000000..61723c9 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java @@ -0,0 +1,113 @@ +package elucent.eidolon.item.curio; + +import java.util.Random; + +import elucent.eidolon.Registry; +import elucent.eidolon.entity.AngelArrowEntity; +import elucent.eidolon.item.ItemBase; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ArrowItem; +import net.minecraft.world.item.BowItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.stats.Stats; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.entity.player.ArrowLooseEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import top.theillusivec4.curios.api.CuriosApi; + +import net.minecraft.world.item.Item.Properties; + +public class AngelSightItem extends ItemBase { + static Random random = new Random(); + + public AngelSightItem(Properties properties) { + super(properties); + MinecraftForge.EVENT_BUS.addListener(AngelSightItem::onLoose); + } + + @SubscribeEvent + public static void onLoose(ArrowLooseEvent event) { + Player player = event.getPlayer(); + ItemStack stack = event.getBow(), ammo = player.getProjectile(stack); + Level world = event.getWorld(); + + if (!event.hasAmmo()) return; + + if (ammo.isEmpty()) { + ammo = new ItemStack(Items.ARROW); + } + + if (!CuriosApi.getCuriosHelper().findEquippedCurio(Registry.ANGELS_SIGHT.get(), event.getEntityLiving()).isPresent()) + return; + + float f = BowItem.getPowerForTime(event.getCharge()); + if (!((double)f < 0.1D)) { + boolean flag1 = player.getAbilities().instabuild || (ammo.getItem() instanceof ArrowItem && ((ArrowItem) ammo.getItem()).isInfinite(ammo, stack, player)); + if (!world.isClientSide) { + ArrowItem arrowitem = (ArrowItem) (ammo.getItem() instanceof ArrowItem ? ammo.getItem() : Items.ARROW); + AbstractArrow innerarrow = arrowitem.createArrow(world, ammo, player); + innerarrow = ((BowItem)stack.getItem()).customArrow(innerarrow); + AngelArrowEntity abstractarrowentity = new AngelArrowEntity(world, player); + abstractarrowentity.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, f * 3.0F, 1.0F); + if (f == 1.0F) { + innerarrow.setCritArrow(true); + abstractarrowentity.setCritArrow(true); + } + + int j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack); + if (j > 0) { + innerarrow.setBaseDamage(innerarrow.getBaseDamage() + (double) j * 0.5D + 0.5D); + } + + int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack); + if (k > 0) { + innerarrow.setKnockback(k); + } + + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) { + innerarrow.setSecondsOnFire(100); + } + abstractarrowentity.setArrow(innerarrow); + + stack.hurtAndBreak(1, player, (p) -> { + p.broadcastBreakEvent(player.getUsedItemHand()); + }); + if (flag1 || player.getAbilities().instabuild && (stack.getItem() == Items.SPECTRAL_ARROW || stack.getItem() == Items.TIPPED_ARROW)) { + abstractarrowentity.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + + world.addFreshEntity(abstractarrowentity); + } + + world.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 1.2F) + f * 0.5F); + if (!flag1 && !player.getAbilities().instabuild) { + ammo.shrink(1); + if (ammo.isEmpty()) { + player.getInventory().removeItem(ammo); + } + } + + player.awardStat(Stats.ITEM_USED.get(stack.getItem())); + } + event.setCanceled(true); + } + + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { + return new EidolonCurio(stack) { + @Override + public boolean canRightClickEquip() { + return true; + } + }; + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java index 8c92737..90fcd49 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java @@ -1,30 +1,20 @@ package elucent.eidolon.item.curio; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.GlobalEntityTypeAttributes; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.*; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraftforge.common.MinecraftForge; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.living.LivingAttackEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.items.IItemHandlerModifiable; -import top.theillusivec4.curios.api.CuriosApi; -import top.theillusivec4.curios.api.type.capability.ICurio; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class BasicAmuletItem extends Item { UUID ATTR_ID = new UUID(1821688469367197801l, 2986247575840977557l); @@ -33,7 +23,7 @@ public BasicAmuletItem(Properties properties) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java b/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java index 9b7d9d2..88d2f9c 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java @@ -1,18 +1,20 @@ package elucent.eidolon.item.curio; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class BasicBeltItem extends ItemBase { UUID ATTR_ID = new UUID(5892388994722937059l, 8235504439637777033l); @@ -21,7 +23,7 @@ public BasicBeltItem(Properties properties) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java b/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java index c60ed88..571160e 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java @@ -1,18 +1,20 @@ package elucent.eidolon.item.curio; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import top.theillusivec4.curios.api.type.capability.ICurio; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class BasicRingItem extends Item { UUID ATTR_ID = new UUID(7207179027447911419l, 1628308750126455317l); @@ -21,7 +23,7 @@ public BasicRingItem(Properties properties) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/EidolonCurio.java b/src/main/java/elucent/eidolon/item/curio/EidolonCurio.java index 89568e8..1fa33f6 100644 --- a/src/main/java/elucent/eidolon/item/curio/EidolonCurio.java +++ b/src/main/java/elucent/eidolon/item/curio/EidolonCurio.java @@ -1,15 +1,13 @@ package elucent.eidolon.item.curio; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.core.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import top.theillusivec4.curios.api.CuriosCapability; import top.theillusivec4.curios.api.type.capability.ICurio; -import javax.annotation.Nonnull; - public class EidolonCurio implements ICurio, ICapabilityProvider { private final ItemStack stack; @@ -26,4 +24,9 @@ public LazyOptional getCapability(Capability cap) { public LazyOptional getCapability(Capability cap, Direction side) { return getCapability(cap); } + + @Override + public ItemStack getStack() { + return stack; + } } diff --git a/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java b/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java new file mode 100644 index 0000000..d1a147b --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java @@ -0,0 +1,24 @@ +package elucent.eidolon.item.curio; + +import elucent.eidolon.item.ItemBase; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + +import net.minecraft.world.item.Item.Properties; + +public class EnervatingRingItem extends ItemBase { + public EnervatingRingItem(Properties properties) { + super(properties); + } + + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { + return new EidolonCurio(stack) { + @Override + public boolean canRightClickEquip() { + return true; + } + }; + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java b/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java index 39c749d..dc615a4 100644 --- a/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java +++ b/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java @@ -2,21 +2,16 @@ import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.potion.Effects; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; -import net.minecraftforge.event.entity.living.PotionEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class GlassHandItem extends ItemBase { public GlassHandItem(Properties properties) { @@ -29,14 +24,14 @@ public static void onHurt(LivingHurtEvent event) { if (CuriosApi.getCuriosHelper().findEquippedCurio(Registry.GLASS_HAND.get(), event.getEntityLiving()).isPresent()) { event.setAmount(event.getAmount() * 5); } - if (event.getSource().getTrueSource() instanceof LivingEntity && - CuriosApi.getCuriosHelper().findEquippedCurio(Registry.GLASS_HAND.get(), (LivingEntity)event.getSource().getTrueSource()).isPresent()) { + if (event.getSource().getEntity() instanceof LivingEntity && + CuriosApi.getCuriosHelper().findEquippedCurio(Registry.GLASS_HAND.get(), (LivingEntity)event.getSource().getEntity()).isPresent()) { event.setAmount(event.getAmount() * 2); } } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public boolean canRightClickEquip() { diff --git a/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java b/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java index e50c077..86816d2 100644 --- a/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java @@ -1,26 +1,25 @@ package elucent.eidolon.item.curio; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.DamageSource; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class GravityBeltItem extends ItemBase { UUID ATTR_ID = new UUID(6937061617091731127l, 7120126291930051139l); @@ -37,7 +36,7 @@ public static void onFall(LivingFallEvent event) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java b/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java index ab3952e..794b6b3 100644 --- a/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java +++ b/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java @@ -1,49 +1,57 @@ package elucent.eidolon.item.curio; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.potion.Effects; -import net.minecraftforge.common.ForgeMod; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.effect.MobEffects; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; -import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.PotionEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; +import net.minecraft.world.item.Item.Properties; + public class MindShieldingPlateItem extends ItemBase { public MindShieldingPlateItem(Properties properties) { super(properties); MinecraftForge.EVENT_BUS.addListener(MindShieldingPlateItem::onPotion); MinecraftForge.EVENT_BUS.addListener(MindShieldingPlateItem::onClone); + MinecraftForge.EVENT_BUS.addListener(MindShieldingPlateItem::onDropXP); } @SubscribeEvent public static void onPotion(PotionEvent.PotionApplicableEvent event) { - if (event.getPotionEffect().getPotion() == Effects.NAUSEA && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.MIND_SHIELDING_PLATE.get(), event.getEntityLiving()).isPresent()) { + if (event.getPotionEffect().getEffect() == MobEffects.CONFUSION && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.MIND_SHIELDING_PLATE.get(), event.getEntityLiving()).isPresent()) { event.setResult(Event.Result.DENY); } } + static final int LEVEL_FLAG = 1 << 30; + @SubscribeEvent public static void onClone(PlayerEvent.Clone event) { - if (event.getOriginal().experienceLevel > 0 && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.MIND_SHIELDING_PLATE.get(), event.getEntityLiving()).isPresent()) { - event.getPlayer().experienceLevel = event.getOriginal().experienceLevel * 3 / 4; - event.getPlayer().experience = event.getOriginal().experience * 3 / 4; + if ((event.getOriginal().experienceLevel & LEVEL_FLAG) != 0) { + event.getPlayer().experienceLevel = event.getOriginal().experienceLevel & ~LEVEL_FLAG; + event.getPlayer().experienceProgress = event.getOriginal().experienceProgress; + } + } + + @SubscribeEvent + public static void onDropXP(LivingExperienceDropEvent event) { + if (event.getEntity() instanceof Player && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.MIND_SHIELDING_PLATE.get(), event.getEntityLiving()).isPresent()) { + ((Player)event.getEntity()).experienceLevel |= LEVEL_FLAG; + event.setCanceled(true); } } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public boolean canRightClickEquip() { diff --git a/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java b/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java index 9d676bd..a03e22c 100644 --- a/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java +++ b/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java @@ -1,19 +1,20 @@ package elucent.eidolon.item.curio; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class PrestigiousPalmItem extends ItemBase { UUID ATTR_ID = new UUID(297661999713141389l, 6434109711109552363l); @@ -22,7 +23,7 @@ public PrestigiousPalmItem(Properties properties) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java b/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java index 68cc31d..065a9f1 100644 --- a/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java @@ -1,31 +1,30 @@ package elucent.eidolon.item.curio; +import java.util.Random; +import java.util.UUID; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraftforge.common.ForgeMod; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import java.util.Random; -import java.util.UUID; +import net.minecraft.world.item.Item.Properties; public class ResoluteBeltItem extends ItemBase { UUID ATTR_ID = new UUID(3701779382882225399l, 5035874982077300549l); @@ -39,16 +38,16 @@ public ResoluteBeltItem(Properties properties) { @SubscribeEvent public static void onHurt(LivingHurtEvent event) { - if (event.getSource().getTrueSource() instanceof LivingEntity && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.RESOLUTE_BELT.get(), event.getEntityLiving()).isPresent()) { - LivingEntity entity = (LivingEntity)event.getSource().getTrueSource(); - Vector3d diff = event.getEntityLiving().getPositionVec().subtract(entity.getPositionVec()).mul(1, 0, 1).normalize(); - entity.applyKnockback(0.8f, diff.x, diff.z); - if (!entity.world.isRemote) entity.world.playSound(null, entity.getPosition(), SoundEvents.ENTITY_IRON_GOLEM_HURT, SoundCategory.PLAYERS, 1.0f, 1.9f + 0.2f * random.nextFloat()); + if (event.getSource().getEntity() instanceof LivingEntity && CuriosApi.getCuriosHelper().findEquippedCurio(Registry.RESOLUTE_BELT.get(), event.getEntityLiving()).isPresent()) { + LivingEntity entity = (LivingEntity)event.getSource().getEntity(); + Vec3 diff = event.getEntityLiving().position().subtract(entity.position()).multiply(1, 0, 1).normalize(); + entity.knockback(0.8f, diff.x, diff.z); + if (!entity.level.isClientSide) entity.level.playSound(null, entity.blockPosition(), SoundEvents.IRON_GOLEM_HURT, SoundSource.PLAYERS, 1.0f, 1.9f + 0.2f * random.nextFloat()); } } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public Multimap getAttributeModifiers(String identifier) { diff --git a/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java index 834850d..7f61b44 100644 --- a/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java @@ -1,20 +1,33 @@ package elucent.eidolon.item.curio; +import javax.annotation.Nonnull; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.datafixers.util.Either; +import com.mojang.math.Matrix4f; + import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.AbstractGui; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.EnderPearlEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.StringTextComponent; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.TextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.client.event.RenderTooltipEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; @@ -22,17 +35,14 @@ import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; -import top.theillusivec4.curios.api.CuriosApi; -import top.theillusivec4.curios.api.CuriosCapability; -import top.theillusivec4.curios.api.type.capability.ICurio; -import javax.annotation.Nonnull; +import net.minecraft.world.item.Item.Properties; public class SanguineAmuletItem extends ItemBase { public SanguineAmuletItem(Properties properties) { super(properties); DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> { - MinecraftForge.EVENT_BUS.addListener(SanguineAmuletItem::addTooltip); + MinecraftForgeClient.registerTooltipComponentFactory(SanguineAmuletTooltipInfo.class, SanguineAmuletTooltipComponent::new); MinecraftForge.EVENT_BUS.addListener(SanguineAmuletItem::renderTooltip); return null; }); @@ -46,33 +56,33 @@ static int getCharge(ItemStack stack) { } static void addCharge(ItemStack stack, int diff) { - int newCharge = MathHelper.clamp(getCharge(stack) + diff, 0, 40); + int newCharge = Mth.clamp(getCharge(stack) + diff, 0, 40); stack.getOrCreateTag().putInt("charge", newCharge); } static void setCharge(ItemStack stack, int charge) { - int newCharge = MathHelper.clamp(charge, 0, 40); + int newCharge = Mth.clamp(charge, 0, 40); stack.getOrCreateTag().putInt("charge", newCharge); } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public void curioTick(String type, int index, LivingEntity entity) { - if (!entity.world.isRemote) { - if (entity.ticksExisted % 80 == 0 && - entity.getHealth() == entity.getMaxHealth() && - entity instanceof PlayerEntity && ((PlayerEntity) entity).getFoodStats().getFoodLevel() >= 18 && + if (!entity.level.isClientSide) { + if (entity.tickCount % 80 == 0 && + entity.getHealth() >= entity.getMaxHealth() - 0.0001 && + entity instanceof Player && ((Player) entity).getFoodData().getFoodLevel() >= 18 && getCharge(stack) < 40) { - PlayerEntity player = (PlayerEntity) entity; - float f = player.getFoodStats().getSaturationLevel() > 0 ? - Math.min(4 * player.getFoodStats().getSaturationLevel(), 16.0F) : 4.0f; - player.addExhaustion(f); + Player player = (Player) entity; + float f = player.getFoodData().getSaturationLevel() > 0 ? + Math.min(4 * player.getFoodData().getSaturationLevel(), 16.0F) : 4.0f; + player.causeFoodExhaustion(f); addCharge(stack, 1); - EnderPearlEntity e; + ThrownEnderpearl e; } - if (entity.ticksExisted % 10 == 0 && + if (entity.tickCount % 10 == 0 && getCharge(stack) > 0 && entity.getHealth() < entity.getMaxHealth()) { int taken = (int) Math.min(1, entity.getMaxHealth() - entity.getHealth()); addCharge(stack, -taken); @@ -87,13 +97,13 @@ public boolean canSync(String identifier, int index, LivingEntity livingEntity) } @Nonnull - public CompoundNBT writeSyncData() { - CompoundNBT nbt = new CompoundNBT(); + public CompoundTag writeSyncData() { + CompoundTag nbt = new CompoundTag(); nbt.putInt("charge", getCharge(stack)); return nbt; } - public void readSyncData(CompoundNBT compound) { + public void readSyncData(CompoundTag compound) { setCharge(stack, compound.getInt("charge")); } @@ -103,36 +113,60 @@ public boolean canRightClickEquip() { } }; } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void addTooltip(ItemTooltipEvent event) { - if (event.getItemStack().getItem() == Registry.SANGUINE_AMULET.get()) { - int charge = getCharge(event.getItemStack()); - if (charge > 0) event.getToolTip().add(new StringTextComponent(" ")); - for (int i = 0; i < charge; i += 20) { - event.getToolTip().add(new StringTextComponent(" ")); - } - } + + public static class SanguineAmuletTooltipInfo implements TooltipComponent { + ItemStack stack; + int maxWidth; + + public SanguineAmuletTooltipInfo(ItemStack stack, int maxWidth) { + this.stack = stack; + this.maxWidth = maxWidth; + } } + + public static class SanguineAmuletTooltipComponent implements ClientTooltipComponent { + ItemStack stack; + int maxWidth; + public SanguineAmuletTooltipComponent(SanguineAmuletTooltipInfo info) { + this.stack = info.stack; + this.maxWidth = info.maxWidth; + } + + @Override + public int getHeight() { + int charge = getCharge(stack); + int rows = (charge + 19) / 20; + return 8 + 12 * rows; + } - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public static void renderTooltip(RenderTooltipEvent.PostText event) { - ItemStack stack = event.getStack(); - if (stack.getItem() == Registry.SANGUINE_AMULET.get()) { + @Override + public int getWidth(Font font) { + return maxWidth; + } + + @Override + public void renderImage(Font font, int x, int y, PoseStack poseStack, ItemRenderer itemRender, int p_194053_) { Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(new ResourceLocation("minecraft", "textures/gui/icons.png")); - int charge = getCharge(event.getStack()); + RenderSystem.setShaderTexture(0, new ResourceLocation("minecraft", "textures/gui/icons.png")); + int charge = getCharge(stack); int rows = (charge + 19) / 20; for (int i = 0; i < charge; i += 20) { - for (int j = 0; j < MathHelper.clamp(charge - i, 0, 20); j += 2) { + for (int j = 0; j < Mth.clamp(charge - i, 0, 20); j += 2) { if (charge - (i + j) == 1) { - AbstractGui.blit(event.getMatrixStack(), event.getX() - 1 + j / 2 * 8, event.getY() + (event.getLines().size() - rows) * (event.getFontRenderer().FONT_HEIGHT + 1) + (i / 20) * 9 + 2, 61, 0, 9, 9, 256, 256); + GuiComponent.blit(poseStack, x - 1 + j / 2 * 8, y + (i / 20) * 9 + 2, 61, 0, 9, 9, 256, 256); } else - AbstractGui.blit(event.getMatrixStack(), event.getX() - 1 + j / 2 * 8, event.getY() + (event.getLines().size() - rows) * (event.getFontRenderer().FONT_HEIGHT + 1) + (i / 20) * 9 + 2, 52, 0, 9, 9, 256, 256); + GuiComponent.blit(poseStack, x - 1 + j / 2 * 8, y + (i / 20) * 9 + 2, 52, 0, 9, 9, 256, 256); } } + } + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void renderTooltip(RenderTooltipEvent.GatherComponents event) { + ItemStack stack = event.getItemStack(); + if (stack.getItem() == Registry.SANGUINE_AMULET.get()) { + event.getTooltipElements().add(Either.right(new SanguineAmuletTooltipInfo(stack, event.getMaxWidth()))); } } } diff --git a/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java b/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java new file mode 100644 index 0000000..d1d31d3 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java @@ -0,0 +1,59 @@ +package elucent.eidolon.item.curio; + +import elucent.eidolon.Registry; +import elucent.eidolon.entity.SpellProjectileEntity; +import elucent.eidolon.item.ItemBase; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import top.theillusivec4.curios.api.CuriosApi; + +import net.minecraft.world.item.Item.Properties; + +public class TerminusMirrorItem extends ItemBase { + public TerminusMirrorItem(Properties properties) { + super(properties); + MinecraftForge.EVENT_BUS.addListener(TerminusMirrorItem::onDamage); + } + + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { + return new EidolonCurio(stack) { + @Override + public boolean canRightClickEquip() { + return true; + } + }; + } + + @SubscribeEvent + public static void onDamage(LivingAttackEvent event) { + if (event.getEntityLiving() instanceof Player) { + CuriosApi.getCuriosHelper().getEquippedCurios(event.getEntityLiving()).resolve().ifPresent((slots) -> { + boolean hasVoid = false; + int i; + for (i = 0; i < slots.getSlots(); i ++) { + if (slots.getStackInSlot(i).getItem() == Registry.TERMINUS_MIRROR.get()) { + hasVoid = true; + break; + } + } + ItemStack stack = slots.getStackInSlot(i); + if (hasVoid && + (event.getSource().getDirectEntity() instanceof Projectile + || event.getSource().getDirectEntity() instanceof SpellProjectileEntity)) { + event.setCanceled(true); + if (!event.getEntity().getCommandSenderWorld().isClientSide) + event.getEntity().getCommandSenderWorld().playSound(null, event.getEntity().blockPosition(), SoundEvents.WITHER_HURT, SoundSource.PLAYERS, 1.0f, 0.75f); + } + }); + } + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java index 6faa254..306452c 100644 --- a/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java @@ -3,37 +3,24 @@ import elucent.eidolon.Registry; import elucent.eidolon.entity.SpellProjectileEntity; import elucent.eidolon.item.ItemBase; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.AbstractGui; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.EnderPearlEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.*; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.StringTextComponent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.RenderTooltipEvent; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.LlamaSpit; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.ShulkerBullet; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.event.entity.living.LivingAttackEvent; -import net.minecraftforge.event.entity.living.LivingHurtEvent; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; import top.theillusivec4.curios.api.CuriosApi; -import top.theillusivec4.curios.api.type.capability.ICurio; -import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler; -import javax.annotation.Nonnull; +import net.minecraft.world.item.Item.Properties; public class VoidAmuletItem extends ItemBase { public VoidAmuletItem(Properties properties) { @@ -53,11 +40,11 @@ static void setCooldown(ItemStack stack, int cooldown) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public void curioTick(String type, int index, LivingEntity entity) { - if (!entity.world.isRemote) { + if (!entity.level.isClientSide) { if (getCooldown(stack) > 0) setCooldown(stack, getCooldown(stack) - 1); } } @@ -71,7 +58,7 @@ public boolean canRightClickEquip() { @SubscribeEvent public static void onDamage(LivingAttackEvent event) { - if (event.getEntityLiving() instanceof PlayerEntity) { + if (event.getEntityLiving() instanceof Player) { CuriosApi.getCuriosHelper().getEquippedCurios(event.getEntityLiving()).resolve().ifPresent((slots) -> { boolean hasVoid = false; int i; @@ -85,15 +72,15 @@ public static void onDamage(LivingAttackEvent event) { } ItemStack stack = slots.getStackInSlot(i); if (hasVoid && - (event.getSource().getImmediateSource() instanceof FireballEntity - || event.getSource().getImmediateSource() instanceof LlamaSpitEntity - || event.getSource().getImmediateSource() instanceof SmallFireballEntity - || event.getSource().getImmediateSource() instanceof ShulkerBulletEntity - || event.getSource().getImmediateSource() instanceof PotionEntity - || event.getSource().getImmediateSource() instanceof SpellProjectileEntity)) { + (event.getSource().getDirectEntity() instanceof LargeFireball + || event.getSource().getDirectEntity() instanceof LlamaSpit + || event.getSource().getDirectEntity() instanceof SmallFireball + || event.getSource().getDirectEntity() instanceof ShulkerBullet + || event.getSource().getDirectEntity() instanceof ThrownPotion + || event.getSource().getDirectEntity() instanceof SpellProjectileEntity)) { event.setCanceled(true); - if (!event.getEntity().getEntityWorld().isRemote) { - event.getEntity().getEntityWorld().playSound(null, event.getEntity().getPosition(), SoundEvents.ENTITY_WITHER_HURT, SoundCategory.PLAYERS, 1.0f, 0.75f); + if (!event.getEntity().getCommandSenderWorld().isClientSide) { + event.getEntity().getCommandSenderWorld().playSound(null, event.getEntity().blockPosition(), SoundEvents.WITHER_HURT, SoundSource.PLAYERS, 1.0f, 0.75f); setCooldown(stack, 200); } } diff --git a/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java b/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java index 68d491f..300c9de 100644 --- a/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java +++ b/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java @@ -2,23 +2,16 @@ import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.*; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.DamageSource; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.api.distmarker.Dist; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.damagesource.DamageSource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.IItemHandlerModifiable; import top.theillusivec4.curios.api.CuriosApi; -import top.theillusivec4.curios.api.type.capability.ICurio; + +import net.minecraft.world.item.Item.Properties; public class WardedMailItem extends ItemBase { public WardedMailItem(Properties properties) { @@ -27,7 +20,7 @@ public WardedMailItem(Properties properties) { } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) { + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { return new EidolonCurio(stack) { @Override public boolean canRightClickEquip() { @@ -38,13 +31,13 @@ public boolean canRightClickEquip() { @SubscribeEvent public static void onDamage(LivingAttackEvent event) { - if (event.getSource().isMagicDamage()) { + if (event.getSource().isMagic()) { CuriosApi.getCuriosHelper().getEquippedCurios(event.getEntityLiving()).resolve().ifPresent((slots) -> { boolean hasMail = false; for (int i = 0; i < slots.getSlots(); i ++) { if (slots.getStackInSlot(i).getItem() == Registry.WARDED_MAIL.get()) { event.setCanceled(true); - event.getEntityLiving().attackEntityFrom(new DamageSource(event.getSource().getDamageType()), event.getAmount()); + event.getEntityLiving().hurt(new DamageSource(event.getSource().getMsgId()), event.getAmount()); return; } } diff --git a/src/main/java/elucent/eidolon/item/model/ArmorModel.java b/src/main/java/elucent/eidolon/item/model/ArmorModel.java index 5472d4b..56ce4d8 100644 --- a/src/main/java/elucent/eidolon/item/model/ArmorModel.java +++ b/src/main/java/elucent/eidolon/item/model/ArmorModel.java @@ -1,66 +1,104 @@ -package elucent.eidolon.item.model;// Made with Blockbench 3.7.4 -// Exported for Minecraft version 1.15 -// Paste this class into your mod and generate all required imports - - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.renderer.entity.model.BipedModel; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.entity.LivingEntity; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.util.math.MathHelper; - -public abstract class ArmorModel extends BipedModel { - EquipmentSlotType slot; - - public ModelRenderer copyWithoutBoxes(ModelRenderer box) { - ModelRenderer newbox = new ModelRenderer(this); - newbox.setRotationPoint(box.rotationPointX, box.rotationPointY, box.rotationPointZ); - setRotationAngle(newbox, box.rotateAngleX, box.rotateAngleY, box.rotateAngleZ); - newbox.mirror = box.mirror; - newbox.showModel = box.showModel; - return newbox; - } - - public ArmorModel(EquipmentSlotType slot, int texWidth, int texHeight) { - super(0, 0, texWidth, texHeight); - this.slot = slot; - - bipedHead = copyWithoutBoxes(bipedHead); - bipedBody = copyWithoutBoxes(bipedBody); - bipedLeftArm = copyWithoutBoxes(bipedLeftArm); - bipedLeftLeg = copyWithoutBoxes(bipedLeftLeg); - bipedRightArm = copyWithoutBoxes(bipedRightArm); - bipedRightLeg = copyWithoutBoxes(bipedRightLeg); - } - - @Override - public void render(MatrixStack matrixStack, IVertexBuilder buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ - bipedHeadwear.showModel = false; - bipedBody.showModel = bipedLeftArm.showModel = bipedRightArm.showModel = - bipedHead.showModel = bipedLeftLeg.showModel = bipedRightLeg.showModel = false; - - if (slot == EquipmentSlotType.CHEST) { - bipedBody.showModel = true; - bipedLeftArm.showModel = true; - bipedRightArm.showModel = true; - } - - if (slot == EquipmentSlotType.HEAD) { - bipedHead.showModel = true; - } - - if (slot == EquipmentSlotType.FEET) { - bipedLeftLeg.showModel = true; - bipedRightLeg.showModel = true; - } - super.render(matrixStack, buffer, packedLight, packedOverlay, red, green, blue, alpha); - } - - public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) { - modelRenderer.rotateAngleX = x; - modelRenderer.rotateAngleY = y; - modelRenderer.rotateAngleZ = z; - } +package elucent.eidolon.item.model;// Made with Blockbench 3.7.4 +// Exported for Minecraft version 1.15 +// Paste this class into your mod and generate all required imports + + +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.EquipmentSlot; + +public abstract class ArmorModel extends HumanoidModel { + public EquipmentSlot slot; + ModelPart root, head, body, leftArm, rightArm, pelvis, leftLegging, rightLegging, leftFoot, rightFoot; + +// public ModelPart copyWithoutBoxes(ModelPart box) { +// ModelPart newbox = new ModelPart(this); +// newbox.setPos(box.x, box.y, box.z); +// setRotationAngle(newbox, box.xRot, box.yRot, box.zRot); +// newbox.mirror = box.mirror; +// newbox.visible = box.visible; +// return newbox; +// } + + public ArmorModel(ModelPart root) { + super(root); + this.root = root; + this.head = root.getChild("head"); + this.body = root.getChild("body"); + this.pelvis = root.getChild("pelvis"); + this.leftArm = root.getChild("left_arm"); + this.rightArm = root.getChild("right_arm"); + this.leftLegging = root.getChild("left_legging"); + this.rightLegging = root.getChild("right_legging"); + this.leftFoot = root.getChild("left_foot"); + this.rightFoot = root.getChild("right_foot"); + } + + public static PartDefinition createHumanoidAlias(MeshDefinition mesh) { + PartDefinition root = mesh.getRoot(); + root.addOrReplaceChild("body", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("pelvis", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("head", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("left_legging", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("left_foot", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("right_legging", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("right_foot", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("left_arm", new CubeListBuilder(), PartPose.ZERO); + root.addOrReplaceChild("right_arm", new CubeListBuilder(), PartPose.ZERO); + + return root; + } + + @Override + protected Iterable headParts() { + return slot == EquipmentSlot.HEAD ? ImmutableList.of(head) : ImmutableList.of(); + } + + @Override + protected Iterable bodyParts() { + if (slot == EquipmentSlot.CHEST) { + return ImmutableList.of(body, leftArm, rightArm); + } + else if (slot == EquipmentSlot.LEGS) { + return ImmutableList.of(leftLegging, rightLegging, pelvis); + } + else if (slot == EquipmentSlot.FEET) { + return ImmutableList.of(leftFoot, rightFoot); + } + else return ImmutableList.of(); + } + + @Override + public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ + super.renderToBuffer(matrixStack, buffer, packedLight, packedOverlay, red, green, blue, alpha); + } + + public void copyFromDefault(HumanoidModel model) { + body.copyFrom(model.body); + pelvis.copyFrom(model.body); + head.copyFrom(model.head); + leftArm.copyFrom(model.leftArm); + rightArm.copyFrom(model.rightArm); + leftLegging.copyFrom(leftLeg); + rightLegging.copyFrom(rightLeg); + leftFoot.copyFrom(leftLeg); + rightFoot.copyFrom(rightLeg); + } + + public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { + modelRenderer.xRot = x; + modelRenderer.yRot = y; + modelRenderer.zRot = z; + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java b/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java new file mode 100644 index 0000000..839018e --- /dev/null +++ b/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java @@ -0,0 +1,51 @@ +package elucent.eidolon.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.EquipmentSlot; + +public class SilverArmorModel extends ArmorModel { + public SilverArmorModel(ModelPart part) { + super(part); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition mesh = HumanoidModel.createMesh(new CubeDeformation(0), 0); + PartDefinition root = createHumanoidAlias(mesh); + + PartDefinition body = root.getChild("body"); + PartDefinition pelvis = root.getChild("pelvis"); + PartDefinition right_foot = root.getChild("right_foot"); + PartDefinition left_foot = root.getChild("left_foot"); + PartDefinition right_legging = root.getChild("right_legging"); + PartDefinition left_legging = root.getChild("left_legging"); + PartDefinition left_arm = root.getChild("left_arm"); + PartDefinition right_arm = root.getChild("right_arm"); + PartDefinition head = root.getChild("head"); + + PartDefinition chest = body.addOrReplaceChild("chest", CubeListBuilder.create().texOffs(16, 16).addBox(-4.0F, -12.0F, -2.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(1.0F)), PartPose.offset(0.0F, 12.0F, 0.0F)); + PartDefinition right_shoulder = right_arm.addOrReplaceChild("right_shoulder", new CubeListBuilder().mirror().texOffs(40, 16).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 5.0F, 4.0F, new CubeDeformation(1.0f)), PartPose.ZERO); + PartDefinition left_shoulder = left_arm.addOrReplaceChild("left_shoulder", new CubeListBuilder().texOffs(40, 16).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 5.0F, 4.0F, new CubeDeformation(1.0f)), PartPose.ZERO); + PartDefinition helm = head.addOrReplaceChild("helm", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(1.0F)), PartPose.ZERO); + PartDefinition guard = helm.addOrReplaceChild("guard", CubeListBuilder.create().texOffs(6, 41).addBox(-5.0F, -6.0F, -5.5F, 10.0F, 10.0F, 10.0F, new CubeDeformation(1.0F)), PartPose.offsetAndRotation(0.0F, -3.0F, 0.0F, 0.0F, 0.7854F, 0.0F)); + PartDefinition left_boot = left_foot.addOrReplaceChild("left_boot", new CubeListBuilder().texOffs(0, 22).mirror().addBox(-2.0F, 6.0F, -2.0F, 4.0F, 6.0F, 4.0F, new CubeDeformation(1.0f)), PartPose.ZERO); + PartDefinition right_boot = right_foot.addOrReplaceChild("right_boot", new CubeListBuilder().texOffs(0, 22).addBox(-2.0F, 6.0F, -2.0F, 4.0F, 6.0F, 4.0F, new CubeDeformation(1.0f)), PartPose.ZERO); + PartDefinition left_leg = left_legging.addOrReplaceChild("left_leg", new CubeListBuilder().texOffs(0, 32).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 9.0F, 4.0F, new CubeDeformation(0.5f)), PartPose.ZERO); + PartDefinition right_leg = right_legging.addOrReplaceChild("right_leg", new CubeListBuilder().texOffs(0, 32).mirror().addBox(-2.0F, 0.0F, -2.0F, 4.0F, 9.0F, 4.0F, new CubeDeformation(0.5f)), PartPose.ZERO); + PartDefinition codpiece = pelvis.addOrReplaceChild("codpiece", CubeListBuilder.create().texOffs(16, 32).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 5.0F, 4.0F, new CubeDeformation(0.5F)), PartPose.offset(0.0F, 7.0F, 0.0F)); + + return LayerDefinition.create(mesh, 64, 64); + } + + public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { + modelRenderer.xRot = x; + modelRenderer.yRot = y; + modelRenderer.zRot = z; + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/TopHatModel.java b/src/main/java/elucent/eidolon/item/model/TopHatModel.java index cfb80c7..124fc79 100644 --- a/src/main/java/elucent/eidolon/item/model/TopHatModel.java +++ b/src/main/java/elucent/eidolon/item/model/TopHatModel.java @@ -1,33 +1,42 @@ -package elucent.eidolon.item.model;// Made with Blockbench 3.7.4 -// Exported for Minecraft version 1.15 -// Paste this class into your mod and generate all required imports - - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.renderer.entity.model.BipedModel; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.inventory.EquipmentSlotType; - -public class TopHatModel extends ArmorModel { - private final ModelRenderer hat; - - public TopHatModel() { - super(EquipmentSlotType.HEAD, 64, 32); - textureWidth = 64; - textureHeight = 32; - - hat = new ModelRenderer(this); - hat.setRotationPoint(0.0F, -7.0F, 0.0F); - bipedHead.addChild(hat); - setRotationAngle(hat, -0.0873F, 0.0F, 0.0F); - hat.setTextureOffset(0, 0).addBox(-5.0F, -2.0F, -5.0F, 10.0F, 2.0F, 10.0F, 0.0F, false); - hat.setTextureOffset(0, 12).addBox(-4.0F, -12.0F, -4.0F, 8.0F, 10.0F, 8.0F, 0.0F, false); - } - - @Override - public void setRotationAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - // - } +package elucent.eidolon.item.model;// Made with Blockbench 3.7.4 +// Exported for Minecraft version 1.15 +// Paste this class into your mod and generate all required imports + + +import com.google.common.collect.ImmutableList; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.EquipmentSlot; + +public class TopHatModel extends ArmorModel { + public TopHatModel(ModelPart part) { + super(part); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition mesh = HumanoidModel.createMesh(new CubeDeformation(0), 0); + PartDefinition root = createHumanoidAlias(mesh); + + PartDefinition head = root.getChild("head"); + + PartDefinition hat = head.addOrReplaceChild("hat", CubeListBuilder.create() + .texOffs(0, 0).addBox(-5.0F, -2.0F, -5.0F, 10.0F, 2.0F, 10.0F, new CubeDeformation(0)) + .texOffs(0, 12).addBox(-4.0F, -12.0F, -4.0F, 8.0F, 10.0F, 8.0F, new CubeDeformation(0)), + PartPose.offsetAndRotation(0.0F, -7.0F, 0.0F, -0.0873F, 0.0F, 0.0F)); + + return LayerDefinition.create(mesh, 64, 32); + } + + @Override + public void setupAnim(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ + // + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java b/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java new file mode 100644 index 0000000..f417ea7 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java @@ -0,0 +1,228 @@ +package elucent.eidolon.item.model; + +// Made with Blockbench 3.8.4 +// Exported for Minecraft version 1.15 - 1.16 +// Paste this class into your mod and generate all required imports + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.world.entity.Entity; + +public class UnholySymbolModel extends EntityModel { +// private final ModelPart model; +// private final ModelPart watchTop; +// private final ModelPart cube_r1; +// private final ModelPart cube_r2; +// private final ModelPart cube_r3; +// private final ModelPart cube_r4; +// private final ModelPart cube_r5; +// private final ModelPart cube_r6; +// private final ModelPart cube_r7; +// private final ModelPart cube_r8; +// private final ModelPart cube_r9; +// private final ModelPart cube_r10; +// private final ModelPart cube_r11; +// private final ModelPart cube_r12; +// private final ModelPart cube_r13; +// private final ModelPart cube_r14; +// private final ModelPart watchBottom; +// private final ModelPart cube_r15; +// private final ModelPart cube_r16; +// private final ModelPart cube_r17; +// private final ModelPart cube_r18; +// private final ModelPart cube_r19; +// private final ModelPart cube_r20; +// private final ModelPart cube_r21; +// private final ModelPart cube_r22; +// private final ModelPart cube_r23; +// private final ModelPart cube_r24; + + public UnholySymbolModel() { +// texWidth = 32; +// texHeight = 16; +// +// model = new ModelPart(this); +// model.setPos(0.0F, 29.0F, 2.0F); +// setRotationAngle(model, -1.5708F, 0.0F, 0.0F); +// model.texOffs(12, 4).addBox(-1.5F, 0.55F, 3.0F, 3.0F, 3.0F, 2.0F, 0.0F, false); +// +// watchTop = new ModelPart(this); +// watchTop.setPos(0.0F, 2.0F, 4.0F); +// model.addChild(watchTop); +// setRotationAngle(watchTop, 0.0436F, 0.0F, 0.0F); +// watchTop.texOffs(12, 0).addBox(-3.5F, 0.0F, -6.0F, 7.0F, 1.0F, 3.0F, 0.0F, false); +// watchTop.texOffs(22, 4).addBox(-1.5F, 0.0F, -3.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r1 = new ModelPart(this); +// cube_r1.setPos(0.5F, 1.5F, -1.0F); +// watchTop.addChild(cube_r1); +// setRotationAngle(cube_r1, 0.0F, -0.3142F, 0.0F); +// cube_r1.texOffs(12, 9).addBox(1.75F, -0.97F, -3.65F, 1.0F, 1.0F, 1.0F, 0.0F, true); +// +// cube_r2 = new ModelPart(this); +// cube_r2.setPos(3.5901F, 1.05F, -3.2292F); +// watchTop.addChild(cube_r2); +// setRotationAngle(cube_r2, 0.0F, -2.1991F, 0.0F); +// cube_r2.texOffs(12, 9).addBox(-3.275F, -0.53F, 3.1F, 1.0F, 1.0F, 1.0F, 0.0F, true); +// +// cube_r3 = new ModelPart(this); +// cube_r3.setPos(-3.5901F, 1.05F, -3.2292F); +// watchTop.addChild(cube_r3); +// setRotationAngle(cube_r3, 0.0F, 2.1991F, 0.0F); +// cube_r3.texOffs(12, 13).addBox(2.275F, -0.51F, 3.1F, 1.0F, 1.0F, 1.0F, 0.0F, false); +// +// cube_r4 = new ModelPart(this); +// cube_r4.setPos(-0.5F, 1.5F, -1.0F); +// watchTop.addChild(cube_r4); +// setRotationAngle(cube_r4, 0.0F, 0.3142F, 0.0F); +// cube_r4.texOffs(12, 13).addBox(-2.75F, -0.97F, -3.65F, 1.0F, 1.0F, 1.0F, 0.0F, false); +// +// cube_r5 = new ModelPart(this); +// cube_r5.setPos(0.091F, 0.0F, -1.8839F); +// watchTop.addChild(cube_r5); +// setRotationAngle(cube_r5, 0.0F, -0.7854F, 0.0F); +// cube_r5.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); +// +// cube_r6 = new ModelPart(this); +// cube_r6.setPos(0.0F, 0.0F, -2.0F); +// watchTop.addChild(cube_r6); +// setRotationAngle(cube_r6, 0.0F, 0.7854F, 0.0F); +// cube_r6.texOffs(22, 4).addBox(0.259F, -0.005F, -0.2339F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r7 = new ModelPart(this); +// cube_r7.setPos(0.091F, 0.0F, -7.1161F); +// watchTop.addChild(cube_r7); +// setRotationAngle(cube_r7, 0.0F, -2.3562F, 0.0F); +// cube_r7.texOffs(22, 4).addBox(0.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); +// +// cube_r8 = new ModelPart(this); +// cube_r8.setPos(-0.091F, 0.0F, -7.1161F); +// watchTop.addChild(cube_r8); +// setRotationAngle(cube_r8, 0.0F, 2.3562F, 0.0F); +// cube_r8.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r9 = new ModelPart(this); +// cube_r9.setPos(0.0F, 0.0F, -7.0F); +// watchTop.addChild(cube_r9); +// setRotationAngle(cube_r9, 0.0F, 3.1416F, 0.0F); +// cube_r9.texOffs(22, 4).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r10 = new ModelPart(this); +// cube_r10.setPos(2.25F, 1.0F, -7.5F); +// watchTop.addChild(cube_r10); +// setRotationAngle(cube_r10, 1.5708F, -0.3142F, 0.0F); +// cube_r10.texOffs(4, 8).addBox(-0.5F, -0.01F, -0.5F, 1.0F, 7.0F, 1.0F, 0.0F, true); +// +// cube_r11 = new ModelPart(this); +// cube_r11.setPos(2.25F, 1.0F, -7.5F); +// watchTop.addChild(cube_r11); +// setRotationAngle(cube_r11, 1.5708F, -0.9425F, 0.0F); +// cube_r11.texOffs(4, 8).addBox(-0.5F, 0.0F, -0.51F, 1.0F, 7.0F, 1.0F, 0.0F, true); +// +// cube_r12 = new ModelPart(this); +// cube_r12.setPos(-3.5F, 1.0F, -3.25F); +// watchTop.addChild(cube_r12); +// setRotationAngle(cube_r12, 1.5708F, 1.5708F, 0.0F); +// cube_r12.texOffs(0, 8).addBox(-0.45F, 0.0F, -0.52F, 1.0F, 7.0F, 1.0F, 0.0F, false); +// +// cube_r13 = new ModelPart(this); +// cube_r13.setPos(-2.25F, 1.0F, -7.5F); +// watchTop.addChild(cube_r13); +// setRotationAngle(cube_r13, 1.5708F, 0.9425F, 0.0F); +// cube_r13.texOffs(8, 8).addBox(-0.5F, 0.0F, -0.49F, 1.0F, 7.0F, 1.0F, 0.0F, false); +// +// cube_r14 = new ModelPart(this); +// cube_r14.setPos(-2.25F, 1.0F, -7.5F); +// watchTop.addChild(cube_r14); +// setRotationAngle(cube_r14, 1.5708F, 0.3142F, 0.0F); +// cube_r14.texOffs(0, 8).addBox(-0.5F, 0.0F, -0.53F, 1.0F, 7.0F, 1.0F, 0.0F, false); +// +// watchBottom = new ModelPart(this); +// watchBottom.setPos(0.0F, 0.0F, 0.0F); +// model.addChild(watchBottom); +// watchBottom.texOffs(12, 0).addBox(-3.5F, 0.0F, -2.0F, 7.0F, 1.0F, 3.0F, 0.0F, false); +// watchBottom.texOffs(22, 4).addBox(-1.5F, 0.0F, 1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r15 = new ModelPart(this); +// cube_r15.setPos(1.9F, 1.5F, -4.0F); +// watchBottom.addChild(cube_r15); +// setRotationAngle(cube_r15, 2.3562F, 0.0F, -1.5708F); +// cube_r15.texOffs(0, 4).addBox(-0.5F, 2.3207F, -5.45F, 1.0F, 3.0F, 1.0F, 0.0F, false); +// cube_r15.texOffs(8, 4).addBox(-0.5F, 2.3207F, 2.175F, 1.0F, 3.0F, 1.0F, 0.0F, false); +// +// cube_r16 = new ModelPart(this); +// cube_r16.setPos(1.9F, 1.5F, -4.0F); +// watchBottom.addChild(cube_r16); +// setRotationAngle(cube_r16, 0.7854F, 0.0F, -1.5708F); +// cube_r16.texOffs(0, 4).addBox(-0.5F, -0.3543F, 7.125F, 1.0F, 3.0F, 1.0F, 0.0F, false); +// cube_r16.texOffs(4, 4).addBox(-0.5F, -0.3543F, -0.5F, 1.0F, 3.0F, 1.0F, 0.0F, false); +// +// cube_r17 = new ModelPart(this); +// cube_r17.setPos(2.0F, 1.5F, -4.0F); +// watchBottom.addChild(cube_r17); +// setRotationAngle(cube_r17, 0.0F, 0.0F, -1.5708F); +// cube_r17.texOffs(8, 0).addBox(-0.5F, -4.0F, -0.6F, 1.0F, 4.0F, 1.0F, 0.0F, false); +// +// cube_r18 = new ModelPart(this); +// cube_r18.setPos(3.5F, 1.5F, -2.5F); +// watchBottom.addChild(cube_r18); +// setRotationAngle(cube_r18, 1.5708F, 0.0F, -1.5708F); +// cube_r18.texOffs(4, 0).addBox(-0.5F, 0.0F, 6.6F, 1.0F, 4.0F, 1.0F, 0.0F, false); +// cube_r18.texOffs(4, 0).addBox(-0.5F, 0.025F, -0.625F, 1.0F, 4.0F, 1.0F, 0.0F, false); +// +// cube_r19 = new ModelPart(this); +// cube_r19.setPos(-2.0F, 1.5F, 3.0F); +// watchBottom.addChild(cube_r19); +// setRotationAngle(cube_r19, 0.0F, 0.0F, -1.5708F); +// cube_r19.texOffs(0, 0).addBox(-0.5F, 0.0F, -0.375F, 1.0F, 4.0F, 1.0F, 0.0F, false); +// +// cube_r20 = new ModelPart(this); +// cube_r20.setPos(0.091F, 0.0F, 2.1161F); +// watchBottom.addChild(cube_r20); +// setRotationAngle(cube_r20, 0.0F, -0.7854F, 0.0F); +// cube_r20.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); +// +// cube_r21 = new ModelPart(this); +// cube_r21.setPos(0.0F, 0.0F, 2.0F); +// watchBottom.addChild(cube_r21); +// setRotationAngle(cube_r21, 0.0F, 0.7854F, 0.0F); +// cube_r21.texOffs(22, 4).addBox(0.259F, -0.005F, -0.2339F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r22 = new ModelPart(this); +// cube_r22.setPos(0.091F, 0.0F, -3.1161F); +// watchBottom.addChild(cube_r22); +// setRotationAngle(cube_r22, 0.0F, -2.3562F, 0.0F); +// cube_r22.texOffs(22, 4).addBox(0.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); +// +// cube_r23 = new ModelPart(this); +// cube_r23.setPos(-0.091F, 0.0F, -3.1161F); +// watchBottom.addChild(cube_r23); +// setRotationAngle(cube_r23, 0.0F, 2.3562F, 0.0F); +// cube_r23.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, false); +// +// cube_r24 = new ModelPart(this); +// cube_r24.setPos(0.0F, 0.0F, -3.0F); +// watchBottom.addChild(cube_r24); +// setRotationAngle(cube_r24, 0.0F, 3.1416F, 0.0F); +// cube_r24.texOffs(22, 4).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); + } + + @Override + public void setupAnim(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ + //previously the render function, render code was moved to a method below + } + + @Override + public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ +// model.render(matrixStack, buffer, packedLight, packedOverlay); + } + + public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { + modelRenderer.xRot = x; + modelRenderer.yRot = y; + modelRenderer.zRot = z; + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java b/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java index 8f5c5f2..3b1d9f4 100644 --- a/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java +++ b/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java @@ -1,165 +1,77 @@ -package elucent.eidolon.item.model;// Made with Blockbench 3.7.4 -// Exported for Minecraft version 1.15 -// Paste this class into your mod and generate all required imports - - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.renderer.entity.model.BipedModel; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.util.math.MathHelper; - -public class WarlockArmorModel extends ArmorModel { - private ModelRenderer left_boot = null; - private ModelRenderer left_boot_cuff = null; - private ModelRenderer right_boot = null; - private ModelRenderer right_boot_cuff = null; - private ModelRenderer left_sleeve = null; - private ModelRenderer left_cuff = null; - private ModelRenderer right_sleeve = null; - private ModelRenderer right_cuff = null; - private ModelRenderer hat = null; - private ModelRenderer hatMid = null; - private ModelRenderer hatUpper = null; - private ModelRenderer hatTip = null; - private ModelRenderer cloak = null; - private ModelRenderer left_side = null; - private ModelRenderer right_side = null; - private ModelRenderer back_side = null; - - public WarlockArmorModel(EquipmentSlotType slot) { - super(slot, 64, 128); - - if (slot == EquipmentSlotType.FEET) { - right_boot = new ModelRenderer(this); - right_boot.setRotationPoint(0.0F, 0.0F, 0.0F); - bipedRightLeg.addChild(right_boot); - setRotationAngle(right_boot, 0.0F, 0.0873F, 0.0F); - right_boot.setTextureOffset(0, 84).addBox(-2.5F, 5.5F, -2.5F, 5.0F, 7.0F, 5.0F, 0.0F, false); - right_boot.setTextureOffset(0, 80).addBox(-2.5F, 9.5F, -3.5F, 5.0F, 3.0F, 1.0F, 0.0F, false); - - right_boot_cuff = new ModelRenderer(this); - right_boot_cuff.setRotationPoint(0.0F, 5.0F, 0.0F); - right_boot.addChild(right_boot_cuff); - setRotationAngle(right_boot_cuff, 0.0F, 0.0F, -0.0873F); - right_boot_cuff.setTextureOffset(20, 84).addBox(-3.0F, -1.0F, -3.0F, 6.0F, 2.0F, 6.0F, 0.0F, false); - - left_boot = new ModelRenderer(this); - left_boot.setRotationPoint(0.0F, 0.0F, 0.0F); - bipedLeftLeg.addChild(left_boot); - setRotationAngle(left_boot, 0.0F, -0.0873F, 0.0F); - left_boot.setTextureOffset(0, 84).addBox(-2.5F, 5.5F, -2.5F, 5.0F, 7.0F, 5.0F, 0.0F, false); - left_boot.setTextureOffset(0, 80).addBox(-2.5F, 9.5F, -3.5F, 5.0F, 3.0F, 1.0F, 0.0F, false); - - left_boot_cuff = new ModelRenderer(this); - left_boot_cuff.setRotationPoint(0.0F, 5.0F, 0.0F); - left_boot.addChild(left_boot_cuff); - setRotationAngle(left_boot_cuff, 0.0F, 0.0F, 0.0873F); - left_boot_cuff.setTextureOffset(20, 84).addBox(-3.0F, -1.0F, -3.0F, 6.0F, 2.0F, 6.0F, 0.0F, false); - } - - if (slot == EquipmentSlotType.CHEST) { - right_sleeve = new ModelRenderer(this); - right_sleeve.setRotationPoint(0.0F, 0.0F, 0.0F); - bipedRightArm.addChild(right_sleeve); - setRotationAngle(right_sleeve, 0.0F, 0.0F, 0.1745F); - right_sleeve.setTextureOffset(28, 38).addBox(-4.5F, -2.0F, -2.5F, 5.0F, 5.0F, 5.0F, 0.0F, false); - - right_cuff = new ModelRenderer(this); - right_cuff.setRotationPoint(-1.0F, 3.0F, 0.0F); - right_sleeve.addChild(right_cuff); - setRotationAngle(right_cuff, 0.0F, 0.0873F, 0.0873F); - right_cuff.setTextureOffset(28, 48).addBox(-4.5F, -0.5F, -3.0F, 6.0F, 2.0F, 6.0F, 0.0F, false); - - left_sleeve = new ModelRenderer(this); - left_sleeve.setRotationPoint(0.0F, 0.0F, 0.0F); - bipedLeftArm.addChild(left_sleeve); - setRotationAngle(left_sleeve, 0.0F, 0.0F, -0.1745F); - left_sleeve.setTextureOffset(28, 38).addBox(-0.5F, -2.0F, -2.5F, 5.0F, 5.0F, 5.0F, 0.0F, true); - - left_cuff = new ModelRenderer(this); - left_cuff.setRotationPoint(1.0F, 3.0F, 0.0F); - left_sleeve.addChild(left_cuff); - setRotationAngle(left_cuff, 0.0F, -0.0873F, -0.0873F); - left_cuff.setTextureOffset(28, 48).addBox(-1.5F, -0.5F, -3.0F, 6.0F, 2.0F, 6.0F, 0.0F, true); - - cloak = new ModelRenderer(this); - cloak.setRotationPoint(2.0F, 12.0F, 0.0F); - bipedBody.addChild(cloak); - cloak.setTextureOffset(0, 41).addBox(-6.5F, -12.499F, -2.501F, 9.0F, 15.0F, 5.0F, 0.0F, false); - cloak.setTextureOffset(28, 56).addBox(-7.0F, -12.5F, -3.0F, 10.0F, 8.0F, 6.0F, 0.0F, false); - - left_side = new ModelRenderer(this); - left_side.setRotationPoint(-5.0F, -4.5F, -3.0F); - cloak.addChild(left_side); - setRotationAngle(left_side, 0.0F, 0.0F, 0.1745F); - left_side.setTextureOffset(0, 64).addBox(-2.0F, 0.0F, 0.01F, 2.0F, 10.0F, 6.0F, 0.0F, false); - - right_side = new ModelRenderer(this); - right_side.setRotationPoint(1.0F, -4.5F, -3.0F); - cloak.addChild(right_side); - setRotationAngle(right_side, 0.0F, 0.0F, -0.1745F); - right_side.setTextureOffset(0, 64).addBox(0.0F, 0.0F, 0.01F, 2.0F, 10.0F, 6.0F, 0.0F, false); - - back_side = new ModelRenderer(this); - back_side.setRotationPoint(-2.0F, -4.5F, 1.0F); - cloak.addChild(back_side); - setRotationAngle(back_side, 0.1745F, 0.0F, 0.0F); - back_side.setTextureOffset(17, 70).addBox(-5.01F, 0.0F, 0.0F, 10.0F, 12.0F, 2.0F, 0.0F, false); - } - - if (slot == EquipmentSlotType.HEAD) { - hat = new ModelRenderer(this); - hat.setRotationPoint(0.0F, -7.0F, 0.0F); - bipedHead.addChild(hat); - setRotationAngle(hat, -0.1745F, 0.0F, -0.0873F); - hat.setTextureOffset(0, 0).addBox(-7.0F, -1.0F, -7.0F, 14.0F, 2.0F, 14.0F, 0.0F, false); - - hatMid = new ModelRenderer(this); - hatMid.setRotationPoint(0.0F, 0.0F, 0.0F); - hat.addChild(hatMid); - setRotationAngle(hatMid, -0.0873F, 0.0F, 0.0873F); - hatMid.setTextureOffset(0, 16).addBox(-4.5F, -5.75F, -4.5F, 9.0F, 6.0F, 9.0F, 0.0F, false); - - hatUpper = new ModelRenderer(this); - hatUpper.setRotationPoint(0.0F, -5.0F, 0.0F); - hatMid.addChild(hatUpper); - setRotationAngle(hatUpper, -0.1745F, 0.0F, 0.0436F); - hatUpper.setTextureOffset(0, 31).addBox(-3.0F, -4.0F, -3.0F, 6.0F, 4.0F, 6.0F, 0.0F, false); - - hatTip = new ModelRenderer(this); - hatTip.setRotationPoint(0.0F, -3.0F, 0.0F); - hatUpper.addChild(hatTip); - setRotationAngle(hatTip, -0.2618F, 0.0F, 0.0873F); - hatTip.setTextureOffset(24, 31).addBox(-1.5F, -4.5F, -1.5F, 3.0F, 4.0F, 3.0F, 0.0F, false); - } - } - - @Override - public void setRotationAngles(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - super.setRotationAngles(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - float f = 1.0F; - if (entity.getTicksElytraFlying() > 4) { - f = (float)entity.getMotion().lengthSquared(); - f = f / 0.2F; - f = f * f * f; - } - if (f < 1.0F) { - f = 1.0F; - } - if (slot == EquipmentSlotType.CHEST) { - back_side.rotateAngleX = 0.1745f + MathHelper.abs(MathHelper.cos(limbSwing * 0.6662f) * 0.7f * limbSwingAmount / f); - left_side.rotateAngleZ = 0.1745f + MathHelper.cos(limbSwing * 0.6662f + (float)Math.PI) * 0.2f * limbSwingAmount / f + 0.1f * limbSwingAmount / f; - right_side.rotateAngleZ = -0.1745f - MathHelper.cos(limbSwing * 0.6662f) * 0.2f * limbSwingAmount / f - 0.1f * limbSwingAmount / f; - } - } - - public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) { - modelRenderer.rotateAngleX = x; - modelRenderer.rotateAngleY = y; - modelRenderer.rotateAngleZ = z; - } +package elucent.eidolon.item.model; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.util.Mth; + +public class WarlockArmorModel extends ArmorModel { + public WarlockArmorModel(ModelPart root) { + super(root); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition mesh = HumanoidModel.createMesh(new CubeDeformation(0), 0); + PartDefinition root = createHumanoidAlias(mesh); + + PartDefinition body = root.getChild("body"); + PartDefinition right_foot = root.getChild("right_foot"); + PartDefinition left_foot = root.getChild("left_foot"); + PartDefinition left_arm = root.getChild("left_arm"); + PartDefinition right_arm = root.getChild("right_arm"); + PartDefinition head = root.getChild("head"); + + PartDefinition left_boot = left_foot.addOrReplaceChild("left_boot", CubeListBuilder.create().texOffs(0, 84).addBox(-2.5F, 5.5F, -2.5F, 5.0F, 7.0F, 5.0F, new CubeDeformation(0.0F)) + .texOffs(0, 80).addBox(-2.5F, 9.5F, -3.5F, 5.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.25F, 0.0F, 0.0F, 0.0F, -0.0873F, 0.0F)); + PartDefinition left_boot_cuff = left_boot.addOrReplaceChild("left_boot_cuff", CubeListBuilder.create().texOffs(20, 84).addBox(-3.0F, -1.0F, -3.0F, 6.0F, 2.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 5.0F, 0.0F, 0.0F, 0.0F, 0.0873F)); + PartDefinition right_boot = right_foot.addOrReplaceChild("right_boot", CubeListBuilder.create().texOffs(0, 84).addBox(-2.5F, 5.5F, -2.5F, 5.0F, 7.0F, 5.0F, new CubeDeformation(0.0F)) + .texOffs(0, 80).addBox(-2.5F, 9.5F, -3.5F, 5.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.25F, 0.0F, 0.0F, 0.0F, 0.0873F, 0.0F)); + PartDefinition right_boot_cuff = right_boot.addOrReplaceChild("right_boot_cuff", CubeListBuilder.create().texOffs(20, 84).addBox(-3.0F, -1.0F, -3.0F, 6.0F, 2.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 5.0F, 0.0F, 0.0F, 0.0F, -0.0873F)); + PartDefinition right_sleeve = right_arm.addOrReplaceChild("right_sleeve", CubeListBuilder.create().texOffs(28, 38).addBox(-4.5F, -2.0F, -2.5F, 5.0F, 5.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(1.0F, -1.0F, 0.0F, 0.0F, 0.0F, 0.1745F)); + PartDefinition right_cuff = right_sleeve.addOrReplaceChild("right_cuff", CubeListBuilder.create().texOffs(28, 48).addBox(-4.5F, -0.5F, -3.0F, 6.0F, 2.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-1.0F, 3.0F, 0.0F, 0.0F, 0.0873F, 0.0873F)); + PartDefinition left_sleeve = left_arm.addOrReplaceChild("left_sleeve", CubeListBuilder.create().texOffs(28, 38).mirror().addBox(-0.5F, -2.0F, -2.5F, 5.0F, 5.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-1.0F, -1.0F, 0.0F, 0.0F, 0.0F, -0.1745F)); + PartDefinition left_cuff = left_sleeve.addOrReplaceChild("left_cuff", CubeListBuilder.create().texOffs(28, 48).mirror().addBox(-1.5F, -0.5F, -3.0F, 6.0F, 2.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(1.0F, 3.0F, 0.0F, 0.0F, -0.0873F, -0.0873F)); + PartDefinition hat = head.addOrReplaceChild("hat", CubeListBuilder.create().texOffs(0, 0).addBox(-7.0F, -1.0F, -7.0F, 14.0F, 2.0F, 14.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -6.5F, 0.0F, -0.1745F, 0.0F, -0.0873F)); + PartDefinition hatMid = hat.addOrReplaceChild("hatMid", CubeListBuilder.create().texOffs(0, 16).addBox(-4.5F, -5.75F, -4.5F, 9.0F, 6.0F, 9.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, -0.0873F, 0.0F, 0.0873F)); + PartDefinition hatUpper = hatMid.addOrReplaceChild("hatUpper", CubeListBuilder.create().texOffs(0, 31).addBox(-3.0F, -4.0F, -3.0F, 6.0F, 4.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -5.0F, 0.0F, -0.1745F, 0.0F, 0.0436F)); + PartDefinition hatTip = hatUpper.addOrReplaceChild("hatTip", CubeListBuilder.create().texOffs(24, 31).addBox(-1.5F, -4.5F, -1.5F, 3.0F, 4.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -3.0F, 0.0F, -0.2618F, 0.0F, 0.0873F)); + PartDefinition cloak = body.addOrReplaceChild("cloak", CubeListBuilder.create().texOffs(0, 41).addBox(-6.5F, -12.4F, -2.5F, 9.0F, 15.0F, 5.0F, new CubeDeformation(0.0F)) + .texOffs(28, 56).addBox(-7.0F, -12.5F, -3.0F, 10.0F, 8.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(2.0F, 12.0F, 0.0F)); + PartDefinition left_side = cloak.addOrReplaceChild("left_side", CubeListBuilder.create().texOffs(0, 64).addBox(-2.0F, 0.0F, 0.01F, 2.0F, 10.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-5.0F, -4.5F, -3.0F, 0.0F, 0.0F, 0.1745F)); + PartDefinition right_side = cloak.addOrReplaceChild("right_side", CubeListBuilder.create().texOffs(0, 64).addBox(0.0F, 0.0F, 0.01F, 2.0F, 10.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(1.0F, -4.5F, -3.0F, 0.0F, 0.0F, -0.1745F)); + PartDefinition back_side = cloak.addOrReplaceChild("back_side", CubeListBuilder.create().texOffs(17, 70).addBox(-5.01F, 0.0F, 0.0F, 10.0F, 12.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-2.0F, -4.5F, 1.0F, 0.1745F, 0.0F, 0.0F)); + + return LayerDefinition.create(mesh, 64, 128); + } + + @Override + public void setupAnim(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + float f = 1.0F; + if (entity.getFallFlyingTicks() > 4) { + f = (float)entity.getDeltaMovement().lengthSqr(); + f = f / 0.2F; + f = f * f * f; + } + if (f < 1.0F) { + f = 1.0F; + } + if (slot == EquipmentSlot.CHEST) { + body.getChild("cloak").getChild("back_side").xRot = 0.1745f + Mth.abs(Mth.cos(limbSwing * 0.6662f) * 0.7f * limbSwingAmount / f); + body.getChild("cloak").getChild("left_side").zRot = 0.1745f + Mth.cos(limbSwing * 0.6662f + (float)Math.PI) * 0.2f * limbSwingAmount / f + 0.1f * limbSwingAmount / f; + body.getChild("cloak").getChild("right_side").zRot = -0.1745f - Mth.cos(limbSwing * 0.6662f) * 0.2f * limbSwingAmount / f - 0.1f * limbSwingAmount / f; + } + } } \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/mixin/AbstractArrowMixin.java b/src/main/java/elucent/eidolon/mixin/AbstractArrowMixin.java new file mode 100644 index 0000000..dfb5f2e --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/AbstractArrowMixin.java @@ -0,0 +1,17 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.EntityHitResult; + +@Mixin(AbstractArrow.class) +public interface AbstractArrowMixin { + @Invoker + ItemStack callGetPickupItem(); + + @Invoker + void callOnHitEntity(EntityHitResult result); +} diff --git a/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java b/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java new file mode 100644 index 0000000..08414ad --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java @@ -0,0 +1,19 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.renderer.LevelRenderer; + +@Mixin(LevelRenderer.class) +public class LevelRendererMixin { + @Inject(method = "renderLevel", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 1)) + private void customUpdateCameraAndRender(CallbackInfo ci) { + ClientEvents.getDelayedRender().endBatch(RenderUtil.VAPOR_TRANSLUCENT); + } +} diff --git a/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java b/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java index 81a298d..bc12110 100644 --- a/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java +++ b/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java @@ -1,20 +1,19 @@ package elucent.eidolon.mixin; -import elucent.eidolon.Registry; -import elucent.eidolon.event.SpeedFactorEvent; -import elucent.eidolon.item.ReaperScytheItem; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.network.IPacket; -import net.minecraft.util.DamageSource; -import net.minecraftforge.common.MinecraftForge; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import elucent.eidolon.Registry; +import elucent.eidolon.event.SpeedFactorEvent; +import elucent.eidolon.item.ReaperScytheItem; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraftforge.common.MinecraftForge; + @Mixin(LivingEntity.class) public class LivingEntityMixin { @Inject(method = "getSpeedFactor()F", at = @At("RETURN"), cancellable = true) @@ -25,12 +24,12 @@ private void customGetSpeedFactor(CallbackInfoReturnable cir) { cir.setReturnValue(event.getSpeedFactor()); } - @Inject(method = "dropLoot", at = @At("HEAD"), cancellable = true) - protected void customDropLoot(DamageSource source, boolean hitRecently, CallbackInfo ci) { - if (((LivingEntity)(Object)this).isEntityUndead() - && (source.getDamageType() == Registry.RITUAL_DAMAGE.getDamageType() - || source.getTrueSource() instanceof LivingEntity - && ((LivingEntity) source.getTrueSource()).getHeldItemMainhand().getItem() instanceof ReaperScytheItem)) { + @Inject(method = "dropFromLootTable", at = @At("HEAD"), cancellable = true) + protected void customDropFromLootTable(DamageSource source, boolean hitRecently, CallbackInfo ci) { + if (((LivingEntity)(Object)this).isInvertedHealAndHarm() + && (source.getMsgId() == Registry.RITUAL_DAMAGE.getMsgId() + || source.getEntity() instanceof LivingEntity + && ((LivingEntity) source.getEntity()).getMainHandItem().getItem() instanceof ReaperScytheItem)) { ci.cancel(); } } diff --git a/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java b/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java new file mode 100644 index 0000000..48a38c1 --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java @@ -0,0 +1,17 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import elucent.eidolon.entity.RavenVariantLayer; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; + +@Mixin(PlayerRenderer.class) +public class PlayerRendererMixin { + @Inject(method = "", at = @At("RETURN"), cancellable = true) + public void constructor(CallbackInfo ci) { + // ((PlayerRenderer)(Object)this).addLayer(new RavenVariantLayer<>(((PlayerRenderer)(Object)this))); + } +} diff --git a/src/main/java/elucent/eidolon/mixin/PotionBrewingMixin.java b/src/main/java/elucent/eidolon/mixin/PotionBrewingMixin.java index 8544f15..4745978 100644 --- a/src/main/java/elucent/eidolon/mixin/PotionBrewingMixin.java +++ b/src/main/java/elucent/eidolon/mixin/PotionBrewingMixin.java @@ -1,13 +1,12 @@ package elucent.eidolon.mixin; -import net.minecraft.item.Item; -import net.minecraft.potion.Potion; -import net.minecraft.potion.PotionBrewing; -import net.minecraft.world.server.ServerWorld; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionBrewing; + @Mixin(PotionBrewing.class) public interface PotionBrewingMixin { @Invoker diff --git a/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java b/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java new file mode 100644 index 0000000..7264d7c --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java @@ -0,0 +1,25 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; + +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.StructureSettings; +import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; + +@Mixin(StructureSettings.class) +public interface StructureSettingsMixin { + @Accessor + public void setConfiguredStructures(ImmutableMap, ImmutableMultimap, ResourceKey>> configuredStructures); + + @Accessor + public ImmutableMap, ImmutableMultimap, ResourceKey>> getConfiguredStructures(); +} diff --git a/src/main/java/elucent/eidolon/mixin/ZombieVillagerEntityMixin.java b/src/main/java/elucent/eidolon/mixin/ZombieVillagerEntityMixin.java deleted file mode 100644 index df6a605..0000000 --- a/src/main/java/elucent/eidolon/mixin/ZombieVillagerEntityMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package elucent.eidolon.mixin; - -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.monster.ZombieVillagerEntity; -import net.minecraft.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(ZombieVillagerEntity.class) -public interface ZombieVillagerEntityMixin { - @Invoker - void callCureZombie(ServerWorld world); -} diff --git a/src/main/java/elucent/eidolon/mixin/ZombieVillagerMixin.java b/src/main/java/elucent/eidolon/mixin/ZombieVillagerMixin.java new file mode 100644 index 0000000..30124d3 --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/ZombieVillagerMixin.java @@ -0,0 +1,13 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.server.level.ServerLevel; + +@Mixin(ZombieVillager.class) +public interface ZombieVillagerMixin { + @Invoker + void callFinishConversion(ServerLevel world); +} diff --git a/src/main/java/elucent/eidolon/network/AttemptCastPacket.java b/src/main/java/elucent/eidolon/network/AttemptCastPacket.java index 79a4a6d..92dba22 100644 --- a/src/main/java/elucent/eidolon/network/AttemptCastPacket.java +++ b/src/main/java/elucent/eidolon/network/AttemptCastPacket.java @@ -1,36 +1,31 @@ package elucent.eidolon.network; -import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; + import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.KnowledgeProvider; import elucent.eidolon.entity.ChantCasterEntity; -import elucent.eidolon.particle.Particles; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.world.level.Level; + -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; public class AttemptCastPacket { List signs = new ArrayList<>(); UUID uuid; - public AttemptCastPacket(PlayerEntity player, List signs) { + public AttemptCastPacket(Player player, List signs) { this.signs.addAll(signs); - this.uuid = player.getUniqueID(); + this.uuid = player.getUUID(); } public AttemptCastPacket(UUID uuid, List signs) { @@ -38,34 +33,34 @@ public AttemptCastPacket(UUID uuid, List signs) { this.uuid = uuid; } - public static void encode(AttemptCastPacket object, PacketBuffer buffer) { + public static void encode(AttemptCastPacket object, FriendlyByteBuf buffer) { buffer.writeInt(object.signs.size()); - for (int i = 0; i < object.signs.size(); i ++) buffer.writeString(object.signs.get(i).getRegistryName().toString(), 255); - buffer.writeUniqueId(object.uuid); + for (int i = 0; i < object.signs.size(); i ++) buffer.writeUtf(object.signs.get(i).getRegistryName().toString(), 255); + buffer.writeUUID(object.uuid); } - public static AttemptCastPacket decode(PacketBuffer buffer) { + public static AttemptCastPacket decode(FriendlyByteBuf buffer) { int n = buffer.readInt(); List signs = new ArrayList<>(); - for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readString(255)))); - return new AttemptCastPacket(buffer.readUniqueId(), signs); + for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readUtf(255)))); + return new AttemptCastPacket(buffer.readUUID(), signs); } public static void consume(AttemptCastPacket packet, Supplier ctx) { ctx.get().enqueueWork(() -> { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_SERVER; - World world = ctx.get().getSender().world; + Level world = ctx.get().getSender().level; if (world != null) { - PlayerEntity player = world.getPlayerByUuid(packet.uuid); + Player player = world.getPlayerByUUID(packet.uuid); if (player != null) { List signs = packet.signs; - IKnowledge knowledge = player.getCapability(KnowledgeProvider.CAPABILITY, null).resolve().get(); + IKnowledge knowledge = player.getCapability(IKnowledge.INSTANCE, null).resolve().get(); for (Sign sign : signs) if (!knowledge.knowsSign(sign)) return; - Vector3d placement = player.getPositionVec().add(0, player.getHeight() * 2 / 3, 0).add(player.getLookVec()); + Vec3 placement = player.position().add(0, player.getBbHeight() * 2 / 3, 0).add(player.getLookAngle()); ChantCasterEntity entity = new ChantCasterEntity(world, player, signs); - entity.setPosition(placement.x, placement.y, placement.z); - world.addEntity(entity); + entity.setPos(placement.x, placement.y, placement.z); + world.addFreshEntity(entity); } } }); diff --git a/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java b/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java index 6c62727..3c402f0 100644 --- a/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java @@ -1,19 +1,20 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; -import net.minecraft.block.Blocks; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketBuffer; -import net.minecraft.particles.BlockParticleData; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.world.level.block.Blocks; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; + -import java.util.function.Supplier; public class ChilledEffectPacket { double x, y, z; @@ -24,13 +25,13 @@ public ChilledEffectPacket(double x, double y, double z) { this.z = z; } - public static void encode(ChilledEffectPacket object, PacketBuffer buffer) { + public static void encode(ChilledEffectPacket object, FriendlyByteBuf buffer) { buffer.writeDouble(object.x); buffer.writeDouble(object.y); buffer.writeDouble(object.z); } - public static ChilledEffectPacket decode(PacketBuffer buffer) { + public static ChilledEffectPacket decode(FriendlyByteBuf buffer) { return new ChilledEffectPacket(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); } @@ -38,15 +39,15 @@ public static void consume(ChilledEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - PlayerEntity player = Eidolon.proxy.getPlayer(); + Player player = Eidolon.proxy.getPlayer(); if (player != null) { - World world = player.world; - world.playSound(player, player.getPosX(), player.getPosY(), player.getPosZ(), SoundEvents.BLOCK_GLASS_BREAK, SoundCategory.PLAYERS, 1.0f, 1.0f); + Level world = player.level; + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.GLASS_BREAK, SoundSource.PLAYERS, 1.0f, 1.0f); for (int i = 0; i < 5; i ++) { world.addParticle( - new BlockParticleData(ParticleTypes.BLOCK, Blocks.ICE.getDefaultState()), + new BlockParticleOption(ParticleTypes.BLOCK, Blocks.ICE.defaultBlockState()), packet.x, packet.y, packet.z, - 0.05f * world.rand.nextGaussian(), 0.05f * world.rand.nextGaussian(), 0.05f * world.rand.nextGaussian() + 0.05f * world.random.nextGaussian(), 0.05f * world.random.nextGaussian(), 0.05f * world.random.nextGaussian() ); } } diff --git a/src/main/java/elucent/eidolon/network/CrucibleFailPacket.java b/src/main/java/elucent/eidolon/network/CrucibleFailPacket.java index 441c582..55fa66b 100644 --- a/src/main/java/elucent/eidolon/network/CrucibleFailPacket.java +++ b/src/main/java/elucent/eidolon/network/CrucibleFailPacket.java @@ -1,17 +1,19 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class CrucibleFailPacket { BlockPos pos; @@ -20,11 +22,11 @@ public CrucibleFailPacket(BlockPos pos) { this.pos = pos; } - public static void encode(CrucibleFailPacket object, PacketBuffer buffer) { + public static void encode(CrucibleFailPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); } - public static CrucibleFailPacket decode(PacketBuffer buffer) { + public static CrucibleFailPacket decode(FriendlyByteBuf buffer) { return new CrucibleFailPacket(buffer.readBlockPos()); } @@ -32,11 +34,11 @@ public static void consume(CrucibleFailPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 0.625, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1.0f, 1.0f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 1.0f, 1.0f); Particles.create(Registry.SMOKE_PARTICLE) .setAlpha(0.125f, 0).setScale(0.3125f, 0.125f).setLifetime(40) diff --git a/src/main/java/elucent/eidolon/network/CrucibleSuccessPacket.java b/src/main/java/elucent/eidolon/network/CrucibleSuccessPacket.java index b7c54a6..5897797 100644 --- a/src/main/java/elucent/eidolon/network/CrucibleSuccessPacket.java +++ b/src/main/java/elucent/eidolon/network/CrucibleSuccessPacket.java @@ -1,17 +1,19 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class CrucibleSuccessPacket { BlockPos pos; @@ -24,12 +26,12 @@ public CrucibleSuccessPacket(BlockPos pos, float r, float g, float b) { this.b = b; } - public static void encode(CrucibleSuccessPacket object, PacketBuffer buffer) { + public static void encode(CrucibleSuccessPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); buffer.writeFloat(object.r).writeFloat(object.g).writeFloat(object.b); } - public static CrucibleSuccessPacket decode(PacketBuffer buffer) { + public static CrucibleSuccessPacket decode(FriendlyByteBuf buffer) { return new CrucibleSuccessPacket(buffer.readBlockPos(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); } @@ -37,12 +39,12 @@ public static void consume(CrucibleSuccessPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 1, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1.0f, 0.75f); - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.ENTITY_PLAYER_LEVELUP, SoundCategory.BLOCKS, 1.0f, 0.75f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 1.0f, 0.75f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.PLAYER_LEVELUP, SoundSource.BLOCKS, 1.0f, 0.75f); Particles.create(Registry.STEAM_PARTICLE) .setAlpha(0.0625f, 0).setScale(0.375f, 0.125f).setLifetime(40) diff --git a/src/main/java/elucent/eidolon/network/CrystallizeEffectPacket.java b/src/main/java/elucent/eidolon/network/CrystallizeEffectPacket.java index 67ace2c..c04b1af 100644 --- a/src/main/java/elucent/eidolon/network/CrystallizeEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/CrystallizeEffectPacket.java @@ -1,17 +1,17 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class CrystallizeEffectPacket { BlockPos pos; @@ -20,11 +20,11 @@ public CrystallizeEffectPacket(BlockPos pos) { this.pos = pos; } - public static void encode(CrystallizeEffectPacket object, PacketBuffer buffer) { + public static void encode(CrystallizeEffectPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); } - public static CrystallizeEffectPacket decode(PacketBuffer buffer) { + public static CrystallizeEffectPacket decode(FriendlyByteBuf buffer) { return new CrystallizeEffectPacket(buffer.readBlockPos()); } @@ -32,7 +32,7 @@ public static void consume(CrystallizeEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 0.1, z = pos.getZ() + 0.5; diff --git a/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java b/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java index ddcfd70..4d8622a 100644 --- a/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java @@ -1,17 +1,19 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class ExtinguishEffectPacket { BlockPos pos; @@ -20,11 +22,11 @@ public ExtinguishEffectPacket(BlockPos pos) { this.pos = pos; } - public static void encode(ExtinguishEffectPacket object, PacketBuffer buffer) { + public static void encode(ExtinguishEffectPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); } - public static ExtinguishEffectPacket decode(PacketBuffer buffer) { + public static ExtinguishEffectPacket decode(FriendlyByteBuf buffer) { return new ExtinguishEffectPacket(buffer.readBlockPos()); } @@ -32,11 +34,11 @@ public static void consume(ExtinguishEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 1, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1.0f, 1.0f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 1.0f, 1.0f); Particles.create(Registry.SMOKE_PARTICLE) .setAlpha(0.125f, 0).setScale(0.3125f, 0.125f).setLifetime(80) diff --git a/src/main/java/elucent/eidolon/network/FlameEffectPacket.java b/src/main/java/elucent/eidolon/network/FlameEffectPacket.java index 9595976..cc5be8d 100644 --- a/src/main/java/elucent/eidolon/network/FlameEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/FlameEffectPacket.java @@ -1,17 +1,19 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class FlameEffectPacket { BlockPos pos; @@ -24,12 +26,12 @@ public FlameEffectPacket(BlockPos pos, float r, float g, float b) { this.b = b; } - public static void encode(FlameEffectPacket object, PacketBuffer buffer) { + public static void encode(FlameEffectPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); buffer.writeFloat(object.r).writeFloat(object.g).writeFloat(object.b); } - public static FlameEffectPacket decode(PacketBuffer buffer) { + public static FlameEffectPacket decode(FriendlyByteBuf buffer) { return new FlameEffectPacket(buffer.readBlockPos(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); } @@ -37,11 +39,11 @@ public static void consume(FlameEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 1, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.ENTITY_BLAZE_SHOOT, SoundCategory.BLOCKS, 1.0f, 0.75f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.BLAZE_SHOOT, SoundSource.BLOCKS, 1.0f, 0.75f); Particles.create(Registry.FLAME_PARTICLE) .setAlpha(0.75f, 0).setScale(0.5f, 0.25f).setLifetime(40) @@ -55,7 +57,7 @@ public static void consume(FlameEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 1, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.ITEM_FLINTANDSTEEL_USE, SoundCategory.BLOCKS, 1.0f, 1.0f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0f, 1.0f); Particles.create(Registry.FLAME_PARTICLE) .setAlpha(0.75f, 0).setScale(0.5f, 0.25f).setLifetime(20) @@ -55,7 +57,7 @@ public static void consume(IgniteEffectPacket packet, Supplier { - this.tag = (CompoundNBT)KnowledgeProvider.CAPABILITY.getStorage().writeNBT(KnowledgeProvider.CAPABILITY, k, null); + public KnowledgeUpdatePacket(Player entity, boolean playSound) { + this.uuid = entity.getUUID(); + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + this.tag = ((INBTSerializable)k).serializeNBT(); }); this.playSound = playSound; } - public static void encode(KnowledgeUpdatePacket object, PacketBuffer buffer) { - buffer.writeUniqueId(object.uuid); - buffer.writeCompoundTag(object.tag); + public static void encode(KnowledgeUpdatePacket object, FriendlyByteBuf buffer) { + buffer.writeUUID(object.uuid); + buffer.writeNbt(object.tag); buffer.writeBoolean(object.playSound); } - public static KnowledgeUpdatePacket decode(PacketBuffer buffer) { - return new KnowledgeUpdatePacket(buffer.readUniqueId(), buffer.readCompoundTag(), buffer.readBoolean()); + public static KnowledgeUpdatePacket decode(FriendlyByteBuf buffer) { + return new KnowledgeUpdatePacket(buffer.readUUID(), buffer.readNbt(), buffer.readBoolean()); } public static void consume(KnowledgeUpdatePacket packet, Supplier ctx) { ctx.get().enqueueWork(() -> { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); - PlayerEntity player = world.getPlayerByUuid(packet.uuid); + Level world = Eidolon.proxy.getWorld(); + Player player = world.getPlayerByUUID(packet.uuid); if (player != null) { - player.getCapability(KnowledgeProvider.CAPABILITY, null).ifPresent((k) -> { - KnowledgeProvider.CAPABILITY.getStorage().readNBT(KnowledgeProvider.CAPABILITY, k, null, packet.tag); - if (packet.playSound) player.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1.0f, 0.5f); + player.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + ((INBTSerializable)k).deserializeNBT(packet.tag); + if (packet.playSound) player.playSound(SoundEvents.PLAYER_LEVELUP, 1.0f, 0.5f); }); } }); diff --git a/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java b/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java index 20f976a..f6eb9c7 100644 --- a/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java @@ -1,17 +1,17 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class LifestealEffectPacket { BlockPos src, dst; @@ -25,12 +25,12 @@ public LifestealEffectPacket(BlockPos src, BlockPos dst, float r, float g, float this.b = b; } - public static void encode(LifestealEffectPacket object, PacketBuffer buffer) { + public static void encode(LifestealEffectPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.src).writeBlockPos(object.dst); buffer.writeFloat(object.r).writeFloat(object.g).writeFloat(object.b); } - public static LifestealEffectPacket decode(PacketBuffer buffer) { + public static LifestealEffectPacket decode(FriendlyByteBuf buffer) { return new LifestealEffectPacket(buffer.readBlockPos(), buffer.readBlockPos(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); } @@ -38,12 +38,12 @@ public static void consume(LifestealEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos src = packet.src, dst = packet.dst; for (int i = 0; i < 10; i ++) { Particles.create(Registry.LINE_WISP_PARTICLE) - .setAlpha(0.75f, 0).setScale(0.25f + 0.125f * world.rand.nextFloat(), 0).setLifetime(16 + world.rand.nextInt(4)) + .setAlpha(0.75f, 0).setScale(0.25f + 0.125f * world.random.nextFloat(), 0).setLifetime(16 + world.random.nextInt(4)) .randomOffset(0.375, 0.375).randomVelocity(0.125, 0.125) .addVelocity(dst.getX() + 0.5, dst.getY() + 0.5, dst.getZ() + 0.5) .setColor(packet.r, packet.g, packet.b, packet.r, packet.g * 0.5f, packet.b * 1.5f) diff --git a/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java b/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java index e677782..ac16321 100644 --- a/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java @@ -1,16 +1,18 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; import elucent.eidolon.util.ColorUtil; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class MagicBurstEffectPacket { float x, y, z; @@ -28,12 +30,12 @@ public MagicBurstEffectPacket(double x, double y, double z, int color1, int colo this.c2 = color2; } - public static void encode(MagicBurstEffectPacket object, PacketBuffer buffer) { + public static void encode(MagicBurstEffectPacket object, FriendlyByteBuf buffer) { buffer.writeFloat(object.x).writeFloat(object.y).writeFloat(object.z); buffer.writeInt(object.c1).writeInt(object.c2); } - public static MagicBurstEffectPacket decode(PacketBuffer buffer) { + public static MagicBurstEffectPacket decode(FriendlyByteBuf buffer) { return new MagicBurstEffectPacket(buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt(), buffer.readInt()); } @@ -41,7 +43,7 @@ public static void consume(MagicBurstEffectPacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { double x = packet.x, y = packet.y, z = packet.z; @@ -58,7 +60,7 @@ public static void consume(MagicBurstEffectPacket packet, Supplier void sendToDimension(World world, MSG msg, RegistryKey dimension) { + public static void sendToDimension(Level world, MSG msg, ResourceKey dimension) { Networking.INSTANCE.send(PacketDistributor.DIMENSION.with(() -> dimension), msg); } - public static void sendToTracking(World world, BlockPos pos, MSG msg) { + public static void sendToTracking(Level world, BlockPos pos, MSG msg) { Networking.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), msg); } - public static void sendTo(PlayerEntity entity, MSG msg) { - Networking.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity)entity), msg); + public static void sendTo(Player entity, MSG msg) { + Networking.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer)entity), msg); } public static void sendToServer(MSG msg) { diff --git a/src/main/java/elucent/eidolon/network/RitualCompletePacket.java b/src/main/java/elucent/eidolon/network/RitualCompletePacket.java index 2396158..fcdcc28 100644 --- a/src/main/java/elucent/eidolon/network/RitualCompletePacket.java +++ b/src/main/java/elucent/eidolon/network/RitualCompletePacket.java @@ -1,17 +1,19 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.particle.Particles; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + -import java.util.function.Supplier; public class RitualCompletePacket { BlockPos pos; @@ -24,12 +26,12 @@ public RitualCompletePacket(BlockPos pos, float r, float g, float b) { this.b = b; } - public static void encode(RitualCompletePacket object, PacketBuffer buffer) { + public static void encode(RitualCompletePacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); buffer.writeFloat(object.r).writeFloat(object.g).writeFloat(object.b); } - public static RitualCompletePacket decode(PacketBuffer buffer) { + public static RitualCompletePacket decode(FriendlyByteBuf buffer) { return new RitualCompletePacket(buffer.readBlockPos(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); } @@ -37,11 +39,11 @@ public static void consume(RitualCompletePacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos pos = packet.pos; double x = pos.getX() + 0.5, y = pos.getY() + 1, z = pos.getZ() + 0.5; - world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.ENTITY_PLAYER_LEVELUP, SoundCategory.BLOCKS, 1.0f, 1.0f); + world.playSound(Eidolon.proxy.getPlayer(), x, y, z, SoundEvents.PLAYER_LEVELUP, SoundSource.BLOCKS, 1.0f, 1.0f); Particles.create(Registry.FLAME_PARTICLE) .setAlpha(0.75f, 0).setScale(0.5f, 0.25f).setLifetime(40) @@ -55,7 +57,7 @@ public static void consume(RitualCompletePacket packet, Supplier { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { BlockPos src = packet.src, dst = packet.dst; - world.playSound(Eidolon.proxy.getPlayer(), src.getX() + 0.5, src.getY() + 0.5, src.getZ() + 0.5, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 1.0f, 1.0f); + world.playSound(Eidolon.proxy.getPlayer(), src.getX() + 0.5, src.getY() + 0.5, src.getZ() + 0.5, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, 1.0f, 1.0f); for (int i = 0; i < 10; i ++) { Particles.create(Registry.LINE_WISP_PARTICLE) - .setAlpha(0.75f, 0).setScale(0.25f + 0.125f * world.rand.nextFloat(), 0).setLifetime(16 + world.rand.nextInt(4)) + .setAlpha(0.75f, 0).setScale(0.25f + 0.125f * world.random.nextFloat(), 0).setLifetime(16 + world.random.nextInt(4)) .randomOffset(0.375, 0.375).randomVelocity(0.125, 0.125) .addVelocity(dst.getX() + 0.5, dst.getY() + 1, dst.getZ() + 0.5) .setColor(packet.r, packet.g, packet.b, packet.r, packet.g * 0.5f, packet.b * 1.5f) diff --git a/src/main/java/elucent/eidolon/network/SpellCastPacket.java b/src/main/java/elucent/eidolon/network/SpellCastPacket.java index 553b25a..aa4b380 100644 --- a/src/main/java/elucent/eidolon/network/SpellCastPacket.java +++ b/src/main/java/elucent/eidolon/network/SpellCastPacket.java @@ -1,26 +1,22 @@ package elucent.eidolon.network; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; -import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.KnowledgeProvider; -import elucent.eidolon.entity.ChantCasterEntity; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; import elucent.eidolon.spell.Spell; import elucent.eidolon.spell.Spells; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; public class SpellCastPacket { List signs = new ArrayList<>(); @@ -28,11 +24,11 @@ public class SpellCastPacket { BlockPos pos; UUID uuid; - public SpellCastPacket(PlayerEntity player, BlockPos pos, Spell spell, List signs) { + public SpellCastPacket(Player player, BlockPos pos, Spell spell, List signs) { this.signs.addAll(signs); this.pos = pos; this.spell = spell; - this.uuid = player.getUniqueID(); + this.uuid = player.getUUID(); } public SpellCastPacket(UUID uuid, BlockPos pos, ResourceLocation location, List signs) { @@ -42,29 +38,29 @@ public SpellCastPacket(UUID uuid, BlockPos pos, ResourceLocation location, List< this.uuid = uuid; } - public static void encode(SpellCastPacket object, PacketBuffer buffer) { - buffer.writeString(object.spell.getRegistryName().toString()); + public static void encode(SpellCastPacket object, FriendlyByteBuf buffer) { + buffer.writeUtf(object.spell.getRegistryName().toString()); buffer.writeInt(object.signs.size()); - for (int i = 0; i < object.signs.size(); i ++) buffer.writeString(object.signs.get(i).getRegistryName().toString()); - buffer.writeUniqueId(object.uuid); + for (int i = 0; i < object.signs.size(); i ++) buffer.writeUtf(object.signs.get(i).getRegistryName().toString()); + buffer.writeUUID(object.uuid); buffer.writeBlockPos(object.pos); } - public static SpellCastPacket decode(PacketBuffer buffer) { - ResourceLocation spell = new ResourceLocation(buffer.readString()); + public static SpellCastPacket decode(FriendlyByteBuf buffer) { + ResourceLocation spell = new ResourceLocation(buffer.readUtf()); int n = buffer.readInt(); List signs = new ArrayList<>(); - for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readString()))); - return new SpellCastPacket(buffer.readUniqueId(), buffer.readBlockPos(), spell, signs); + for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readUtf()))); + return new SpellCastPacket(buffer.readUUID(), buffer.readBlockPos(), spell, signs); } public static void consume(SpellCastPacket packet, Supplier ctx) { ctx.get().enqueueWork(() -> { assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; - World world = Eidolon.proxy.getWorld(); + Level world = Eidolon.proxy.getWorld(); if (world != null) { - PlayerEntity player = world.getPlayerByUuid(packet.uuid); + Player player = world.getPlayerByUUID(packet.uuid); if (player != null) { List signs = packet.signs; packet.spell.cast(world, packet.pos, player, signs); diff --git a/src/main/java/elucent/eidolon/network/TESyncPacket.java b/src/main/java/elucent/eidolon/network/TESyncPacket.java index 2daa579..b191b1c 100644 --- a/src/main/java/elucent/eidolon/network/TESyncPacket.java +++ b/src/main/java/elucent/eidolon/network/TESyncPacket.java @@ -1,53 +1,51 @@ package elucent.eidolon.network; +import java.util.function.Supplier; + import elucent.eidolon.Eidolon; -import net.minecraft.block.Blocks; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.NBTUtil; -import net.minecraft.network.PacketBuffer; -import net.minecraft.particles.BlockParticleData; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + -import java.util.function.Supplier; public class TESyncPacket { BlockPos pos; - CompoundNBT tag; + CompoundTag tag; - public TESyncPacket(BlockPos pos, CompoundNBT tag) { + public TESyncPacket(BlockPos pos, CompoundTag tag) { this.pos = pos; this.tag = tag; } - public static void encode(TESyncPacket object, PacketBuffer buffer) { + public static void encode(TESyncPacket object, FriendlyByteBuf buffer) { buffer.writeBlockPos(object.pos); - buffer.writeCompoundTag(object.tag); + buffer.writeNbt(object.tag); } - public static TESyncPacket decode(PacketBuffer buffer) { - return new TESyncPacket(buffer.readBlockPos(), buffer.readCompoundTag()); + public static TESyncPacket decode(FriendlyByteBuf buffer) { + return new TESyncPacket(buffer.readBlockPos(), buffer.readNbt()); } public static void consume(TESyncPacket packet, Supplier ctx) { ctx.get().enqueueWork(() -> { - World world; + Level world; if (ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT) world = Eidolon.proxy.getWorld(); else { if (ctx.get().getSender() == null) return; - world = ctx.get().getSender().world; + world = ctx.get().getSender().level; } - world.getTileEntity(packet.pos).read(world.getBlockState(packet.pos), packet.tag); - world.getTileEntity(packet.pos).markDirty(); + BlockEntity t = world.getBlockEntity(packet.pos); + if (t != null) { + world.getBlockEntity(packet.pos).load(packet.tag); + world.getBlockEntity(packet.pos).setChanged(); + } }); ctx.get().setPacketHandled(true); } diff --git a/src/main/java/elucent/eidolon/particle/BubbleParticle.java b/src/main/java/elucent/eidolon/particle/BubbleParticle.java index af9009e..0e70062 100644 --- a/src/main/java/elucent/eidolon/particle/BubbleParticle.java +++ b/src/main/java/elucent/eidolon/particle/BubbleParticle.java @@ -1,34 +1,33 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.tileentity.BedTileEntityRenderer; -import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.blockentity.BedRenderer; +import net.minecraft.client.multiplayer.ClientLevel; public class BubbleParticle extends GenericParticle { - IAnimatedSprite animation; + SpriteSet animation; - public BubbleParticle(ClientWorld world, GenericParticleData data, IAnimatedSprite animation, double x, double y, double z, double vx, double vy, double vz) { + public BubbleParticle(ClientLevel world, GenericParticleData data, SpriteSet animation, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); - BedTileEntityRenderer ch; + BedRenderer ch; this.animation = animation; } @Override public void tick() { super.tick(); - this.motionY *= 0.8; - selectSpriteWithAge(this.animation); + this.yd *= 0.8; + setSpriteFromAge(this.animation); } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/BubbleParticleType.java b/src/main/java/elucent/eidolon/particle/BubbleParticleType.java index 3bfa22b..d0b6ef6 100644 --- a/src/main/java/elucent/eidolon/particle/BubbleParticleType.java +++ b/src/main/java/elucent/eidolon/particle/BubbleParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class BubbleParticleType extends ParticleType { public BubbleParticleType() { @@ -13,21 +14,21 @@ public BubbleParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { BubbleParticle ret = new BubbleParticle(world, data, sprite, x, y, z, mx, my, mz); - ret.selectSpriteWithAge(sprite); + ret.setSpriteFromAge(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/FlameParticle.java b/src/main/java/elucent/eidolon/particle/FlameParticle.java index 907e4ec..af26ad1 100644 --- a/src/main/java/elucent/eidolon/particle/FlameParticle.java +++ b/src/main/java/elucent/eidolon/particle/FlameParticle.java @@ -1,26 +1,25 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; public class FlameParticle extends GenericParticle { - public FlameParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public FlameParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); } @Override - protected int getBrightnessForRender(float partialTicks) { + protected int getLightColor(float partialTicks) { return 0xF000F0; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/FlameParticleType.java b/src/main/java/elucent/eidolon/particle/FlameParticleType.java index 08be7fb..bbce9b1 100644 --- a/src/main/java/elucent/eidolon/particle/FlameParticleType.java +++ b/src/main/java/elucent/eidolon/particle/FlameParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class FlameParticleType extends ParticleType { public FlameParticleType() { @@ -13,21 +14,21 @@ public FlameParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { FlameParticle ret = new FlameParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/GenericParticle.java b/src/main/java/elucent/eidolon/particle/GenericParticle.java index 035a6a6..42cbf15 100644 --- a/src/main/java/elucent/eidolon/particle/GenericParticle.java +++ b/src/main/java/elucent/eidolon/particle/GenericParticle.java @@ -1,48 +1,48 @@ package elucent.eidolon.particle; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.particle.SpriteTexturedParticle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.ColorHelper; -import net.minecraft.util.math.MathHelper; +import java.awt.Color; -import java.awt.*; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.particle.TextureSheetParticle; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; -public class GenericParticle extends SpriteTexturedParticle { +public class GenericParticle extends TextureSheetParticle { GenericParticleData data; float[] hsv1 = new float[3], hsv2 = new float[3]; - public GenericParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public GenericParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, x, y, z, vx, vy, vz); - this.setPosition(x, y, z); + this.setPos(x, y, z); this.data = data; - this.motionX = vx; - this.motionY = vy; - this.motionZ = vz; - this.setMaxAge(data.lifetime); - this.particleGravity = data.gravity ? 1 : 0; + this.xd = vx; + this.yd = vy; + this.zd = vz; + this.setLifetime(data.lifetime); + this.gravity = data.gravity ? 1 : 0; Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r1)), (int)(255 * Math.min(1.0f, data.g1)), (int)(255 * Math.min(1.0f, data.b1)), hsv1); Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r2)), (int)(255 * Math.min(1.0f, data.g2)), (int)(255 * Math.min(1.0f, data.b2)), hsv2); updateTraits(); } protected float getCoeff() { - return (float)this.age / this.maxAge; + return (float)this.age / this.lifetime; } protected void updateTraits() { float coeff = getCoeff(); - particleScale = MathHelper.lerp(coeff, data.scale1, data.scale2); - float h = MathHelper.interpolateAngle(coeff, 360 * hsv1[0], 360 * hsv2[0]) / 360; - float s = MathHelper.lerp(coeff, hsv1[1], hsv2[1]); - float v = MathHelper.lerp(coeff, hsv1[2], hsv2[2]); + quadSize = Mth.lerp(coeff, data.scale1, data.scale2); + float h = Mth.rotLerp(coeff, 360 * hsv1[0], 360 * hsv2[0]) / 360; + float s = Mth.lerp(coeff, hsv1[1], hsv2[1]); + float v = Mth.lerp(coeff, hsv1[2], hsv2[2]); int packed = Color.HSBtoRGB(h, s, v); - float r = ColorHelper.PackedColor.getRed(packed) / 255.0f; - float g = ColorHelper.PackedColor.getGreen(packed) / 255.0f; - float b = ColorHelper.PackedColor.getBlue(packed) / 255.0f; + float r = FastColor.ARGB32.red(packed) / 255.0f; + float g = FastColor.ARGB32.green(packed) / 255.0f; + float b = FastColor.ARGB32.blue(packed) / 255.0f; setColor(r, g, b); - setAlphaF(MathHelper.lerp(coeff, data.a1, data.a2)); - prevParticleAngle = particleAngle; - particleAngle += data.spin; + setAlpha(Mth.lerp(coeff, data.a1, data.a2)); + oRoll = roll; + roll += data.spin; } @Override @@ -52,7 +52,7 @@ public void tick() { } @Override - public IParticleRenderType getRenderType() { + public ParticleRenderType getRenderType() { return SpriteParticleRenderType.INSTANCE; } } diff --git a/src/main/java/elucent/eidolon/particle/GenericParticleData.java b/src/main/java/elucent/eidolon/particle/GenericParticleData.java index 343e965..3f0fcbc 100644 --- a/src/main/java/elucent/eidolon/particle/GenericParticleData.java +++ b/src/main/java/elucent/eidolon/particle/GenericParticleData.java @@ -4,14 +4,14 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import elucent.eidolon.Registry; -import net.minecraft.network.PacketBuffer; -import net.minecraft.particles.IParticleData; -import net.minecraft.particles.ParticleType; -import java.util.Locale; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; -public class GenericParticleData implements IParticleData { +import net.minecraft.core.particles.ParticleOptions.Deserializer; + +public class GenericParticleData implements ParticleOptions { float r1 = 1, g1 = 1, b1 = 1, a1 = 1, r2 = 1, g2 = 1, b2 = 1, a2 = 0; float scale1 = 1, scale2 = 0; int lifetime = 20; @@ -59,7 +59,7 @@ public ParticleType getType() { } @Override - public void write(PacketBuffer buffer) { + public void writeToNetwork(FriendlyByteBuf buffer) { buffer.writeFloat(r1).writeFloat(g1).writeFloat(b1).writeFloat(a1); buffer.writeFloat(r2).writeFloat(g2).writeFloat(b2).writeFloat(a2); buffer.writeFloat(scale1).writeFloat(scale2); @@ -69,13 +69,13 @@ public void write(PacketBuffer buffer) { } @Override - public String getParameters() { + public String writeToString() { return getClass().getSimpleName() + ":internal"; } - public static final IDeserializer DESERIALIZER = new IDeserializer() { + public static final Deserializer DESERIALIZER = new Deserializer() { @Override - public GenericParticleData deserialize(ParticleType type, StringReader reader) throws CommandSyntaxException { + public GenericParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { reader.expect(' '); float r1 = reader.readFloat(); reader.expect(' '); @@ -120,7 +120,7 @@ public GenericParticleData deserialize(ParticleType type, S } @Override - public GenericParticleData read(ParticleType type, PacketBuffer buf) { + public GenericParticleData fromNetwork(ParticleType type, FriendlyByteBuf buf) { float r1 = buf.readFloat(); float g1 = buf.readFloat(); float b1 = buf.readFloat(); diff --git a/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java b/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java index 60b0c8b..fbd1722 100644 --- a/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java @@ -1,47 +1,49 @@ package elucent.eidolon.particle; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; +import elucent.eidolon.Registry; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.particle.ParticleRenderType; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import org.lwjgl.opengl.GL11; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; -public class GlowParticleRenderType implements IParticleRenderType { +public class GlowParticleRenderType implements ParticleRenderType { public static final GlowParticleRenderType INSTANCE = new GlowParticleRenderType(); private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManager textureManager) { RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); - RenderSystem.disableAlphaTest(); - RenderSystem.disableLighting(); - - textureManager.bindTexture(AtlasTexture.LOCATION_PARTICLES_TEXTURE); - bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); + ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); + bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); } private static void endRenderCommon() { - Minecraft.getInstance().textureManager.getTexture(AtlasTexture.LOCATION_PARTICLES_TEXTURE).restoreLastBlurMipmap(); - RenderSystem.enableAlphaTest(); + Minecraft.getInstance().textureManager.getTexture(TextureAtlas.LOCATION_PARTICLES).restoreLastBlurMipmap(); RenderSystem.disableBlend(); RenderSystem.depthMask(true); } @Override - public void beginRender(BufferBuilder b, TextureManager tex) { + public void begin(BufferBuilder b, TextureManager tex) { beginRenderCommon(b, tex); } @Override - public void finishRender(Tessellator t) { - t.draw(); + public void end(Tesselator t) { + t.end(); ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE); RenderSystem.enableDepthTest(); endRenderCommon(); diff --git a/src/main/java/elucent/eidolon/particle/LineWispParticle.java b/src/main/java/elucent/eidolon/particle/LineWispParticle.java index 419e48a..0ea0053 100644 --- a/src/main/java/elucent/eidolon/particle/LineWispParticle.java +++ b/src/main/java/elucent/eidolon/particle/LineWispParticle.java @@ -1,50 +1,49 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.item.SpawnEggItem; -import net.minecraft.util.math.MathHelper; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.util.Mth; public class LineWispParticle extends GenericParticle { double ix, iy, iz, tx, ty, tz; - public LineWispParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public LineWispParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); - this.ix = posX; - this.iy = posY; - this.iz = posZ; - this.tx = motionX; - this.ty = motionY; - this.tz = motionZ; - motionX = motionY = motionZ = 0; + this.ix = x; + this.iy = y; + this.iz = z; + this.tx = xd; + this.ty = yd; + this.tz = zd; + xd = yd = zd = 0; } @Override public void tick() { super.tick(); - prevPosX = posX; - prevPosY = posY; - prevPosZ = posZ; - float coeff = (float)age / maxAge; + xo = x; + yo = y; + zo = z; + float coeff = (float)age / lifetime; coeff *= coeff; - posX = MathHelper.lerp(coeff, ix, tx); - posY = MathHelper.lerp(1 - (1 - coeff) * (1 - coeff), iy, ty); - posZ = MathHelper.lerp(coeff, iz, tz); + x = Mth.lerp(coeff, ix, tx); + y = Mth.lerp(1 - (1 - coeff) * (1 - coeff), iy, ty); + z = Mth.lerp(coeff, iz, tz); SpawnEggItem i; } @Override - protected int getBrightnessForRender(float partialTicks) { + protected int getLightColor(float partialTicks) { return 0xF000F0; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/LineWispParticleType.java b/src/main/java/elucent/eidolon/particle/LineWispParticleType.java index 4e05700..8f73e17 100644 --- a/src/main/java/elucent/eidolon/particle/LineWispParticleType.java +++ b/src/main/java/elucent/eidolon/particle/LineWispParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class LineWispParticleType extends ParticleType { public LineWispParticleType() { @@ -13,21 +14,21 @@ public LineWispParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { LineWispParticle ret = new LineWispParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/Particles.java b/src/main/java/elucent/eidolon/particle/Particles.java index aea4759..f15d8c3 100644 --- a/src/main/java/elucent/eidolon/particle/Particles.java +++ b/src/main/java/elucent/eidolon/particle/Particles.java @@ -1,14 +1,10 @@ package elucent.eidolon.particle; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.merchant.villager.VillagerEntity; -import net.minecraft.particles.ParticleType; -import net.minecraft.world.World; -import net.minecraftforge.fml.RegistryObject; - import java.util.Random; -import java.util.function.Function; + +import net.minecraft.core.particles.ParticleType; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.RegistryObject; public class Particles { public static class ParticleBuilder { @@ -147,7 +143,7 @@ public ParticleBuilder randomOffset(double maxXDist, double maxYDist, double max return this; } - public ParticleBuilder spawn(World world, double x, double y, double z) { + public ParticleBuilder spawn(Level world, double x, double y, double z) { double yaw = random.nextFloat() * Math.PI * 2, pitch = random.nextFloat() * Math.PI - Math.PI / 2, xSpeed = random.nextFloat() * maxXSpeed, ySpeed = random.nextFloat() * maxYSpeed, zSpeed = random.nextFloat() * maxZSpeed; this.vx += Math.sin(yaw) * Math.cos(pitch) * xSpeed; @@ -163,7 +159,7 @@ public ParticleBuilder spawn(World world, double x, double y, double z) { return this; } - public ParticleBuilder repeat(World world, double x, double y, double z, int n) { + public ParticleBuilder repeat(Level world, double x, double y, double z, int n) { for (int i = 0; i < n; i ++) spawn(world, x, y, z); return this; } diff --git a/src/main/java/elucent/eidolon/particle/SignParticle.java b/src/main/java/elucent/eidolon/particle/SignParticle.java index 919b63f..95184f8 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticle.java +++ b/src/main/java/elucent/eidolon/particle/SignParticle.java @@ -1,61 +1,58 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.particle.SpriteTexturedParticle; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.ColorHelper; -import net.minecraft.util.math.MathHelper; - -import java.awt.*; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.particle.TextureSheetParticle; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.Mth; -public class SignParticle extends SpriteTexturedParticle { +public class SignParticle extends TextureSheetParticle { Sign sign; - public SignParticle(ClientWorld world, Sign sign, double x, double y, double z, double vx, double vy, double vz) { + public SignParticle(ClientLevel world, Sign sign, double x, double y, double z, double vx, double vy, double vz) { super(world, x, y, z, vx, vy, vz); - this.setPosition(x, y, z); + this.setPos(x, y, z); this.sign = sign; - this.motionX = vx; - this.motionY = vy; - this.motionZ = vz; - this.setMaxAge(20); - this.particleGravity = -0.05f; + this.xd = vx; + this.yd = vy; + this.zd = vz; + this.setLifetime(20); + this.gravity = -0.05f; setColor(sign.getRed(), sign.getGreen(), sign.getBlue()); updateTraits(); } protected float getCoeff() { - return (float)this.age / this.maxAge; + return (float)this.age / this.lifetime; } protected void updateTraits() { float coeff = getCoeff(); - particleScale = MathHelper.lerp(coeff, 0.25f, 0.125f); - setAlphaF(MathHelper.lerp(coeff * coeff, 0.75f, 0)); + quadSize = Mth.lerp(coeff, 0.25f, 0.125f); + setAlpha(Mth.lerp(coeff * coeff, 0.75f, 0)); } @Override public void tick() { updateTraits(); super.tick(); - motionX *= 0.98; - motionY *= 0.98; - motionZ *= 0.98; + xd *= 0.98; + yd *= 0.98; + zd *= 0.98; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_BLOCK_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_BLOCK_PARTICLE) : b, info, pticks); } @Override - public IParticleRenderType getRenderType() { + public ParticleRenderType getRenderType() { return SignParticleRenderType.INSTANCE; } } diff --git a/src/main/java/elucent/eidolon/particle/SignParticleData.java b/src/main/java/elucent/eidolon/particle/SignParticleData.java index af35a5e..485c6d9 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticleData.java +++ b/src/main/java/elucent/eidolon/particle/SignParticleData.java @@ -4,15 +4,18 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; + import elucent.eidolon.Registry; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; -import net.minecraft.network.PacketBuffer; -import net.minecraft.particles.IParticleData; -import net.minecraft.particles.ParticleType; -import net.minecraft.util.ResourceLocation; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.resources.ResourceLocation; + +import net.minecraft.core.particles.ParticleOptions.Deserializer; -public class SignParticleData implements IParticleData { +public class SignParticleData implements ParticleOptions { Sign sign; public static Codec codecFor(ParticleType type) { @@ -34,18 +37,18 @@ public ParticleType getType() { } @Override - public void write(PacketBuffer buffer) { - buffer.writeString(sign.toString()); + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeUtf(sign.toString()); } @Override - public String getParameters() { + public String writeToString() { return getClass().getSimpleName() + ":internal"; } - public static final IDeserializer DESERIALIZER = new IDeserializer() { + public static final Deserializer DESERIALIZER = new Deserializer() { @Override - public SignParticleData deserialize(ParticleType type, StringReader reader) throws CommandSyntaxException { + public SignParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { reader.expect(' '); String loc = reader.readString(); SignParticleData data = new SignParticleData(Signs.find(new ResourceLocation(loc))); @@ -53,8 +56,8 @@ public SignParticleData deserialize(ParticleType type, StringR } @Override - public SignParticleData read(ParticleType type, PacketBuffer buf) { - String loc = buf.readString(); + public SignParticleData fromNetwork(ParticleType type, FriendlyByteBuf buf) { + String loc = buf.readUtf(); SignParticleData data = new SignParticleData(Signs.find(new ResourceLocation(loc))); return data; } diff --git a/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java b/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java index 00081f8..e9c82d1 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java @@ -1,14 +1,17 @@ package elucent.eidolon.particle; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.systems.RenderSystem; + import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.AtlasTexture; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import org.lwjgl.opengl.GL11; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; public class SignParticleRenderType extends SpriteParticleRenderType { public static final SignParticleRenderType INSTANCE = new SignParticleRenderType(); @@ -17,27 +20,23 @@ private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManage RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 0.00390625f); - - textureManager.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); - bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); } private static void endRenderCommon() { - Minecraft.getInstance().textureManager.getTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap(); - RenderSystem.enableAlphaTest(); - RenderSystem.defaultAlphaFunc(); + Minecraft.getInstance().textureManager.getTexture(TextureAtlas.LOCATION_BLOCKS).restoreLastBlurMipmap(); RenderSystem.depthMask(true); } @Override - public void beginRender(BufferBuilder b, TextureManager tex) { + public void begin(BufferBuilder b, TextureManager tex) { beginRenderCommon(b, tex); } @Override - public void finishRender(Tessellator t) { - t.draw(); + public void end(Tesselator t) { + t.end(); RenderSystem.enableDepthTest(); endRenderCommon(); } diff --git a/src/main/java/elucent/eidolon/particle/SignParticleType.java b/src/main/java/elucent/eidolon/particle/SignParticleType.java index 30380fe..d2acef8 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticleType.java +++ b/src/main/java/elucent/eidolon/particle/SignParticleType.java @@ -1,16 +1,17 @@ package elucent.eidolon.particle; +import java.util.Random; + import com.mojang.serialization.Codec; + import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; - -import java.util.Random; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class SignParticleType extends ParticleType { public SignParticleType() { @@ -18,27 +19,27 @@ public SignParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return SignParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { + public static class Factory implements ParticleProvider { public Factory() { // } @Override - public Particle makeParticle(SignParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(SignParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { SignParticle ret = new SignParticle(world, data.sign, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(new IAnimatedSprite() { + ret.pickSprite(new SpriteSet() { @Override public TextureAtlasSprite get(int particleAge, int particleMaxAge) { - return Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(ret.sign.getSprite()); + return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ret.sign.getSprite()); } @Override public TextureAtlasSprite get(Random rand) { - return Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(ret.sign.getSprite()); + return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ret.sign.getSprite()); } }); return ret; diff --git a/src/main/java/elucent/eidolon/particle/SmokeParticle.java b/src/main/java/elucent/eidolon/particle/SmokeParticle.java index fbe62ed..9160e39 100644 --- a/src/main/java/elucent/eidolon/particle/SmokeParticle.java +++ b/src/main/java/elucent/eidolon/particle/SmokeParticle.java @@ -1,32 +1,32 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.MathHelper; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.Mth; public class SmokeParticle extends GenericParticle { - public SmokeParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public SmokeParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); } @Override protected float getCoeff() { - return 1.0f - MathHelper.sin((float)Math.PI * (float)this.age / this.maxAge); + return 1.0f - Mth.sin((float)Math.PI * (float)this.age / this.lifetime); } @Override public void tick() { super.tick(); - motionY *= 0.98; + yd *= 0.98; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.DELAYED_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.DELAYED_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/SmokeParticleType.java b/src/main/java/elucent/eidolon/particle/SmokeParticleType.java index 1dcba24..eac5cb2 100644 --- a/src/main/java/elucent/eidolon/particle/SmokeParticleType.java +++ b/src/main/java/elucent/eidolon/particle/SmokeParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class SmokeParticleType extends ParticleType { public SmokeParticleType() { @@ -13,21 +14,21 @@ public SmokeParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { SmokeParticle ret = new SmokeParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/SparkleParticle.java b/src/main/java/elucent/eidolon/particle/SparkleParticle.java index 4a630fd..bcea950 100644 --- a/src/main/java/elucent/eidolon/particle/SparkleParticle.java +++ b/src/main/java/elucent/eidolon/particle/SparkleParticle.java @@ -1,28 +1,27 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.tileentity.BedTileEntityRenderer; -import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.blockentity.BedRenderer; +import net.minecraft.client.multiplayer.ClientLevel; public class SparkleParticle extends GenericParticle { - public SparkleParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public SparkleParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); - BedTileEntityRenderer ch; + BedRenderer ch; } @Override - protected int getBrightnessForRender(float partialTicks) { + protected int getLightColor(float partialTicks) { return 0xF000F0; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/SparkleParticleType.java b/src/main/java/elucent/eidolon/particle/SparkleParticleType.java index 1ee7566..08b3a92 100644 --- a/src/main/java/elucent/eidolon/particle/SparkleParticleType.java +++ b/src/main/java/elucent/eidolon/particle/SparkleParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class SparkleParticleType extends ParticleType { public SparkleParticleType() { @@ -13,21 +14,21 @@ public SparkleParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { SparkleParticle ret = new SparkleParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java b/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java index a2ba2a1..1c83dc8 100644 --- a/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java @@ -1,43 +1,47 @@ package elucent.eidolon.particle; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.systems.RenderSystem; + import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.particle.ParticleRenderType; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.Registry; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import org.lwjgl.opengl.GL11; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; -public class SpriteParticleRenderType implements IParticleRenderType { +public class SpriteParticleRenderType implements ParticleRenderType { public static final SpriteParticleRenderType INSTANCE = new SpriteParticleRenderType(); private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManager textureManager) { RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - RenderSystem.alphaFunc(GL11.GL_GEQUAL, 0.00390625f); - - textureManager.bindTexture(AtlasTexture.LOCATION_PARTICLES_TEXTURE); - bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); + ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); + bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); } private static void endRenderCommon() { - Minecraft.getInstance().textureManager.getTexture(AtlasTexture.LOCATION_PARTICLES_TEXTURE).restoreLastBlurMipmap(); - RenderSystem.enableAlphaTest(); - RenderSystem.defaultAlphaFunc(); + Minecraft.getInstance().textureManager.getTexture(TextureAtlas.LOCATION_PARTICLES).restoreLastBlurMipmap(); RenderSystem.depthMask(true); } @Override - public void beginRender(BufferBuilder b, TextureManager tex) { + public void begin(BufferBuilder b, TextureManager tex) { beginRenderCommon(b, tex); } @Override - public void finishRender(Tessellator t) { - t.draw(); + public void end(Tesselator t) { + t.end(); RenderSystem.enableDepthTest(); endRenderCommon(); } diff --git a/src/main/java/elucent/eidolon/particle/SteamParticle.java b/src/main/java/elucent/eidolon/particle/SteamParticle.java index 592b989..7c9a6b4 100644 --- a/src/main/java/elucent/eidolon/particle/SteamParticle.java +++ b/src/main/java/elucent/eidolon/particle/SteamParticle.java @@ -1,33 +1,32 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.MathHelper; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.Mth; public class SteamParticle extends GenericParticle { - public SteamParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public SteamParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); } @Override protected float getCoeff() { - return 1.0f - MathHelper.sin((float)Math.PI * (float)this.age / this.maxAge); + return 1.0f - Mth.sin((float)Math.PI * (float)this.age / this.lifetime); } @Override public void tick() { super.tick(); - motionY *= 0.99; + yd *= 0.99; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/SteamParticleType.java b/src/main/java/elucent/eidolon/particle/SteamParticleType.java index 8779382..10a4641 100644 --- a/src/main/java/elucent/eidolon/particle/SteamParticleType.java +++ b/src/main/java/elucent/eidolon/particle/SteamParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class SteamParticleType extends ParticleType { public SteamParticleType() { @@ -13,21 +14,21 @@ public SteamParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { SteamParticle ret = new SteamParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/particle/WispParticle.java b/src/main/java/elucent/eidolon/particle/WispParticle.java index 15c7644..636d2a8 100644 --- a/src/main/java/elucent/eidolon/particle/WispParticle.java +++ b/src/main/java/elucent/eidolon/particle/WispParticle.java @@ -1,26 +1,25 @@ package elucent.eidolon.particle; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientConfig; import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.particle.IParticleRenderType; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; public class WispParticle extends GenericParticle { - public WispParticle(ClientWorld world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { + public WispParticle(ClientLevel world, GenericParticleData data, double x, double y, double z, double vx, double vy, double vz) { super(world, data, x, y, z, vx, vy, vz); } @Override - protected int getBrightnessForRender(float partialTicks) { + protected int getLightColor(float partialTicks) { return 0xF000F0; } @Override - public void renderParticle(IVertexBuilder b, ActiveRenderInfo info, float pticks) { - super.renderParticle(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); + public void render(VertexConsumer b, Camera info, float pticks) { + super.render(ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_PARTICLE) : b, info, pticks); } } diff --git a/src/main/java/elucent/eidolon/particle/WispParticleType.java b/src/main/java/elucent/eidolon/particle/WispParticleType.java index 6000601..c712684 100644 --- a/src/main/java/elucent/eidolon/particle/WispParticleType.java +++ b/src/main/java/elucent/eidolon/particle/WispParticleType.java @@ -1,11 +1,12 @@ package elucent.eidolon.particle; import com.mojang.serialization.Codec; -import net.minecraft.client.particle.IAnimatedSprite; -import net.minecraft.client.particle.IParticleFactory; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.Particle; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.particles.ParticleType; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; public class WispParticleType extends ParticleType { public WispParticleType() { @@ -13,21 +14,21 @@ public WispParticleType() { } @Override - public Codec func_230522_e_() { + public Codec codec() { return GenericParticleData.codecFor(this); } - public static class Factory implements IParticleFactory { - private final IAnimatedSprite sprite; + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; - public Factory(IAnimatedSprite sprite) { + public Factory(SpriteSet sprite) { this.sprite = sprite; } @Override - public Particle makeParticle(GenericParticleData data, ClientWorld world, double x, double y, double z, double mx, double my, double mz) { + public Particle createParticle(GenericParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { WispParticle ret = new WispParticle(world, data, x, y, z, mx, my, mz); - ret.selectSpriteRandomly(sprite); + ret.pickSprite(sprite); return ret; } } diff --git a/src/main/java/elucent/eidolon/potion/AnchoredEffect.java b/src/main/java/elucent/eidolon/potion/AnchoredEffect.java index c8d6d72..d6c93ee 100644 --- a/src/main/java/elucent/eidolon/potion/AnchoredEffect.java +++ b/src/main/java/elucent/eidolon/potion/AnchoredEffect.java @@ -1,66 +1,49 @@ package elucent.eidolon.potion; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; import elucent.eidolon.util.ColorUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.player.ClientPlayerEntity; -import net.minecraft.client.gui.AbstractGui; -import net.minecraft.client.gui.DisplayEffectsScreen; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; -import net.minecraft.potion.Effect; -import net.minecraft.potion.EffectInstance; -import net.minecraft.potion.EffectType; -import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.client.gui.ForgeIngameGui; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.extensions.IForgeEffect; -import net.minecraftforge.event.entity.living.EnderTeleportEvent; -import net.minecraftforge.event.entity.living.LivingHealEvent; -import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.common.extensions.IForgeMobEffect; +import net.minecraftforge.event.entity.EntityTeleportEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.DistExecutor; -import java.util.Random; - -public class AnchoredEffect extends Effect implements IForgeEffect { +public class AnchoredEffect extends MobEffect implements IForgeMobEffect { public AnchoredEffect() { - super(EffectType.BENEFICIAL, ColorUtil.packColor(255, 154, 58, 232)); + super(MobEffectCategory.BENEFICIAL, ColorUtil.packColor(255, 154, 58, 232)); MinecraftForge.EVENT_BUS.addListener(this::anchor); } @SubscribeEvent - public void anchor(EnderTeleportEvent event) { - LivingEntity e = event.getEntityLiving(); - if (e.isPotionActive(this)) { + public void anchor(EntityTeleportEvent event) { + Entity e = event.getEntity(); + if (e instanceof LivingEntity && ((LivingEntity)e).hasEffect(this)) { event.setCanceled(true); } } protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/anchored.png"); - @OnlyIn(Dist.CLIENT) - @Override - public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { - Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(EFFECT_TEXTURE); - gui.blit(mStack, x, y, 0, 0, 18, 18); - } - - @OnlyIn(Dist.CLIENT) - @Override - public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { - Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(EFFECT_TEXTURE); - gui.blit(mStack, x, y, 0, 0, 18, 18); - } +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +// +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } } diff --git a/src/main/java/elucent/eidolon/potion/ChilledEffect.java b/src/main/java/elucent/eidolon/potion/ChilledEffect.java index c17c38a..5f80d04 100644 --- a/src/main/java/elucent/eidolon/potion/ChilledEffect.java +++ b/src/main/java/elucent/eidolon/potion/ChilledEffect.java @@ -1,60 +1,40 @@ package elucent.eidolon.potion; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.Random; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import elucent.eidolon.network.ChilledEffectPacket; -import elucent.eidolon.network.Networking; -import io.netty.util.NetUtil; -import net.minecraft.block.Blocks; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.player.ClientPlayerEntity; -import net.minecraft.client.gui.AbstractGui; -import net.minecraft.client.gui.DisplayEffectsScreen; -import net.minecraft.client.gui.IngameGui; -import net.minecraft.data.advancements.AdventureAdvancements; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.NetworkSystem; -import net.minecraft.network.PacketThreadUtil; -import net.minecraft.particles.BlockParticleData; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.potion.*; -import net.minecraft.util.ColorHelper; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.gen.feature.structure.StrongholdStructure; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.gui.ForgeIngameGui; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.extensions.IForgeEffect; +import net.minecraftforge.common.extensions.IForgeMobEffect; import net.minecraftforge.event.entity.living.LivingHealEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.network.NetworkHooks; -import net.minecraftforge.fml.network.PacketDispatcher; -import net.minecraftforge.fml.network.PacketDistributor; -import org.spongepowered.asm.mixin.MixinEnvironment; -import javax.annotation.Resource; -import java.util.Random; - -public class ChilledEffect extends Effect implements IForgeEffect { +public class ChilledEffect extends MobEffect implements IForgeMobEffect { static int packColor(int alpha, int red, int green, int blue) { return alpha << 24 | red << 16 | green << 8 | blue; } public ChilledEffect() { - super(EffectType.HARMFUL, packColor(255, 147, 189, 245)); + super(MobEffectCategory.HARMFUL, packColor(255, 147, 189, 245)); MinecraftForge.EVENT_BUS.addListener(this::chill); DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> { MinecraftForge.EVENT_BUS.addListener(ChilledEffect::renderChill); @@ -65,7 +45,7 @@ public ChilledEffect() { @SubscribeEvent public void chill(LivingHealEvent event) { LivingEntity e = event.getEntityLiving(); - if (e.isPotionActive(this)) { + if (e.hasEffect(this)) { event.setCanceled(true); } } @@ -73,74 +53,70 @@ public void chill(LivingHealEvent event) { protected static final ResourceLocation ICONS_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/gui/icons.png"); protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/chilled.png"); - @OnlyIn(Dist.CLIENT) - @Override - public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { - Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(EFFECT_TEXTURE); - gui.blit(mStack, x, y, 0, 0, 18, 18); - } - - @OnlyIn(Dist.CLIENT) - @Override - public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { - Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(EFFECT_TEXTURE); - gui.blit(mStack, x, y, 0, 0, 18, 18); - } +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +// +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } @OnlyIn(Dist.CLIENT) @SubscribeEvent(priority = EventPriority.LOWEST) public static void renderChill(RenderGameOverlayEvent.Post event) { Minecraft mc = Minecraft.getInstance(); - ClientPlayerEntity player = mc.player; - if (event.getType() == RenderGameOverlayEvent.ElementType.HEALTH - && player.isPotionActive(Registry.CHILLED_EFFECT.get())) { + LocalPlayer player = mc.player; + if (event.getType() == RenderGameOverlayEvent.ElementType.ALL + && player.hasEffect(Registry.CHILLED_EFFECT.get())) { - MatrixStack mStack = event.getMatrixStack(); - mStack.push(); + PoseStack mStack = event.getMatrixStack(); + mStack.pushPose(); mStack.translate(0, 0, 0.01); - int health = MathHelper.ceil(player.getHealth()); - float absorb = MathHelper.ceil(player.getAbsorptionAmount()); - ModifiableAttributeInstance attrMaxHealth = player.getAttribute(Attributes.MAX_HEALTH); + int health = Mth.ceil(player.getHealth()); + float absorb = Mth.ceil(player.getAbsorptionAmount()); + AttributeInstance attrMaxHealth = player.getAttribute(Attributes.MAX_HEALTH); float healthMax = (float)attrMaxHealth.getValue(); - int ticks = mc.ingameGUI.getTicks(); + int ticks = mc.gui.getGuiTicks(); int regen = -1; - if (player.isPotionActive(Effects.REGENERATION)) regen = ticks % 25; + if (player.hasEffect(MobEffects.REGENERATION)) regen = ticks % 25; Random rand = new Random(); rand.setSeed((long)(ticks * 312871)); - int left = event.getWindow().getScaledWidth() / 2 - 91; - int top = event.getWindow().getScaledHeight() - ForgeIngameGui.left_height; + int left = event.getWindow().getGuiScaledWidth() / 2 - 91; + int top = event.getWindow().getGuiScaledHeight() - ((ForgeIngameGui)Minecraft.getInstance().gui).left_height; - int healthRows = MathHelper.ceil((healthMax + absorb) / 2.0F / 10.0F); + int healthRows = Mth.ceil((healthMax + absorb) / 2.0F / 10.0F); int rowHeight = Math.max(10 - (healthRows - 2), 3); - RenderSystem.pushTextureAttributes(); - mc.getTextureManager().bindTexture(ICONS_TEXTURE); - for (int i = MathHelper.ceil((healthMax) / 2.0F) - 1; i >= 0; -- i) { - int row = MathHelper.ceil((float)(i + 1) / 10.0F) - 1; + RenderSystem.setShaderTexture(0, ICONS_TEXTURE); + for (int i = Mth.ceil((healthMax) / 2.0F) - 1; i >= 0; -- i) { + int row = Mth.ceil((float)(i + 1) / 10.0F) - 1; int x = left + i % 10 * 8; - int y = top + rowHeight - 1; // we don't need to worry about rowHeight, the usual health rendering already added it to top + int y = top + rowHeight * 2 - 2; // we don't need to worry about rowHeight, the usual health rendering already added it to top if (health <= 4) y += rand.nextInt(2); if (i == regen) y -= 2; - RenderSystem.disableAlphaTest(); RenderSystem.enableBlend(); if (i * 2 + 1 < health) - mc.ingameGUI.blit(mStack, x, y, 0, 0, 9, 9); + mc.gui.blit(mStack, x, y, 0, 0, 9, 9); else if (i * 2 + 1 == health) - mc.ingameGUI.blit(mStack, x, y, 9, 0, 9, 9); + mc.gui.blit(mStack, x, y, 9, 0, 9, 9); RenderSystem.disableBlend(); - RenderSystem.enableAlphaTest(); } - RenderSystem.popAttributes(); - mStack.pop(); + mStack.popPose(); } } } diff --git a/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java b/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java new file mode 100644 index 0000000..49d8cb1 --- /dev/null +++ b/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java @@ -0,0 +1,37 @@ +package elucent.eidolon.potion; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeMobEffect; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +public class ReinforcedEffect extends MobEffect implements IForgeMobEffect { + public ReinforcedEffect() { + super(MobEffectCategory.BENEFICIAL, ColorUtil.packColor(255, 250, 214, 74)); + } + + protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/reinforced.png"); + +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +// +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +} diff --git a/src/main/java/elucent/eidolon/potion/StrictBrewingRecipe.java b/src/main/java/elucent/eidolon/potion/StrictBrewingRecipe.java index aa1a215..4087980 100644 --- a/src/main/java/elucent/eidolon/potion/StrictBrewingRecipe.java +++ b/src/main/java/elucent/eidolon/potion/StrictBrewingRecipe.java @@ -1,21 +1,21 @@ package elucent.eidolon.potion; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraftforge.common.brewing.BrewingRecipe; - import javax.annotation.Nonnull; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraftforge.common.brewing.BrewingRecipe; + public class StrictBrewingRecipe extends BrewingRecipe { ItemStack inputStack; public StrictBrewingRecipe(ItemStack input, Ingredient ingredient, ItemStack output) { - super(Ingredient.fromStacks(input), ingredient, output); + super(Ingredient.of(input), ingredient, output); this.inputStack = input; } @Override public boolean isInput(@Nonnull ItemStack stack) { - return ItemStack.areItemsEqual(inputStack, stack) - && ItemStack.areItemStackTagsEqual(inputStack, stack); + return ItemStack.isSame(inputStack, stack) + && ItemStack.tagMatches(inputStack, stack); } } diff --git a/src/main/java/elucent/eidolon/potion/VulnerableEffect.java b/src/main/java/elucent/eidolon/potion/VulnerableEffect.java new file mode 100644 index 0000000..ada1e8d --- /dev/null +++ b/src/main/java/elucent/eidolon/potion/VulnerableEffect.java @@ -0,0 +1,37 @@ +package elucent.eidolon.potion; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeMobEffect; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +public class VulnerableEffect extends MobEffect implements IForgeMobEffect { + public VulnerableEffect() { + super(MobEffectCategory.HARMFUL, ColorUtil.packColor(255, 90, 102, 161)); + } + + protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/vulnerable.png"); + +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +// +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +} diff --git a/src/main/java/elucent/eidolon/proxy/ClientProxy.java b/src/main/java/elucent/eidolon/proxy/ClientProxy.java index 8c98c17..79d22ef 100644 --- a/src/main/java/elucent/eidolon/proxy/ClientProxy.java +++ b/src/main/java/elucent/eidolon/proxy/ClientProxy.java @@ -4,19 +4,19 @@ import elucent.eidolon.Registry; import elucent.eidolon.codex.CodexGui; import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.world.World; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; public class ClientProxy implements ISidedProxy { @Override - public PlayerEntity getPlayer() { + public Player getPlayer() { return Minecraft.getInstance().player; } @Override - public World getWorld() { - return Minecraft.getInstance().world; + public Level getWorld() { + return Minecraft.getInstance().level; } @Override @@ -27,6 +27,6 @@ public void init() { @Override public void openCodexGui() { - Minecraft.getInstance().displayGuiScreen(CodexGui.getInstance()); + Minecraft.getInstance().setScreen(CodexGui.getInstance()); } } diff --git a/src/main/java/elucent/eidolon/proxy/ISidedProxy.java b/src/main/java/elucent/eidolon/proxy/ISidedProxy.java index 9c25e3b..1d6c9c0 100644 --- a/src/main/java/elucent/eidolon/proxy/ISidedProxy.java +++ b/src/main/java/elucent/eidolon/proxy/ISidedProxy.java @@ -1,11 +1,11 @@ package elucent.eidolon.proxy; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.world.World; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; public interface ISidedProxy { - PlayerEntity getPlayer(); - World getWorld(); + Player getPlayer(); + Level getWorld(); void init(); void openCodexGui(); diff --git a/src/main/java/elucent/eidolon/proxy/ServerProxy.java b/src/main/java/elucent/eidolon/proxy/ServerProxy.java index d4e2cdb..af800f0 100644 --- a/src/main/java/elucent/eidolon/proxy/ServerProxy.java +++ b/src/main/java/elucent/eidolon/proxy/ServerProxy.java @@ -1,18 +1,16 @@ package elucent.eidolon.proxy; -import elucent.eidolon.Registry; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.world.World; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; public class ServerProxy implements ISidedProxy { @Override - public PlayerEntity getPlayer() { + public Player getPlayer() { return null; } @Override - public World getWorld() { + public Level getWorld() { return null; } diff --git a/src/main/java/elucent/eidolon/reagent/CrimsolReagent.java b/src/main/java/elucent/eidolon/reagent/CrimsolReagent.java new file mode 100644 index 0000000..828eacf --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/CrimsolReagent.java @@ -0,0 +1,20 @@ +package elucent.eidolon.reagent; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +public class CrimsolReagent extends Reagent { + public CrimsolReagent(ResourceLocation name) { + super(name, new ResourceLocation(Eidolon.MODID, "block/crimsol"), false); + } + + @Override + public void worldEffect(Level world, BlockPos pos, int amount) { + if (!world.isClientSide) + world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1); + } +} diff --git a/src/main/java/elucent/eidolon/reagent/EspritReagent.java b/src/main/java/elucent/eidolon/reagent/EspritReagent.java new file mode 100644 index 0000000..2eb06b5 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/EspritReagent.java @@ -0,0 +1,20 @@ +package elucent.eidolon.reagent; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +public class EspritReagent extends Reagent { + public EspritReagent(ResourceLocation name) { + super(name, new ResourceLocation(Eidolon.MODID, "block/esprit"), false); + } + + @Override + public void worldEffect(Level world, BlockPos pos, int amount) { + if (!world.isClientSide) + world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1); + } +} diff --git a/src/main/java/elucent/eidolon/reagent/IReagentTankProvider.java b/src/main/java/elucent/eidolon/reagent/IReagentTankProvider.java new file mode 100644 index 0000000..bc5491b --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/IReagentTankProvider.java @@ -0,0 +1,10 @@ +package elucent.eidolon.reagent; + +import net.minecraft.core.Direction; + +public interface IReagentTankProvider { + ReagentTank getTank(); + boolean isOutput(Direction direction); + boolean isInput(Direction direction); + void onContentsChanged(); +} diff --git a/src/main/java/elucent/eidolon/reagent/Reagent.java b/src/main/java/elucent/eidolon/reagent/Reagent.java new file mode 100644 index 0000000..b23f9e4 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/Reagent.java @@ -0,0 +1,40 @@ +package elucent.eidolon.reagent; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class Reagent { + ResourceLocation name, texture; + boolean gas; + + public Reagent(ResourceLocation name, ResourceLocation texture, boolean isGas) { + this.name = name; + this.texture = texture; + this.gas = isGas; + } + + public ResourceLocation getRegistryName() { + return name; + } + + public ResourceLocation getTexture() { + return texture; + } + + @OnlyIn(Dist.CLIENT) + public TextureAtlasSprite getSprite() { + return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture); + } + + public boolean isGas() { + return gas; + } + + public abstract void worldEffect(Level world, BlockPos pos, int amount); +} diff --git a/src/main/java/elucent/eidolon/reagent/ReagentRegistry.java b/src/main/java/elucent/eidolon/reagent/ReagentRegistry.java new file mode 100644 index 0000000..92da958 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/ReagentRegistry.java @@ -0,0 +1,33 @@ +package elucent.eidolon.reagent; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nullable; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; + +public class ReagentRegistry { + static Map reagents = new HashMap<>(); + + public static Reagent register(Reagent r) { + reagents.put(r.getRegistryName(), r); + return r; + } + + public static Collection getReagents() { + return reagents.values(); + } + + @Nullable + public static Reagent find(ResourceLocation location) { + return reagents.getOrDefault(location, null); + } + + public static Reagent + STEAM = register(new SteamReagent(new ResourceLocation(Eidolon.MODID, "steam"))), + ESPRIT = register(new EspritReagent(new ResourceLocation(Eidolon.MODID, "esprit"))), + CRIMSOL = register(new CrimsolReagent(new ResourceLocation(Eidolon.MODID, "crimsol"))); +} diff --git a/src/main/java/elucent/eidolon/reagent/ReagentStack.java b/src/main/java/elucent/eidolon/reagent/ReagentStack.java new file mode 100644 index 0000000..eeedebe --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/ReagentStack.java @@ -0,0 +1,30 @@ +package elucent.eidolon.reagent; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; + +public class ReagentStack { + public Reagent reagent; + public int amount; + + public ReagentStack(Reagent reagent, int amount) { + this.reagent = reagent; + this.amount = amount; + } + + public ReagentStack(CompoundTag nbt) { + this.reagent = ReagentRegistry.find(new ResourceLocation(nbt.getString("reagent"))); + this.amount = nbt.getInt("amount"); + } + + public boolean isEmpty() { + return amount == 0; + } + + public CompoundTag write() { + CompoundTag nbt = new CompoundTag(); + nbt.putString("reagent", reagent.getRegistryName().toString()); + nbt.putInt("amount", amount); + return nbt; + } +} diff --git a/src/main/java/elucent/eidolon/reagent/ReagentTank.java b/src/main/java/elucent/eidolon/reagent/ReagentTank.java new file mode 100644 index 0000000..3f957f4 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/ReagentTank.java @@ -0,0 +1,54 @@ +package elucent.eidolon.reagent; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +public class ReagentTank { + int capacity; + ReagentStack contents; + + public ReagentTank(int capacity) { + this.capacity = capacity; + this.contents = new ReagentStack(ReagentRegistry.STEAM, 0); + } + + public ReagentStack getContents() { + return contents; + } + + public int getCapacity() { + return capacity; + } + + public float getPressure() { + return (float)contents.amount / capacity; + } + + public CompoundTag write() { + CompoundTag nbt = new CompoundTag(); + if (contents != null) nbt.put("contents", contents.write()); + nbt.putInt("capacity", capacity); + return nbt; + } + + public void read(CompoundTag nbt) { + contents = nbt.contains("contents") ? new ReagentStack(nbt.getCompound("contents")) : new ReagentStack(ReagentRegistry.STEAM, 0); + capacity = nbt.getInt("capacity"); + } + + public boolean canFill(ReagentStack stack) { + return contents.isEmpty() || contents.reagent == stack.reagent; + } + + public boolean fill(Level world, BlockPos pos, ReagentStack stack) { + if (!contents.isEmpty() && contents.reagent != stack.reagent) return false; + if (contents.isEmpty()) contents.reagent = stack.reagent; + contents.amount += stack.amount; + if (contents.amount > capacity * 1.25) { + contents.reagent.worldEffect(world, pos, contents.amount); + world.destroyBlock(pos, false); + } + return true; + } +} diff --git a/src/main/java/elucent/eidolon/reagent/RegisterReagentsEvent.java b/src/main/java/elucent/eidolon/reagent/RegisterReagentsEvent.java new file mode 100644 index 0000000..ea238c8 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/RegisterReagentsEvent.java @@ -0,0 +1,7 @@ +package elucent.eidolon.reagent; + +import net.minecraftforge.eventbus.api.Event; + +public class RegisterReagentsEvent extends Event { + // +} diff --git a/src/main/java/elucent/eidolon/reagent/SteamReagent.java b/src/main/java/elucent/eidolon/reagent/SteamReagent.java new file mode 100644 index 0000000..c6ddbc4 --- /dev/null +++ b/src/main/java/elucent/eidolon/reagent/SteamReagent.java @@ -0,0 +1,20 @@ +package elucent.eidolon.reagent; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +public class SteamReagent extends Reagent { + public SteamReagent(ResourceLocation name) { + super(name, new ResourceLocation(Eidolon.MODID, "block/vapor"), true); + } + + @Override + public void worldEffect(Level world, BlockPos pos, int amount) { + if (!world.isClientSide) + world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1); + } +} diff --git a/src/main/java/elucent/eidolon/recipe/CrucibleRecipe.java b/src/main/java/elucent/eidolon/recipe/CrucibleRecipe.java index f29bdf5..56cdf5c 100644 --- a/src/main/java/elucent/eidolon/recipe/CrucibleRecipe.java +++ b/src/main/java/elucent/eidolon/recipe/CrucibleRecipe.java @@ -1,25 +1,29 @@ package elucent.eidolon.recipe; -import elucent.eidolon.ritual.IRitualItemFocus; -import elucent.eidolon.ritual.MultiItemSacrifice; -import elucent.eidolon.ritual.Ritual; -import elucent.eidolon.ritual.RitualRegistry; -import elucent.eidolon.tile.CrucibleTileEntity; -import elucent.eidolon.tile.CrucibleTileEntity.CrucibleStep; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.tags.ITag; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.lang.reflect.Array; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -public class CrucibleRecipe { +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.tile.CrucibleTileEntity.CrucibleStep; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.registries.ForgeRegistryEntry; + +public class CrucibleRecipe implements Recipe { List steps = new ArrayList<>(); ResourceLocation registryName; ItemStack result; @@ -29,16 +33,17 @@ public ItemStack getResult() { } public static class Step { - public List matches = new ArrayList<>(); + public List matches = new ArrayList<>(); public int stirs; - public Step(int stirs, List matches) { + public Step(int stirs, List matches) { this.stirs = stirs; this.matches.addAll(matches); } }; - public CrucibleRecipe(ItemStack result) { + public CrucibleRecipe(List steps, ItemStack result) { + this.steps = steps; this.result = result; } @@ -60,41 +65,10 @@ public CrucibleRecipe setRegistryName(ResourceLocation registryName) { return this; } - public CrucibleRecipe addStep(Object... matches) { - addStirringStep(0, matches); - return this; - } - - public CrucibleRecipe addStep(int stirs) { - addStirringStep(stirs, new Object[]{}); - return this; - } - - public CrucibleRecipe addStirringStep(int stirs, Object... matches) { - steps.add(new Step(stirs, Arrays.asList(matches))); - return this; - } - - static boolean matches(Object match, ItemStack sacrifice) { - if (match instanceof ItemStack) { - if (ItemStack.areItemStacksEqual((ItemStack)match, sacrifice)) return true; - } - else if (match instanceof Item) { - if ((Item)match == sacrifice.getItem()) return true; - } - else if (match instanceof Block) { - if (((Block)match).asItem() == sacrifice.getItem()) return true; - } - else if (match instanceof ITag) { - if (((ITag)match).contains(sacrifice.getItem())) return true; - } - return false; - } - public boolean matches(List items) { if (steps.size() != items.size()) return false; - List matchList = new ArrayList<>(); + List matchList = new ArrayList<>(); List itemList = new ArrayList<>(); for (int i = 0; i < steps.size(); i ++) { @@ -109,7 +83,7 @@ public boolean matches(List items) { for (int j = 0; j < matchList.size(); j ++) { for (int k = 0; k < itemList.size(); k ++) { - if (matches(matchList.get(j), itemList.get(k))) { + if (matchList.get(j).test(itemList.get(k))) { matchList.remove(j --); itemList.remove(k --); break; @@ -117,9 +91,105 @@ public boolean matches(List items) { } } - if (matchList.size() != 0) return false; + if (matchList.size() != 0 || itemList.size() != 0) return false; } return true; } + + @Override + public boolean matches(Container inv, Level worldIn) { + return false; // we don't use a single inventory, so we ignore this one + } + + @Override + public ItemStack assemble(Container inv) { + return getResultItem(); + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return false; // we don't use a single inventory, so we ignore this one + } + + @Override + public ItemStack getResultItem() { + return result; + } + + @Override + public ResourceLocation getId() { + return registryName; + } + + public static class Type implements RecipeType { + @Override + public String toString () { + return Eidolon.MODID + ":crucible"; + } + + public static final CrucibleRecipe.Type INSTANCE = new CrucibleRecipe.Type(); + } + + public static class Serializer extends ForgeRegistryEntry> implements RecipeSerializer { + @Override + public CrucibleRecipe fromJson(ResourceLocation recipeId, JsonObject json) { + List steps = new ArrayList<>(); + JsonArray stepArray = json.getAsJsonArray("steps"); + for (JsonElement elt : stepArray) { + if (!elt.isJsonObject()) throw new JsonSyntaxException("Expected JSON object for crucible step."); + JsonObject step = elt.getAsJsonObject(); + int stirs = step.has("stirs") ? step.get("stirs").getAsInt() : 0; + List matches = new ArrayList<>(); + if (step.has("items")) { + JsonArray items = step.get("items").getAsJsonArray(); + for (JsonElement item : items) matches.add(Ingredient.fromJson(item)); + } + steps.add(new Step(stirs, matches)); + } + ItemStack result = CraftingHelper.getItemStack(json.getAsJsonObject("result"), true); + return CrucibleRegistry.register(new CrucibleRecipe(steps, result).setRegistryName(recipeId)); + } + + @Override + public CrucibleRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + int count = buffer.readInt(); + List steps = new ArrayList<>(); + for (int i = 0; i < count; i ++) { + int stirs = buffer.readInt(); + int ingredients = buffer.readInt(); + List matches = new ArrayList<>(); + for (int j = 0; j < ingredients; j ++) matches.add(Ingredient.fromNetwork(buffer)); + steps.add(new Step(stirs, matches)); + } + ItemStack result = buffer.readItem(); + return CrucibleRegistry.register(new CrucibleRecipe(steps, result).setRegistryName(recipeId)); + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, CrucibleRecipe recipe) { + buffer.writeInt(recipe.steps.size()); + for (Step step : recipe.steps) { + buffer.writeInt(step.stirs); + buffer.writeInt(step.matches.size()); + for (Ingredient i : step.matches) i.toNetwork(buffer); + } + buffer.writeItem(recipe.result); + } + } + + @Override + public RecipeSerializer getSerializer() { + return Registry.CRUCIBLE_RECIPE.get(); + } + + @Override + public RecipeType getType() { + return CrucibleRecipe.Type.INSTANCE; + } + + @Override + public boolean isSpecial() { + return true; // needed to prevent errors loading modded recipes in the recipe book + } } diff --git a/src/main/java/elucent/eidolon/recipe/CrucibleRegistry.java b/src/main/java/elucent/eidolon/recipe/CrucibleRegistry.java index 6da60a2..7dacaa5 100644 --- a/src/main/java/elucent/eidolon/recipe/CrucibleRegistry.java +++ b/src/main/java/elucent/eidolon/recipe/CrucibleRegistry.java @@ -1,37 +1,28 @@ package elucent.eidolon.recipe; -import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import elucent.eidolon.codex.CruciblePage; import elucent.eidolon.codex.Page; -import elucent.eidolon.gui.jei.CrucibleCategory; import elucent.eidolon.gui.jei.RecipeWrappers; -import elucent.eidolon.ritual.Ritual; -import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.CrucibleTileEntity.CrucibleStep; -import elucent.eidolon.util.StackUtil; -import net.minecraft.block.Blocks; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.tags.ItemTags; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.Tags; - -import javax.annotation.Resource; -import java.util.*; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; public class CrucibleRegistry { static Map linkedPages = new HashMap<>(); static Map recipes = new HashMap<>(); - public static void register(CrucibleRecipe recipe) { + public static CrucibleRecipe register(CrucibleRecipe recipe) { ResourceLocation loc = recipe.getRegistryName(); assert loc != null; recipes.put(loc, recipe); + return recipe; } public static void condense(List stacks) { @@ -39,7 +30,7 @@ public static void condense(List stacks) { ItemStack last = ItemStack.EMPTY; while (iter.hasNext()) { ItemStack i = iter.next(); - if (!ItemStack.areItemsEqual(i, last) || !ItemStack.areItemStackTagsEqual(i, last) || last.getCount() + i.getCount() > last.getMaxStackSize()) { + if (!ItemStack.isSame(i, last) || !ItemStack.tagMatches(i, last) || last.getCount() + i.getCount() > last.getMaxStackSize()) { last = i; } else { @@ -52,7 +43,7 @@ public static void condense(List stacks) { public static Page getDefaultPage(CrucibleRecipe recipe) { List steps = new ArrayList<>(); for (CrucibleRecipe.Step step : recipe.getSteps()) { - List stacks = StackUtil.stacksFromObjects(step.matches); + List stacks = step.matches.stream().map((i) -> i.getItems()[0].copy()).collect(Collectors.toList()); condense(stacks); steps.add(new CruciblePage.CrucibleStep(step.stirs, stacks.toArray(new ItemStack[stacks.size()]))); } @@ -65,10 +56,10 @@ public static void linkPage(ResourceLocation recipe, Page page) { public static List getWrappedRecipes() { List wrappers = new ArrayList<>(); - for (Map.Entry entry : recipes.entrySet()) { - Page page = linkedPages.getOrDefault(entry.getKey(), null); + for (CrucibleRecipe recipe : recipes.values()) { + Page page = null; // linkedPages.getOrDefault(entry.getKey(), null); wrappers.add(new RecipeWrappers.Crucible( - entry.getValue(), + recipe, page )); } @@ -85,80 +76,80 @@ public static CrucibleRecipe find(List steps) { } public static void init() { - register(new CrucibleRecipe(new ItemStack(Registry.ARCANE_GOLD_INGOT.get(), 2)).setRegistryName(Eidolon.MODID, "arcane_gold") - .addStep(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Registry.SOUL_SHARD.get()) - .addStep(Tags.Items.INGOTS_GOLD, Tags.Items.INGOTS_GOLD)); - register(new CrucibleRecipe(new ItemStack(Registry.LESSER_SOUL_GEM.get())).setRegistryName(Eidolon.MODID, "lesser_soul_gem") - .addStep(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.GEMS_LAPIS, Tags.Items.GEMS_LAPIS) - .addStirringStep(2, Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get()) - .addStep(Tags.Items.GEMS_QUARTZ)); - register(new CrucibleRecipe(new ItemStack(Registry.SHADOW_GEM.get())).setRegistryName(Eidolon.MODID, "shadow_gem") - .addStep(Items.COAL) - .addStirringStep(1, Items.GHAST_TEAR, Registry.DEATH_ESSENCE.get()) - .addStirringStep(1, Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.DEATH_ESSENCE.get()) - .addStep(Tags.Items.GEMS_DIAMOND)); - register(new CrucibleRecipe(new ItemStack(Registry.SULFUR.get(), 2)).setRegistryName(Eidolon.MODID, "sulfur") - .addStep(Items.COAL, Registry.ENCHANTED_ASH.get())); - register(new CrucibleRecipe(new ItemStack(Registry.ENDER_CALX.get(), 2)).setRegistryName(Eidolon.MODID, "ender_calx") - .addStep(Tags.Items.ENDER_PEARLS, Registry.ENCHANTED_ASH.get())); - register(new CrucibleRecipe(new ItemStack(Items.LEATHER, 1)).setRegistryName(Eidolon.MODID, "leather_from_flesh") - .addStep(Registry.ENCHANTED_ASH.get(), Registry.ENCHANTED_ASH.get()) - .addStirringStep(2, Items.ROTTEN_FLESH)); - register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_beef") - .addStep(Items.BEEF, Tags.Items.MUSHROOMS)); - register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_pork") - .addStep(Items.PORKCHOP, Tags.Items.MUSHROOMS)); - register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_mutton") - .addStep(Items.MUTTON, Tags.Items.MUSHROOMS)); - register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_chicken") - .addStep(Items.CHICKEN, Tags.Items.MUSHROOMS)); - register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_rabbit") - .addStep(Items.RABBIT, Tags.Items.MUSHROOMS)); - register(new CrucibleRecipe(new ItemStack(Items.GUNPOWDER, 4)).setRegistryName(Eidolon.MODID, "gunpowder") - .addStep(Registry.SULFUR.get(), Items.BONE_MEAL) - .addStirringStep(1, Items.CHARCOAL)); - register(new CrucibleRecipe(new ItemStack(Items.GOLDEN_APPLE, 1)).setRegistryName(Eidolon.MODID, "gilded_apple") - .addStep(Tags.Items.INGOTS_GOLD, Tags.Items.INGOTS_GOLD) - .addStirringStep(2, Registry.ENCHANTED_ASH.get()) - .addStep(Items.APPLE)); - register(new CrucibleRecipe(new ItemStack(Items.GOLDEN_CARROT, 1)).setRegistryName(Eidolon.MODID, "gilded_carrot") - .addStep(Tags.Items.NUGGETS_GOLD, Tags.Items.NUGGETS_GOLD) - .addStirringStep(2, Registry.ENCHANTED_ASH.get()) - .addStep(Items.CARROT)); - register(new CrucibleRecipe(new ItemStack(Items.GLISTERING_MELON_SLICE, 1)).setRegistryName(Eidolon.MODID, "gilded_melon") - .addStep(Tags.Items.NUGGETS_GOLD, Tags.Items.NUGGETS_GOLD) - .addStirringStep(2, Registry.ENCHANTED_ASH.get()) - .addStep(Items.MELON_SLICE)); - register(new CrucibleRecipe(new ItemStack(Registry.DEATH_ESSENCE.get(), 4)).setRegistryName(Eidolon.MODID, "death_essence") - .addStep(Registry.ZOMBIE_HEART.get(), Items.ROTTEN_FLESH) - .addStirringStep(2, Items.BONE_MEAL, Items.BONE_MEAL) - .addStep(Items.CHARCOAL)); - register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 4)).setRegistryName(Eidolon.MODID, "crimson_essence_fungus") - .addStep(Items.CRIMSON_FUNGUS, Items.NETHER_WART) - .addStirringStep(1, Registry.SULFUR.get())); - register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 2)).setRegistryName(Eidolon.MODID, "crimson_essence_roots") - .addStep(Items.CRIMSON_ROOTS, Items.NETHER_WART) - .addStirringStep(1, Registry.SULFUR.get())); - register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 2)).setRegistryName(Eidolon.MODID, "crimson_essence_vines") - .addStep(Items.WEEPING_VINES, Items.NETHER_WART) - .addStirringStep(1, Registry.SULFUR.get())); - register(new CrucibleRecipe(new ItemStack(Registry.FUNGUS_SPROUTS.get(), 2)).setRegistryName(Eidolon.MODID, "fungus_sprouts") - .addStep(Tags.Items.MUSHROOMS) - .addStirringStep(2, Items.BONE_MEAL) - .addStep(Items.WHEAT_SEEDS)); - register(new CrucibleRecipe(new ItemStack(Registry.WARPED_SPROUTS.get(), 2)).setRegistryName(Eidolon.MODID, "warped_sprouts") - .addStep(Blocks.WARPED_FUNGUS) - .addStirringStep(2, Registry.ENDER_CALX.get()) - .addStep(Items.NETHER_WART)); - register(new CrucibleRecipe(new ItemStack(Registry.POLISHED_PLANKS.getBlock(), 32)).setRegistryName(Eidolon.MODID, "polished_planks") - .addStep(ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, - ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS) - .addStirringStep(1, Registry.SOUL_SHARD.get(), Registry.ENCHANTED_ASH.get())); +// register(new CrucibleRecipe(new ItemStack(Registry.ARCANE_GOLD_INGOT.get(), 2)).setRegistryName(Eidolon.MODID, "arcane_gold") +// .addStep(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Registry.SOUL_SHARD.get()) +// .addStep(Tags.Items.INGOTS_GOLD, Tags.Items.INGOTS_GOLD)); +// register(new CrucibleRecipe(new ItemStack(Registry.LESSER_SOUL_GEM.get())).setRegistryName(Eidolon.MODID, "lesser_soul_gem") +// .addStep(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.GEMS_LAPIS, Tags.Items.GEMS_LAPIS) +// .addStirringStep(2, Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get()) +// .addStep(Tags.Items.GEMS_QUARTZ)); +// register(new CrucibleRecipe(new ItemStack(Registry.SHADOW_GEM.get())).setRegistryName(Eidolon.MODID, "shadow_gem") +// .addStep(Items.COAL) +// .addStirringStep(1, Items.GHAST_TEAR, Registry.DEATH_ESSENCE.get()) +// .addStirringStep(1, Registry.SOUL_SHARD.get(), Registry.SOUL_SHARD.get(), Registry.DEATH_ESSENCE.get()) +// .addStep(Tags.Items.GEMS_DIAMOND)); +// register(new CrucibleRecipe(new ItemStack(Registry.SULFUR.get(), 2)).setRegistryName(Eidolon.MODID, "sulfur") +// .addStep(Items.COAL, Registry.ENCHANTED_ASH.get())); +// register(new CrucibleRecipe(new ItemStack(Registry.ENDER_CALX.get(), 2)).setRegistryName(Eidolon.MODID, "ender_calx") +// .addStep(Tags.Items.ENDER_PEARLS, Registry.ENCHANTED_ASH.get())); +// register(new CrucibleRecipe(new ItemStack(Items.LEATHER, 1)).setRegistryName(Eidolon.MODID, "leather_from_flesh") +// .addStep(Registry.ENCHANTED_ASH.get(), Registry.ENCHANTED_ASH.get()) +// .addStirringStep(2, Items.ROTTEN_FLESH)); +// register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_beef") +// .addStep(Items.BEEF, Tags.Items.MUSHROOMS)); +// register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_pork") +// .addStep(Items.PORKCHOP, Tags.Items.MUSHROOMS)); +// register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_mutton") +// .addStep(Items.MUTTON, Tags.Items.MUSHROOMS)); +// register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_chicken") +// .addStep(Items.CHICKEN, Tags.Items.MUSHROOMS)); +// register(new CrucibleRecipe(new ItemStack(Items.ROTTEN_FLESH, 1)).setRegistryName(Eidolon.MODID, "rotten_rabbit") +// .addStep(Items.RABBIT, Tags.Items.MUSHROOMS)); +// register(new CrucibleRecipe(new ItemStack(Items.GUNPOWDER, 4)).setRegistryName(Eidolon.MODID, "gunpowder") +// .addStep(Registry.SULFUR.get(), Items.BONE_MEAL) +// .addStirringStep(1, Items.CHARCOAL)); +// register(new CrucibleRecipe(new ItemStack(Items.GOLDEN_APPLE, 1)).setRegistryName(Eidolon.MODID, "gilded_apple") +// .addStep(Tags.Items.INGOTS_GOLD, Tags.Items.INGOTS_GOLD) +// .addStirringStep(2, Registry.ENCHANTED_ASH.get()) +// .addStep(Items.APPLE)); +// register(new CrucibleRecipe(new ItemStack(Items.GOLDEN_CARROT, 1)).setRegistryName(Eidolon.MODID, "gilded_carrot") +// .addStep(Tags.Items.NUGGETS_GOLD, Tags.Items.NUGGETS_GOLD) +// .addStirringStep(2, Registry.ENCHANTED_ASH.get()) +// .addStep(Items.CARROT)); +// register(new CrucibleRecipe(new ItemStack(Items.GLISTERING_MELON_SLICE, 1)).setRegistryName(Eidolon.MODID, "gilded_melon") +// .addStep(Tags.Items.NUGGETS_GOLD, Tags.Items.NUGGETS_GOLD) +// .addStirringStep(2, Registry.ENCHANTED_ASH.get()) +// .addStep(Items.MELON_SLICE)); +// register(new CrucibleRecipe(new ItemStack(Registry.DEATH_ESSENCE.get(), 4)).setRegistryName(Eidolon.MODID, "death_essence") +// .addStep(Registry.ZOMBIE_HEART.get(), Items.ROTTEN_FLESH) +// .addStirringStep(2, Items.BONE_MEAL, Items.BONE_MEAL) +// .addStep(Items.CHARCOAL)); +// register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 4)).setRegistryName(Eidolon.MODID, "crimson_essence_fungus") +// .addStep(Items.CRIMSON_FUNGUS, Items.NETHER_WART) +// .addStirringStep(1, Registry.SULFUR.get())); +// register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 2)).setRegistryName(Eidolon.MODID, "crimson_essence_roots") +// .addStep(Items.CRIMSON_ROOTS, Items.NETHER_WART) +// .addStirringStep(1, Registry.SULFUR.get())); +// register(new CrucibleRecipe(new ItemStack(Registry.CRIMSON_ESSENCE.get(), 2)).setRegistryName(Eidolon.MODID, "crimson_essence_vines") +// .addStep(Items.WEEPING_VINES, Items.NETHER_WART) +// .addStirringStep(1, Registry.SULFUR.get())); +// register(new CrucibleRecipe(new ItemStack(Registry.FUNGUS_SPROUTS.get(), 2)).setRegistryName(Eidolon.MODID, "fungus_sprouts") +// .addStep(Tags.Items.MUSHROOMS) +// .addStirringStep(2, Items.BONE_MEAL) +// .addStep(Items.WHEAT_SEEDS)); +// register(new CrucibleRecipe(new ItemStack(Registry.WARPED_SPROUTS.get(), 2)).setRegistryName(Eidolon.MODID, "warped_sprouts") +// .addStep(Blocks.WARPED_FUNGUS) +// .addStirringStep(2, Registry.ENDER_CALX.get()) +// .addStep(Items.NETHER_WART)); +// register(new CrucibleRecipe(new ItemStack(Registry.POLISHED_PLANKS.getBlock(), 32)).setRegistryName(Eidolon.MODID, "polished_planks") +// .addStep(ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, +// ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS, ItemTags.PLANKS) +// .addStirringStep(1, Registry.SOUL_SHARD.get(), Registry.ENCHANTED_ASH.get())); } } diff --git a/src/main/java/elucent/eidolon/recipe/WorktableRecipe.java b/src/main/java/elucent/eidolon/recipe/WorktableRecipe.java index fc9dc2b..2ba0887 100644 --- a/src/main/java/elucent/eidolon/recipe/WorktableRecipe.java +++ b/src/main/java/elucent/eidolon/recipe/WorktableRecipe.java @@ -1,20 +1,34 @@ package elucent.eidolon.recipe; -import net.minecraft.block.Block; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.tags.ITag; -import net.minecraft.util.NonNullList; -import net.minecraft.util.ResourceLocation; - -public class WorktableRecipe { - Object[] core, extras; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.NonNullList; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.registries.ForgeRegistryEntry; + +public class WorktableRecipe implements Recipe { + Ingredient[] core, extras; ItemStack result; ResourceLocation registryName; - public WorktableRecipe(Object[] core, Object[] extras, ItemStack result) { + public WorktableRecipe(Ingredient[] core, Ingredient[] extras, ItemStack result) { this.core = core; this.extras = extras; this.result = result; @@ -34,47 +48,31 @@ public WorktableRecipe setRegistryName(ResourceLocation registryName) { return this; } - public Object[] getCore() { + public Ingredient[] getCore() { return core; } - public Object[] getOuter() { + public Ingredient[] getOuter() { return extras; } - static boolean matches(Object match, ItemStack sacrifice) { - if (match instanceof ItemStack) { - if (ItemStack.areItemStacksEqual((ItemStack)match, sacrifice)) return true; - } - else if (match instanceof Item) { - if ((Item)match == sacrifice.getItem()) return true; - } - else if (match instanceof Block) { - if (((Block)match).asItem() == sacrifice.getItem()) return true; - } - else if (match instanceof ITag) { - if (((ITag)match).contains(sacrifice.getItem())) return true; - } - return false; - } - - public boolean matches(IInventory coreInv, IInventory extraInv) { - if (coreInv.getSizeInventory() < 9 || extraInv.getSizeInventory() < 4) return false; + public boolean matches(Container coreInv, Container extraInv) { + if (coreInv.getContainerSize() < 9 || extraInv.getContainerSize() < 4) return false; for (int i = 0; i < core.length; i ++) { - if (!matches(core[i], coreInv.getStackInSlot(i))) return false; + if (!core[i].test(coreInv.getItem(i))) return false; } for (int i = 0; i < extras.length; i ++) { - if (!matches(extras[i], extraInv.getStackInSlot(i))) return false; + if (!extras[i].test(extraInv.getItem(i))) return false; } return true; } - public NonNullList getRemainingItems(IInventory coreInv, IInventory extraInv) { + public NonNullList getRemainingItems(Container coreInv, Container extraInv) { NonNullList items = NonNullList.withSize(13, ItemStack.EMPTY); for(int i = 0; i < items.size(); ++i) { - IInventory inv = i < 9 ? coreInv : extraInv; - ItemStack item = inv.getStackInSlot(i < 9 ? i : i - 9); + Container inv = i < 9 ? coreInv : extraInv; + ItemStack item = inv.getItem(i < 9 ? i : i - 9); if (item.hasContainerItem()) { items.set(i, item.getContainerItem()); } @@ -86,4 +84,100 @@ public NonNullList getRemainingItems(IInventory coreInv, IInventory e public ItemStack getResult() { return result.copy(); } + + @Override + public boolean matches(Container inv, Level worldIn) { + return false; // we don't use a single inventory, so we ignore this one + } + + @Override + public ItemStack assemble(Container inv) { + return getResultItem(); + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return false; // we don't use a single inventory, so we ignore this one + } + + @Override + public ItemStack getResultItem() { + return result; + } + + @Override + public ResourceLocation getId() { + return registryName; + } + + public static class Type implements RecipeType { + @Override + public String toString () { + return Eidolon.MODID + ":worktable"; + } + + public static final Type INSTANCE = new Type(); + } + + public static class Serializer extends ForgeRegistryEntry> implements RecipeSerializer { + @Override + public WorktableRecipe fromJson(ResourceLocation recipeId, JsonObject json) { + Map ingredientMap = new HashMap<>(); + JsonObject keys = json.getAsJsonObject("key"); + for (Map.Entry e : keys.entrySet()) { + if (e.getKey().length() != 1) throw new RuntimeException("Recipe ingredient key must be a single character"); + ingredientMap.put(e.getKey(), Ingredient.fromJson(e.getValue().getAsJsonObject())); + } + Ingredient[] core = new Ingredient[9], extras = new Ingredient[4]; + JsonArray pattern = json.getAsJsonArray("pattern"); + if (pattern.size() != 3) throw new JsonSyntaxException("All worktable recipes must have three rows."); + for (int i = 0; i < 3; i ++) { + if (pattern.get(i).getAsString().length() != 3) throw new JsonSyntaxException("All worktable recipe rows must have three columns."); + for (int j = 0; j < 3; j ++) { + String key = pattern.get(i).getAsString().substring(j, j + 1); + Ingredient item = key.equals(" ") ? Ingredient.EMPTY : ingredientMap.get(key); + core[i * 3 + j] = item; + } + } + String reagents = json.get("reagents").getAsString(); + if (reagents.length() != 4) throw new JsonSyntaxException("All worktable recipes must have reagent strings of length 4."); + for (int i = 0; i < 4; i ++) { + String key = reagents.substring(i, i + 1); + extras[i] = key.equals(" ") ? Ingredient.EMPTY : ingredientMap.get(key); + } + ItemStack result = CraftingHelper.getItemStack(json.getAsJsonObject("result"), true); + return WorktableRegistry.register(new WorktableRecipe(core, extras, result).setRegistryName(recipeId)); + } + + @Override + public WorktableRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) { + Ingredient[] core = new Ingredient[9], extras = new Ingredient[4]; + for (int i = 0; i < 9; i ++) core[i] = Ingredient.fromNetwork(buffer); + for (int i = 0; i < 4; i ++) extras[i] = Ingredient.fromNetwork(buffer); + ItemStack result = buffer.readItem(); + return WorktableRegistry.register(new WorktableRecipe(core, extras, result).setRegistryName(recipeId)); + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, WorktableRecipe recipe) { + for (int i = 0; i < 9; i ++) recipe.core[i].toNetwork(buffer); + for (int i = 0; i < 4; i ++) recipe.extras[i].toNetwork(buffer); + buffer.writeItem(recipe.result); + } + } + + @Override + public RecipeSerializer getSerializer() { + return Registry.WORKTABLE_RECIPE.get(); + } + + @Override + public RecipeType getType() { + return Type.INSTANCE; + } + + @Override + public boolean isSpecial() { + return true; // needed to prevent errors loading modded recipes in the recipe book + } } diff --git a/src/main/java/elucent/eidolon/recipe/WorktableRegistry.java b/src/main/java/elucent/eidolon/recipe/WorktableRegistry.java index 9759c8c..8aca6ae 100644 --- a/src/main/java/elucent/eidolon/recipe/WorktableRegistry.java +++ b/src/main/java/elucent/eidolon/recipe/WorktableRegistry.java @@ -1,54 +1,41 @@ package elucent.eidolon.recipe; -import com.sun.corba.se.spi.orbutil.threadpool.Work; -import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; -import elucent.eidolon.codex.CruciblePage; -import elucent.eidolon.codex.Page; -import elucent.eidolon.codex.WorktablePage; -import elucent.eidolon.gui.jei.RecipeWrappers; -import elucent.eidolon.tile.CrucibleTileEntity; -import elucent.eidolon.util.StackUtil; -import net.minecraft.block.Blocks; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.ForgeTagHandler; -import net.minecraftforge.common.Tags; -import net.minecraftforge.common.data.ForgeBlockTagsProvider; -import net.minecraftforge.common.data.ForgeItemTagsProvider; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import elucent.eidolon.codex.Page; +import elucent.eidolon.codex.WorktablePage; +import elucent.eidolon.gui.jei.RecipeWrappers; +import elucent.eidolon.util.RecipeUtil; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; + public class WorktableRegistry { static Map recipes = new HashMap<>(); - public static void register(WorktableRecipe recipe) { + public static WorktableRecipe register(WorktableRecipe recipe) { ResourceLocation loc = recipe.getRegistryName(); assert loc != null; recipes.put(loc, recipe); + return recipe; } public static Page getDefaultPage(WorktableRecipe recipe) { List stacks = new ArrayList<>(); - for (Object o : recipe.core) stacks.add(StackUtil.stackFromObject(o)); - for (Object o : recipe.extras) stacks.add(StackUtil.stackFromObject(o)); + for (Object o : recipe.core) stacks.add(RecipeUtil.stackFromObject(o)); + for (Object o : recipe.extras) stacks.add(RecipeUtil.stackFromObject(o)); return new WorktablePage(recipe.result.copy(), stacks.toArray(new ItemStack[stacks.size()])); } public static List getWrappedRecipes() { List wrappers = new ArrayList<>(); - for (Map.Entry entry : recipes.entrySet()) { + for (WorktableRecipe recipe : recipes.values()) { Page page = null; // linkedPages.getOrDefault(entry.getKey(), null); wrappers.add(new RecipeWrappers.Worktable( - entry.getValue(), + recipe, page )); } @@ -59,201 +46,8 @@ public static WorktableRecipe find(ResourceLocation loc) { return recipes.get(loc); } - public static WorktableRecipe find(IInventory core, IInventory outer) { + public static WorktableRecipe find(Container core, Container outer) { for (WorktableRecipe recipe : recipes.values()) if (recipe.matches(core, outer)) return recipe; return null; } - - public static void init() { - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.PEWTER_INGOT.get(), ItemStack.EMPTY, - Registry.PEWTER_INLAY.get(), Registry.BASIC_AMULET.get(), Registry.PEWTER_INLAY.get(), - ItemStack.EMPTY, Blocks.OBSIDIAN, ItemStack.EMPTY - }, new Object[]{ - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY, - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.VOID_AMULET.get())).setRegistryName(Eidolon.MODID, "void_amulet")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.LESSER_SOUL_GEM.get(), ItemStack.EMPTY, - Registry.ENCHANTED_ASH.get(), Items.IRON_CHESTPLATE, Registry.ENCHANTED_ASH.get(), - ItemStack.EMPTY, Registry.ENCHANTED_ASH.get(), ItemStack.EMPTY - }, new Object[]{ - Registry.PEWTER_INLAY.get(), - Registry.PEWTER_INLAY.get(), - Registry.PEWTER_INLAY.get(), - Registry.PEWTER_INLAY.get() - }, new ItemStack(Registry.WARDED_MAIL.get())).setRegistryName(Eidolon.MODID, "warded_mail")); - register(new WorktableRecipe(new Object[]{ - Registry.PEWTER_INGOT.get(), Registry.PEWTER_INGOT.get(), ItemStack.EMPTY, - ItemStack.EMPTY, Items.STICK, Registry.PEWTER_INGOT.get(), - Items.STICK, ItemStack.EMPTY, ItemStack.EMPTY - }, new Object[]{ - Registry.UNHOLY_SYMBOL.get(), - Registry.SOUL_SHARD.get(), - Registry.TATTERED_CLOTH.get(), - Registry.SOUL_SHARD.get() - }, new ItemStack(Registry.REAPER_SCYTHE.get())).setRegistryName(Eidolon.MODID, "reaper_scythe")); - register(new WorktableRecipe(new Object[]{ - Registry.PEWTER_INGOT.get(), Registry.PEWTER_INGOT.get(), ItemStack.EMPTY, - Registry.PEWTER_INGOT.get(), Items.STICK, ItemStack.EMPTY, - ItemStack.EMPTY, Items.STICK, ItemStack.EMPTY - }, new Object[]{ - Registry.UNHOLY_SYMBOL.get(), - ItemStack.EMPTY, - Registry.PEWTER_INLAY.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.CLEAVING_AXE.get())).setRegistryName(Eidolon.MODID, "cleaving_axe")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Items.BOOK, ItemStack.EMPTY, - Registry.ARCANE_GOLD_INGOT.get(), Blocks.OBSIDIAN, Registry.ARCANE_GOLD_INGOT.get(), - Blocks.OBSIDIAN, Blocks.OBSIDIAN, Blocks.OBSIDIAN - }, new Object[]{ - Tags.Items.GEMS_DIAMOND, - Registry.GOLD_INLAY.get(), - Tags.Items.GEMS_DIAMOND, - Registry.GOLD_INLAY.get() - }, new ItemStack(Registry.SOUL_ENCHANTER.get())).setRegistryName(Eidolon.MODID, "soul_enchanter")); - register(new WorktableRecipe(new Object[]{ - Blocks.OBSIDIAN, Blocks.CRYING_OBSIDIAN, Blocks.OBSIDIAN, - ItemStack.EMPTY, Registry.PEWTER_INGOT.get(), ItemStack.EMPTY, - ItemStack.EMPTY, Registry.PEWTER_INLAY.get(), ItemStack.EMPTY - }, new Object[]{ - Items.ENDER_PEARL, - Registry.SOUL_SHARD.get(), - Registry.LESSER_SOUL_GEM.get(), - Registry.SOUL_SHARD.get() - }, new ItemStack(Registry.REVERSAL_PICK.get())).setRegistryName(Eidolon.MODID, "reversal_pick")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.ARCANE_GOLD_INGOT.get(), Registry.SHADOW_GEM.get(), - ItemStack.EMPTY, Items.STICK, Registry.ARCANE_GOLD_INGOT.get(), - Registry.GOLD_INLAY.get(), ItemStack.EMPTY, ItemStack.EMPTY - }, new Object[]{ - Registry.LESSER_SOUL_GEM.get(), - Items.BLAZE_POWDER, - Items.BLAZE_POWDER, - Items.BLAZE_POWDER - }, new ItemStack(Registry.SOULFIRE_WAND.get())).setRegistryName(Eidolon.MODID, "soulfire_wand")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.PEWTER_INGOT.get(), Registry.WRAITH_HEART.get(), - ItemStack.EMPTY, Items.STICK, Registry.PEWTER_INGOT.get(), - Registry.PEWTER_INLAY.get(), ItemStack.EMPTY, ItemStack.EMPTY - }, new Object[]{ - Registry.LESSER_SOUL_GEM.get(), - Items.BONE_MEAL, - Items.BONE_MEAL, - Items.BONE_MEAL - }, new ItemStack(Registry.BONECHILL_WAND.get())).setRegistryName(Eidolon.MODID, "bonechill_wand")); - register(new WorktableRecipe(new Object[]{ - Blocks.SMOOTH_STONE_SLAB, Blocks.SMOOTH_STONE_SLAB, Blocks.SMOOTH_STONE_SLAB, - Tags.Items.STONE, Tags.Items.STONE, Tags.Items.STONE, - Tags.Items.STONE, Registry.PEWTER_INLAY.get(), Tags.Items.STONE - }, new Object[]{ - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY, - ItemStack.EMPTY, - ItemStack.EMPTY - }, new ItemStack(Registry.STONE_ALTAR.get(), 3)).setRegistryName(Eidolon.MODID, "stone_altar")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Blocks.SMOOTH_STONE, ItemStack.EMPTY, - Tags.Items.STONE, Tags.Items.STONE, Tags.Items.STONE, - ItemStack.EMPTY, Tags.Items.STONE, ItemStack.EMPTY - }, new Object[]{ - Registry.UNHOLY_SYMBOL.get(), - ItemStack.EMPTY, - Registry.GOLD_INLAY.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.UNHOLY_EFFIGY.get())).setRegistryName(Eidolon.MODID, "unholy_effigy")); - register(new WorktableRecipe(new Object[]{ - Blocks.WHITE_WOOL, Blocks.WHITE_WOOL, Blocks.WHITE_WOOL, - Blocks.WHITE_WOOL, Registry.SHADOW_GEM.get(), Blocks.WHITE_WOOL, - Blocks.WHITE_WOOL, Blocks.WHITE_WOOL, Blocks.WHITE_WOOL - }, new Object[]{ - Registry.UNHOLY_SYMBOL.get(), - ItemStack.EMPTY, - Tags.Items.DYES_BLUE, - ItemStack.EMPTY - }, new ItemStack(Registry.WICKED_WEAVE.get(), 8)).setRegistryName(Eidolon.MODID, "wicked_weave")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, - ItemStack.EMPTY, Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, - Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, Registry.WICKED_WEAVE.get() - }, new Object[]{ - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY, - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.WARLOCK_HAT.get())).setRegistryName(Eidolon.MODID, "warlock_hat")); - register(new WorktableRecipe(new Object[]{ - Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), - Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), - Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, Registry.WICKED_WEAVE.get() - }, new Object[]{ - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY, - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.WARLOCK_CLOAK.get())).setRegistryName(Eidolon.MODID, "warlock_cloak")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, - Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, Registry.WICKED_WEAVE.get(), - Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, Registry.WICKED_WEAVE.get() - }, new Object[]{ - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY, - Registry.SOUL_SHARD.get(), - ItemStack.EMPTY - }, new ItemStack(Registry.WARLOCK_BOOTS.get())).setRegistryName(Eidolon.MODID, "warlock_boots")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Tags.Items.ENDER_PEARLS, ItemStack.EMPTY, - Tags.Items.FEATHERS, Registry.BASIC_BELT.get(), Tags.Items.FEATHERS, - ItemStack.EMPTY, Registry.LESSER_SOUL_GEM.get(), ItemStack.EMPTY - }, new Object[]{ - Registry.ENDER_CALX.get(), - Registry.PEWTER_INLAY.get(), - Registry.ENDER_CALX.get(), - Registry.PEWTER_INLAY.get() - }, new ItemStack(Registry.GRAVITY_BELT.get())).setRegistryName(Eidolon.MODID, "gravity_belt")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.GOLD_INLAY.get(), ItemStack.EMPTY, - Registry.ARCANE_GOLD_INGOT.get(), Registry.BASIC_BELT.get(), Registry.ARCANE_GOLD_INGOT.get(), - ItemStack.EMPTY, Tags.Items.GEMS_DIAMOND, ItemStack.EMPTY - }, new Object[]{ - Items.LEATHER, - Registry.SOUL_SHARD.get(), - Registry.ENCHANTED_ASH.get(), - Registry.SOUL_SHARD.get() - }, new ItemStack(Registry.RESOLUTE_BELT.get())).setRegistryName(Eidolon.MODID, "resolute_belt")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Registry.WICKED_WEAVE.get(), ItemStack.EMPTY, - Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), Registry.WICKED_WEAVE.get(), - ItemStack.EMPTY, Registry.LESSER_SOUL_GEM.get(), ItemStack.EMPTY - }, new Object[]{ - Registry.WARPED_SPROUTS.get(), - Registry.ENDER_CALX.get(), - Registry.SOUL_SHARD.get(), - Registry.ENDER_CALX.get() - }, new ItemStack(Registry.PRESTIGIOUS_PALM.get())).setRegistryName(Eidolon.MODID, "prestigious_palm")); - register(new WorktableRecipe(new Object[]{ - Registry.LEAD_INGOT.get(), Registry.LEAD_INGOT.get(), Registry.LEAD_INGOT.get(), - Registry.LEAD_INGOT.get(), Registry.LEAD_INGOT.get(), Registry.LEAD_INGOT.get(), - Items.LEATHER, Registry.SOUL_SHARD.get(), Items.LEATHER - }, new Object[]{ - Tags.Items.STORAGE_BLOCKS_LAPIS, - ItemStack.EMPTY, - Tags.Items.GEMS_QUARTZ, - ItemStack.EMPTY - }, new ItemStack(Registry.MIND_SHIELDING_PLATE.get())).setRegistryName(Eidolon.MODID, "mind_shielding_plate")); - register(new WorktableRecipe(new Object[]{ - ItemStack.EMPTY, Tags.Items.STORAGE_BLOCKS_DIAMOND, ItemStack.EMPTY, - ItemStack.EMPTY, Registry.BASIC_AMULET.get(), ItemStack.EMPTY, - ItemStack.EMPTY, Blocks.GLASS, ItemStack.EMPTY - }, new Object[]{ - Registry.ZOMBIE_HEART.get(), - Registry.LESSER_SOUL_GEM.get(), - Registry.WRAITH_HEART.get(), - Registry.LESSER_SOUL_GEM.get() - }, new ItemStack(Registry.GLASS_HAND.get())).setRegistryName(Eidolon.MODID, "glass_hand")); - } } diff --git a/src/main/java/elucent/eidolon/ritual/AllureRitual.java b/src/main/java/elucent/eidolon/ritual/AllureRitual.java index 898dded..15051be 100644 --- a/src/main/java/elucent/eidolon/ritual/AllureRitual.java +++ b/src/main/java/elucent/eidolon/ritual/AllureRitual.java @@ -1,19 +1,17 @@ package elucent.eidolon.ritual; +import java.util.List; +import java.util.stream.Collectors; + import elucent.eidolon.Eidolon; import elucent.eidolon.entity.ai.GoToPositionGoal; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.ai.brain.BrainUtil; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.merchant.villager.VillagerEntity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.List; -import java.util.stream.Collectors; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class AllureRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/allure_ritual"); @@ -23,17 +21,17 @@ public AllureRitual() { } @Override - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { if (world.getGameTime() % 200 == 0) { - List animals = world.getEntitiesWithinAABB(AnimalEntity.class, new AxisAlignedBB(pos).grow(96, 16, 96)); - for (AnimalEntity a : animals) { + List animals = world.getEntitiesOfClass(Animal.class, new AABB(pos).inflate(96, 16, 96)); + for (Animal a : animals) { boolean hasGoal = a.goalSelector.getRunningGoals() .filter((goal) -> goal.getGoal() instanceof GoToPositionGoal) .count() > 0; - if (!hasGoal && a.getDistanceSq(pos.getX(), pos.getY(), pos.getZ()) >= 12 * 12 && world.rand.nextInt(40) == 0) { - BlockPos target = pos.down().add(world.rand.nextInt(9) - 4, 0, world.rand.nextInt(9) - 4); + if (!hasGoal && a.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) >= 12 * 12 && world.random.nextInt(40) == 0) { + BlockPos target = pos.below().offset(world.random.nextInt(9) - 4, 0, world.random.nextInt(9) - 4); a.goalSelector.addGoal(1, new GoToPositionGoal(a, target, 1.0)); - } else if (hasGoal && a.getDistanceSq(pos.getX(), pos.getY(), pos.getZ()) < 8 * 8) { + } else if (hasGoal && a.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) < 8 * 8) { List goals = a.goalSelector.getRunningGoals().filter((goal) -> goal.getGoal() instanceof GoToPositionGoal) .collect(Collectors.toList()); for (Goal g : goals) a.goalSelector.removeGoal(g); diff --git a/src/main/java/elucent/eidolon/ritual/CrystalRitual.java b/src/main/java/elucent/eidolon/ritual/CrystalRitual.java index 48681bc..7b5580b 100644 --- a/src/main/java/elucent/eidolon/ritual/CrystalRitual.java +++ b/src/main/java/elucent/eidolon/ritual/CrystalRitual.java @@ -1,21 +1,18 @@ package elucent.eidolon.ritual; +import java.util.List; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.network.CrystallizeEffectPacket; import elucent.eidolon.network.Networking; -import elucent.eidolon.particle.GenericParticle; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.particles.ParticleType; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Resource; -import java.util.List; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class CrystalRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/crystal_ritual"); @@ -25,13 +22,13 @@ public CrystalRitual() { } @Override - public RitualResult start(World world, BlockPos pos) { - List entities = world.getEntitiesWithinAABB(LivingEntity.class, getSearchBounds(pos), (e) -> e.isEntityUndead()); + public RitualResult start(Level world, BlockPos pos) { + List entities = world.getEntitiesOfClass(LivingEntity.class, getSearchBounds(pos), (e) -> e.isInvertedHealAndHarm() && e.canChangeDimensions()); for (LivingEntity e : entities) { - e.attackEntityFrom(Registry.RITUAL_DAMAGE, e.getMaxHealth() * 1000); - if (!world.isRemote) { - Networking.sendToTracking(world, e.getPosition(), new CrystallizeEffectPacket(e.getPosition())); - world.addEntity(new ItemEntity(world, e.getPosX(), e.getPosY(), e.getPosZ(), new ItemStack(Registry.SOUL_SHARD.get(), 1 + world.rand.nextInt(3)))); + e.hurt(Registry.RITUAL_DAMAGE, e.getMaxHealth() * 1000); + if (!world.isClientSide) { + Networking.sendToTracking(world, e.blockPosition(), new CrystallizeEffectPacket(e.blockPosition())); + world.addFreshEntity(new ItemEntity(world, e.getX(), e.getY(), e.getZ(), new ItemStack(Registry.SOUL_SHARD.get(), 1 + world.random.nextInt(3)))); } } return RitualResult.TERMINATE; diff --git a/src/main/java/elucent/eidolon/ritual/DaylightRitual.java b/src/main/java/elucent/eidolon/ritual/DaylightRitual.java index d12b0f6..45118d1 100644 --- a/src/main/java/elucent/eidolon/ritual/DaylightRitual.java +++ b/src/main/java/elucent/eidolon/ritual/DaylightRitual.java @@ -1,24 +1,15 @@ package elucent.eidolon.ritual; import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; -import elucent.eidolon.network.CrystallizeEffectPacket; -import elucent.eidolon.network.Networking; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.network.play.server.SUpdateTimePacket; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.GameRules; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.ServerWorldInfo; -import org.apache.logging.log4j.core.jmx.Server; - -import java.util.List; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.storage.PrimaryLevelData; public class DaylightRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/daylight_ritual"); @@ -28,12 +19,12 @@ public DaylightRitual() { } @Override - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { if (world.getDayTime() % 24000 < 1000 || world.getDayTime() % 24000 >= 12000) { - if (!world.isRemote) { - ((ServerWorldInfo) world.getWorldInfo()).setDayTime(world.getDayTime() + 100); - for (ServerPlayerEntity player : ((ServerWorld) world).getPlayers()) { - player.connection.sendPacket(new SUpdateTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE))); + if (!world.isClientSide) { + ((PrimaryLevelData) world.getLevelData()).setDayTime(world.getDayTime() + 100); + for (ServerPlayer player : ((ServerLevel) world).players()) { + player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); } } return RitualResult.PASS; diff --git a/src/main/java/elucent/eidolon/ritual/DeceitRitual.java b/src/main/java/elucent/eidolon/ritual/DeceitRitual.java index a7cfafc..798e175 100644 --- a/src/main/java/elucent/eidolon/ritual/DeceitRitual.java +++ b/src/main/java/elucent/eidolon/ritual/DeceitRitual.java @@ -1,22 +1,14 @@ package elucent.eidolon.ritual; +import java.util.List; + import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; -import elucent.eidolon.network.CrystallizeEffectPacket; -import elucent.eidolon.network.Networking; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.goal.ReturnToVillageGoal; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.merchant.villager.VillagerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.village.GossipManager; -import net.minecraft.world.World; - -import java.util.List; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class DeceitRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/deceit_ritual"); @@ -26,11 +18,11 @@ public DeceitRitual() { } @Override - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { if (world.getGameTime() % 20 == 0) { - List villagers = world.getEntitiesWithinAABB(VillagerEntity.class, new AxisAlignedBB(pos).grow(48, 16, 48)); - for (VillagerEntity v : villagers) { - if (world.rand.nextInt(120) == 0) v.getGossip().tick(); + List villagers = world.getEntitiesOfClass(Villager.class, new AABB(pos).inflate(48, 16, 48)); + for (Villager v : villagers) { + if (world.random.nextInt(120) == 0) v.getGossips().decay(); } } return RitualResult.PASS; diff --git a/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java b/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java index f5d50e4..c82e234 100644 --- a/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java +++ b/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java @@ -1,16 +1,16 @@ package elucent.eidolon.ritual; +import java.util.List; + import elucent.eidolon.network.Networking; import elucent.eidolon.network.RitualConsumePacket; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.tags.ITag; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.List; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.tags.Tag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class FocusItemRequirement implements IRequirement { Object match; @@ -24,39 +24,39 @@ public FocusItemRequirement(Item item) { } public FocusItemRequirement(Block block) { - this.match = Item.getItemFromBlock(block); + this.match = Item.byBlock(block); } - public FocusItemRequirement(ITag item) { + public FocusItemRequirement(Tag item) { this.match = item; } @Override - public RequirementInfo isMet(Ritual ritual, World world, BlockPos pos) { + public RequirementInfo isMet(Ritual ritual, Level world, BlockPos pos) { List tiles = Ritual.getTilesWithinAABB(IRitualItemProvider.class, world, ritual.getSearchBounds(pos)); System.out.println(tiles.size()); if (tiles.isEmpty()) return RequirementInfo.FALSE; for (int i = 0; i < tiles.size(); i ++) { ItemStack stack = tiles.get(i).provide(); - if (match instanceof ItemStack && ItemStack.areItemStacksEqual((ItemStack)match, stack)) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + if (match instanceof ItemStack && ItemStack.matches((ItemStack)match, stack)) { + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } else if (match instanceof Item && stack.getItem() == (Item)match) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } - else if (match instanceof ITag && ((ITag)match).contains(stack.getItem())) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + else if (match instanceof Tag && ((Tag)match).contains(stack.getItem())) { + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } } return RequirementInfo.FALSE; } - public void whenMet(Ritual ritual, World world, BlockPos pos, RequirementInfo info) { - ((IRitualItemProvider)world.getTileEntity(info.getPos())).take(); - if (!world.isRemote) { - Networking.sendToTracking(world, pos.up(2), new RitualConsumePacket(info.getPos(), pos.up(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + public void whenMet(Ritual ritual, Level world, BlockPos pos, RequirementInfo info) { + ((IRitualItemProvider)world.getBlockEntity(info.getPos())).take(); + if (!world.isClientSide) { + Networking.sendToTracking(world, pos.above(2), new RitualConsumePacket(info.getPos(), pos.above(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); } } } diff --git a/src/main/java/elucent/eidolon/ritual/HealthRequirement.java b/src/main/java/elucent/eidolon/ritual/HealthRequirement.java index 8f34fa6..07bf6dc 100644 --- a/src/main/java/elucent/eidolon/ritual/HealthRequirement.java +++ b/src/main/java/elucent/eidolon/ritual/HealthRequirement.java @@ -1,21 +1,16 @@ package elucent.eidolon.ritual; +import java.util.ArrayList; +import java.util.List; + import elucent.eidolon.Registry; import elucent.eidolon.network.Networking; import elucent.eidolon.network.RitualConsumePacket; -import net.minecraft.block.Block; -import net.minecraft.entity.CreatureEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.tags.ITag; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.ArrayList; -import java.util.List; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class HealthRequirement implements IRequirement { float health; @@ -25,9 +20,9 @@ public HealthRequirement(float health) { } @Override - public RequirementInfo isMet(Ritual ritual, World world, BlockPos pos) { - List entities = world.getEntitiesWithinAABB(CreatureEntity.class, Ritual.getDefaultBounds(pos), (entity) -> !entity.isEntityUndead()); - List players = world.getEntitiesWithinAABB(PlayerEntity.class, Ritual.getDefaultBounds(pos)); + public RequirementInfo isMet(Ritual ritual, Level world, BlockPos pos) { + List entities = world.getEntitiesOfClass(PathfinderMob.class, Ritual.getDefaultBounds(pos), (entity) -> !entity.isInvertedHealAndHarm()); + List players = world.getEntitiesOfClass(Player.class, Ritual.getDefaultBounds(pos)); List targets = new ArrayList<>(); targets.addAll(entities); targets.addAll(players); @@ -39,9 +34,9 @@ public RequirementInfo isMet(Ritual ritual, World world, BlockPos pos) { return RequirementInfo.FALSE; } - public void whenMet(Ritual ritual, World world, BlockPos pos, RequirementInfo info) { - List entities = world.getEntitiesWithinAABB(CreatureEntity.class, Ritual.getDefaultBounds(pos), (entity) -> !entity.isEntityUndead()); - List players = world.getEntitiesWithinAABB(PlayerEntity.class, Ritual.getDefaultBounds(pos)); + public void whenMet(Ritual ritual, Level world, BlockPos pos, RequirementInfo info) { + List entities = world.getEntitiesOfClass(PathfinderMob.class, Ritual.getDefaultBounds(pos), (entity) -> !entity.isInvertedHealAndHarm()); + List players = world.getEntitiesOfClass(Player.class, Ritual.getDefaultBounds(pos)); List targets = new ArrayList<>(); targets.addAll(entities); targets.addAll(players); @@ -49,11 +44,11 @@ public void whenMet(Ritual ritual, World world, BlockPos pos, RequirementInfo in for (int i = 0; i < targets.size(); i ++) { float targetHealth = targets.get(i).getHealth(); if (this.health - acc < targetHealth) - targets.get(i).attackEntityFrom(Registry.RITUAL_DAMAGE, this.health - acc); - else targets.get(i).attackEntityFrom(Registry.RITUAL_DAMAGE, targetHealth); + targets.get(i).hurt(Registry.RITUAL_DAMAGE, this.health - acc); + else targets.get(i).hurt(Registry.RITUAL_DAMAGE, targetHealth); acc += targetHealth; - if (!world.isRemote) Networking.sendToTracking(world, pos, new RitualConsumePacket(targets.get(i).getPosition(), pos, ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + if (!world.isClientSide) Networking.sendToTracking(world, pos, new RitualConsumePacket(targets.get(i).blockPosition(), pos, ritual.getRed(), ritual.getGreen(), ritual.getBlue())); if (acc >= this.health) return; } } diff --git a/src/main/java/elucent/eidolon/ritual/IRequirement.java b/src/main/java/elucent/eidolon/ritual/IRequirement.java index 30b55b0..8ba927c 100644 --- a/src/main/java/elucent/eidolon/ritual/IRequirement.java +++ b/src/main/java/elucent/eidolon/ritual/IRequirement.java @@ -1,11 +1,11 @@ package elucent.eidolon.ritual; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public interface IRequirement { - RequirementInfo isMet(Ritual ritual, World world, BlockPos pos); - default void whenMet(Ritual ritual, World world, BlockPos pos, RequirementInfo info) { + RequirementInfo isMet(Ritual ritual, Level world, BlockPos pos); + default void whenMet(Ritual ritual, Level world, BlockPos pos, RequirementInfo info) { // } } diff --git a/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java b/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java index 2b02dd0..33bf705 100644 --- a/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java +++ b/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java @@ -1,5 +1,3 @@ package elucent.eidolon.ritual; -import net.minecraft.item.ItemStack; - public interface IRitualItemFocus extends IRitualItemProvider {} diff --git a/src/main/java/elucent/eidolon/ritual/IRitualItemProvider.java b/src/main/java/elucent/eidolon/ritual/IRitualItemProvider.java index 65f41b5..511794d 100644 --- a/src/main/java/elucent/eidolon/ritual/IRitualItemProvider.java +++ b/src/main/java/elucent/eidolon/ritual/IRitualItemProvider.java @@ -1,6 +1,6 @@ package elucent.eidolon.ritual; -import net.minecraft.item.ItemStack; +import net.minecraft.world.item.ItemStack; public interface IRitualItemProvider { ItemStack provide(); diff --git a/src/main/java/elucent/eidolon/ritual/ItemRequirement.java b/src/main/java/elucent/eidolon/ritual/ItemRequirement.java index 810dd8a..6962812 100644 --- a/src/main/java/elucent/eidolon/ritual/ItemRequirement.java +++ b/src/main/java/elucent/eidolon/ritual/ItemRequirement.java @@ -1,19 +1,16 @@ package elucent.eidolon.ritual; +import java.util.List; + import elucent.eidolon.network.Networking; import elucent.eidolon.network.RitualConsumePacket; -import elucent.eidolon.ritual.Ritual.SetupResult; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.tags.ITag; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.minecraft.tags.Tag; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.Tags; - -import java.util.List; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class ItemRequirement implements IRequirement { Object match; @@ -27,38 +24,38 @@ public ItemRequirement(Item item) { } public ItemRequirement(Block block) { - this.match = Item.getItemFromBlock(block); + this.match = Item.byBlock(block); } - public ItemRequirement(ITag item) { + public ItemRequirement(Tag item) { this.match = item; } @Override - public RequirementInfo isMet(Ritual ritual, World world, BlockPos pos) { + public RequirementInfo isMet(Ritual ritual, Level world, BlockPos pos) { List tiles = Ritual.getTilesWithinAABB(IRitualItemProvider.class, world, ritual.getSearchBounds(pos)); if (tiles.isEmpty()) return RequirementInfo.FALSE; for (int i = 0; i < tiles.size(); i ++) { ItemStack stack = tiles.get(i).provide(); - if (match instanceof ItemStack && ItemStack.areItemStacksEqual((ItemStack)match, stack)) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + if (match instanceof ItemStack && ItemStack.matches((ItemStack)match, stack)) { + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } else if (match instanceof Item && stack.getItem() == (Item)match) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } - else if (match instanceof ITag && ((ITag)match).contains(stack.getItem())) { - return new RequirementInfo(true, ((TileEntity)tiles.get(i)).getPos()); + else if (match instanceof Tag && ((Tag)match).contains(stack.getItem())) { + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } } return RequirementInfo.FALSE; } - public void whenMet(Ritual ritual, World world, BlockPos pos, RequirementInfo info) { - ((IRitualItemProvider)world.getTileEntity(info.getPos())).take(); - if (!world.isRemote) { - Networking.sendToTracking(world, pos.up(2), new RitualConsumePacket(info.getPos(), pos.up(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + public void whenMet(Ritual ritual, Level world, BlockPos pos, RequirementInfo info) { + ((IRitualItemProvider)world.getBlockEntity(info.getPos())).take(); + if (!world.isClientSide) { + Networking.sendToTracking(world, pos.above(2), new RitualConsumePacket(info.getPos(), pos.above(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); } } diff --git a/src/main/java/elucent/eidolon/ritual/MoonlightRitual.java b/src/main/java/elucent/eidolon/ritual/MoonlightRitual.java index cef7dc8..b02b633 100644 --- a/src/main/java/elucent/eidolon/ritual/MoonlightRitual.java +++ b/src/main/java/elucent/eidolon/ritual/MoonlightRitual.java @@ -1,18 +1,15 @@ package elucent.eidolon.ritual; import elucent.eidolon.Eidolon; -import elucent.eidolon.network.Networking; import elucent.eidolon.util.ColorUtil; -import net.minecraft.block.BedBlock; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.network.play.server.SUpdateTimePacket; -import net.minecraft.tileentity.BedTileEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.GameRules; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.ServerWorldInfo; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.storage.PrimaryLevelData; public class MoonlightRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/moonlight_ritual"); @@ -22,12 +19,12 @@ public MoonlightRitual() { } @Override - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { if (world.getDayTime() % 24000 < 13000 && world.getDayTime() % 24000 >= 0) { - if (!world.isRemote) { - ((ServerWorldInfo) world.getWorldInfo()).setDayTime(world.getDayTime() + 100); - for (ServerPlayerEntity player : ((ServerWorld) world).getPlayers()) { - player.connection.sendPacket(new SUpdateTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE))); + if (!world.isClientSide) { + ((PrimaryLevelData) world.getLevelData()).setDayTime(world.getDayTime() + 100); + for (ServerPlayer player : ((ServerLevel) world).players()) { + player.connection.send(new ClientboundSetTimePacket(world.getGameTime(), world.getDayTime(), world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); } } return RitualResult.PASS; diff --git a/src/main/java/elucent/eidolon/ritual/PurifyRitual.java b/src/main/java/elucent/eidolon/ritual/PurifyRitual.java index 4136869..86c9f33 100644 --- a/src/main/java/elucent/eidolon/ritual/PurifyRitual.java +++ b/src/main/java/elucent/eidolon/ritual/PurifyRitual.java @@ -1,32 +1,25 @@ package elucent.eidolon.ritual; +import java.util.List; + import elucent.eidolon.Eidolon; -import elucent.eidolon.entity.ai.GoToPositionGoal; -import elucent.eidolon.mixin.ZombieVillagerEntityMixin; +import elucent.eidolon.mixin.ZombieVillagerMixin; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.CreatureEntity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.monster.HoglinEntity; -import net.minecraft.entity.monster.ZoglinEntity; -import net.minecraft.entity.monster.ZombieVillagerEntity; -import net.minecraft.entity.monster.ZombifiedPiglinEntity; -import net.minecraft.entity.monster.piglin.PiglinEntity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.List; -import java.util.stream.Collectors; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.Entity.RemovalReason; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.monster.hoglin.Hoglin; +import net.minecraft.world.entity.monster.Zoglin; +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; public class PurifyRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/purify_ritual"); @@ -36,27 +29,27 @@ public PurifyRitual() { } @Override - public RitualResult start(World world, BlockPos pos) { - List purifiable = world.getEntitiesWithinAABB(CreatureEntity.class, Ritual.getDefaultBounds(pos), (entity) -> entity instanceof ZombieVillagerEntity || entity instanceof ZombifiedPiglinEntity || entity instanceof ZoglinEntity); + public RitualResult start(Level world, BlockPos pos) { + List purifiable = world.getEntitiesOfClass(PathfinderMob.class, Ritual.getDefaultBounds(pos), (entity) -> entity instanceof ZombieVillager || entity instanceof ZombifiedPiglin || entity instanceof Zoglin); - if (purifiable.size() > 0 && !world.isRemote) world.playSound(null, pos, SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, SoundCategory.PLAYERS, 1.0f, 1.0f); - if (!world.isRemote) for (CreatureEntity entity : purifiable) { - if (entity instanceof ZombieVillagerEntity) { - ((ZombieVillagerEntityMixin)entity).callCureZombie((ServerWorld)world); + if (purifiable.size() > 0 && !world.isClientSide) world.playSound(null, pos, SoundEvents.ZOMBIE_VILLAGER_CURE, SoundSource.PLAYERS, 1.0f, 1.0f); + if (!world.isClientSide) for (PathfinderMob entity : purifiable) { + if (entity instanceof ZombieVillager) { + ((ZombieVillagerMixin)entity).callFinishConversion((ServerLevel)world); } - if (entity instanceof ZombifiedPiglinEntity) { - entity.remove(); - PiglinEntity piglin = new PiglinEntity(EntityType.PIGLIN, world); - piglin.copyLocationAndAnglesFrom(entity); - piglin.onInitialSpawn((ServerWorld)world, world.getDifficultyForLocation(pos), SpawnReason.MOB_SUMMONED, null, null); - world.addEntity(piglin); + if (entity instanceof ZombifiedPiglin) { + entity.remove(RemovalReason.KILLED); + Piglin piglin = new Piglin(EntityType.PIGLIN, world); + piglin.copyPosition(entity); + piglin.finalizeSpawn((ServerLevel)world, world.getCurrentDifficultyAt(pos), MobSpawnType.MOB_SUMMONED, null, null); + world.addFreshEntity(piglin); } - if (entity instanceof ZoglinEntity) { - entity.remove(); - HoglinEntity hoglin = new HoglinEntity(EntityType.HOGLIN, world); - hoglin.copyLocationAndAnglesFrom(entity); - hoglin.onInitialSpawn((ServerWorld)world, world.getDifficultyForLocation(pos), SpawnReason.MOB_SUMMONED, null, null); - world.addEntity(hoglin); + if (entity instanceof Zoglin) { + entity.remove(RemovalReason.KILLED); + Hoglin hoglin = new Hoglin(EntityType.HOGLIN, world); + hoglin.copyPosition(entity); + hoglin.finalizeSpawn((ServerLevel)world, world.getCurrentDifficultyAt(pos), MobSpawnType.MOB_SUMMONED, null, null); + world.addFreshEntity(hoglin); } } return RitualResult.TERMINATE; diff --git a/src/main/java/elucent/eidolon/ritual/RepellingRitual.java b/src/main/java/elucent/eidolon/ritual/RepellingRitual.java index 66b9f88..0cd4a42 100644 --- a/src/main/java/elucent/eidolon/ritual/RepellingRitual.java +++ b/src/main/java/elucent/eidolon/ritual/RepellingRitual.java @@ -1,27 +1,20 @@ package elucent.eidolon.ritual; +import java.util.List; +import java.util.stream.Collectors; + import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; import elucent.eidolon.entity.ai.GoToPositionGoal; -import elucent.eidolon.network.CrystallizeEffectPacket; -import elucent.eidolon.network.Networking; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.goal.Goal; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.monster.MonsterEntity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; -import net.minecraft.world.World; -import net.minecraft.world.gen.Heightmap; - -import java.util.List; -import java.util.stream.Collectors; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.Vec3; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.Heightmap; public class RepellingRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/repelling_ritual"); @@ -31,21 +24,21 @@ public RepellingRitual() { } @Override - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { if (world.getGameTime() % 200 == 0) { - List monsters = world.getEntitiesWithinAABB(MonsterEntity.class, new AxisAlignedBB(pos).grow(96, 16, 96)); - for (MonsterEntity a : monsters) { + List monsters = world.getEntitiesOfClass(Monster.class, new AABB(pos).inflate(96, 16, 96)); + for (Monster a : monsters) { boolean hasGoal = a.goalSelector.getRunningGoals() .filter((goal) -> goal.getGoal() instanceof GoToPositionGoal) .count() > 0; - if (!hasGoal && a.getDistanceSq(pos.getX(), pos.getY(), pos.getZ()) <= 80 * 80) { - Vector3i diff = a.getPosition().subtract(pos); - Vector3d diffv = new Vector3d(diff.getX(), 0, diff.getZ()); + if (!hasGoal && a.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) <= 80 * 80) { + Vec3i diff = a.blockPosition().subtract(pos); + Vec3 diffv = new Vec3(diff.getX(), 0, diff.getZ()); diffv = diffv.scale(90 / diffv.length()); int i = pos.getX() + (int)diffv.x, j = pos.getZ() + (int)diffv.z; - BlockPos target = world.getHeight(Heightmap.Type.WORLD_SURFACE, new BlockPos(i, 0, j)); + BlockPos target = world.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, new BlockPos(i, 0, j)); a.goalSelector.addGoal(1, new GoToPositionGoal(a, target, 1.0)); - } else if (hasGoal && a.getDistanceSq(pos.getX(), pos.getY(), pos.getZ()) > 88 * 88) { + } else if (hasGoal && a.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) > 88 * 88) { List goals = a.goalSelector.getRunningGoals().filter((goal) -> goal.getGoal() instanceof GoToPositionGoal) .collect(Collectors.toList()); for (Goal g : goals) a.goalSelector.removeGoal(g); diff --git a/src/main/java/elucent/eidolon/ritual/RequirementInfo.java b/src/main/java/elucent/eidolon/ritual/RequirementInfo.java index 5a9aee5..e9db673 100644 --- a/src/main/java/elucent/eidolon/ritual/RequirementInfo.java +++ b/src/main/java/elucent/eidolon/ritual/RequirementInfo.java @@ -1,6 +1,6 @@ package elucent.eidolon.ritual; -import net.minecraft.util.math.BlockPos; +import net.minecraft.core.BlockPos; public class RequirementInfo { public static final RequirementInfo diff --git a/src/main/java/elucent/eidolon/ritual/Ritual.java b/src/main/java/elucent/eidolon/ritual/Ritual.java index ef43eaf..19191cb 100644 --- a/src/main/java/elucent/eidolon/ritual/Ritual.java +++ b/src/main/java/elucent/eidolon/ritual/Ritual.java @@ -1,33 +1,17 @@ package elucent.eidolon.ritual; -import com.google.common.eventbus.Subscribe; -import elucent.eidolon.particle.GenericParticle; -import elucent.eidolon.particle.GenericParticleData; -import elucent.eidolon.particle.Particles; -import elucent.eidolon.potion.ChilledEffect; -import elucent.eidolon.util.ColorUtil; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.texture.AtlasTexture.SheetData; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.particles.ParticleType; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ColorHelper; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.IChunk; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.DistExecutor; - import java.util.ArrayList; import java.util.List; import java.util.Set; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.ChunkAccess; + public abstract class Ritual { ResourceLocation name = null; int color; @@ -103,7 +87,7 @@ public enum RitualResult { TERMINATE } - public SetupResult setup(World world, BlockPos pos, int step) { + public SetupResult setup(Level world, BlockPos pos, int step) { if (step >= stepRequirements.size()) return SetupResult.SUCCEED; for (IRequirement req : continuousRequirements) { RequirementInfo info = req.isMet(this, world, pos); @@ -117,30 +101,30 @@ public SetupResult setup(World world, BlockPos pos, int step) { return SetupResult.PASS; } - public AxisAlignedBB getSearchBounds(BlockPos pos) { + public AABB getSearchBounds(BlockPos pos) { return getDefaultBounds(pos); } - public static AxisAlignedBB getDefaultBounds(BlockPos pos) { - return new AxisAlignedBB(pos.getX() - 8, pos.getY() - 6, pos.getZ() - 8, pos.getX() + 9, pos.getY() + 11, pos.getZ() + 9); + public static AABB getDefaultBounds(BlockPos pos) { + return new AABB(pos.getX() - 8, pos.getY() - 6, pos.getZ() - 8, pos.getX() + 9, pos.getY() + 11, pos.getZ() + 9); } - public RitualResult tick(World world, BlockPos pos) { + public RitualResult tick(Level world, BlockPos pos) { return RitualResult.PASS; } - public RitualResult start(World world, BlockPos pos) { + public RitualResult start(Level world, BlockPos pos) { return RitualResult.PASS; } - public static List getTilesWithinAABB(Class type, World world, AxisAlignedBB bb) { + public static List getTilesWithinAABB(Class type, Level world, AABB bb) { List tileList = new ArrayList<>(); for (int i = (int)Math.floor(bb.minX); i < (int)Math.ceil(bb.maxX) + 16; i += 16) { for (int j = (int)Math.floor(bb.minZ); j < (int)Math.ceil(bb.maxZ) + 16; j += 16) { - IChunk c = world.getChunk(new BlockPos(i, 0, j)); - Set tiles = c.getTileEntitiesPos(); + ChunkAccess c = world.getChunk(new BlockPos(i, 0, j)); + Set tiles = c.getBlockEntitiesPos(); for (BlockPos p : tiles) if (bb.contains(p.getX() + 0.5, p.getY() + 0.5, p.getZ() + 0.5)) { - TileEntity t = world.getTileEntity(p); + BlockEntity t = world.getBlockEntity(p); if (type.isInstance(t)) tileList.add((T)t); } } diff --git a/src/main/java/elucent/eidolon/ritual/RitualRegistry.java b/src/main/java/elucent/eidolon/ritual/RitualRegistry.java index 74d1a1b..cd47230 100644 --- a/src/main/java/elucent/eidolon/ritual/RitualRegistry.java +++ b/src/main/java/elucent/eidolon/ritual/RitualRegistry.java @@ -1,37 +1,35 @@ package elucent.eidolon.ritual; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.codex.Page; import elucent.eidolon.codex.RitualPage; -import elucent.eidolon.codex.WorktablePage; import elucent.eidolon.gui.jei.RecipeWrappers; -import elucent.eidolon.recipe.WorktableRecipe; -import elucent.eidolon.util.StackUtil; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.entity.EntityType; -import net.minecraft.inventory.ItemStackHelper; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.potion.PotionUtils; -import net.minecraft.potion.Potions; -import net.minecraft.tags.ITag; +import elucent.eidolon.util.RecipeUtil; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; import net.minecraft.tags.Tag; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; import net.minecraftforge.common.Tags; -import java.util.*; -import java.util.Map.Entry; - public class RitualRegistry { static Map rituals = new HashMap<>(); static BiMap matches = HashBiMap.create(); @@ -55,11 +53,11 @@ public static Ritual register(Block sacrifice, Ritual ritual) { ResourceLocation name = ritual.getRegistryName(); assert name != null; rituals.put(name, ritual); - matches.put(Item.getItemFromBlock(sacrifice), ritual); + matches.put(Item.byBlock(sacrifice), ritual); return ritual; } - public static Ritual register(ITag sacrifice, Ritual ritual) { + public static Ritual register(Tag sacrifice, Ritual ritual) { ResourceLocation name = ritual.getRegistryName(); assert name != null; rituals.put(name, ritual); @@ -79,19 +77,19 @@ public static Page getDefaultPage(Ritual ritual, Object sacrifice) { List inputs = new ArrayList<>(); List foci = new ArrayList<>(); if (sacrifice instanceof MultiItemSacrifice) for (Object o : ((MultiItemSacrifice)sacrifice).items) { - foci.add(StackUtil.stackFromObject(o)); + foci.add(RecipeUtil.stackFromObject(o)); } int slot = 0; for (IRequirement r : ritual.getRequirements()) { if (r instanceof ItemRequirement) - inputs.add(new RitualPage.RitualIngredient(StackUtil.stackFromObject(((ItemRequirement)r).getMatch()), false)); + inputs.add(new RitualPage.RitualIngredient(RecipeUtil.stackFromObject(((ItemRequirement)r).getMatch()), false)); slot ++; } Iterator iter = foci.iterator(); while (iter.hasNext()) { ItemStack focus = iter.next(); for (RitualPage.RitualIngredient input : inputs) { - if (ItemStack.areItemsEqual(focus, input.stack) && ItemStack.areItemStackTagsEqual(focus, input.stack) + if (ItemStack.isSame(focus, input.stack) && ItemStack.tagMatches(focus, input.stack) && !input.isFocus) { input.isFocus = true; iter.remove(); @@ -99,7 +97,7 @@ public static Page getDefaultPage(Ritual ritual, Object sacrifice) { } } } - ItemStack center = StackUtil.stackFromObject(sacrifice instanceof MultiItemSacrifice ? ((MultiItemSacrifice)sacrifice).main : sacrifice); + ItemStack center = RecipeUtil.stackFromObject(sacrifice instanceof MultiItemSacrifice ? ((MultiItemSacrifice)sacrifice).main : sacrifice); return new RitualPage(ritual, center, inputs.toArray(new RitualPage.RitualIngredient[inputs.size()])); } @@ -122,18 +120,18 @@ public static Ritual find(ResourceLocation name) { return rituals.get(name); } - static boolean matches(World world, BlockPos pos, Object match, ItemStack sacrifice) { + static boolean matches(Level world, BlockPos pos, Object match, ItemStack sacrifice) { if (match instanceof ItemStack) { - if (ItemStack.areItemStacksEqual((ItemStack)match, sacrifice)) return true; + if (ItemStack.matches((ItemStack)match, sacrifice)) return true; } else if (match instanceof Block) { - if (Item.getItemFromBlock((Block)match) == sacrifice.getItem()) return true; + if (Item.byBlock((Block)match) == sacrifice.getItem()) return true; } else if (match instanceof Item) { if ((Item)match == sacrifice.getItem()) return true; } - else if (match instanceof ITag) { - if (((ITag)match).contains(sacrifice.getItem())) return true; + else if (match instanceof Tag) { + if (((Tag)match).contains(sacrifice.getItem())) return true; } else if (match instanceof MultiItemSacrifice) { // check main item first, avoid complicated work @@ -163,7 +161,7 @@ else if (match instanceof MultiItemSacrifice) { return false; } - public static Ritual find(World world, BlockPos pos, ItemStack sacrifice) { + public static Ritual find(Level world, BlockPos pos, ItemStack sacrifice) { for (Entry entry : matches.entrySet()) { if (matches(world, pos, entry.getKey(), sacrifice)) return entry.getValue(); } @@ -252,11 +250,11 @@ public static void init() { PURIFY_RITUAL = register(Items.GLISTERING_MELON_SLICE, new PurifyRitual().setRegistryName(Eidolon.MODID, "purify") .addRequirement(new ItemRequirement(Registry.ENCHANTED_ASH.get())) .addRequirement(new ItemRequirement(Registry.ENCHANTED_ASH.get())) - .addRequirement(new ItemRequirement(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HEALING))) + .addRequirement(new ItemRequirement(PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HEALING))) .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get())) .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get()))); - SANGUINE_SWORD = register(new MultiItemSacrifice(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HARMING), Items.IRON_SWORD), new SanguineRitual(new ItemStack(Registry.SAPPING_SWORD.get())).setRegistryName(Eidolon.MODID, "sanguine_sapping_sword") + SANGUINE_SWORD = register(new MultiItemSacrifice(PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HARMING), Items.IRON_SWORD), new SanguineRitual(new ItemStack(Registry.SAPPING_SWORD.get())).setRegistryName(Eidolon.MODID, "sanguine_sapping_sword") .addRequirement(new ItemRequirement(Registry.SHADOW_GEM.get())) .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get())) .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get())) @@ -266,7 +264,7 @@ public static void init() { .addRequirement(new ItemRequirement(Items.GHAST_TEAR)) .addRequirement(new HealthRequirement(20))); - SANGUINE_AMULET = register(new MultiItemSacrifice(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.HARMING), Registry.BASIC_AMULET.get()), new SanguineRitual(new ItemStack(Registry.SANGUINE_AMULET.get())).setRegistryName(Eidolon.MODID, "sanguine_sanguine_amulet") + SANGUINE_AMULET = register(new MultiItemSacrifice(PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.HARMING), Registry.BASIC_AMULET.get()), new SanguineRitual(new ItemStack(Registry.SANGUINE_AMULET.get())).setRegistryName(Eidolon.MODID, "sanguine_sanguine_amulet") .addRequirement(new ItemRequirement(Tags.Items.GEMS_DIAMOND)) .addRequirement(new ItemRequirement(Tags.Items.DUSTS_REDSTONE)) .addRequirement(new ItemRequirement(Tags.Items.DUSTS_REDSTONE)) diff --git a/src/main/java/elucent/eidolon/ritual/SanguineRitual.java b/src/main/java/elucent/eidolon/ritual/SanguineRitual.java index 19fd7b6..23dc51c 100644 --- a/src/main/java/elucent/eidolon/ritual/SanguineRitual.java +++ b/src/main/java/elucent/eidolon/ritual/SanguineRitual.java @@ -2,11 +2,11 @@ import elucent.eidolon.Eidolon; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class SanguineRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/sanguine_ritual"); @@ -18,9 +18,9 @@ public SanguineRitual(ItemStack result) { } @Override - public RitualResult start(World world, BlockPos pos) { - if (!world.isRemote) { - world.addEntity(new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 2.5, pos.getZ() + 0.5, result.copy())); + public RitualResult start(Level world, BlockPos pos) { + if (!world.isClientSide) { + world.addFreshEntity(new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 2.5, pos.getZ() + 0.5, result.copy())); } return RitualResult.TERMINATE; } diff --git a/src/main/java/elucent/eidolon/ritual/SummonRitual.java b/src/main/java/elucent/eidolon/ritual/SummonRitual.java index 3dd397e..91f3124 100644 --- a/src/main/java/elucent/eidolon/ritual/SummonRitual.java +++ b/src/main/java/elucent/eidolon/ritual/SummonRitual.java @@ -1,20 +1,14 @@ package elucent.eidolon.ritual; import elucent.eidolon.Eidolon; -import elucent.eidolon.Registry; import elucent.eidolon.network.CrystallizeEffectPacket; import elucent.eidolon.network.Networking; import elucent.eidolon.util.ColorUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.List; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class SummonRitual extends Ritual { public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/summon_ritual"); @@ -26,12 +20,12 @@ public SummonRitual(EntityType entity) { } @Override - public RitualResult start(World world, BlockPos pos) { - if (!world.isRemote) { + public RitualResult start(Level world, BlockPos pos) { + if (!world.isClientSide) { Networking.sendToTracking(world, pos, new CrystallizeEffectPacket(pos)); Entity e = entity.create(world); - e.setPosition(pos.getX() + 0.5, pos.getY() + 1.5, pos.getZ() + 0.5); - world.addEntity(e); + e.setPos(pos.getX() + 0.5, pos.getY() + 1.5, pos.getZ() + 0.5); + world.addFreshEntity(e); } return RitualResult.TERMINATE; } diff --git a/src/main/java/elucent/eidolon/spell/AltarEntries.java b/src/main/java/elucent/eidolon/spell/AltarEntries.java index b6c0e01..2031ae6 100644 --- a/src/main/java/elucent/eidolon/spell/AltarEntries.java +++ b/src/main/java/elucent/eidolon/spell/AltarEntries.java @@ -1,14 +1,14 @@ package elucent.eidolon.spell; -import elucent.eidolon.Registry; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.SkullBlock; -import net.minecraft.state.properties.BlockStateProperties; - import java.util.HashMap; import java.util.Map; +import elucent.eidolon.Registry; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SkullBlock; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + public class AltarEntries { static Map entries = new HashMap<>(); @@ -17,22 +17,22 @@ public static AltarEntry find(BlockState state) { } public static void init() { - entries.put(Blocks.TORCH.getDefaultState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(1)); - entries.put(Blocks.LANTERN.getDefaultState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(1).setCapacity(1)); - entries.put(Registry.CANDLE.get().getDefaultState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(2)); - entries.put(Registry.CANDLESTICK.get().getDefaultState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(2)); + entries.put(Blocks.TORCH.defaultBlockState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(1)); + entries.put(Blocks.LANTERN.defaultBlockState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(1).setCapacity(1)); + entries.put(Registry.CANDLE.get().defaultBlockState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(2)); + entries.put(Registry.CANDLESTICK.get().defaultBlockState(), new AltarEntry(AltarKeys.LIGHT_KEY).setPower(2)); - for (int i : BlockStateProperties.ROTATION_0_15.getAllowedValues()) { - entries.put(Blocks.SKELETON_SKULL.getDefaultState().with(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(2)); - entries.put(Blocks.ZOMBIE_HEAD.getDefaultState().with(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(1).setPower(1)); - entries.put(Blocks.WITHER_SKELETON_SKULL.getDefaultState().with(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(3).setPower(1)); + for (int i : BlockStateProperties.ROTATION_16.getPossibleValues()) { + entries.put(Blocks.SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(2)); + entries.put(Blocks.ZOMBIE_HEAD.defaultBlockState().setValue(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(1).setPower(1)); + entries.put(Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, i), new AltarEntry(AltarKeys.SKULL_KEY).setCapacity(3).setPower(1)); } - entries.put(Blocks.POTTED_WARPED_ROOTS.getDefaultState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(1)); - entries.put(Blocks.POTTED_CRIMSON_ROOTS.getDefaultState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(1)); - entries.put(Blocks.POTTED_WARPED_FUNGUS.getDefaultState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(2)); - entries.put(Blocks.POTTED_CRIMSON_FUNGUS.getDefaultState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(2)); - entries.put(Blocks.POTTED_WITHER_ROSE.getDefaultState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(3)); - entries.put(Registry.GOBLET.get().getDefaultState(), new AltarEntry(AltarKeys.GOBLET_KEY).setCapacity(2)); + entries.put(Blocks.POTTED_WARPED_ROOTS.defaultBlockState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(1)); + entries.put(Blocks.POTTED_CRIMSON_ROOTS.defaultBlockState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(1)); + entries.put(Blocks.POTTED_WARPED_FUNGUS.defaultBlockState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(2)); + entries.put(Blocks.POTTED_CRIMSON_FUNGUS.defaultBlockState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(2)); + entries.put(Blocks.POTTED_WITHER_ROSE.defaultBlockState(), new AltarEntry(AltarKeys.PLANT_KEY).setPower(3)); + entries.put(Registry.GOBLET.get().defaultBlockState(), new AltarEntry(AltarKeys.GOBLET_KEY).setCapacity(2)); } } diff --git a/src/main/java/elucent/eidolon/spell/AltarEntry.java b/src/main/java/elucent/eidolon/spell/AltarEntry.java index 8ff4c76..b5a4623 100644 --- a/src/main/java/elucent/eidolon/spell/AltarEntry.java +++ b/src/main/java/elucent/eidolon/spell/AltarEntry.java @@ -1,9 +1,9 @@ package elucent.eidolon.spell; -import net.minecraft.util.ResourceLocation; - import java.util.function.Consumer; +import net.minecraft.resources.ResourceLocation; + public class AltarEntry { double capacity = 0, power = 0; ResourceLocation key = null; diff --git a/src/main/java/elucent/eidolon/spell/AltarInfo.java b/src/main/java/elucent/eidolon/spell/AltarInfo.java index 00562c1..c911fea 100644 --- a/src/main/java/elucent/eidolon/spell/AltarInfo.java +++ b/src/main/java/elucent/eidolon/spell/AltarInfo.java @@ -1,15 +1,20 @@ package elucent.eidolon.spell; -import elucent.eidolon.block.TableBlockBase; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Queue; +import java.util.Set; -import java.util.*; +import elucent.eidolon.block.TableBlockBase; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class AltarInfo { static class AltarAttributes { @@ -22,31 +27,31 @@ public AltarAttributes() {} Map attributes = new HashMap<>(); - public static Set getAltarPositions(World world, BlockPos pos) { + public static Set getAltarPositions(Level world, BlockPos pos) { Set result = new HashSet<>(); Queue visit = new ArrayDeque(); - BlockState below = world.getBlockState(pos.down()); + BlockState below = world.getBlockState(pos.below()); Block b = below.getBlock(); - if (below.getBlock() instanceof TableBlockBase) visit.add(pos.down()); + if (below.getBlock() instanceof TableBlockBase) visit.add(pos.below()); while (!visit.isEmpty()) { BlockPos visited = visit.remove(); if (result.contains(visited)) continue; result.add(visited); - for (Direction d : BlockStateProperties.HORIZONTAL_FACING.getAllowedValues()) - if (world.getBlockState(visited.offset(d)).getBlock() == b - && !result.contains(visited.offset(d))) - visit.add(visited.offset(d)); + for (Direction d : BlockStateProperties.HORIZONTAL_FACING.getPossibleValues()) + if (world.getBlockState(visited.relative(d)).getBlock() == b + && !result.contains(visited.relative(d))) + visit.add(visited.relative(d)); } return result; } - public static AltarInfo getAltarInfo(World world, BlockPos pos) { + public static AltarInfo getAltarInfo(Level world, BlockPos pos) { AltarInfo info = new AltarInfo(); info.icon = world.getBlockState(pos).getBlock(); Set altarPositions = getAltarPositions(world, pos); for (BlockPos p : altarPositions) { if (info.altar == null) info.altar = world.getBlockState(p).getBlock(); - BlockState state = world.getBlockState(p.up()); + BlockState state = world.getBlockState(p.above()); AltarEntry entry = AltarEntries.find(state); if (entry != null) { entry.apply(info); diff --git a/src/main/java/elucent/eidolon/spell/AltarKeys.java b/src/main/java/elucent/eidolon/spell/AltarKeys.java index 771450f..1d8127a 100644 --- a/src/main/java/elucent/eidolon/spell/AltarKeys.java +++ b/src/main/java/elucent/eidolon/spell/AltarKeys.java @@ -1,11 +1,11 @@ package elucent.eidolon.spell; -import elucent.eidolon.Eidolon; -import net.minecraft.util.ResourceLocation; - import java.util.HashSet; import java.util.Set; +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; + public class AltarKeys { Set keys = new HashSet<>(); diff --git a/src/main/java/elucent/eidolon/spell/AnimalSacrificeSpell.java b/src/main/java/elucent/eidolon/spell/AnimalSacrificeSpell.java index 1ac2ad3..8705bff 100644 --- a/src/main/java/elucent/eidolon/spell/AnimalSacrificeSpell.java +++ b/src/main/java/elucent/eidolon/spell/AnimalSacrificeSpell.java @@ -1,28 +1,28 @@ package elucent.eidolon.spell; +import java.util.Comparator; +import java.util.List; + import elucent.eidolon.Registry; import elucent.eidolon.block.HorizontalBlockBase; -import elucent.eidolon.capability.ReputationProvider; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.deity.Deity; import elucent.eidolon.deity.DeityLocks; import elucent.eidolon.particle.Particles; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.tile.EffigyTileEntity; import elucent.eidolon.tile.GobletTileEntity; -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.Comparator; -import java.util.List; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class AnimalSacrificeSpell extends StaticSpell { Deity deity; @@ -33,63 +33,61 @@ public AnimalSacrificeSpell(ResourceLocation name, Deity deity, Sign... signs) { } @Override - public boolean canCast(World world, BlockPos pos, PlayerEntity player) { - if (!world.getCapability(ReputationProvider.CAPABILITY).isPresent()) return false; - if (!world.getCapability(ReputationProvider.CAPABILITY).resolve().get().canPray(player, world.getGameTime())) return false; - if (world.getCapability(ReputationProvider.CAPABILITY).resolve().get().getReputation(player.getUniqueID(), deity.getId()) < 3.0) return false; - List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public boolean canCast(Level world, BlockPos pos, Player player) { + if (!world.getCapability(IReputation.INSTANCE).isPresent()) return false; + if (!world.getCapability(IReputation.INSTANCE).resolve().get().canPray(player, getRegistryName(), world.getGameTime())) return false; + if (world.getCapability(IReputation.INSTANCE).resolve().get().getReputation(player.getUUID(), deity.getId()) < 3.0) return false; + List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0 || goblets.size() == 0) return false; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); if (goblet.getEntityType() == null) return false; Entity test = goblet.getEntityType().create(world); - return test instanceof AnimalEntity && effigy.ready(); + return test instanceof Animal && effigy.ready(); } @Override - public void cast(World world, BlockPos pos, PlayerEntity player) { - List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public void cast(Level world, BlockPos pos, Player player) { + List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0 || goblets.size() == 0) return; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - if (!world.isRemote) { + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + if (!world.isClientSide) { effigy.pray(); goblet.setEntityType(null); - AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getPos()); - world.getCapability(ReputationProvider.CAPABILITY, null).ifPresent((rep) -> { - rep.pray(player, world.getGameTime()); + AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getBlockPos()); + world.getCapability(IReputation.INSTANCE, null).ifPresent((rep) -> { + rep.pray(player, getRegistryName(), world.getGameTime()); double prev = rep.getReputation(player, deity.getId()); - if (rep.unlock(player, deity.getId(), DeityLocks.SACRIFICE_MOB)) - deity.onReputationUnlock(player, rep, DeityLocks.SACRIFICE_MOB); + rep.unlock(player, deity.getId(), DeityLocks.SACRIFICE_MOB); rep.addReputation(player, deity.getId(), 3.0 + 0.5 * info.getPower()); - deity.onReputationChange(player, rep, prev, rep.getReputation(player, deity.getId())); }); } else { - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.NEUTRAL, 10000.0F, 0.6F + world.rand.nextFloat() * 0.2F); - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.NEUTRAL, 2.0F, 0.5F + world.rand.nextFloat() * 0.2F); - BlockState state = world.getBlockState(effigy.getPos()); - Direction dir = state.get(HorizontalBlockBase.HORIZONTAL_FACING); - Direction tangent = dir.rotateY(); - float x = effigy.getPos().getX() + 0.5f + dir.getXOffset() * 0.21875f; - float y = effigy.getPos().getY() + 0.8125f; - float z = effigy.getPos().getZ() + 0.5f + dir.getZOffset() * 0.21875f; + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.NEUTRAL, 10000.0F, 0.6F + world.random.nextFloat() * 0.2F); + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.NEUTRAL, 2.0F, 0.5F + world.random.nextFloat() * 0.2F); + BlockState state = world.getBlockState(effigy.getBlockPos()); + Direction dir = state.getValue(HorizontalBlockBase.HORIZONTAL_FACING); + Direction tangent = dir.getClockWise(); + float x = effigy.getBlockPos().getX() + 0.5f + dir.getStepX() * 0.21875f; + float y = effigy.getBlockPos().getY() + 0.8125f; + float z = effigy.getBlockPos().getZ() + 0.5f + dir.getStepZ() * 0.21875f; Particles.create(Registry.FLAME_PARTICLE) .setColor(Signs.BLOOD_SIGN.getRed(), Signs.BLOOD_SIGN.getGreen(), Signs.BLOOD_SIGN.getBlue()) .setAlpha(0.5f, 0) .setScale(0.125f, 0.0625f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x + 0.09375f * tangent.getXOffset(), y, z + 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x + 0.09375f * tangent.getStepX(), y, z + 0.09375f * tangent.getStepZ(), 8); Particles.create(Registry.FLAME_PARTICLE) .setColor(Signs.BLOOD_SIGN.getRed(), Signs.BLOOD_SIGN.getGreen(), Signs.BLOOD_SIGN.getBlue()) .setAlpha(0.5f, 0) .setScale(0.1875f, 0.125f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x - 0.09375f * tangent.getXOffset(), y, z - 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x - 0.09375f * tangent.getStepX(), y, z - 0.09375f * tangent.getStepZ(), 8); } } } diff --git a/src/main/java/elucent/eidolon/spell/DarkTouchSpell.java b/src/main/java/elucent/eidolon/spell/DarkTouchSpell.java index 48870a5..8b406bb 100644 --- a/src/main/java/elucent/eidolon/spell/DarkTouchSpell.java +++ b/src/main/java/elucent/eidolon/spell/DarkTouchSpell.java @@ -1,44 +1,27 @@ package elucent.eidolon.spell; -import com.google.common.eventbus.Subscribe; +import java.util.List; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import elucent.eidolon.block.HorizontalBlockBase; -import elucent.eidolon.capability.ReputationProvider; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.deity.Deities; -import elucent.eidolon.deity.Deity; import elucent.eidolon.network.MagicBurstEffectPacket; import elucent.eidolon.network.Networking; -import elucent.eidolon.particle.Particles; -import elucent.eidolon.ritual.Ritual; -import elucent.eidolon.tile.EffigyTileEntity; -import net.minecraft.block.BlockState; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ProjectileHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.MusicDiscItem; -import net.minecraft.util.*; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceContext; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.living.LivingHurtEvent; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.DistExecutor; - -import java.util.Comparator; -import java.util.List; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.RecordItem; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.level.Level; public class DarkTouchSpell extends StaticSpell { public static final String NECROTIC_KEY = new ResourceLocation(Eidolon.MODID, "necrotic").toString(); @@ -79,13 +62,13 @@ public DarkTouchSpell(ResourceLocation name, Sign... signs) { // } @Override - public boolean canCast(World world, BlockPos pos, PlayerEntity player) { - if (!world.getCapability(ReputationProvider.CAPABILITY).isPresent()) return false; - if (world.getCapability(ReputationProvider.CAPABILITY).resolve().get().getReputation(player, Deities.DARK_DEITY.getId()) < 4.0) return false; + public boolean canCast(Level world, BlockPos pos, Player player) { + if (!world.getCapability(IReputation.INSTANCE).isPresent()) return false; + if (world.getCapability(IReputation.INSTANCE).resolve().get().getReputation(player, Deities.DARK_DEITY.getId()) < 4.0) return false; - RayTraceResult ray = world.rayTraceBlocks(new RayTraceContext(player.getEyePosition(0), player.getEyePosition(0).add(player.getLookVec().scale(4)), RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, player)); - Vector3d v = ray.getType() == RayTraceResult.Type.BLOCK ? ray.getHitVec() : player.getEyePosition(0).add(player.getLookVec().scale(4)); - List items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(v.x - 1.5, v.y - 1.5, v.z - 1.5, v.x + 1.5, v.y + 1.5, v.z + 1.5)); + HitResult ray = world.clip(new ClipContext(player.getEyePosition(0), player.getEyePosition(0).add(player.getLookAngle().scale(4)), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); + Vec3 v = ray.getType() == HitResult.Type.BLOCK ? ray.getLocation() : player.getEyePosition(0).add(player.getLookAngle().scale(4)); + List items = world.getEntitiesOfClass(ItemEntity.class, new AABB(v.x - 1.5, v.y - 1.5, v.z - 1.5, v.x + 1.5, v.y + 1.5, v.z + 1.5)); if (items.size() != 1) return false; ItemStack stack = items.get(0).getItem(); return stack.getCount() == 1 && canTouch(stack); @@ -94,7 +77,7 @@ public boolean canCast(World world, BlockPos pos, PlayerEntity player) { boolean canTouch(ItemStack stack) { return stack.getItem() == Registry.PEWTER_INLAY.get() // is pewter || stack.getItem() == Items.BLACK_WOOL - || (stack.getItem() instanceof MusicDiscItem && stack.getItem() != Registry.PAROUSIA_DISC.get()); + || (stack.getItem() instanceof RecordItem && stack.getItem() != Registry.PAROUSIA_DISC.get()); // || (stack.isDamageable() && stack.getMaxStackSize() == 1); // is tool } @@ -103,7 +86,7 @@ ItemStack touchResult(ItemStack stack) { // assumes canTouch is true return new ItemStack(Registry.UNHOLY_SYMBOL.get()); else if (stack.getItem() == Items.BLACK_WOOL) return new ItemStack(Registry.TOP_HAT.get()); - else if (stack.getItem() instanceof MusicDiscItem && stack.getItem() != Registry.PAROUSIA_DISC.get()) + else if (stack.getItem() instanceof RecordItem && stack.getItem() != Registry.PAROUSIA_DISC.get()) return new ItemStack(Registry.PAROUSIA_DISC.get()); // else { // stack.getOrCreateTag().putBoolean(NECROTIC_KEY, true); @@ -113,21 +96,21 @@ else if (stack.getItem() instanceof MusicDiscItem && stack.getItem() != Registry } @Override - public void cast(World world, BlockPos pos, PlayerEntity player) { - RayTraceResult ray = world.rayTraceBlocks(new RayTraceContext(player.getEyePosition(0), player.getEyePosition(0).add(player.getLookVec().scale(4)), RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, player)); - Vector3d v = ray.getType() == RayTraceResult.Type.BLOCK ? ray.getHitVec() : player.getEyePosition(0).add(player.getLookVec().scale(4)); - List items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(v.x - 1.5, v.y - 1.5, v.z - 1.5, v.x + 1.5, v.y + 1.5, v.z + 1.5)); + public void cast(Level world, BlockPos pos, Player player) { + HitResult ray = world.clip(new ClipContext(player.getEyePosition(0), player.getEyePosition(0).add(player.getLookAngle().scale(4)), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); + Vec3 v = ray.getType() == HitResult.Type.BLOCK ? ray.getLocation() : player.getEyePosition(0).add(player.getLookAngle().scale(4)); + List items = world.getEntitiesOfClass(ItemEntity.class, new AABB(v.x - 1.5, v.y - 1.5, v.z - 1.5, v.x + 1.5, v.y + 1.5, v.z + 1.5)); if (items.size() == 1) { - if (!world.isRemote) { + if (!world.isClientSide) { ItemStack stack = items.get(0).getItem(); if (canTouch(stack)) { items.get(0).setItem(touchResult(stack)); - Vector3d p = items.get(0).getPositionVec(); - items.get(0).setDefaultPickupDelay(); - Networking.sendToTracking(world, items.get(0).getPosition(), new MagicBurstEffectPacket(p.x, p.y, p.z, Signs.WICKED_SIGN.getColor(), Signs.BLOOD_SIGN.getColor())); + Vec3 p = items.get(0).position(); + items.get(0).setDefaultPickUpDelay(); + Networking.sendToTracking(world, items.get(0).blockPosition(), new MagicBurstEffectPacket(p.x, p.y, p.z, Signs.WICKED_SIGN.getColor(), Signs.BLOOD_SIGN.getColor())); } } else { - world.playSound(player, player.getPosition(), SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE, SoundCategory.NEUTRAL, 1.0F, 0.6F + world.rand.nextFloat() * 0.2F); + world.playSound(player, player.blockPosition(), SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.NEUTRAL, 1.0F, 0.6F + world.random.nextFloat() * 0.2F); } } } diff --git a/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java b/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java index c52b372..410066a 100644 --- a/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java +++ b/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java @@ -1,50 +1,48 @@ package elucent.eidolon.spell; -import elucent.eidolon.capability.KnowledgeProvider; +import elucent.eidolon.capability.IKnowledge; import elucent.eidolon.network.KnowledgeUpdatePacket; import elucent.eidolon.network.Networking; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.network.play.server.STitlePacket; -import net.minecraft.network.play.server.SUpdateTimePacket; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.world.GameRules; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.chat.TranslatableComponent; public class KnowledgeUtil { public static void grantSign(Entity entity, Sign sign) { - if (!(entity instanceof PlayerEntity)) return; - entity.getCapability(KnowledgeProvider.CAPABILITY, null).ifPresent((k) -> { + if (!(entity instanceof Player)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { if (k.knowsSign(sign)) return; k.addSign(sign); - ((ServerPlayerEntity)entity).connection.sendPacket(new STitlePacket(STitlePacket.Type.ACTIONBAR, new TranslationTextComponent("eidolon.title.new_sign", new TranslationTextComponent(sign.key.getNamespace() + ".sign." + sign.key.getPath())))); - Networking.sendTo((PlayerEntity)entity, new KnowledgeUpdatePacket((PlayerEntity)entity, true)); + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_sign", new TranslatableComponent(sign.key.getNamespace() + ".sign." + sign.key.getPath())))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); }); } public static void grantFact(Entity entity, ResourceLocation fact) { - if (!(entity instanceof PlayerEntity)) return; - entity.getCapability(KnowledgeProvider.CAPABILITY, null).ifPresent((k) -> { + if (!(entity instanceof Player)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { if (k.knowsFact(fact)) return; k.addFact(fact); - ((ServerPlayerEntity)entity).connection.sendPacket(new STitlePacket(STitlePacket.Type.ACTIONBAR, new TranslationTextComponent("eidolon.title.new_fact"))); - Networking.sendTo((PlayerEntity)entity, new KnowledgeUpdatePacket((PlayerEntity)entity, true)); + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_fact"))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); }); } - public static boolean knowsSign(PlayerEntity player, Sign sign) { - if (player.getCapability(KnowledgeProvider.CAPABILITY).isPresent()) { - return player.getCapability(KnowledgeProvider.CAPABILITY).resolve().get().knowsSign(sign); + public static boolean knowsSign(Player player, Sign sign) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsSign(sign); } return false; } - public static boolean knowsFact(PlayerEntity player, ResourceLocation fact) { - if (player.getCapability(KnowledgeProvider.CAPABILITY).isPresent()) { - return player.getCapability(KnowledgeProvider.CAPABILITY).resolve().get().knowsFact(fact); + public static boolean knowsFact(Player player, ResourceLocation fact) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsFact(fact); } return false; } diff --git a/src/main/java/elucent/eidolon/spell/PrayerSpell.java b/src/main/java/elucent/eidolon/spell/PrayerSpell.java index f72c9e4..f739c51 100644 --- a/src/main/java/elucent/eidolon/spell/PrayerSpell.java +++ b/src/main/java/elucent/eidolon/spell/PrayerSpell.java @@ -1,25 +1,24 @@ package elucent.eidolon.spell; +import java.util.Comparator; +import java.util.List; + import elucent.eidolon.Registry; import elucent.eidolon.block.HorizontalBlockBase; -import elucent.eidolon.capability.KnowledgeProvider; -import elucent.eidolon.capability.ReputationProvider; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.deity.Deity; import elucent.eidolon.particle.Particles; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.tile.EffigyTileEntity; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.Comparator; -import java.util.List; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class PrayerSpell extends StaticSpell { Deity deity; @@ -30,53 +29,53 @@ public PrayerSpell(ResourceLocation name, Deity deity, Sign... signs) { } @Override - public boolean canCast(World world, BlockPos pos, PlayerEntity player) { - if (!world.getCapability(ReputationProvider.CAPABILITY).isPresent()) return false; - if (!world.getCapability(ReputationProvider.CAPABILITY).resolve().get().canPray(player, world.getGameTime())) return false; - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public boolean canCast(Level world, BlockPos pos, Player player) { + if (!world.getCapability(IReputation.INSTANCE).isPresent()) return false; + if (!world.getCapability(IReputation.INSTANCE).resolve().get().canPray(player, getRegistryName(), world.getGameTime())) return false; + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0) return false; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); return effigy.ready(); } @Override - public void cast(World world, BlockPos pos, PlayerEntity player) { - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public void cast(Level world, BlockPos pos, Player player) { + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0) return; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - if (!world.isRemote) { + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + if (!world.isClientSide) { effigy.pray(); - AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getPos()); - world.getCapability(ReputationProvider.CAPABILITY, null).ifPresent((rep) -> { - rep.pray(player, world.getGameTime()); + AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getBlockPos()); + world.getCapability(IReputation.INSTANCE, null).ifPresent((rep) -> { + rep.pray(player, getRegistryName(), world.getGameTime()); double prev = rep.getReputation(player, deity.getId()); + KnowledgeUtil.grantSign(player, Signs.FLAME_SIGN); rep.addReputation(player, deity.getId(), 1.0 + 0.25 * info.getPower()); - deity.onReputationChange(player, rep, prev, rep.getReputation(player, deity.getId())); }); } else { - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.NEUTRAL, 10000.0F, 0.6F + world.rand.nextFloat() * 0.2F); - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.NEUTRAL, 2.0F, 0.5F + world.rand.nextFloat() * 0.2F); - BlockState state = world.getBlockState(effigy.getPos()); - Direction dir = state.get(HorizontalBlockBase.HORIZONTAL_FACING); - Direction tangent = dir.rotateY(); - float x = effigy.getPos().getX() + 0.5f + dir.getXOffset() * 0.21875f; - float y = effigy.getPos().getY() + 0.8125f; - float z = effigy.getPos().getZ() + 0.5f + dir.getZOffset() * 0.21875f; + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.NEUTRAL, 10000.0F, 0.6F + world.random.nextFloat() * 0.2F); + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.NEUTRAL, 2.0F, 0.5F + world.random.nextFloat() * 0.2F); + BlockState state = world.getBlockState(effigy.getBlockPos()); + Direction dir = state.getValue(HorizontalBlockBase.HORIZONTAL_FACING); + Direction tangent = dir.getClockWise(); + float x = effigy.getBlockPos().getX() + 0.5f + dir.getStepX() * 0.21875f; + float y = effigy.getBlockPos().getY() + 0.8125f; + float z = effigy.getBlockPos().getZ() + 0.5f + dir.getStepZ() * 0.21875f; Particles.create(Registry.FLAME_PARTICLE) .setColor(deity.getRed(), deity.getGreen(), deity.getBlue()) .setAlpha(0.5f, 0) .setScale(0.125f, 0.0625f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x + 0.09375f * tangent.getXOffset(), y, z + 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x + 0.09375f * tangent.getStepX(), y, z + 0.09375f * tangent.getStepZ(), 8); Particles.create(Registry.FLAME_PARTICLE) .setColor(deity.getRed(), deity.getGreen(), deity.getBlue()) .setAlpha(0.5f, 0) .setScale(0.1875f, 0.125f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x - 0.09375f * tangent.getXOffset(), y, z - 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x - 0.09375f * tangent.getStepX(), y, z - 0.09375f * tangent.getStepZ(), 8); } } } diff --git a/src/main/java/elucent/eidolon/spell/Sign.java b/src/main/java/elucent/eidolon/spell/Sign.java index 12128c2..4a02e45 100644 --- a/src/main/java/elucent/eidolon/spell/Sign.java +++ b/src/main/java/elucent/eidolon/spell/Sign.java @@ -1,9 +1,7 @@ package elucent.eidolon.spell; import elucent.eidolon.util.ColorUtil; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Resource; +import net.minecraft.resources.ResourceLocation; public class Sign { ResourceLocation key, sprite; diff --git a/src/main/java/elucent/eidolon/spell/Signs.java b/src/main/java/elucent/eidolon/spell/Signs.java index f6fe331..48e2726 100644 --- a/src/main/java/elucent/eidolon/spell/Signs.java +++ b/src/main/java/elucent/eidolon/spell/Signs.java @@ -1,14 +1,14 @@ package elucent.eidolon.spell; -import elucent.eidolon.Eidolon; -import elucent.eidolon.util.ColorUtil; -import net.minecraft.util.ResourceLocation; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import elucent.eidolon.Eidolon; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.resources.ResourceLocation; + public class Signs { static List signs = new ArrayList<>(); static Map signMap = new HashMap<>(); @@ -62,5 +62,10 @@ public static List getSigns() { new ResourceLocation(Eidolon.MODID, "energy"), new ResourceLocation(Eidolon.MODID, "particle/energy_sign"), ColorUtil.packColor(255, 145, 250, 100) + )), + FLAME_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "flame"), + new ResourceLocation(Eidolon.MODID, "particle/flame_sign"), + ColorUtil.packColor(255, 255, 128, 64) )); } diff --git a/src/main/java/elucent/eidolon/spell/Spell.java b/src/main/java/elucent/eidolon/spell/Spell.java index 86f6839..5448924 100644 --- a/src/main/java/elucent/eidolon/spell/Spell.java +++ b/src/main/java/elucent/eidolon/spell/Spell.java @@ -1,12 +1,12 @@ package elucent.eidolon.spell; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - import java.util.List; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + public abstract class Spell { ResourceLocation registryName; public Spell(ResourceLocation registryName) { @@ -18,6 +18,6 @@ public ResourceLocation getRegistryName() { } public abstract boolean matches(List signs); - public abstract boolean canCast(World world, BlockPos pos, PlayerEntity player, List signs); - public abstract void cast(World world, BlockPos pos, PlayerEntity player, List signs); + public abstract boolean canCast(Level world, BlockPos pos, Player player, List signs); + public abstract void cast(Level world, BlockPos pos, Player player, List signs); } diff --git a/src/main/java/elucent/eidolon/spell/Spells.java b/src/main/java/elucent/eidolon/spell/Spells.java index 460923e..a4e9a1d 100644 --- a/src/main/java/elucent/eidolon/spell/Spells.java +++ b/src/main/java/elucent/eidolon/spell/Spells.java @@ -1,14 +1,14 @@ package elucent.eidolon.spell; -import elucent.eidolon.Eidolon; -import elucent.eidolon.deity.Deities; -import net.minecraft.util.ResourceLocation; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import elucent.eidolon.Eidolon; +import elucent.eidolon.deity.Deities; +import net.minecraft.resources.ResourceLocation; + public class Spells { static List spells = new ArrayList<>(); static Map spellMap = new HashMap<>(); @@ -51,5 +51,10 @@ public static List getSpells() { new ResourceLocation(Eidolon.MODID, "dark_villager_sacrifice"), Deities.DARK_DEITY, Signs.BLOOD_SIGN, Signs.WICKED_SIGN, Signs.BLOOD_SIGN, Signs.SOUL_SIGN + )), + LIGHT_PRAYER = register(new PrayerSpell( + new ResourceLocation(Eidolon.MODID, "light_prayer"), + Deities.LIGHT_DEITY, + Signs.SACRED_SIGN, Signs.SACRED_SIGN, Signs.SACRED_SIGN )); } diff --git a/src/main/java/elucent/eidolon/spell/StaticSpell.java b/src/main/java/elucent/eidolon/spell/StaticSpell.java index 6efc0aa..eb50839 100644 --- a/src/main/java/elucent/eidolon/spell/StaticSpell.java +++ b/src/main/java/elucent/eidolon/spell/StaticSpell.java @@ -1,14 +1,13 @@ package elucent.eidolon.spell; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + public abstract class StaticSpell extends Spell { List signs; @@ -24,17 +23,17 @@ public boolean matches(List signs) { return true; } - public abstract boolean canCast(World world, BlockPos pos, PlayerEntity player); + public abstract boolean canCast(Level world, BlockPos pos, Player player); @Override - public boolean canCast(World world, BlockPos pos, PlayerEntity player, List signs) { + public boolean canCast(Level world, BlockPos pos, Player player, List signs) { return canCast(world, pos, player); } - public abstract void cast(World world, BlockPos pos, PlayerEntity player); + public abstract void cast(Level world, BlockPos pos, Player player); @Override - public void cast(World world, BlockPos pos, PlayerEntity player, List signs) { + public void cast(Level world, BlockPos pos, Player player, List signs) { cast(world, pos, player); } } diff --git a/src/main/java/elucent/eidolon/spell/VillagerSacrificeSpell.java b/src/main/java/elucent/eidolon/spell/VillagerSacrificeSpell.java index 31d3f8f..aaec91e 100644 --- a/src/main/java/elucent/eidolon/spell/VillagerSacrificeSpell.java +++ b/src/main/java/elucent/eidolon/spell/VillagerSacrificeSpell.java @@ -1,29 +1,28 @@ package elucent.eidolon.spell; +import java.util.Comparator; +import java.util.List; + import elucent.eidolon.Registry; import elucent.eidolon.block.HorizontalBlockBase; -import elucent.eidolon.capability.ReputationProvider; +import elucent.eidolon.capability.IReputation; import elucent.eidolon.deity.Deity; import elucent.eidolon.deity.DeityLocks; import elucent.eidolon.particle.Particles; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.tile.EffigyTileEntity; import elucent.eidolon.tile.GobletTileEntity; -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; -import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.Comparator; -import java.util.List; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; public class VillagerSacrificeSpell extends StaticSpell { Deity deity; @@ -34,65 +33,63 @@ public VillagerSacrificeSpell(ResourceLocation name, Deity deity, Sign... signs) } @Override - public boolean canCast(World world, BlockPos pos, PlayerEntity player) { - if (!world.getCapability(ReputationProvider.CAPABILITY).isPresent()) return false; - if (!world.getCapability(ReputationProvider.CAPABILITY).resolve().get().canPray(player, world.getGameTime())) return false; - if (world.getCapability(ReputationProvider.CAPABILITY).resolve().get().getReputation(player.getUniqueID(), deity.getId()) < 15.0) return false; - List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public boolean canCast(Level world, BlockPos pos, Player player) { + if (!world.getCapability(IReputation.INSTANCE).isPresent()) return false; + if (!world.getCapability(IReputation.INSTANCE).resolve().get().canPray(player, getRegistryName(), world.getGameTime())) return false; + if (world.getCapability(IReputation.INSTANCE).resolve().get().getReputation(player.getUUID(), deity.getId()) < 15.0) return false; + List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0 || goblets.size() == 0) return false; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); if (goblet.getEntityType() == null) return false; - AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getPos()); + AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getBlockPos()); if (info.getAltar() != Registry.STONE_ALTAR.get() || info.getIcon() != Registry.UNHOLY_EFFIGY.get()) return false; Entity test = goblet.getEntityType().create(world); - return (test instanceof AbstractVillagerEntity || test instanceof PlayerEntity) && effigy.ready(); + return (test instanceof AbstractVillager || test instanceof Player) && effigy.ready(); } @Override - public void cast(World world, BlockPos pos, PlayerEntity player) { - List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); - List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AxisAlignedBB(pos.add(-4, -4, -4), pos.add(5, 5, 5))); + public void cast(Level world, BlockPos pos, Player player) { + List goblets = Ritual.getTilesWithinAABB(GobletTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); + List effigies = Ritual.getTilesWithinAABB(EffigyTileEntity.class, world, new AABB(pos.offset(-4, -4, -4), pos.offset(5, 5, 5))); if (effigies.size() == 0 || goblets.size() == 0) return; - EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getPos().distanceSq(pos))).get(); - if (!world.isRemote) { + EffigyTileEntity effigy = effigies.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + GobletTileEntity goblet = goblets.stream().min(Comparator.comparingDouble((e) -> e.getBlockPos().distSqr(pos))).get(); + if (!world.isClientSide) { effigy.pray(); goblet.setEntityType(null); - AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getPos()); - world.getCapability(ReputationProvider.CAPABILITY, null).ifPresent((rep) -> { - rep.pray(player, world.getGameTime()); + AltarInfo info = AltarInfo.getAltarInfo(world, effigy.getBlockPos()); + world.getCapability(IReputation.INSTANCE, null).ifPresent((rep) -> { + rep.pray(player, getRegistryName(), world.getGameTime()); double prev = rep.getReputation(player, deity.getId()); - if (rep.unlock(player, deity.getId(), DeityLocks.SACRIFICE_VILLAGER)) - deity.onReputationUnlock(player, rep, DeityLocks.SACRIFICE_VILLAGER); + rep.unlock(player, deity.getId(), DeityLocks.SACRIFICE_VILLAGER); rep.addReputation(player, deity.getId(), 6.0 + 1.0 * info.getPower()); - deity.onReputationChange(player, rep, prev, rep.getReputation(player, deity.getId())); }); } else { - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.NEUTRAL, 10000.0F, 0.6F + world.rand.nextFloat() * 0.2F); - world.playSound(player, effigy.getPos(), SoundEvents.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.NEUTRAL, 2.0F, 0.5F + world.rand.nextFloat() * 0.2F); - BlockState state = world.getBlockState(effigy.getPos()); - Direction dir = state.get(HorizontalBlockBase.HORIZONTAL_FACING); - Direction tangent = dir.rotateY(); - float x = effigy.getPos().getX() + 0.5f + dir.getXOffset() * 0.21875f; - float y = effigy.getPos().getY() + 0.8125f; - float z = effigy.getPos().getZ() + 0.5f + dir.getZOffset() * 0.21875f; + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.NEUTRAL, 10000.0F, 0.6F + world.random.nextFloat() * 0.2F); + world.playSound(player, effigy.getBlockPos(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.NEUTRAL, 2.0F, 0.5F + world.random.nextFloat() * 0.2F); + BlockState state = world.getBlockState(effigy.getBlockPos()); + Direction dir = state.getValue(HorizontalBlockBase.HORIZONTAL_FACING); + Direction tangent = dir.getClockWise(); + float x = effigy.getBlockPos().getX() + 0.5f + dir.getStepX() * 0.21875f; + float y = effigy.getBlockPos().getY() + 0.8125f; + float z = effigy.getBlockPos().getZ() + 0.5f + dir.getStepZ() * 0.21875f; Particles.create(Registry.FLAME_PARTICLE) .setColor(Signs.SOUL_SIGN.getRed(), Signs.SOUL_SIGN.getGreen(), Signs.SOUL_SIGN.getBlue()) .setAlpha(0.5f, 0) .setScale(0.125f, 0.0625f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x + 0.09375f * tangent.getXOffset(), y, z + 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x + 0.09375f * tangent.getStepX(), y, z + 0.09375f * tangent.getStepZ(), 8); Particles.create(Registry.FLAME_PARTICLE) .setColor(Signs.SOUL_SIGN.getRed(), Signs.SOUL_SIGN.getGreen(), Signs.SOUL_SIGN.getBlue()) .setAlpha(0.5f, 0) .setScale(0.1875f, 0.125f) .randomOffset(0.01f) .randomVelocity(0.0025f).addVelocity(0, 0.005f, 0) - .repeat(world, x - 0.09375f * tangent.getXOffset(), y, z - 0.09375f * tangent.getZOffset(), 8); + .repeat(world, x - 0.09375f * tangent.getStepX(), y, z - 0.09375f * tangent.getStepZ(), 8); } } } diff --git a/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java b/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java index a730ef1..d0ed0f2 100644 --- a/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java @@ -1,31 +1,32 @@ package elucent.eidolon.tile; import elucent.eidolon.Registry; -import elucent.eidolon.network.*; -import elucent.eidolon.particle.GenericParticleData; +import elucent.eidolon.network.ExtinguishEffectPacket; +import elucent.eidolon.network.FlameEffectPacket; +import elucent.eidolon.network.IgniteEffectPacket; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.RitualCompletePacket; import elucent.eidolon.particle.Particles; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.ritual.Ritual.RitualResult; import elucent.eidolon.ritual.Ritual.SetupResult; import elucent.eidolon.ritual.RitualRegistry; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.tileentity.ITickableTileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.fml.network.PacketDispatcher; -import net.minecraftforge.fml.network.PacketDistributor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.Containers; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.TickingBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; -public class BrazierTileEntity extends TileEntityBase implements ITickableTileEntity { +public class BrazierTileEntity extends TileEntityBase { ItemStack stack = ItemStack.EMPTY; boolean burning = false; int findingCounter = 0; @@ -34,57 +35,57 @@ public class BrazierTileEntity extends TileEntityBase implements ITickableTileEn int step = 0; boolean ritualDone = false; - public BrazierTileEntity() { - this(Registry.BRAZIER_TILE_ENTITY); + public BrazierTileEntity(BlockPos pos, BlockState state) { + this(Registry.BRAZIER_TILE_ENTITY, pos, state); } - public BrazierTileEntity(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); + public BrazierTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); } @Override public void onDestroyed(BlockState state, BlockPos pos) { super.onDestroyed(state, pos); - if (!stack.isEmpty()) InventoryHelper.spawnItemStack(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); + if (!stack.isEmpty()) Containers.dropItemStack(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); } @Override - public ActionResultType onActivated(BlockState state, BlockPos pos, PlayerEntity player, Hand hand) { - if (hand == Hand.MAIN_HAND) { - if (burning && player.isSneaking() && player.getHeldItem(hand).isEmpty()) { + public InteractionResult onActivated(BlockState state, BlockPos pos, Player player, InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + if (burning && player.isShiftKeyDown() && player.getItemInHand(hand).isEmpty()) { extinguish(); - return ActionResultType.SUCCESS; + return InteractionResult.SUCCESS; } - else if (!burning && player.getHeldItem(hand).isEmpty() && !stack.isEmpty()) { - player.addItemStackToInventory(stack); + else if (!burning && player.getItemInHand(hand).isEmpty() && !stack.isEmpty()) { + player.addItem(stack); stack = ItemStack.EMPTY; - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } else if (!burning && !stack.isEmpty() - && player.getHeldItem(hand).getItem() == Items.FLINT_AND_STEEL) { - player.getHeldItem(hand).damageItem(1, player, (p) -> { - p.sendBreakAnimation(hand); + && player.getItemInHand(hand).getItem() == Items.FLINT_AND_STEEL) { + player.getItemInHand(hand).hurtAndBreak(1, player, (p) -> { + p.broadcastBreakEvent(hand); }); startBurning(); - return ActionResultType.SUCCESS; + return InteractionResult.SUCCESS; } - else if (!player.getHeldItem(hand).isEmpty() && stack.isEmpty()) { - stack = player.getHeldItem(hand).copy(); + else if (!player.getItemInHand(hand).isEmpty() && stack.isEmpty()) { + stack = player.getItemInHand(hand).copy(); stack.setCount(1); - player.getHeldItem(hand).shrink(1); - if (player.getHeldItem(hand).isEmpty()) player.setHeldItem(hand, ItemStack.EMPTY); - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + player.getItemInHand(hand).shrink(1); + if (player.getItemInHand(hand).isEmpty()) player.setItemInHand(hand, ItemStack.EMPTY); + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } } - return ActionResultType.PASS; + return InteractionResult.PASS; } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); - stack = ItemStack.read(tag.getCompound("stack")); + public void load(CompoundTag tag) { + super.load(tag); + stack = ItemStack.of(tag.getCompound("stack")); burning = tag.getBoolean("burning"); ritual = tag.contains("ritual") ? RitualRegistry.find(new ResourceLocation(tag.getString("ritual"))) : null; step = tag.getInt("step"); @@ -92,9 +93,9 @@ public void read(BlockState state, CompoundNBT tag) { } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); - tag.put("stack", stack.write(new CompoundNBT())); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); + tag.put("stack", stack.save(new CompoundTag())); tag.putBoolean("burning", burning); if (ritual != null) tag.putString("ritual", ritual.getRegistryName().toString()); tag.putInt("step", step); @@ -106,11 +107,11 @@ protected void complete() { burning = false; stepCounter = 0; findingCounter = 0; - if (!world.isRemote) { + if (!level.isClientSide) { if (ritual != null) - Networking.sendToTracking(world, pos.up(2), new RitualCompletePacket(pos.up(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + Networking.sendToTracking(level, worldPosition.above(2), new RitualCompletePacket(worldPosition.above(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); ritual = null; - Networking.sendToTracking(world, pos, new ExtinguishEffectPacket(pos)); + Networking.sendToTracking(level, worldPosition, new ExtinguishEffectPacket(worldPosition)); sync(); } ritual = null; @@ -120,11 +121,11 @@ protected void extinguish() { burning = false; stepCounter = 0; findingCounter = 0; - if (!world.isRemote) { + if (!level.isClientSide) { if (ritual != null) - Networking.sendToTracking(world, pos.up(2), new FlameEffectPacket(pos.up(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + Networking.sendToTracking(level, worldPosition.above(2), new FlameEffectPacket(worldPosition.above(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); ritual = null; - Networking.sendToTracking(world, pos, new ExtinguishEffectPacket(pos)); + Networking.sendToTracking(level, worldPosition, new ExtinguishEffectPacket(worldPosition)); sync(); } ritual = null; @@ -133,8 +134,8 @@ protected void extinguish() { protected void startBurning() { burning = true; findingCounter = 0; - if (!world.isRemote) { - Networking.sendToTracking(world, pos, new IgniteEffectPacket(pos, 1.0f, 0.5f, 0.25f)); + if (!level.isClientSide) { + Networking.sendToTracking(level, worldPosition, new IgniteEffectPacket(worldPosition, 1.0f, 0.5f, 0.25f)); sync(); } } @@ -146,32 +147,31 @@ protected void setRitual(Ritual ritual) { stepCounter = 0; step = 0; ritualDone = false; - if (!world.isRemote) { - Networking.sendToTracking(world, pos.up(2), new FlameEffectPacket(pos.up(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); + if (!level.isClientSide) { + Networking.sendToTracking(level, worldPosition.above(2), new FlameEffectPacket(worldPosition.above(2), ritual.getRed(), ritual.getGreen(), ritual.getBlue())); sync(); } } } - @Override public void tick() { if (burning && findingCounter < 80 && ritual == null) { float progress = (findingCounter - 40) / 40.0f; if (progress >= 0) for (int i = 0; i < 8; i ++) { float angle = progress * (float)Math.PI / 4 + i * (float)Math.PI / 4; - float radius = 0.625f * MathHelper.sin(4 * angle); + float radius = 0.625f * Mth.sin(4 * angle); angle += (float)Math.PI / 4; - float x = getPos().getX() + 0.5f + MathHelper.sin(angle) * radius; - float y = getPos().getY() + 0.875f; - float z = getPos().getZ() + 0.5f + MathHelper.cos(angle) * radius; + float x = getBlockPos().getX() + 0.5f + Mth.sin(angle) * radius; + float y = getBlockPos().getY() + 0.875f; + float z = getBlockPos().getZ() + 0.5f + Mth.cos(angle) * radius; Particles.create(Registry.WISP_PARTICLE) .setAlpha(0.25f * progress, 0).setScale(0.125f, 0.0625f).setLifetime(20) .setColor(1.0f, 0.5f, 0.25f, 1.0f, 0.25f, 0.375f) - .spawn(world, x, y, z); + .spawn(level, x, y, z); } findingCounter ++; if (findingCounter == 80) { - Ritual r = RitualRegistry.find(world, pos, stack); + Ritual r = RitualRegistry.find(level, worldPosition, stack); stack = ItemStack.EMPTY; findingCounter = 81; setRitual(r); @@ -180,14 +180,14 @@ public void tick() { if (burning && ritual != null && !ritualDone) { stepCounter ++; if (stepCounter == 40) { - SetupResult result = ritual.setup(world, pos, step); + SetupResult result = ritual.setup(level, worldPosition, step); if (result == SetupResult.SUCCEED) { ritualDone = true; - if (!world.isRemote) sync(); - if (ritual.start(world, pos) == RitualResult.TERMINATE) complete(); + if (!level.isClientSide) sync(); + if (ritual.start(level, worldPosition) == RitualResult.TERMINATE) complete(); } - else if (result == SetupResult.FAIL && !world.isRemote) extinguish(); - else if (!world.isRemote) { + else if (result == SetupResult.FAIL && !level.isClientSide) extinguish(); + else if (!level.isClientSide) { stepCounter = 0; step ++; sync(); @@ -195,10 +195,10 @@ else if (!world.isRemote) { } } if (burning && ritual != null && ritualDone) { - if (ritual.tick(world, pos) == RitualResult.TERMINATE) complete(); + if (ritual.tick(level, worldPosition) == RitualResult.TERMINATE) complete(); } - if (world.isRemote && burning) { - float x = getPos().getX() + 0.5f, y = getPos().getY() + 1, z = getPos().getZ() + 0.5f; + if (level.isClientSide && burning) { + float x = getBlockPos().getX() + 0.5f, y = getBlockPos().getY() + 1, z = getBlockPos().getZ() + 0.5f; float r = ritual == null ? 1.0f : ritual.getRed(); float g = ritual == null ? 0.5f : ritual.getGreen(); float b = ritual == null ? 0.25f : ritual.getBlue(); @@ -207,25 +207,25 @@ else if (!world.isRemote) { .randomOffset(0.25, 0.125).randomVelocity(0.00625f, 0.01875f) .addVelocity(0, 0.00625f, 0) .setColor(r, g, b, r, g * 0.5f, b * 1.5f) - .spawn(world, x, y, z); - if (world.rand.nextInt(5) == 0) Particles.create(Registry.SMOKE_PARTICLE) + .spawn(level, x, y, z); + if (level.random.nextInt(5) == 0) Particles.create(Registry.SMOKE_PARTICLE) .setAlpha(0.125f, 0).setScale(0.375f, 0.125f).setLifetime(80) .randomOffset(0.25, 0.125).randomVelocity(0.025f, 0.025f) .addVelocity(0, 0.1f, 0) .setColor(0.5f, 0.5f, 0.5f, 0.25f, 0.25f, 0.25f) - .spawn(world, x, y + 0.125, z); - if (world.rand.nextInt(40) == 0) Particles.create(Registry.SPARKLE_PARTICLE) + .spawn(level, x, y + 0.125, z); + if (level.random.nextInt(40) == 0) Particles.create(Registry.SPARKLE_PARTICLE) .setAlpha(1, 0).setScale(0.0625f, 0).setLifetime(40) .randomOffset(0.0625, 0).randomVelocity(0.125f, 0) .addVelocity(0, 0.125f, 0) .setColor(r, g * 1.5f, b * 2, r, g, b) .enableGravity().setSpin(0.4f) - .spawn(world, x, y, z); + .spawn(level, x, y, z); } } @Override - public AxisAlignedBB getRenderBoundingBox() { - return new AxisAlignedBB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 4, pos.getZ() + 1); + public AABB getRenderBoundingBox() { + return new AABB(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), worldPosition.getX() + 1, worldPosition.getY() + 4, worldPosition.getZ() + 1); } } diff --git a/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java b/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java index 635f744..c21778e 100644 --- a/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java @@ -1,47 +1,45 @@ package elucent.eidolon.tile; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.ClientEvents; -import elucent.eidolon.Events; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.core.BlockPos; +import com.mojang.math.Vector3f; -public class BrazierTileRenderer extends TileEntityRenderer { - public BrazierTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); - } +public class BrazierTileRenderer implements BlockEntityRenderer { + public BrazierTileRenderer() {} @Override - public void render(BrazierTileEntity tileEntityIn, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { + public void render(BrazierTileEntity tileEntityIn, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { Minecraft mc = Minecraft.getInstance(); ItemRenderer ir = mc.getItemRenderer(); if (!tileEntityIn.stack.isEmpty()) { - matrixStackIn.push(); + matrixStackIn.pushPose(); matrixStackIn.translate(0.5,0.9375, 0.5); - matrixStackIn.rotate(Vector3f.YP.rotationDegrees(3 * (mc.world.getGameTime() % 360 + partialTicks))); - ir.renderItem(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn); - matrixStackIn.pop(); + matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(3 * (mc.level.getGameTime() % 360 + partialTicks))); + ir.renderStatic(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn, 0); + matrixStackIn.popPose(); } if (tileEntityIn.ritual != null) { - IRenderTypeBuffer buffer = ClientEvents.getDelayedRender(); + MultiBufferSource buffer = ClientEvents.getDelayedRender(); Ritual ritual = tileEntityIn.ritual; float r = ritual.getRed(), g = ritual.getGreen(), b = ritual.getBlue(); RenderUtil.dragon(matrixStackIn, buffer, 0.5, 3.0, 0.5, 1, r, g, b); - TextureAtlasSprite sprite = mc.getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(ritual.getSymbol()); + TextureAtlasSprite sprite = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ritual.getSymbol()); - BlockPos pos = tileEntityIn.getPos(); + BlockPos pos = tileEntityIn.getBlockPos(); RenderUtil.litBillboard(matrixStackIn, buffer, 0.5, 3.0, 0.5, r, g, b, sprite); RenderUtil.litBillboard(matrixStackIn, buffer, 0.5, 3.0, 0.5, r, g, b, sprite); } diff --git a/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java b/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java index e88d302..0201700 100644 --- a/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java @@ -1,5 +1,10 @@ package elucent.eidolon.tile; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.function.Predicate; + import elucent.eidolon.Registry; import elucent.eidolon.network.CrucibleFailPacket; import elucent.eidolon.network.CrucibleSuccessPacket; @@ -7,33 +12,26 @@ import elucent.eidolon.particle.Particles; import elucent.eidolon.recipe.CrucibleRecipe; import elucent.eidolon.recipe.CrucibleRegistry; -import elucent.eidolon.ritual.IRitualItemProvider; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.CampfireBlock; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.INBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.tileentity.ITickableTileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.*; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.util.Constants; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.CampfireBlock; +import net.minecraft.world.entity.Entity.RemovalReason; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.AABB; +import net.minecraft.core.BlockPos; -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.function.Predicate; - -public class CrucibleTileEntity extends TileEntityBase implements ITickableTileEntity { +public class CrucibleTileEntity extends TileEntityBase { boolean boiling = false; boolean hasWater = false; int stirTicks = 0; @@ -75,17 +73,17 @@ public List getContents() { return contents; } - public CrucibleStep(CompoundNBT nbt) { + public CrucibleStep(CompoundTag nbt) { stirs = nbt.getInt("stirs"); - ListNBT list = nbt.getList("contents", Constants.NBT.TAG_COMPOUND); - for (INBT item : list) contents.add(ItemStack.read((CompoundNBT)item)); + ListTag list = nbt.getList("contents", Tag.TAG_COMPOUND); + for (Tag item : list) contents.add(ItemStack.of((CompoundTag)item)); } - public CompoundNBT write() { - CompoundNBT nbt = new CompoundNBT(); + public CompoundTag write() { + CompoundTag nbt = new CompoundTag(); nbt.putInt("stirs", stirs); - ListNBT list = new ListNBT(); - for (ItemStack stack : contents) list.add(stack.write(new CompoundNBT())); + ListTag list = new ListTag(); + for (ItemStack stack : contents) list.add(stack.save(new CompoundTag())); nbt.put("contents", list); return nbt; } @@ -96,60 +94,60 @@ public CompoundNBT write() { (BlockState b) -> b.getBlock() == Blocks.FIRE, (BlockState b) -> b.getBlock() == Blocks.SOUL_FIRE, (BlockState b) -> b.getBlock() == Blocks.LAVA, - (BlockState b) -> b.getBlock() == Blocks.CAMPFIRE && b.get(CampfireBlock.LIT), - (BlockState b) -> b.getBlock() == Blocks.SOUL_CAMPFIRE && b.get(CampfireBlock.LIT) + (BlockState b) -> b.getBlock() == Blocks.CAMPFIRE && b.getValue(CampfireBlock.LIT), + (BlockState b) -> b.getBlock() == Blocks.SOUL_CAMPFIRE && b.getValue(CampfireBlock.LIT) }; - public CrucibleTileEntity() { - this(Registry.CRUCIBLE_TILE_ENTITY); + public CrucibleTileEntity(BlockPos pos, BlockState state) { + this(Registry.CRUCIBLE_TILE_ENTITY, pos, state); } - public CrucibleTileEntity(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); + public CrucibleTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state); } @Override - public ActionResultType onActivated(BlockState state, BlockPos pos, PlayerEntity player, Hand hand) { - if (hand == Hand.MAIN_HAND) { - if (player.isSneaking() && player.getHeldItem(hand).isEmpty() && hasWater) { + public InteractionResult onActivated(BlockState state, BlockPos pos, Player player, InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + if (player.isShiftKeyDown() && player.getItemInHand(hand).isEmpty() && hasWater) { boiling = false; hasWater = false; stirs = 0; steps.clear(); - if (!world.isRemote) { + if (!level.isClientSide) { sync(); - world.playSound(null, pos, SoundEvents.ITEM_BUCKET_EMPTY, SoundCategory.BLOCKS, 1.0f, 1.0f); + level.playSound(null, pos, SoundEvents.BUCKET_EMPTY, SoundSource.BLOCKS, 1.0f, 1.0f); } - return ActionResultType.SUCCESS; + return InteractionResult.SUCCESS; } - else if (player.getHeldItem(hand).isEmpty() && stirTicks == 0 && this.steps.size() > 0) { + else if (player.getItemInHand(hand).isEmpty() && stirTicks == 0 && this.steps.size() > 0) { stirs ++; stirTicks = 20; - if (!world.isRemote) { - world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_SPLASH, SoundCategory.BLOCKS, 1.0f, 1.0f); + if (!level.isClientSide) { + level.playSound(null, pos, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0f, 1.0f); sync(); } - return ActionResultType.SUCCESS; + return InteractionResult.SUCCESS; } - if (player.getHeldItem(hand).getItem() == Items.WATER_BUCKET) { - player.setHeldItem(hand, new ItemStack(Items.BUCKET)); - hasWater = true; - if (!world.isRemote) { + if (player.getItemInHand(hand).getItem() == Items.WATER_BUCKET) { + player.setItemInHand(hand, new ItemStack(Items.BUCKET)); + if (!level.isClientSide) { + hasWater = true; sync(); - world.playSound(null, pos, SoundEvents.ITEM_BUCKET_EMPTY, SoundCategory.BLOCKS, 1.0f, 1.0f); + level.playSound(null, pos, SoundEvents.BUCKET_EMPTY, SoundSource.BLOCKS, 1.0f, 1.0f); } - return ActionResultType.SUCCESS; + return InteractionResult.SUCCESS; } } - return ActionResultType.PASS; + return InteractionResult.PASS; } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); + public void load(CompoundTag tag) { + super.load(tag); this.steps.clear(); - ListNBT steps = tag.getList("steps", Constants.NBT.TAG_COMPOUND); - for (INBT step : steps) this.steps.add(new CrucibleStep((CompoundNBT)step)); + ListTag steps = tag.getList("steps", Tag.TAG_COMPOUND); + for (Tag step : steps) this.steps.add(new CrucibleStep((CompoundTag)step)); boiling = tag.getBoolean("boiling"); hasWater = tag.getBoolean("hasWater"); stirs = tag.getInt("stirs"); @@ -158,9 +156,9 @@ public void read(BlockState state, CompoundNBT tag) { } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); - ListNBT steps = new ListNBT(); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); + ListTag steps = new ListTag(); for (CrucibleStep step : this.steps) steps.add(step.write()); tag.put("steps", steps); tag.putBoolean("boiling", boiling); @@ -170,21 +168,20 @@ public CompoundNBT write(CompoundNBT tag) { return tag; } - @Override public void tick() { if (stirTicks > 0) stirTicks --; - if (hasWater && world.getGameTime() % 200 == 0) { - BlockState state = world.getBlockState(pos.down()); + if (hasWater && level.getGameTime() % 200 == 0) { + BlockState state = level.getBlockState(worldPosition.below()); boolean isHeated = false; for (Predicate pred : HOT_BLOCKS) if (pred.test(state)) isHeated = true; if (boiling && !isHeated) { boiling = false; - if (!world.isRemote) sync(); + if (!level.isClientSide) sync(); } else if (!boiling && isHeated) { boiling = true; - if (!world.isRemote) sync(); + if (!level.isClientSide) sync(); } } @@ -195,31 +192,31 @@ else if (!boiling && isHeated) { float steamG = steps.size() > 0 ? Math.min(1.0f, 1 - (float)Math.pow(1 - getGreen(), 2)) : 1.0f; float steamB = steps.size() > 0 ? Math.min(1.0f, 1 - (float)Math.pow(1 - getBlue(), 2)) : 1.0f; - if (world.isRemote && hasWater && boiling) for (int i = 0; i < 2; i ++){ + if (level.isClientSide && hasWater && boiling) for (int i = 0; i < 2; i ++){ Particles.create(Registry.BUBBLE_PARTICLE) .setScale(0.05f) .setLifetime(10) .addVelocity(0, 0.015625, 0) .setColor(bubbleR, bubbleG, bubbleB) .setAlpha(1.0f, 0.75f) - .spawn(world, pos.getX() + 0.125 + 0.75 * world.rand.nextFloat(), pos.getY() + 0.6875, pos.getZ() + 0.125 + 0.75 * world.rand.nextFloat()); - if (world.rand.nextInt(8) == 0) Particles.create(Registry.STEAM_PARTICLE) + .spawn(level, worldPosition.getX() + 0.125 + 0.75 * level.random.nextFloat(), worldPosition.getY() + 0.6875, worldPosition.getZ() + 0.125 + 0.75 * level.random.nextFloat()); + if (level.random.nextInt(8) == 0) Particles.create(Registry.STEAM_PARTICLE) .setAlpha(0.0625f, 0).setScale(0.375f, 0.125f).setLifetime(80) .randomOffset(0.375, 0.125).randomVelocity(0.0125f, 0.025f) .addVelocity(0, 0.05f, 0) .setColor(steamR, steamG, steamB) - .spawn(world, pos.getX() + 0.5, pos.getY() + 0.625, pos.getZ() + 0.5); + .spawn(level, worldPosition.getX() + 0.5, worldPosition.getY() + 0.625, worldPosition.getZ() + 0.5); } - if (!world.isRemote && boiling && hasWater && world.getGameTime() % 8 == 0) { - List items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(pos).shrink(0.125)); - for (ItemEntity item : items) item.setPickupDelay(20); + if (!level.isClientSide && boiling && hasWater && level.getGameTime() % 8 == 0) { + List items = level.getEntitiesOfClass(ItemEntity.class, new AABB(worldPosition).deflate(0.125)); + for (ItemEntity item : items) item.setPickUpDelay(20); } - if (!world.isRemote && stepCounter > 0) { + if (!level.isClientSide && stepCounter > 0) { -- stepCounter; if (stepCounter == 0) { - List items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(pos).shrink(0.125)); + List items = level.getEntitiesOfClass(ItemEntity.class, new AABB(worldPosition).deflate(0.125)); List contents = new ArrayList<>(); for (ItemEntity item : items) { for (int i = 0; i < item.getItem().getCount(); i ++) { @@ -227,10 +224,10 @@ else if (!boiling && isHeated) { stack.setCount(1); contents.add(stack); } - item.remove(); + item.remove(RemovalReason.DISCARDED); } if (stirs == 0 && contents.isEmpty()) { // no action done; end recipe - Networking.sendToTracking(world, pos, new CrucibleFailPacket(pos)); + Networking.sendToTracking(level, worldPosition, new CrucibleFailPacket(worldPosition)); contents.clear(); steps.clear(); stirs = 0; @@ -243,18 +240,18 @@ else if (!boiling && isHeated) { CrucibleRecipe recipe = CrucibleRegistry.find(steps); if (recipe != null) { // if recipe found - Networking.sendToTracking(world, pos, new CrucibleSuccessPacket(pos, steamR, steamG, steamB)); - double angle = world.rand.nextDouble() * Math.PI * 2; - ItemEntity entity = new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 0.75, pos.getZ() + 0.5, recipe.getResult().copy()); - entity.setMotion(Math.sin(angle) * 0.125, 0.25, Math.cos(angle) * 0.125); - entity.setPickupDelay(10); - world.addEntity(entity); + Networking.sendToTracking(level, worldPosition, new CrucibleSuccessPacket(worldPosition, steamR, steamG, steamB)); + double angle = level.random.nextDouble() * Math.PI * 2; + ItemEntity entity = new ItemEntity(level, worldPosition.getX() + 0.5, worldPosition.getY() + 0.75, worldPosition.getZ() + 0.5, recipe.getResult().copy()); + entity.setDeltaMovement(Math.sin(angle) * 0.125, 0.25, Math.cos(angle) * 0.125); + entity.setPickUpDelay(10); + level.addFreshEntity(entity); contents.clear(); steps.clear(); hasWater = boiling = false; } else { - world.playSound(null, pos, SoundEvents.BLOCK_BREWING_STAND_BREW, SoundCategory.BLOCKS, 1.0f, 1.0f); // try continue + level.playSound(null, worldPosition, SoundEvents.BREWING_STAND_BREW, SoundSource.BLOCKS, 1.0f, 1.0f); // try continue stepCounter = 100; } stirs = 0; @@ -263,9 +260,9 @@ else if (!boiling && isHeated) { } } - if (!world.isRemote && stepCounter == 0 && steps.size() == 0 - && hasWater && boiling && world.getGameTime() % 100 == 0) { - List items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(pos).shrink(0.125)); + if (!level.isClientSide && stepCounter == 0 && steps.size() == 0 + && hasWater && boiling && level.getGameTime() % 100 == 0) { + List items = level.getEntitiesOfClass(ItemEntity.class, new AABB(worldPosition).deflate(0.125)); if (items.size() > 0) stepCounter = 40; } } diff --git a/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java b/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java index 1b20736..b6adab3 100644 --- a/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java @@ -1,80 +1,68 @@ package elucent.eidolon.tile; -import com.ibm.icu.impl.data.ResourceReader; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.Eidolon; -import elucent.eidolon.ritual.CrystalRitual; -import elucent.eidolon.ritual.Ritual; -import elucent.eidolon.util.RenderUtil; -import net.minecraft.block.CauldronBlock; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureUtil; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.ColorHelper; -import net.minecraft.util.ColorHelper.PackedColor; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.world.biome.BiomeColors; - -import javax.annotation.Resource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.util.FastColor.ARGB32; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import net.minecraft.client.renderer.BiomeColors; -public class CrucibleTileRenderer extends TileEntityRenderer { - private final ModelRenderer stirrer; +public class CrucibleTileRenderer implements BlockEntityRenderer { +// private final ModelPart stirrer; public static final ResourceLocation STIRRER_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/block/crucible_stirrer.png"); - public CrucibleTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); - stirrer = new ModelRenderer(16, 16, 0, 0); - stirrer.setRotationPoint(0.0F, 0.0F, 0.0F); - stirrer.setTextureOffset(0, 8).addBox(-1.5F, 0.0F, -1.5F, 3.0F, 3.0F, 3.0F, 0.0F, false); - stirrer.setTextureOffset(0, 0).addBox(-1.0F, 3.0F, -1.0F, 2.0F, 6.0F, 2.0F, 0.0F, false); + public CrucibleTileRenderer() { +// stirrer = new ModelPart(16, 16, 0, 0); +// stirrer.setPos(0.0F, 0.0F, 0.0F); +// stirrer.texOffs(0, 8).addBox(-1.5F, 0.0F, -1.5F, 3.0F, 3.0F, 3.0F, 0.0F, false); +// stirrer.texOffs(0, 0).addBox(-1.0F, 3.0F, -1.0F, 2.0F, 6.0F, 2.0F, 0.0F, false); } @Override - public void render(CrucibleTileEntity tile, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { + public void render(CrucibleTileEntity tile, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { Minecraft mc = Minecraft.getInstance(); - mc.getTextureManager().bindTexture(STIRRER_TEXTURE); + RenderSystem.setShaderTexture(0, STIRRER_TEXTURE); float coeff = tile.stirTicks == 0 ? 0 : (tile.stirTicks - partialTicks) / 20.0f; - if (!tile.getWorld().getBlockState(tile.getPos().up()).isSolidSide(tile.getWorld(), tile.getPos().up(), Direction.DOWN)) { - matrixStackIn.push(); + if (!tile.getLevel().getBlockState(tile.getBlockPos().above()).isFaceSturdy(tile.getLevel(), tile.getBlockPos().above(), Direction.DOWN)) { + matrixStackIn.pushPose(); matrixStackIn.translate(0.5, 0.625, 0.5); - matrixStackIn.rotate(Vector3f.YP.rotationDegrees(45 + coeff * 360)); + matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(45 + coeff * 360)); matrixStackIn.translate(0, -0.125 * Math.sin(coeff * Math.PI), 0.125); - stirrer.rotateAngleX = (float) Math.PI / 8 * (1.0f - (float) Math.sin(coeff * Math.PI)); - stirrer.render(matrixStackIn, bufferIn.getBuffer(RenderType.getEntitySolid(STIRRER_TEXTURE)), combinedLightIn, combinedOverlayIn); - matrixStackIn.pop(); +// stirrer.xRot = (float) Math.PI / 8 * (1.0f - (float) Math.sin(coeff * Math.PI)); +// stirrer.render(matrixStackIn, bufferIn.getBuffer(RenderType.entitySolid(STIRRER_TEXTURE)), combinedLightIn, combinedOverlayIn); + matrixStackIn.popPose(); } if (tile.hasWater) { - CauldronBlock block; - TextureAtlasSprite water = mc.getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE) + TextureAtlasSprite water = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS) .apply(new ResourceLocation("minecraft", "block/water_still")); - IVertexBuilder builder = bufferIn.getBuffer(RenderType.getTranslucentNoCrumbling()); - Matrix4f mat = matrixStackIn.getLast().getMatrix(); - int color = BiomeColors.getWaterColor(tile.getWorld(), tile.getPos()); - int r = PackedColor.getRed(color), g = PackedColor.getGreen(color), - b = PackedColor.getBlue(color), a = PackedColor.getAlpha(color); + VertexConsumer builder = bufferIn.getBuffer(RenderType.translucentNoCrumbling()); + Matrix4f mat = matrixStackIn.last().pose(); + int color = BiomeColors.getAverageWaterColor(tile.getLevel(), tile.getBlockPos()); + int r = ARGB32.red(color), g = ARGB32.green(color), + b = ARGB32.blue(color), a = ARGB32.alpha(color); if (tile.steps.size() > 0) { r = (int)(tile.getRed() * 255); g = (int)(tile.getGreen() * 255); b = (int)(tile.getBlue() * 255); } - builder.pos(mat, 0.125f, 0.75f, 0.125f).color(r, g, b, 192).tex(water.getInterpolatedU(2), water.getInterpolatedV(2)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.125f, 0.75f, 0.875f).color(r, g, b, 192).tex(water.getInterpolatedU(14), water.getInterpolatedV(2)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.875f, 0.75f, 0.875f).color(r, g, b, 192).tex(water.getInterpolatedU(14), water.getInterpolatedV(14)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.875f, 0.75f, 0.125f).color(r, g, b, 192).tex(water.getInterpolatedU(2), water.getInterpolatedV(14)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.125f, 0.75f, 0.125f).color(r, g, b, 192).uv(water.getU(2), water.getV(2)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.125f, 0.75f, 0.875f).color(r, g, b, 192).uv(water.getU(14), water.getV(2)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.875f, 0.75f, 0.875f).color(r, g, b, 192).uv(water.getU(14), water.getV(14)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.875f, 0.75f, 0.125f).color(r, g, b, 192).uv(water.getU(2), water.getV(14)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); } } } diff --git a/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java b/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java index f6831d4..0999d4f 100644 --- a/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java @@ -1,18 +1,15 @@ package elucent.eidolon.tile; import elucent.eidolon.Registry; -import elucent.eidolon.ritual.RitualRegistry; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; public class EffigyTileEntity extends TileEntityBase { long previous = -1; - public EffigyTileEntity() { - super(Registry.EFFIGY_TILE_ENTITY); + public EffigyTileEntity(BlockPos pos, BlockState state) { + super(Registry.EFFIGY_TILE_ENTITY, pos, state); } public boolean ready() { @@ -20,21 +17,21 @@ public boolean ready() { } public void pray() { - if (!world.isRemote) { - previous = world.getGameTime(); + if (!level.isClientSide) { + previous = level.getGameTime(); sync(); } } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); + public void load(CompoundTag tag) { + super.load(tag); previous = tag.getLong("previous"); } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); tag.putLong("previous", previous); return tag; } diff --git a/src/main/java/elucent/eidolon/tile/GobletTileEntity.java b/src/main/java/elucent/eidolon/tile/GobletTileEntity.java index 0187677..e71056d 100644 --- a/src/main/java/elucent/eidolon/tile/GobletTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/GobletTileEntity.java @@ -1,21 +1,18 @@ package elucent.eidolon.tile; import elucent.eidolon.Registry; -import net.minecraft.block.BlockState; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.*; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.EntityType; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.registries.ForgeRegistries; public class GobletTileEntity extends TileEntityBase { EntityType type = null; - public GobletTileEntity() { - super(Registry.GOBLET_TILE_ENTITY); + public GobletTileEntity(BlockPos pos, BlockState state) { + super(Registry.GOBLET_TILE_ENTITY, pos, state); } public EntityType getEntityType() { @@ -28,15 +25,15 @@ public void setEntityType(EntityType type) { } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); + public void load(CompoundTag tag) { + super.load(tag); if (tag.contains("type")) type = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(tag.getString("type"))); else type = null; } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); if (type != null) tag.putString("type", type.getRegistryName().toString()); return tag; } diff --git a/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java b/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java index a886ff2..b96e361 100644 --- a/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java @@ -1,43 +1,35 @@ package elucent.eidolon.tile; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import elucent.eidolon.Eidolon; -import net.minecraft.block.CauldronBlock; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.model.ModelRenderer; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.ColorHelper.PackedColor; -import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.world.biome.BiomeColors; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.resources.ResourceLocation; +import com.mojang.math.Matrix4f; -public class GobletTileRenderer extends TileEntityRenderer { +public class GobletTileRenderer implements BlockEntityRenderer { - public GobletTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); - } + public GobletTileRenderer() {} @Override - public void render(GobletTileEntity tile, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { + public void render(GobletTileEntity tile, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { Minecraft mc = Minecraft.getInstance(); if (tile.getEntityType() != null) { - TextureAtlasSprite water = mc.getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE) + TextureAtlasSprite water = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS) .apply(new ResourceLocation("minecraft", "block/water_still")); - IVertexBuilder builder = bufferIn.getBuffer(RenderType.getTranslucentNoCrumbling()); - Matrix4f mat = matrixStackIn.getLast().getMatrix(); - builder.pos(mat, 0.375f, 0.46875f, 0.375f).color(192, 16, 32, 224).tex(water.getInterpolatedU(6), water.getInterpolatedV(6)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.375f, 0.46875f, 0.625f).color(192, 16, 32, 224).tex(water.getInterpolatedU(10), water.getInterpolatedV(6)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.625f, 0.46875f, 0.625f).color(192, 16, 32, 224).tex(water.getInterpolatedU(10), water.getInterpolatedV(10)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); - builder.pos(mat, 0.625f, 0.46875f, 0.375f).color(192, 16, 32, 224).tex(water.getInterpolatedU(6), water.getInterpolatedV(10)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex(); + VertexConsumer builder = bufferIn.getBuffer(RenderType.translucentNoCrumbling()); + Matrix4f mat = matrixStackIn.last().pose(); + builder.vertex(mat, 0.375f, 0.46875f, 0.375f).color(192, 16, 32, 224).uv(water.getU(6), water.getV(6)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.375f, 0.46875f, 0.625f).color(192, 16, 32, 224).uv(water.getU(10), water.getV(6)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.625f, 0.46875f, 0.625f).color(192, 16, 32, 224).uv(water.getU(10), water.getV(10)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); + builder.vertex(mat, 0.625f, 0.46875f, 0.375f).color(192, 16, 32, 224).uv(water.getU(6), water.getV(10)).uv2(combinedLightIn).normal(0, 1, 0).endVertex(); } } } diff --git a/src/main/java/elucent/eidolon/tile/HandTileEntity.java b/src/main/java/elucent/eidolon/tile/HandTileEntity.java index a4fc682..e358f72 100644 --- a/src/main/java/elucent/eidolon/tile/HandTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/HandTileEntity.java @@ -2,64 +2,63 @@ import elucent.eidolon.Registry; import elucent.eidolon.ritual.IRitualItemProvider; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.Containers; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; public class HandTileEntity extends TileEntityBase implements IRitualItemProvider { ItemStack stack = ItemStack.EMPTY; - public HandTileEntity() { - this(Registry.HAND_TILE_ENTITY); + public HandTileEntity(BlockPos pos, BlockState state) { + this(Registry.HAND_TILE_ENTITY, pos, state); } - public HandTileEntity(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); + public HandTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state); } @Override public void onDestroyed(BlockState state, BlockPos pos) { - if (!stack.isEmpty()) InventoryHelper.spawnItemStack(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); + if (!stack.isEmpty()) Containers.dropItemStack(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); } @Override - public ActionResultType onActivated(BlockState state, BlockPos pos, PlayerEntity player, Hand hand) { - if (hand == Hand.MAIN_HAND) { - if (player.getHeldItem(hand).isEmpty() && !stack.isEmpty()) { - player.addItemStackToInventory(stack); + public InteractionResult onActivated(BlockState state, BlockPos pos, Player player, InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + if (player.getItemInHand(hand).isEmpty() && !stack.isEmpty()) { + player.addItem(stack); stack = ItemStack.EMPTY; - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } - else if (!player.getHeldItem(hand).isEmpty() && stack.isEmpty()) { - stack = player.getHeldItem(hand).copy(); + else if (!player.getItemInHand(hand).isEmpty() && stack.isEmpty()) { + stack = player.getItemInHand(hand).copy(); stack.setCount(1); - player.getHeldItem(hand).shrink(1); - if (player.getHeldItem(hand).isEmpty()) player.setHeldItem(hand, ItemStack.EMPTY); - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + player.getItemInHand(hand).shrink(1); + if (player.getItemInHand(hand).isEmpty()) player.setItemInHand(hand, ItemStack.EMPTY); + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } } - return ActionResultType.PASS; + return InteractionResult.PASS; } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); - stack = ItemStack.read(tag.getCompound("stack")); + public void load(CompoundTag tag) { + super.load(tag); + stack = ItemStack.of(tag.getCompound("stack")); } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); - tag.put("stack", stack.write(new CompoundNBT())); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); + tag.put("stack", stack.save(new CompoundTag())); return tag; } @@ -71,6 +70,6 @@ public ItemStack provide() { @Override public void take() { stack = ItemStack.EMPTY; - if (!world.isRemote) sync(); + if (!level.isClientSide) sync(); } } diff --git a/src/main/java/elucent/eidolon/tile/HandTileRenderer.java b/src/main/java/elucent/eidolon/tile/HandTileRenderer.java index 24be70f..dac242c 100644 --- a/src/main/java/elucent/eidolon/tile/HandTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/HandTileRenderer.java @@ -1,32 +1,28 @@ package elucent.eidolon.tile; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.client.renderer.model.ItemCameraTransforms; -import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Quaternion; -import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import com.mojang.math.Vector3f; -public class HandTileRenderer extends TileEntityRenderer { - public HandTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); - } +public class HandTileRenderer implements BlockEntityRenderer { + public HandTileRenderer() {} @Override - public void render(HandTileEntity tileEntityIn, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { + public void render(HandTileEntity tileEntityIn, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { Minecraft mc = Minecraft.getInstance(); ItemRenderer ir = mc.getItemRenderer(); if (!tileEntityIn.stack.isEmpty()) { - matrixStackIn.push(); + matrixStackIn.pushPose(); matrixStackIn.translate(0.5,0.9375, 0.5); - matrixStackIn.rotate(Vector3f.YP.rotationDegrees(3 * (mc.world.getGameTime() % 360 + partialTicks))); - ir.renderItem(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn); - matrixStackIn.pop(); + matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(3 * (mc.level.getGameTime() % 360 + partialTicks))); + ir.renderStatic(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn, 0); + matrixStackIn.popPose(); } } } diff --git a/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java b/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java index 8ba0d21..c1d7162 100644 --- a/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java @@ -2,64 +2,63 @@ import elucent.eidolon.Registry; import elucent.eidolon.ritual.IRitualItemFocus; -import elucent.eidolon.ritual.IRitualItemProvider; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.Containers; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; public class NecroticFocusTileEntity extends TileEntityBase implements IRitualItemFocus { ItemStack stack = ItemStack.EMPTY; - public NecroticFocusTileEntity() { - this(Registry.NECROTIC_FOCUS_TILE_ENTITY); + public NecroticFocusTileEntity(BlockPos pos, BlockState state) { + this(Registry.NECROTIC_FOCUS_TILE_ENTITY, pos, state); } - public NecroticFocusTileEntity(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); + public NecroticFocusTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state); } @Override public void onDestroyed(BlockState state, BlockPos pos) { - if (!stack.isEmpty()) InventoryHelper.spawnItemStack(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); + if (!stack.isEmpty()) Containers.dropItemStack(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); } @Override - public ActionResultType onActivated(BlockState state, BlockPos pos, PlayerEntity player, Hand hand) { - if (hand == Hand.MAIN_HAND) { - if (player.getHeldItem(hand).isEmpty() && !stack.isEmpty()) { - player.addItemStackToInventory(stack); + public InteractionResult onActivated(BlockState state, BlockPos pos, Player player, InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + if (player.getItemInHand(hand).isEmpty() && !stack.isEmpty()) { + player.addItem(stack); stack = ItemStack.EMPTY; - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } - else if (!player.getHeldItem(hand).isEmpty() && stack.isEmpty()) { - stack = player.getHeldItem(hand).copy(); + else if (!player.getItemInHand(hand).isEmpty() && stack.isEmpty()) { + stack = player.getItemInHand(hand).copy(); stack.setCount(1); - player.getHeldItem(hand).shrink(1); - if (player.getHeldItem(hand).isEmpty()) player.setHeldItem(hand, ItemStack.EMPTY); - if (!world.isRemote) sync(); - return ActionResultType.SUCCESS; + player.getItemInHand(hand).shrink(1); + if (player.getItemInHand(hand).isEmpty()) player.setItemInHand(hand, ItemStack.EMPTY); + if (!level.isClientSide) sync(); + return InteractionResult.SUCCESS; } } - return ActionResultType.PASS; + return InteractionResult.PASS; } @Override - public void read(BlockState state, CompoundNBT tag) { - super.read(state, tag); - stack = ItemStack.read(tag.getCompound("stack")); + public void load(CompoundTag tag) { + super.load(tag); + stack = ItemStack.of(tag.getCompound("stack")); } @Override - public CompoundNBT write(CompoundNBT tag) { - tag = super.write(tag); - tag.put("stack", stack.write(new CompoundNBT())); + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); + tag.put("stack", stack.save(new CompoundTag())); return tag; } @@ -71,6 +70,6 @@ public ItemStack provide() { @Override public void take() { stack = ItemStack.EMPTY; - if (!world.isRemote) sync(); + if (!level.isClientSide) sync(); } } diff --git a/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java b/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java index 0acf73c..43adea3 100644 --- a/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java @@ -1,32 +1,31 @@ package elucent.eidolon.tile; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.PoseStack; + import elucent.eidolon.block.HorizontalBlockBase; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.Direction; -import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.core.Direction; +import com.mojang.math.Vector3f; -public class NecroticFocusTileRenderer extends TileEntityRenderer { - public NecroticFocusTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); - } +public class NecroticFocusTileRenderer implements BlockEntityRenderer { + public NecroticFocusTileRenderer() {} @Override - public void render(NecroticFocusTileEntity tileEntityIn, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { + public void render(NecroticFocusTileEntity tileEntityIn, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { Minecraft mc = Minecraft.getInstance(); ItemRenderer ir = mc.getItemRenderer(); if (!tileEntityIn.stack.isEmpty()) { - matrixStackIn.push(); - Direction dir = tileEntityIn.getWorld().getBlockState(tileEntityIn.getPos()).get(HorizontalBlockBase.HORIZONTAL_FACING); - matrixStackIn.translate(0.5 + dir.getXOffset() * 0.25,0.5 + dir.getYOffset() * 0.25, 0.5 + dir.getZOffset() * 0.25); - matrixStackIn.rotate(Vector3f.YP.rotationDegrees(3 * (mc.world.getGameTime() % 360 + partialTicks))); - ir.renderItem(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn); - matrixStackIn.pop(); + matrixStackIn.pushPose(); + Direction dir = tileEntityIn.getLevel().getBlockState(tileEntityIn.getBlockPos()).getValue(HorizontalBlockBase.HORIZONTAL_FACING); + matrixStackIn.translate(0.5 + dir.getStepX() * 0.25,0.5 + dir.getStepY() * 0.25, 0.5 + dir.getStepZ() * 0.25); + matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(3 * (mc.level.getGameTime() % 360 + partialTicks))); + ir.renderStatic(tileEntityIn.stack, TransformType.GROUND, combinedLightIn, combinedOverlayIn, matrixStackIn, bufferIn, 0); + matrixStackIn.popPose(); } } } diff --git a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileEntity.java b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileEntity.java index 1d1a5de..62aea5f 100644 --- a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileEntity.java @@ -1,59 +1,52 @@ package elucent.eidolon.tile; -import elucent.eidolon.Registry; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.tileentity.ITickableTileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; - import java.util.Random; -public class SoulEnchanterTileEntity extends TileEntityBase implements ITickableTileEntity { - public float field_195523_f; - public float field_195524_g; - public float field_195525_h; - public float field_195526_i; +import elucent.eidolon.Registry; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; + +public class SoulEnchanterTileEntity extends TileEntityBase { + public float flip; + public float oFlip; + public float flipT; + public float flipA; public float nextPageTurningSpeed; public float pageTurningSpeed; public float nextPageAngle; public float pageAngle; - public float field_195531_n; + public float tRot; private static final Random random = new Random(); - public SoulEnchanterTileEntity() { - this(Registry.SOUL_ENCHANTER_TILE_ENTITY); + public SoulEnchanterTileEntity(BlockPos pos, BlockState state) { + this(Registry.SOUL_ENCHANTER_TILE_ENTITY, pos, state); } - public SoulEnchanterTileEntity(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); + public SoulEnchanterTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state); } - @Override public void tick() { this.pageTurningSpeed = this.nextPageTurningSpeed; this.pageAngle = this.nextPageAngle; - PlayerEntity playerentity = this.world.getClosestPlayer((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D, 3.0D, false); + Player playerentity = this.level.getNearestPlayer((double)this.worldPosition.getX() + 0.5D, (double)this.worldPosition.getY() + 0.5D, (double)this.worldPosition.getZ() + 0.5D, 3.0D, false); if (playerentity != null) { - double d0 = playerentity.getPosX() - ((double)this.pos.getX() + 0.5D); - double d1 = playerentity.getPosZ() - ((double)this.pos.getZ() + 0.5D); - this.field_195531_n = (float) MathHelper.atan2(d1, d0); + double d0 = playerentity.getX() - ((double)this.worldPosition.getX() + 0.5D); + double d1 = playerentity.getZ() - ((double)this.worldPosition.getZ() + 0.5D); + this.tRot = (float) Mth.atan2(d1, d0); this.nextPageTurningSpeed += 0.1F; if (this.nextPageTurningSpeed < 0.5F || random.nextInt(40) == 0) { - float f1 = this.field_195525_h; + float f1 = this.flipT; do { - this.field_195525_h += (float)(random.nextInt(4) - random.nextInt(4)); - } while(f1 == this.field_195525_h); + this.flipT += (float)(random.nextInt(4) - random.nextInt(4)); + } while(f1 == this.flipT); } } else { - this.field_195531_n += 0.02F; + this.tRot += 0.02F; this.nextPageTurningSpeed -= 0.1F; } @@ -65,16 +58,16 @@ public void tick() { this.nextPageAngle += ((float)Math.PI * 2F); } - while(this.field_195531_n >= (float)Math.PI) { - this.field_195531_n -= ((float)Math.PI * 2F); + while(this.tRot >= (float)Math.PI) { + this.tRot -= ((float)Math.PI * 2F); } - while(this.field_195531_n < -(float)Math.PI) { - this.field_195531_n += ((float)Math.PI * 2F); + while(this.tRot < -(float)Math.PI) { + this.tRot += ((float)Math.PI * 2F); } float f2; - for(f2 = this.field_195531_n - this.nextPageAngle; f2 >= (float)Math.PI; f2 -= ((float)Math.PI * 2F)) { + for(f2 = this.tRot - this.nextPageAngle; f2 >= (float)Math.PI; f2 -= ((float)Math.PI * 2F)) { } while(f2 < -(float)Math.PI) { @@ -82,12 +75,12 @@ public void tick() { } this.nextPageAngle += f2 * 0.4F; - this.nextPageTurningSpeed = MathHelper.clamp(this.nextPageTurningSpeed, 0.0F, 1.0F); - this.field_195524_g = this.field_195523_f; - float f = (this.field_195525_h - this.field_195523_f) * 0.4F; + this.nextPageTurningSpeed = Mth.clamp(this.nextPageTurningSpeed, 0.0F, 1.0F); + this.oFlip = this.flip; + float f = (this.flipT - this.flip) * 0.4F; float f3 = 0.2F; - f = MathHelper.clamp(f, -0.2F, 0.2F); - this.field_195526_i += (f - this.field_195526_i) * 0.9F; - this.field_195523_f += this.field_195526_i; + f = Mth.clamp(f, -0.2F, 0.2F); + this.flipA += (f - this.flipA) * 0.9F; + this.flip += this.flipA; } } diff --git a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java index 5353f09..a51a372 100644 --- a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java @@ -1,38 +1,38 @@ package elucent.eidolon.tile; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; -import elucent.eidolon.block.HorizontalBlockBase; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.model.BookModel; -import net.minecraft.client.renderer.model.RenderMaterial; -import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3f; - -public class SoulEnchanterTileRenderer extends TileEntityRenderer { +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.BookModel; +import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.client.resources.model.Material; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import com.mojang.math.Vector3f; + +public class SoulEnchanterTileRenderer implements BlockEntityRenderer { public static final ResourceLocation BOOK_TEXTURE = new ResourceLocation(Eidolon.MODID, "entity/enchanter_book"); - public static final RenderMaterial BOOK_MATERIAL = new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, BOOK_TEXTURE); - private final BookModel model = new BookModel(); + public static final Material BOOK_MATERIAL = new Material(TextureAtlas.LOCATION_BLOCKS, BOOK_TEXTURE); + private final BookModel model; - public SoulEnchanterTileRenderer(TileEntityRendererDispatcher rendererDispatcherIn) { - super(rendererDispatcherIn); + public SoulEnchanterTileRenderer() { + model = new BookModel(Minecraft.getInstance().getEntityModels().bakeLayer(ModelLayers.BOOK)); } @Override - public void render(SoulEnchanterTileEntity tileEntityIn, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) { - matrixStackIn.push(); + public void render(SoulEnchanterTileEntity tileEntityIn, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { + matrixStackIn.pushPose(); matrixStackIn.translate(0.5D, 0.75D, 0.5D); float f = ClientEvents.getClientTicks(); - matrixStackIn.translate(0.0D, (double)(0.1F + MathHelper.sin(f * 0.1F) * 0.01F), 0.0D); + matrixStackIn.translate(0.0D, (double)(0.1F + Mth.sin(f * 0.1F) * 0.01F), 0.0D); float f1; for(f1 = tileEntityIn.nextPageAngle - tileEntityIn.pageAngle; f1 >= (float)Math.PI; f1 -= ((float)Math.PI * 2F)) { @@ -43,15 +43,15 @@ public void render(SoulEnchanterTileEntity tileEntityIn, float partialTicks, Mat } float f2 = tileEntityIn.pageAngle + f1 * partialTicks; - matrixStackIn.rotate(Vector3f.YP.rotation(-f2)); - matrixStackIn.rotate(Vector3f.ZP.rotationDegrees(80.0F)); - float f3 = MathHelper.lerp(partialTicks, tileEntityIn.field_195524_g, tileEntityIn.field_195523_f); - float f4 = MathHelper.frac(f3 + 0.25F) * 1.6F - 0.3F; - float f5 = MathHelper.frac(f3 + 0.75F) * 1.6F - 0.3F; - float f6 = MathHelper.lerp(partialTicks, tileEntityIn.pageTurningSpeed, tileEntityIn.nextPageTurningSpeed); - this.model.setBookState(f, MathHelper.clamp(f4, 0.0F, 1.0F), MathHelper.clamp(f5, 0.0F, 1.0F), f6); - IVertexBuilder ivertexbuilder = BOOK_MATERIAL.getBuffer(bufferIn, RenderType::getEntitySolid); - this.model.renderAll(matrixStackIn, ivertexbuilder, combinedLightIn, combinedOverlayIn, 1.0F, 1.0F, 1.0F, 1.0F); - matrixStackIn.pop(); + matrixStackIn.mulPose(Vector3f.YP.rotation(-f2)); + matrixStackIn.mulPose(Vector3f.ZP.rotationDegrees(80.0F)); + float f3 = Mth.lerp(partialTicks, tileEntityIn.oFlip, tileEntityIn.flip); + float f4 = Mth.frac(f3 + 0.25F) * 1.6F - 0.3F; + float f5 = Mth.frac(f3 + 0.75F) * 1.6F - 0.3F; + float f6 = Mth.lerp(partialTicks, tileEntityIn.pageTurningSpeed, tileEntityIn.nextPageTurningSpeed); + this.model.setupAnim(f, Mth.clamp(f4, 0.0F, 1.0F), Mth.clamp(f5, 0.0F, 1.0F), f6); + VertexConsumer ivertexbuilder = BOOK_MATERIAL.buffer(bufferIn, RenderType::entitySolid); + this.model.render(matrixStackIn, ivertexbuilder, combinedLightIn, combinedOverlayIn, 1.0F, 1.0F, 1.0F, 1.0F); + matrixStackIn.popPose(); } } diff --git a/src/main/java/elucent/eidolon/tile/TileEntityBase.java b/src/main/java/elucent/eidolon/tile/TileEntityBase.java index 2e6ecda..ce922da 100644 --- a/src/main/java/elucent/eidolon/tile/TileEntityBase.java +++ b/src/main/java/elucent/eidolon/tile/TileEntityBase.java @@ -2,54 +2,52 @@ import elucent.eidolon.network.Networking; import elucent.eidolon.network.TESyncPacket; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.play.server.SUpdateTileEntityPacket; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; -import net.minecraftforge.fml.network.PacketDistributor; - -public class TileEntityBase extends TileEntity { - public TileEntityBase(TileEntityType tileEntityTypeIn) { - super(tileEntityTypeIn); +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.network.PacketDistributor; +import net.minecraft.world.entity.player.Player; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; + +public class TileEntityBase extends BlockEntity { + public TileEntityBase(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state); } public void onDestroyed(BlockState state, BlockPos pos) { invalidateCaps(); } - public ActionResultType onActivated(BlockState state, BlockPos pos, PlayerEntity player, Hand hand) { - return ActionResultType.PASS; + public InteractionResult onActivated(BlockState state, BlockPos pos, Player player, InteractionHand hand) { + return InteractionResult.PASS; } public void sync() { - markDirty(); - if (world.isRemote) - Networking.INSTANCE.sendToServer(new TESyncPacket(pos, write(new CompoundNBT()))); + setChanged(); + if (level.isClientSide) + Networking.INSTANCE.sendToServer(new TESyncPacket(worldPosition, save(new CompoundTag()))); else - Networking.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), new TESyncPacket(pos, write(new CompoundNBT()))); + Networking.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(worldPosition)), new TESyncPacket(worldPosition, save(new CompoundTag()))); } @Override - public CompoundNBT getUpdateTag() { - return this.write(new CompoundNBT()); + public CompoundTag getUpdateTag() { + return this.save(new CompoundTag()); } @Override - public SUpdateTileEntityPacket getUpdatePacket() { - return new SUpdateTileEntityPacket(this.pos, 3, this.getUpdateTag()); + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); // (this.worldPosition, 3, this.getUpdateTag()); } @Override - public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) { + public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { super.onDataPacket(net, pkt); - handleUpdateTag(world.getBlockState(pkt.getPos()), pkt.getNbtCompound()); + handleUpdateTag(pkt.getTag()); } } diff --git a/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java b/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java index 284bfeb..ef7beb9 100644 --- a/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java @@ -1,41 +1,37 @@ package elucent.eidolon.tile; +import java.util.Arrays; + +import javax.annotation.Nullable; + import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.block.WoodenStandBlock; import elucent.eidolon.gui.WoodenBrewingStandContainer; -import net.minecraft.block.BlockState; -import net.minecraft.block.BrewingStandBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.ISidedInventory; -import net.minecraft.inventory.InventoryHelper; -import net.minecraft.inventory.ItemStackHelper; -import net.minecraft.inventory.container.Container; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.potion.PotionBrewing; -import net.minecraft.tileentity.ITickableTileEntity; -import net.minecraft.tileentity.LockableTileEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.IIntArray; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.world.IBlockReader; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.BrewingStandBlock; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.WorldlyContainer; +import net.minecraft.world.Containers; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.alchemy.PotionBrewing; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.core.Direction; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.core.NonNullList; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraftforge.common.Tags; -import net.minecraftforge.common.brewing.BrewingRecipeRegistry; -import javax.annotation.Nullable; -import java.util.Arrays; - -public class WoodenStandTileEntity extends LockableTileEntity implements ISidedInventory, ITickableTileEntity { +public class WoodenStandTileEntity extends BaseContainerBlockEntity implements WorldlyContainer { private static final int[] SLOTS_FOR_UP = new int[]{3}; private static final int[] SLOTS_FOR_DOWN = new int[]{0, 1, 2, 3}; private static final int[] OUTPUT_SLOTS = new int[]{0, 1, 2}; @@ -43,7 +39,7 @@ public class WoodenStandTileEntity extends LockableTileEntity implements ISidedI private int brewTime, heat; private boolean[] filledSlots; private Item ingredientID; - public final IIntArray field_213954_a = new IIntArray() { + public final ContainerData dataAccess = new ContainerData() { public int get(int index) { switch(index) { case 0: @@ -65,22 +61,22 @@ public void set(int index, int value) { } } - public int size() { + public int getCount() { return 2; } }; - public WoodenStandTileEntity() { - super(Registry.WOODEN_STAND_TILE_ENTITY); + public WoodenStandTileEntity(BlockPos pos, BlockState state) { + super(Registry.WOODEN_STAND_TILE_ENTITY, pos, state); } @Override - protected ITextComponent getDefaultName() { - return new TranslationTextComponent("container." + Eidolon.MODID + ".wooden_brewing_stand"); + protected Component getDefaultName() { + return new TranslatableComponent("container." + Eidolon.MODID + ".wooden_brewing_stand"); } @Override - public int getSizeInventory() { + public int getContainerSize() { return this.brewingItemStacks.size(); } @@ -95,17 +91,16 @@ public boolean isEmpty() { return true; } - @Override public void tick() { boolean flag = this.canBrew(); boolean flag1 = this.brewTime > 0; ItemStack itemstack1 = this.brewingItemStacks.get(3); - if (world.getGameTime() % 20 == 0) { - TileEntity below = world.getTileEntity(pos.down()); + if (level.getGameTime() % 20 == 0) { + BlockEntity below = level.getBlockEntity(worldPosition.below()); if (below instanceof CrucibleTileEntity) { int prevHeat = heat; heat = ((CrucibleTileEntity)below).boiling ? 1 : 0; - if (prevHeat != heat) markDirty(); + if (prevHeat != heat) setChanged(); } } if (flag1) { @@ -113,34 +108,34 @@ public void tick() { boolean flag2 = this.brewTime == 0; if (flag2 && flag) { this.brewPotions(); - this.markDirty(); + this.setChanged(); } else if (!flag || heat == 0) { this.brewTime = 0; - this.markDirty(); + this.setChanged(); } else if (this.ingredientID != itemstack1.getItem()) { this.brewTime = 0; - this.markDirty(); + this.setChanged(); } } else if (flag && heat > 0) { this.brewTime = 800; this.ingredientID = itemstack1.getItem(); - this.markDirty(); + this.setChanged(); } - if (!this.world.isRemote) { + if (!this.level.isClientSide) { boolean[] aboolean = this.createFilledSlotsArray(); if (!Arrays.equals(aboolean, this.filledSlots)) { this.filledSlots = aboolean; - BlockState blockstate = this.world.getBlockState(this.getPos()); + BlockState blockstate = this.level.getBlockState(this.getBlockPos()); if (!(blockstate.getBlock() instanceof WoodenStandBlock)) { return; } for(int i = 0; i < BrewingStandBlock.HAS_BOTTLE.length; ++i) { - blockstate = blockstate.with(BrewingStandBlock.HAS_BOTTLE[i], Boolean.valueOf(aboolean[i])); + blockstate = blockstate.setValue(BrewingStandBlock.HAS_BOTTLE[i], Boolean.valueOf(aboolean[i])); } - this.world.setBlockState(this.pos, blockstate, 2); + this.level.setBlock(this.worldPosition, blockstate, 2); } } } @@ -162,12 +157,12 @@ private boolean canBrew() { if (!itemstack.isEmpty()) return net.minecraftforge.common.brewing.BrewingRecipeRegistry.canBrew(brewingItemStacks, itemstack, OUTPUT_SLOTS); // divert to VanillaBrewingRegistry if (itemstack.isEmpty()) { return false; - } else if (!PotionBrewing.isReagent(itemstack)) { + } else if (!PotionBrewing.isIngredient(itemstack)) { return false; } else { for(int i = 0; i < 3; ++i) { ItemStack itemstack1 = this.brewingItemStacks.get(i); - if (!itemstack1.isEmpty() && PotionBrewing.hasConversions(itemstack1, itemstack)) { + if (!itemstack1.isEmpty() && PotionBrewing.hasMix(itemstack1, itemstack)) { return true; } } @@ -182,55 +177,55 @@ private void brewPotions() { net.minecraftforge.common.brewing.BrewingRecipeRegistry.brewPotions(brewingItemStacks, itemstack, OUTPUT_SLOTS); net.minecraftforge.event.ForgeEventFactory.onPotionBrewed(brewingItemStacks); - BlockPos blockpos = this.getPos(); + BlockPos blockpos = this.getBlockPos(); if (itemstack.hasContainerItem()) { ItemStack itemstack1 = itemstack.getContainerItem(); itemstack.shrink(1); if (itemstack.isEmpty()) { itemstack = itemstack1; - } else if (!this.world.isRemote) { - InventoryHelper.spawnItemStack(this.world, (double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ(), itemstack1); + } else if (!this.level.isClientSide) { + Containers.dropItemStack(this.level, (double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ(), itemstack1); } } else itemstack.shrink(1); this.brewingItemStacks.set(3, itemstack); - this.world.playEvent(1035, blockpos, 0); + this.level.levelEvent(1035, blockpos, 0); } @Override - public void read(BlockState state, CompoundNBT nbt) { - super.read(state, nbt); - this.brewingItemStacks = NonNullList.withSize(this.getSizeInventory(), ItemStack.EMPTY); - ItemStackHelper.loadAllItems(nbt, this.brewingItemStacks); + public void load(CompoundTag nbt) { + super.load(nbt); + this.brewingItemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + ContainerHelper.loadAllItems(nbt, this.brewingItemStacks); this.brewTime = nbt.getShort("BrewTime"); } @Override - public CompoundNBT write(CompoundNBT compound) { - super.write(compound); + public CompoundTag save(CompoundTag compound) { + super.save(compound); compound.putShort("BrewTime", (short)this.brewTime); - ItemStackHelper.saveAllItems(compound, this.brewingItemStacks); + ContainerHelper.saveAllItems(compound, this.brewingItemStacks); return compound; } @Override - public ItemStack getStackInSlot(int index) { + public ItemStack getItem(int index) { return index >= 0 && index < this.brewingItemStacks.size() ? this.brewingItemStacks.get(index) : ItemStack.EMPTY; } @Override - public ItemStack decrStackSize(int index, int count) { - return ItemStackHelper.getAndSplit(this.brewingItemStacks, index, count); + public ItemStack removeItem(int index, int count) { + return ContainerHelper.removeItem(this.brewingItemStacks, index, count); } @Override - public ItemStack removeStackFromSlot(int index) { - return ItemStackHelper.getAndRemove(this.brewingItemStacks, index); + public ItemStack removeItemNoUpdate(int index) { + return ContainerHelper.takeItem(this.brewingItemStacks, index); } @Override - public void setInventorySlotContents(int index, ItemStack stack) { + public void setItem(int index, ItemStack stack) { if (index >= 0 && index < this.brewingItemStacks.size()) { this.brewingItemStacks.set(index, stack); } @@ -238,22 +233,22 @@ public void setInventorySlotContents(int index, ItemStack stack) { } @Override - public boolean isUsableByPlayer(PlayerEntity player) { - if (this.world.getTileEntity(this.pos) != this) { + public boolean stillValid(Player player) { + if (this.level.getBlockEntity(this.worldPosition) != this) { return false; } else { - return !(player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) > 64.0D); + return !(player.distanceToSqr((double)this.worldPosition.getX() + 0.5D, (double)this.worldPosition.getY() + 0.5D, (double)this.worldPosition.getZ() + 0.5D) > 64.0D); } } @Override - public boolean isItemValidForSlot(int index, ItemStack stack) { + public boolean canPlaceItem(int index, ItemStack stack) { if (index == 3) { return net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidIngredient(stack) && !Tags.Items.DUSTS_REDSTONE.contains(stack.getItem()) && !Tags.Items.DUSTS_GLOWSTONE.contains(stack.getItem()); } else { - return net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidInput(stack) && this.getStackInSlot(index).isEmpty(); + return net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidInput(stack) && this.getItem(index).isEmpty(); } } @@ -267,12 +262,12 @@ public int[] getSlotsForFace(Direction side) { } @Override - public boolean canInsertItem(int index, ItemStack itemStackIn, @Nullable Direction direction) { - return this.isItemValidForSlot(index, itemStackIn); + public boolean canPlaceItemThroughFace(int index, ItemStack itemStackIn, @Nullable Direction direction) { + return this.canPlaceItem(index, itemStackIn); } @Override - public boolean canExtractItem(int index, ItemStack stack, Direction direction) { + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { if (index == 3) { return stack.getItem() == Items.GLASS_BOTTLE; } else { @@ -281,13 +276,13 @@ public boolean canExtractItem(int index, ItemStack stack, Direction direction) { } @Override - public void clear() { + public void clearContent() { this.brewingItemStacks.clear(); } @Override - public Container createMenu(int id, PlayerInventory player) { - return new WoodenBrewingStandContainer(id, player, this, this.field_213954_a); + public AbstractContainerMenu createMenu(int id, Inventory player) { + return new WoodenBrewingStandContainer(id, player, this, this.dataAccess); } net.minecraftforge.common.util.LazyOptional[] handlers = @@ -295,7 +290,7 @@ public Container createMenu(int id, PlayerInventory player) { @Override public net.minecraftforge.common.util.LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { - if (!this.removed && facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + if (!this.remove && facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { if (facing == Direction.UP) return handlers[0].cast(); else if (facing == Direction.DOWN) @@ -307,8 +302,8 @@ else if (facing == Direction.DOWN) } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); for (int x = 0; x < handlers.length; x++) handlers[x].invalidate(); } diff --git a/src/main/java/elucent/eidolon/tile/reagent/CisternTileEntity.java b/src/main/java/elucent/eidolon/tile/reagent/CisternTileEntity.java new file mode 100644 index 0000000..098a640 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/reagent/CisternTileEntity.java @@ -0,0 +1,83 @@ +package elucent.eidolon.tile.reagent; + +import elucent.eidolon.Registry; +import elucent.eidolon.block.PillarBlockBase; +import elucent.eidolon.reagent.ReagentStack; +import elucent.eidolon.reagent.ReagentTank; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +public class CisternTileEntity extends ReagentTankTileEntity { + float upPressure = 0, downPressure = 0; + + public static class CisternTank extends ReagentTank { + public CisternTileEntity tile; + + public CisternTank(CisternTileEntity tile, int capacity) { + super(capacity); + this.tile = tile; + } + + @Override + public boolean canFill(ReagentStack stack) { + CisternTileEntity t = tile; + while (t.getBlockState().getValue(PillarBlockBase.BOTTOM)) { + BlockEntity nt = t.level.getBlockEntity(t.worldPosition.below()); + if (nt instanceof CisternTileEntity) t = (CisternTileEntity)nt; + else break; + } + return t.tank.getContents().isEmpty() || t.tank.getContents().reagent == stack.reagent; + } + } + + public CisternTileEntity(BlockPos pos, BlockState state) { + this(Registry.CISTERN_TILE_ENTITY, pos, state); + } + + public CisternTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state, 2048); + tank = new CisternTank(this, 2048); + // tank.fill(world, pos, new ReagentStack(ReagentRegistry.CRIMSOL, 2048)); + } + + @Override + public void tick() { + downPressure = upPressure = 0; + if (getBlockState().getValue(PillarBlockBase.BOTTOM)) { + BlockEntity t = level.getBlockEntity(worldPosition.below()); + if (t instanceof CisternTileEntity) + downPressure = ((CisternTileEntity)t).tank.getPressure(); + if (t instanceof CisternTileEntity + && ((CisternTileEntity)t).tank.getContents().amount < ((CisternTileEntity)t).tank.getCapacity() + && tank.getContents().amount > 0) { + CisternTileEntity c = (CisternTileEntity)t; + int change = tank.getContents().amount; + if (c.tank.getContents().amount + change > c.tank.getCapacity()) + change = c.tank.getCapacity() - c.tank.getContents().amount; + c.tank.fill(level, worldPosition, new ReagentStack(tank.getContents().reagent, change)); + tank.getContents().amount -= change; + c.onContentsChanged(); + onContentsChanged(); + } + } + if (getBlockState().getValue(PillarBlockBase.TOP)) { + BlockEntity t = level.getBlockEntity(worldPosition.above()); + if (t instanceof CisternTileEntity) + upPressure = ((CisternTileEntity)t).tank.getPressure(); + } + super.tick(); + } + + @Override + public boolean isOutput(Direction direction) { + return level.getBlockEntity(worldPosition.relative(direction)) instanceof PipeTileEntity; + } + + @Override + public boolean isInput(Direction direction) { + return true; + } +} diff --git a/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java b/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java new file mode 100644 index 0000000..af454b4 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java @@ -0,0 +1,40 @@ +package elucent.eidolon.tile.reagent; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.block.PillarBlockBase; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; + +public class CisternTileRenderer implements BlockEntityRenderer { + + public CisternTileRenderer() {} + + @Override + public void render(CisternTileEntity tile, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { + Minecraft mc = Minecraft.getInstance(); + if (tile.getBlockState().getValue(PillarBlockBase.BOTTOM) && tile.downPressure < 1 && tile.tank.getPressure() < 1 / 64f) return; + if (tile.tank.getContents().amount == 0) return; + TextureAtlasSprite water = tile.tank.getContents().reagent.getSprite(); + float fill = (float)tile.tank.getContents().amount / tile.tank.getCapacity(); + if (fill > 1) fill = 1; + float h = 0.625f + + (tile.getBlockState().getValue(PillarBlockBase.BOTTOM) ? 0.1875f : 0) + + (tile.getBlockState().getValue(PillarBlockBase.TOP) ? 0.1875f : 0); + float yoff = tile.getBlockState().getValue(PillarBlockBase.BOTTOM) ? 0 : 0.1875f; + VertexConsumer builder = ClientEvents.getDelayedRender().getBuffer(RenderUtil.VAPOR_TRANSLUCENT); + RenderUtil.vaporCube(matrixStackIn, builder, water, + 0.125f, yoff, 0.125f, + 0.875f, yoff + h * fill, 0.875f, + 255, 255, 255, 255, combinedLightIn, + true, true, + !tile.getBlockState().getValue(PillarBlockBase.BOTTOM), + fill < 1 || tile.upPressure == 0, true, true); + } +} diff --git a/src/main/java/elucent/eidolon/tile/reagent/PipeTileEntity.java b/src/main/java/elucent/eidolon/tile/reagent/PipeTileEntity.java new file mode 100644 index 0000000..25dbebf --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/reagent/PipeTileEntity.java @@ -0,0 +1,29 @@ +package elucent.eidolon.tile.reagent; + +import elucent.eidolon.Registry; +import elucent.eidolon.block.PipeBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +public class PipeTileEntity extends ReagentTankTileEntity { + + public PipeTileEntity(BlockPos pos, BlockState state) { + this(Registry.PIPE_TILE_ENTITY, pos, state); + } + + public PipeTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + super(tileEntityTypeIn, pos, state, 128); + } + + @Override + public boolean isOutput(Direction direction) { + return getBlockState().getValue(PipeBlock.OUT) == direction; + } + + @Override + public boolean isInput(Direction direction) { + return getBlockState().getValue(PipeBlock.IN) == direction; + } +} diff --git a/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java b/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java new file mode 100644 index 0000000..2656237 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java @@ -0,0 +1,102 @@ +package elucent.eidolon.tile.reagent; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.block.PipeBlock; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.core.Direction; + +public class PipeTileRenderer implements BlockEntityRenderer { + + public PipeTileRenderer() {} + + public boolean attached(BlockState b, Direction d) { + return b.getValue(PipeBlock.IN) == d && b.getValue(PipeBlock.IN_ATTACHED) + || b.getValue(PipeBlock.OUT) == d && b.getValue(PipeBlock.OUT_ATTACHED); + } + + static final float L = 0.40625f, U = 0.59375f, W = U - L; + + @Override + public void render(PipeTileEntity tile, float partialTicks, PoseStack matrixStackIn, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) { + Minecraft mc = Minecraft.getInstance(); + if (tile.tank.getContents().amount == 0) return; + float fill = (float)tile.tank.getContents().amount / tile.tank.getCapacity(); + if (fill > 1) fill = 1; + BlockState state = tile.getBlockState(); + TextureAtlasSprite water = tile.tank.getContents().reagent.getSprite(); + VertexConsumer builder = ClientEvents.getDelayedRender().getBuffer(RenderUtil.VAPOR_TRANSLUCENT); + boolean nx = state.getValue(PipeBlock.IN) == Direction.WEST || state.getValue(PipeBlock.OUT) == Direction.WEST, + px = state.getValue(PipeBlock.IN) == Direction.EAST || state.getValue(PipeBlock.OUT) == Direction.EAST, + ny = state.getValue(PipeBlock.IN) == Direction.DOWN || state.getValue(PipeBlock.OUT) == Direction.DOWN, + py = state.getValue(PipeBlock.IN) == Direction.UP || state.getValue(PipeBlock.OUT) == Direction.UP, + nz = state.getValue(PipeBlock.IN) == Direction.NORTH || state.getValue(PipeBlock.OUT) == Direction.NORTH, + pz = state.getValue(PipeBlock.IN) == Direction.SOUTH || state.getValue(PipeBlock.OUT) == Direction.SOUTH; + if (py && ny) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L, L, U, U, U, + 255, 255, 255, 255, combinedLightIn, + !nx, !px, !ny, !py, !nz, !pz); + } + else if (py) { + if (fill < 1) RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L + fill * W, L, U, U, U, + 255, 255, 255, 255, combinedLightIn, + true, true, !ny, !py, true, true); + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L, L, U, L + fill * W, U, + 255, 255, 255, 255, combinedLightIn, + !nx, !px, !ny, !py, !nz, !pz); + } + else { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L, L, U, L + fill * W, U, + 255, 255, 255, 255, combinedLightIn, + !nx, !px, !ny, !py, !nz, !pz); + } + if (nx) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + 0, L, L, L, L + W * fill, U, + 255, 255, 255, 255, combinedLightIn, + !attached(state, Direction.WEST), false, true, true, true, true); + } + if (px) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + U, L, L, 1, L + W * fill, U, + 255, 255, 255, 255, combinedLightIn, + false, !attached(state, Direction.EAST), true, true, true, true); + } + if (ny) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, 0, L, U, L, U, + 255, 255, 255, 255, combinedLightIn, + true, true, !attached(state, Direction.DOWN), false, true, true); + } + if (py) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, U, L, U, 1, U, + 255, 255, 255, 255, combinedLightIn, + true, true, false, !attached(state, Direction.UP), true, true); + } + if (nz) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L, 0, U, L + W * fill, L, + 255, 255, 255, 255, combinedLightIn, + true, true, true, true, !attached(state, Direction.NORTH), false); + } + if (pz) { + RenderUtil.vaporCube(matrixStackIn, builder, water, + L, L, U, U, L + W * fill, 1, + 255, 255, 255, 255, combinedLightIn, + true, true, true, true, false, !attached(state, Direction.SOUTH)); + } + } +} diff --git a/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java b/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java new file mode 100644 index 0000000..a64a8a9 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java @@ -0,0 +1,103 @@ +package elucent.eidolon.tile.reagent; + +import java.util.ArrayList; +import java.util.List; + +import elucent.eidolon.reagent.IReagentTankProvider; +import elucent.eidolon.reagent.ReagentStack; +import elucent.eidolon.reagent.ReagentTank; +import elucent.eidolon.tile.TileEntityBase; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.TickingBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +public abstract class ReagentTankTileEntity extends TileEntityBase implements IReagentTankProvider { + ReagentTank tank; + + public ReagentTankTileEntity(BlockEntityType type, BlockPos pos, BlockState state, int capacity) { + super(type, pos, state); + tank = new ReagentTank(capacity); + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + tank.read(tag.getCompound("tank")); + } + + @Override + public CompoundTag save(CompoundTag tag) { + tag = super.save(tag); + tag.put("tank", tank.write()); + return tag; + } + + public void tick() { + if (tank.getContents().amount == 0) return; + List tanks = new ArrayList<>(); + for (Direction d : Direction.values()) { + if (isOutput(d)) { + BlockEntity t = level.getBlockEntity(worldPosition.relative(d)); + if (t instanceof IReagentTankProvider + && ((IReagentTankProvider)t).isInput(d.getOpposite()) + && ((IReagentTankProvider)t).getTank().canFill(tank.getContents()) + && (((IReagentTankProvider)t).getTank().getPressure() < tank.getPressure() || d == Direction.DOWN)) + tanks.add((IReagentTankProvider)t); + } + } + if (tanks.isEmpty()) return; + float total = tank.getPressure(), count = 1; + for (IReagentTankProvider t : tanks) { + total += t.getTank().getPressure(); + count++; + } + boolean dirty = false; + float avg = total / count; + int shared = (tank.getContents().amount - Mth.ceil(tank.getCapacity() * avg)); + float totalPressure = 0; + for (IReagentTankProvider t : tanks) totalPressure += avg - t.getTank().getPressure(); + int[] toSend = new int[tanks.size()]; + int i = 0; + int sum = 0; + for (IReagentTankProvider t : tanks) { + float minDiff = 2.0f / t.getTank().getCapacity(); + float diff = avg - t.getTank().getPressure(); + if (diff > 0 && diff < minDiff) diff = minDiff; + int change = (int) (shared * ((avg - t.getTank().getPressure()) / totalPressure)); + int needed = (int) (diff * t.getTank().getCapacity()); + toSend[i] = Math.min(64, Math.min(change, needed)); + sum += toSend[i]; + i ++; + } + if (tank.getContents().amount - sum <= tanks.size() * 4) { + for (int j = 0; j < tank.getContents().amount - sum; j ++) toSend[j % tanks.size()] ++; + } + i = 0; + for (IReagentTankProvider t : tanks) { + int change = Math.min(tank.getContents().amount, toSend[i ++]); + if (change > 0) { + if (t.getTank().fill(level, ((BlockEntity) t).getBlockPos(), new ReagentStack(tank.getContents().reagent, change))) { + tank.getContents().amount -= change; + t.onContentsChanged(); + dirty = true; + } + } + } + if (dirty) onContentsChanged(); + } + + @Override + public ReagentTank getTank() { + return tank; + } + + @Override + public void onContentsChanged() { + sync(); + } +} diff --git a/src/main/java/elucent/eidolon/util/ChunkUtil.java b/src/main/java/elucent/eidolon/util/ChunkUtil.java index 493c34e..b055551 100644 --- a/src/main/java/elucent/eidolon/util/ChunkUtil.java +++ b/src/main/java/elucent/eidolon/util/ChunkUtil.java @@ -1,17 +1,17 @@ package elucent.eidolon.util; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; public class ChunkUtil { - public static void load(World world, ChunkPos pos) { - assert !world.isRemote; - ((ServerWorld)world).forceChunk(pos.x, pos.z, true); + public static void load(Level world, ChunkPos pos) { + assert !world.isClientSide; + ((ServerLevel)world).setChunkForced(pos.x, pos.z, true); } - public static void unload(World world, ChunkPos pos) { - assert !world.isRemote; - ((ServerWorld)world).forceChunk(pos.x, pos.z, false); + public static void unload(Level world, ChunkPos pos) { + assert !world.isClientSide; + ((ServerLevel)world).setChunkForced(pos.x, pos.z, false); } } diff --git a/src/main/java/elucent/eidolon/util/ColorUtil.java b/src/main/java/elucent/eidolon/util/ColorUtil.java index 9db19bb..4dd3d87 100644 --- a/src/main/java/elucent/eidolon/util/ColorUtil.java +++ b/src/main/java/elucent/eidolon/util/ColorUtil.java @@ -1,8 +1,5 @@ package elucent.eidolon.util; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - public class ColorUtil { public static int getAlpha(int packedColor) { return packedColor >>> 24; diff --git a/src/main/java/elucent/eidolon/util/EntityUtil.java b/src/main/java/elucent/eidolon/util/EntityUtil.java index edd93fb..fd1cfce 100644 --- a/src/main/java/elucent/eidolon/util/EntityUtil.java +++ b/src/main/java/elucent/eidolon/util/EntityUtil.java @@ -1,13 +1,13 @@ package elucent.eidolon.util; import elucent.eidolon.Eidolon; -import net.minecraft.entity.LivingEntity; +import net.minecraft.world.entity.LivingEntity; public class EntityUtil { public static final String THRALL_KEY = Eidolon.MODID + ":thrall"; public static void enthrall(LivingEntity caster, LivingEntity thrall) { - thrall.getPersistentData().putUniqueId(THRALL_KEY, caster.getUniqueID()); + thrall.getPersistentData().putUUID(THRALL_KEY, caster.getUUID()); } public static boolean isEnthralled(LivingEntity entity) { @@ -15,6 +15,6 @@ public static boolean isEnthralled(LivingEntity entity) { } public static boolean isEnthralledBy(LivingEntity entity, LivingEntity owner) { - return entity != null && owner != null && isEnthralled(entity) && entity.getPersistentData().getUniqueId(THRALL_KEY).equals(owner.getUniqueID()); + return entity != null && owner != null && isEnthralled(entity) && entity.getPersistentData().getUUID(THRALL_KEY).equals(owner.getUUID()); } } diff --git a/src/main/java/elucent/eidolon/util/RecipeUtil.java b/src/main/java/elucent/eidolon/util/RecipeUtil.java new file mode 100644 index 0000000..536a032 --- /dev/null +++ b/src/main/java/elucent/eidolon/util/RecipeUtil.java @@ -0,0 +1,53 @@ +package elucent.eidolon.util; + +import java.util.List; +import java.util.stream.Collectors; + +import net.minecraft.world.level.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tags.Tag; +import net.minecraftforge.common.util.LogicalSidedProvider; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class RecipeUtil { + public static RecipeManager getRecipeManager() { + return DistExecutor.unsafeRunForDist( + () -> () -> Minecraft.getInstance().getConnection().getRecipeManager(), + () -> () -> ServerLifecycleHooks.getCurrentServer().getRecipeManager() + ); + } + + public static Ingredient ingredientFromObject(Object object) { + if (object instanceof Item) return Ingredient.of((Item)object); + else if (object instanceof Block) return Ingredient.of(new ItemStack((Block)object)); + else if (object instanceof ItemStack) return Ingredient.of((ItemStack)object); + else if (object instanceof Tag) return Ingredient.of((Tag)object); + else return Ingredient.EMPTY; + } + + public static List ingredientsFromObjects(List objects) { + return objects.stream().map(RecipeUtil::ingredientFromObject).collect(Collectors.toList()); + } + + public static ItemStack stackFromObject(Object object) { + if (object instanceof Item) return new ItemStack((Item)object); + else if (object instanceof Block) return new ItemStack((Block)object); + else if (object instanceof ItemStack) return ((ItemStack)object).copy(); + else if (object instanceof Tag) { + Object first = ((Tag)object).getValues().get(0); + return stackFromObject(first); + } + else return ItemStack.EMPTY; + } + + public static List stacksFromObjects(List objects) { + return objects.stream().map(RecipeUtil::stackFromObject).collect(Collectors.toList()); + } +} diff --git a/src/main/java/elucent/eidolon/util/RenderUtil.java b/src/main/java/elucent/eidolon/util/RenderUtil.java index 48b7cd3..8e7f649 100644 --- a/src/main/java/elucent/eidolon/util/RenderUtil.java +++ b/src/main/java/elucent/eidolon/util/RenderUtil.java @@ -1,32 +1,37 @@ package elucent.eidolon.util; -import com.mojang.blaze3d.matrix.MatrixStack; +import java.util.Random; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + import elucent.eidolon.ClientEvents; import elucent.eidolon.Eidolon; -import elucent.eidolon.Events; +import elucent.eidolon.Registry; import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.renderer.*; -import net.minecraft.client.renderer.entity.EnderDragonRenderer; -import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Rotations; -import net.minecraft.util.math.vector.*; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.model.TransformationHelper; -import org.lwjgl.opengl.GL11; - -import java.util.Random; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; +import net.minecraft.world.phys.Vec3; +import com.mojang.math.Vector3f; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class RenderUtil { - public static final RenderState.TransparencyState ADDITIVE_TRANSPARENCY = new RenderState.TransparencyState("lightning_transparency", () -> { + public static final RenderStateShard.TransparencyStateShard ADDITIVE_TRANSPARENCY = new RenderStateShard.TransparencyStateShard("lightning_transparency", () -> { RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); }, () -> { @@ -34,7 +39,7 @@ public class RenderUtil { RenderSystem.defaultBlendFunc(); }); - public static final RenderState.TransparencyState NORMAL_TRANSPARENCY = new RenderState.TransparencyState("lightning_transparency", () -> { + public static final RenderStateShard.TransparencyStateShard NORMAL_TRANSPARENCY = new RenderStateShard.TransparencyStateShard("lightning_transparency", () -> { RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); }, () -> { @@ -42,102 +47,125 @@ public class RenderUtil { RenderSystem.defaultBlendFunc(); }); - public static RenderType GLOWING_SPRITE = RenderType.makeType( +// @OnlyIn(Dist.CLIENT) +// public static class RescaledLightingState extends RenderStateShard.DiffuseLightingStateShard { +// public RescaledLightingState() { +// super(true); +// } +// +// @Override +// public void setupRenderState() { +// RenderSystem.enableLighting(); +// RenderSystem.enableRescaleNormal(); +// } +// +// @Override +// public void clearRenderState() { +// RenderSystem.disableLighting(); +// RenderSystem.disableRescaleNormal(); +// } +// } + + public static RenderType GLOWING_SPRITE = RenderType.create( Eidolon.MODID + ":glowing_sprite", - DefaultVertexFormats.POSITION_COLOR_TEX, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(false)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(ADDITIVE_TRANSPARENCY) - .texture(new RenderState.TextureState(AtlasTexture.LOCATION_BLOCKS_TEXTURE, false, false)) - .build(false) - ), GLOWING = RenderType.makeType( + DefaultVertexFormat.POSITION_TEX_COLOR, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) + .setShaderState(new ShaderStateShard(Registry::getGlowingSpriteShader)) + .createCompositeState(false) + ), GLOWING = RenderType.create( Eidolon.MODID + ":glowing", - DefaultVertexFormats.POSITION_COLOR, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(true)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(ADDITIVE_TRANSPARENCY) - .build(false) - ), DELAYED_PARTICLE = RenderType.makeType( + DefaultVertexFormat.POSITION_COLOR, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setShaderState(new ShaderStateShard(Registry::getGlowingShader)) + .createCompositeState(false) + ), DELAYED_PARTICLE = RenderType.create( Eidolon.MODID + ":delayed_particle", - DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(true)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(NORMAL_TRANSPARENCY) - .texture(new RenderState.TextureState(AtlasTexture.LOCATION_PARTICLES_TEXTURE, false, false)) - .build(false) - ), GLOWING_PARTICLE = RenderType.makeType( + DefaultVertexFormat.PARTICLE, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setTransparencyState(NORMAL_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_PARTICLES, false, false)) + .setShaderState(new ShaderStateShard(GameRenderer::getParticleShader)) + .createCompositeState(false) + ), GLOWING_PARTICLE = RenderType.create( Eidolon.MODID + ":glowing_particle", - DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(true)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(ADDITIVE_TRANSPARENCY) - .texture(new RenderState.TextureState(AtlasTexture.LOCATION_PARTICLES_TEXTURE, false, false)) - .build(false) - ), GLOWING_BLOCK_PARTICLE = RenderType.makeType( + DefaultVertexFormat.PARTICLE, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_PARTICLES, false, false)) + .setShaderState(new ShaderStateShard(Registry::getGlowingParticleShader)) + .createCompositeState(false) + ), GLOWING_BLOCK_PARTICLE = RenderType.create( Eidolon.MODID + ":glowing_particle", - DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP, - GL11.GL_QUADS, 256, - RenderType.State.getBuilder() - .shadeModel(new RenderState.ShadeModelState(true)) - .writeMask(new RenderState.WriteMaskState(true, false)) - .lightmap(new RenderState.LightmapState(false)) - .diffuseLighting(new RenderState.DiffuseLightingState(false)) - .transparency(ADDITIVE_TRANSPARENCY) - .texture(new RenderState.TextureState(AtlasTexture.LOCATION_BLOCKS_TEXTURE, false, false)) - .build(false) + DefaultVertexFormat.PARTICLE, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) + .setShaderState(new ShaderStateShard(Registry::getGlowingParticleShader)) + .createCompositeState(false) + ), VAPOR_TRANSLUCENT = RenderType.create( + Eidolon.MODID + ":vapor_translucent", + DefaultVertexFormat.BLOCK, + Mode.QUADS, 256, true, false, + RenderType.CompositeState.builder() + .setLightmapState(new RenderStateShard.LightmapStateShard(false)) + .setTransparencyState(NORMAL_TRANSPARENCY) + .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) + .setShaderState(new ShaderStateShard(Registry::getVaporShader)) + .createCompositeState(false) ); static double ticks = 0; - public static void litQuad(MatrixStack mStack, IRenderTypeBuffer buffer, double x, double y, double w, double h, float r, float g, float b, TextureAtlasSprite sprite) { - IVertexBuilder builder = buffer.getBuffer(GLOWING_SPRITE); - - float f7 = sprite.getMinU(); - float f8 = sprite.getMaxU(); - float f5 = sprite.getMinV(); - float f6 = sprite.getMaxV(); - Matrix4f mat = mStack.getLast().getMatrix(); - builder.pos(mat, (float)x, (float)y + (float)h, 0).color(r, g, b, 1.0f).tex(f7, f6).endVertex(); - builder.pos(mat, (float)x + (float)w, (float)y + (float)h, 0).color(r, g, b, 1.0f).tex(f8, f6).endVertex(); - builder.pos(mat, (float)x + (float)w, (float)y, 0).color(r, g, b, 1.0f).tex(f8, f5).endVertex(); - builder.pos(mat, (float)x, (float)y, 0).color(r, g, b, 1.0f).tex(f7, f5).endVertex(); + public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, TextureAtlasSprite sprite) { + VertexConsumer builder = buffer.getBuffer(GLOWING_SPRITE); + + float f7 = sprite.getU0(); + float f8 = sprite.getU1(); + float f5 = sprite.getV0(); + float f6 = sprite.getV1(); + Matrix4f mat = mStack.last().pose(); + builder.vertex(mat, (float)x, (float)y + (float)h, 0).uv(f7, f6).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y + (float)h, 0).uv(f8, f6).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y, 0).uv(f8, f5).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x, (float)y, 0).uv(f7, f5).color(r, g, b, 1.0f).endVertex(); } - public static void litQuad(MatrixStack mStack, IRenderTypeBuffer buffer, double x, double y, double w, double h, float r, float g, float b, float u, float v, float uw, float vh) { - IVertexBuilder builder = buffer.getBuffer(GLOWING_SPRITE); + public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, float u, float v, float uw, float vh) { + VertexConsumer builder = buffer.getBuffer(GLOWING_SPRITE); - Matrix4f mat = mStack.getLast().getMatrix(); - builder.pos(mat, (float)x, (float)y + (float)h, 0).color(r, g, b, 1.0f).tex(u, v + vh).endVertex(); - builder.pos(mat, (float)x + (float)w, (float)y + (float)h, 0).color(r, g, b, 1.0f).tex(u + uw, v + vh).endVertex(); - builder.pos(mat, (float)x + (float)w, (float)y, 0).color(r, g, b, 1.0f).tex(u + uw, v).endVertex(); - builder.pos(mat, (float)x, (float)y, 0).color(r, g, b, 1.0f).tex(u, v).endVertex(); + Matrix4f mat = mStack.last().pose(); + builder.vertex(mat, (float)x, (float)y + (float)h, 0).uv(u, v + vh).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y + (float)h, 0).uv(u + uw, v + vh).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y, 0).uv(u + uw, v).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x, (float)y, 0).uv(u, v).color(r, g, b, 1.0f).endVertex(); } - public static void litBillboard(MatrixStack mStack, IRenderTypeBuffer buffer, double x, double y, double z, float r, float g, float b, TextureAtlasSprite sprite) { - IVertexBuilder builder = buffer.getBuffer(GLOWING_SPRITE); - ActiveRenderInfo renderInfo = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - Vector3d vector3d = renderInfo.getProjectedView(); - float partialTicks = Minecraft.getInstance().getRenderPartialTicks(); + public static void litBillboard(PoseStack mStack, MultiBufferSource buffer, double x, double y, double z, float r, float g, float b, TextureAtlasSprite sprite) { + VertexConsumer builder = buffer.getBuffer(GLOWING_SPRITE); + Camera renderInfo = Minecraft.getInstance().gameRenderer.getMainCamera(); + Vec3 vector3d = renderInfo.getPosition(); + float partialTicks = Minecraft.getInstance().getFrameTime(); float f = (float)(x); float f1 = (float)(y); float f2 = (float)(z); - Quaternion quaternion = renderInfo.getRotation(); + Quaternion quaternion = renderInfo.rotation(); Vector3f[] avector3f = new Vector3f[]{new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.5f, -0.5f, 0.0f)}; float f4 = 1.0f; @@ -149,59 +177,102 @@ public static void litBillboard(MatrixStack mStack, IRenderTypeBuffer buffer, do vector3f.add(f, f1, f2); } - float f7 = sprite.getMinU(); - float f8 = sprite.getMaxU(); - float f5 = sprite.getMinV(); - float f6 = sprite.getMaxV(); - Matrix4f mat = mStack.getLast().getMatrix(); - builder.pos(mat, avector3f[0].getX(), avector3f[0].getY(), avector3f[0].getZ()).color(r, g, b, 1.0f).tex(f8, f6).endVertex(); - builder.pos(mat, avector3f[1].getX(), avector3f[1].getY(), avector3f[1].getZ()).color(r, g, b, 1.0f).tex(f8, f5).endVertex(); - builder.pos(mat, avector3f[2].getX(), avector3f[2].getY(), avector3f[2].getZ()).color(r, g, b, 1.0f).tex(f7, f5).endVertex(); - builder.pos(mat, avector3f[3].getX(), avector3f[3].getY(), avector3f[3].getZ()).color(r, g, b, 1.0f).tex(f7, f6).endVertex(); + float f7 = sprite.getU0(); + float f8 = sprite.getU1(); + float f5 = sprite.getV0(); + float f6 = sprite.getV1(); + Matrix4f mat = mStack.last().pose(); + builder.vertex(mat, avector3f[0].x(), avector3f[0].y(), avector3f[0].z()).uv(f8, f6).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, avector3f[1].x(), avector3f[1].y(), avector3f[1].z()).uv(f8, f5).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, avector3f[2].x(), avector3f[2].y(), avector3f[2].z()).uv(f7, f5).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, avector3f[3].x(), avector3f[3].y(), avector3f[3].z()).uv(f7, f6).color(r, g, b, 1.0f).endVertex(); } - public static void dragon(MatrixStack mStack, IRenderTypeBuffer buf, double x, double y, double z, float radius, float r, float g, float b) { + public static void dragon(PoseStack mStack, MultiBufferSource buf, double x, double y, double z, float radius, float r, float g, float b) { float f5 = 0.5f; // max number of beams float f7 = Math.min(f5 > 0.8F ? (f5 - 0.8F) / 0.2F : 0.0F, 1.0F); Random random = new Random(432L); - IVertexBuilder builder = buf.getBuffer(GLOWING); - mStack.push(); + VertexConsumer builder = buf.getBuffer(GLOWING); + mStack.pushPose(); mStack.translate(x, y, z); float rotation = (float)(ClientEvents.getClientTicks() / 200); for(int i = 0; (float)i < (f5 + f5 * f5) / 2.0F * 60.0F; ++i) { - mStack.rotate(Vector3f.XP.rotationDegrees(random.nextFloat() * 360.0F)); - mStack.rotate(Vector3f.YP.rotationDegrees(random.nextFloat() * 360.0F)); - mStack.rotate(Vector3f.ZP.rotationDegrees(random.nextFloat() * 360.0F)); - mStack.rotate(Vector3f.XP.rotationDegrees(random.nextFloat() * 360.0F)); - mStack.rotate(Vector3f.YP.rotationDegrees(random.nextFloat() * 360.0F)); - mStack.rotate(Vector3f.ZP.rotationDegrees(random.nextFloat() * 360.0F + rotation * 90.0F)); + mStack.mulPose(Vector3f.XP.rotationDegrees(random.nextFloat() * 360.0F)); + mStack.mulPose(Vector3f.YP.rotationDegrees(random.nextFloat() * 360.0F)); + mStack.mulPose(Vector3f.ZP.rotationDegrees(random.nextFloat() * 360.0F)); + mStack.mulPose(Vector3f.XP.rotationDegrees(random.nextFloat() * 360.0F)); + mStack.mulPose(Vector3f.YP.rotationDegrees(random.nextFloat() * 360.0F)); + mStack.mulPose(Vector3f.ZP.rotationDegrees(random.nextFloat() * 360.0F + rotation * 90.0F)); float f3 = random.nextFloat() * 20.0F + 5.0F + f7 * 10.0F; float f4 = random.nextFloat() * 2.0F + 1.0F + f7 * 2.0F; f3 *= 0.05f * radius; f4 *= 0.05f * radius; - Matrix4f mat = mStack.getLast().getMatrix(); + Matrix4f mat = mStack.last().pose(); float alpha = 1 - f7; - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, -ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); - builder.pos(mat, ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); - builder.pos(mat, 0.0F, f3, 1.0F * f4).color(r, g, b, 0).endVertex(); - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); - builder.pos(mat, 0.0F, f3, 1.0F * f4).color(r, g, b, 0).endVertex(); - builder.pos(mat, -ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, -ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, 0.0F, f3, 1.0F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, 0.0F, 0.0F, 0.0F).color(r, g, b, alpha).endVertex(); + builder.vertex(mat, 0.0F, f3, 1.0F * f4).color(r, g, b, 0).endVertex(); + builder.vertex(mat, -ROOT_3 * f4, f3, -0.5F * f4).color(r, g, b, 0).endVertex(); } - mStack.pop(); + mStack.popPose(); } // copied from EnderDragonRenderer private static final float ROOT_3 = (float)(Math.sqrt(3.0D) / 2.0D); + + public static void vaporCube(PoseStack mStack, VertexConsumer builder, TextureAtlasSprite sprite, + float x1, float y1, float z1, float x2, float y2, float z2, + int r, int g, int b, int a, int light, + boolean nx, boolean px, boolean ny, boolean py, boolean nz, boolean pz) { + Matrix4f mat = mStack.last().pose(); + if (py) { + builder.vertex(mat, x1, y2, z1).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(x1 * 16)).uv2(light).normal(0, 1, 0).endVertex(); + builder.vertex(mat, x1, y2, z2).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(x1 * 16)).uv2(light).normal(0, 1, 0).endVertex(); + builder.vertex(mat, x2, y2, z2).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(x2 * 16)).uv2(light).normal(0, 1, 0).endVertex(); + builder.vertex(mat, x2, y2, z1).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(x2 * 16)).uv2(light).normal(0, 1, 0).endVertex(); + } + if (ny) { + builder.vertex(mat, x1, y1, z2).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(x1 * 16)).uv2(light).normal(0, -1, 0).endVertex(); + builder.vertex(mat, x1, y1, z1).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(x1 * 16)).uv2(light).normal(0, -1, 0).endVertex(); + builder.vertex(mat, x2, y1, z1).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(x2 * 16)).uv2(light).normal(0, -1, 0).endVertex(); + builder.vertex(mat, x2, y1, z2).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(x2 * 16)).uv2(light).normal(0, -1, 0).endVertex(); + } + if (nz) { + builder.vertex(mat, x2, y1, z1).color(r, g, b, a).uv(sprite.getU(x1 * 16), sprite.getV(y1 * 16)).uv2(light).normal(0, 0, -1).endVertex(); + builder.vertex(mat, x1, y1, z1).color(r, g, b, a).uv(sprite.getU(x2 * 16), sprite.getV(y1 * 16)).uv2(light).normal(0, 0, -1).endVertex(); + builder.vertex(mat, x1, y2, z1).color(r, g, b, a).uv(sprite.getU(x2 * 16), sprite.getV(y2 * 16)).uv2(light).normal(0, 0, -1).endVertex(); + builder.vertex(mat, x2, y2, z1).color(r, g, b, a).uv(sprite.getU(x1 * 16), sprite.getV(y2 * 16)).uv2(light).normal(0, 0, -1).endVertex(); + } + if (pz) { + builder.vertex(mat, x1, y1, z2).color(r, g, b, a).uv(sprite.getU(x1 * 16), sprite.getV(y1 * 16)).uv2(light).normal(0, 0, 1).endVertex(); + builder.vertex(mat, x2, y1, z2).color(r, g, b, a).uv(sprite.getU(x2 * 16), sprite.getV(y1 * 16)).uv2(light).normal(0, 0, 1).endVertex(); + builder.vertex(mat, x2, y2, z2).color(r, g, b, a).uv(sprite.getU(x2 * 16), sprite.getV(y2 * 16)).uv2(light).normal(0, 0, 1).endVertex(); + builder.vertex(mat, x1, y2, z2).color(r, g, b, a).uv(sprite.getU(x1 * 16), sprite.getV(y2 * 16)).uv2(light).normal(0, 0, 1).endVertex(); + } + if (nx) { + builder.vertex(mat, x1, y1, z1).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(y1 * 16)).uv2(light).normal(-1, 0, 0).endVertex(); + builder.vertex(mat, x1, y1, z2).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(y1 * 16)).uv2(light).normal(-1, 0, 0).endVertex(); + builder.vertex(mat, x1, y2, z2).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(y2 * 16)).uv2(light).normal(-1, 0, 0).endVertex(); + builder.vertex(mat, x1, y2, z1).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(y2 * 16)).uv2(light).normal(-1, 0, 0).endVertex(); + } + if (px) { + builder.vertex(mat, x2, y1, z2).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(y1 * 16)).uv2(light).normal(1, 0, 0).endVertex(); + builder.vertex(mat, x2, y1, z1).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(y1 * 16)).uv2(light).normal(1, 0, 0).endVertex(); + builder.vertex(mat, x2, y2, z1).color(r, g, b, a).uv(sprite.getU(z2 * 16), sprite.getV(y2 * 16)).uv2(light).normal(1, 0, 0).endVertex(); + builder.vertex(mat, x2, y2, z2).color(r, g, b, a).uv(sprite.getU(z1 * 16), sprite.getV(y2 * 16)).uv2(light).normal(1, 0, 0).endVertex(); + } + } } diff --git a/src/main/java/elucent/eidolon/util/StackUtil.java b/src/main/java/elucent/eidolon/util/StackUtil.java deleted file mode 100644 index d75df50..0000000 --- a/src/main/java/elucent/eidolon/util/StackUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package elucent.eidolon.util; - -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.tags.ITag; - -import java.util.List; -import java.util.stream.Collectors; - -public class StackUtil { - public static Ingredient ingredientFromObject(Object object) { - if (object instanceof Item) return Ingredient.fromItems((Item)object); - else if (object instanceof Block) return Ingredient.fromStacks(new ItemStack((Block)object)); - else if (object instanceof ItemStack) return Ingredient.fromStacks((ItemStack)object); - else if (object instanceof ITag) return Ingredient.fromTag((ITag)object); - else return Ingredient.EMPTY; - } - - public static List ingredientsFromObjects(List objects) { - return objects.stream().map(StackUtil::ingredientFromObject).collect(Collectors.toList()); - } - - public static ItemStack stackFromObject(Object object) { - if (object instanceof Item) return new ItemStack((Item)object); - else if (object instanceof Block) return new ItemStack((Block)object); - else if (object instanceof ItemStack) return ((ItemStack)object).copy(); - else if (object instanceof ITag) { - Object first = ((ITag)object).getAllElements().get(0); - return stackFromObject(first); - } - else return ItemStack.EMPTY; - } - - public static List stacksFromObjects(List objects) { - return objects.stream().map(StackUtil::stackFromObject).collect(Collectors.toList()); - } -} diff --git a/src/main/java/elucent/eidolon/world/BasicPiece.java b/src/main/java/elucent/eidolon/world/BasicPiece.java index 8fce5a8..465b198 100644 --- a/src/main/java/elucent/eidolon/world/BasicPiece.java +++ b/src/main/java/elucent/eidolon/world/BasicPiece.java @@ -1,78 +1,75 @@ package elucent.eidolon.world; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.Mirror; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MutableBoundingBox; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.gen.feature.structure.IStructurePieceType; -import net.minecraft.world.gen.feature.structure.TemplateStructurePiece; -import net.minecraft.world.gen.feature.template.BlockIgnoreStructureProcessor; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.gen.feature.template.TemplateManager; - import java.util.Random; +import com.mojang.serialization.Dynamic; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.RuinedPortalPiece; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + public class BasicPiece extends TemplateStructurePiece { private ResourceLocation loc; Rotation rotation; Mirror mirror; - void modifyPlacement(PlacementSettings settings, BlockPos pos) { + void modifyPlacement(StructurePlaceSettings settings, BlockPos pos) { // } void init(BlockPos pos, Random random) { // } - - public BasicPiece(IStructurePieceType structurePieceTypeIn, CompoundNBT nbt) { - super(structurePieceTypeIn, nbt); - this.loc = new ResourceLocation(nbt.getString("template")); + + public BasicPiece(StructurePieceType structurePieceTypeIn, CompoundTag nbt, StructureManager manager) { + super(structurePieceTypeIn, nbt, manager, (rl) -> { + return new StructurePlaceSettings().setRotation(Rotation.valueOf(nbt.getString("rot"))).setMirror(Mirror.valueOf(nbt.getString("mirror"))).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); + }); + this.loc = new ResourceLocation(nbt.getString("Template")); this.rotation = Rotation.valueOf(nbt.getString("rot")); this.mirror = Mirror.valueOf(nbt.getString("mirror")); } - public BasicPiece(IStructurePieceType type, ResourceLocation key, TemplateManager templateManager, CompoundNBT nbt) { - this(type, nbt); - Template part = templateManager.getTemplateDefaulted(key); - PlacementSettings placement = (new PlacementSettings().setRotation(rotation).setMirror(mirror)).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(key); - } - - public BasicPiece(IStructurePieceType type, ResourceLocation key, TemplateManager templateManager, BlockPos pos, Random random) { + public BasicPiece(StructurePieceType type, ResourceLocation key, StructureManager templateManager, BlockPos pos, Random random) { this(type, key, templateManager, pos, Rotation.NONE, Mirror.NONE, random); } - public BasicPiece(IStructurePieceType type, ResourceLocation key, TemplateManager templateManager, BlockPos pos, Rotation rot, Mirror mirror, Random random) { - super(type, 0); + public BasicPiece(StructurePieceType type, ResourceLocation key, StructureManager templateManager, BlockPos pos, Rotation rot, Mirror mirror, Random random) { + super(type, 0, templateManager, key, "eidolon.structure." + key.getPath(), + new StructurePlaceSettings().setRotation(rot).setMirror(Mirror.NONE).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK), pos); this.templatePosition = pos; this.loc = key; this.rotation = rot; this.mirror = mirror; - Template part = templateManager.getTemplateDefaulted(key); - BlockPos d = part.getSize(); + this.template = templateManager.getOrCreate(key); + Vec3i d = template.getSize(); BlockPos o = new BlockPos(-((d.getX() - 1) / 2), 0, -(d.getZ() - 1) / 2); - templatePosition = templatePosition.add(o.rotate(this.rotation)).subtract(o); - - PlacementSettings placement = (new PlacementSettings().setRotation(rotation).setMirror(Mirror.NONE)).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(key); + templatePosition = templatePosition.offset(o.rotate(this.rotation)).subtract(o); } @Override - protected void readAdditional(CompoundNBT tagCompound) { - super.readAdditional(tagCompound); - tagCompound.putString("template", loc.toString()); + protected void addAdditionalSaveData(StructurePieceSerializationContext ctx, CompoundTag tagCompound) { + super.addAdditionalSaveData(ctx, tagCompound); tagCompound.putString("rot", rotation.name()); tagCompound.putString("mirror", mirror.name()); } @Override - protected void handleDataMarker(String function, BlockPos pos, IServerWorld worldIn, Random rand, MutableBoundingBox sbb) {} + protected void handleDataMarker(String function, BlockPos pos, ServerLevelAccessor worldIn, Random rand, BoundingBox sbb) {} } diff --git a/src/main/java/elucent/eidolon/world/CatacombPieces.java b/src/main/java/elucent/eidolon/world/CatacombPieces.java index 2f83aa6..acbbe04 100644 --- a/src/main/java/elucent/eidolon/world/CatacombPieces.java +++ b/src/main/java/elucent/eidolon/world/CatacombPieces.java @@ -1,23 +1,17 @@ package elucent.eidolon.world; -import elucent.eidolon.Eidolon; -import elucent.eidolon.WorldGen; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.Mirror; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MutableBoundingBox; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.gen.feature.structure.IStructurePieceType; -import net.minecraft.world.gen.feature.structure.TemplateStructurePiece; -import net.minecraft.world.gen.feature.template.BlockIgnoreStructureProcessor; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.gen.feature.template.TemplateManager; - import java.util.Random; +import elucent.eidolon.Eidolon; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + public class CatacombPieces { public static final ResourceLocation CORRIDOR_CENTER_ID = new ResourceLocation(Eidolon.MODID, "catacomb_corridor_center"), @@ -33,70 +27,70 @@ public class CatacombPieces { TURNAROUND_ID = new ResourceLocation(Eidolon.MODID, "catacomb_turnaround"), LAB_ID = new ResourceLocation(Eidolon.MODID, "catacomb_lab"); - public static IStructurePieceType + public static StructurePieceType CORRIDOR_CENTER = null, CORRIDOR_DOOR = null, SMALL_ROOM = null, TRAP = null, SHRINE = null, SKULL = null, SPAWNER = null, COFFIN = null, MEDIUM_ROOM = null, GRAVEYARD = null, TURNAROUND = null, LAB = null; public static class CorridorCenter extends RandomlyRotatedPiece { - public CorridorCenter(TemplateManager templateManager, CompoundNBT nbt) { super(CORRIDOR_CENTER, CORRIDOR_CENTER_ID, templateManager, nbt); } - public CorridorCenter(TemplateManager templateManager, BlockPos pos, Random random) { super(CORRIDOR_CENTER, CORRIDOR_CENTER_ID, templateManager, pos, random); } + public CorridorCenter(StructureManager manager, CompoundTag nbt) { super(CORRIDOR_CENTER, nbt, manager); } + public CorridorCenter(StructureManager templateManager, BlockPos pos, Random random) { super(CORRIDOR_CENTER, CORRIDOR_CENTER_ID, templateManager, pos, random); } } public static class CorridorDoor extends BasicPiece { - public CorridorDoor(TemplateManager templateManager, CompoundNBT nbt) { super(CORRIDOR_DOOR, CORRIDOR_DOOR_ID, templateManager, nbt); } - public CorridorDoor(TemplateManager templateManager, BlockPos pos, Rotation rot, Random random) { + public CorridorDoor(StructureManager manager, CompoundTag nbt) { super(CORRIDOR_DOOR, nbt, manager); } + public CorridorDoor(StructureManager templateManager, BlockPos pos, Rotation rot, Random random) { super(CORRIDOR_DOOR, CORRIDOR_DOOR_ID, templateManager, pos, rot, Mirror.NONE, random); } } public static class SmallRoom extends RandomlyRotatedPiece { - public SmallRoom(TemplateManager templateManager, CompoundNBT nbt) { super(SMALL_ROOM, SMALL_ROOM_ID, templateManager, nbt); } - public SmallRoom(TemplateManager templateManager, BlockPos pos, Random random) { super(SMALL_ROOM, SMALL_ROOM_ID, templateManager, pos, random); } + public SmallRoom(StructureManager manager, CompoundTag nbt) { super(SMALL_ROOM, nbt, manager); } + public SmallRoom(StructureManager templateManager, BlockPos pos, Random random) { super(SMALL_ROOM, SMALL_ROOM_ID, templateManager, pos, random); } } public static class Trap extends RandomlyRotatedPiece { - public Trap(TemplateManager templateManager, CompoundNBT nbt) { super(TRAP, TRAP_ID, templateManager, nbt); } - public Trap(TemplateManager templateManager, BlockPos pos, Random random) { super(TRAP, TRAP_ID, templateManager, pos, random); } + public Trap(StructureManager manager, CompoundTag nbt) { super(TRAP, nbt, manager); } + public Trap(StructureManager templateManager, BlockPos pos, Random random) { super(TRAP, TRAP_ID, templateManager, pos, random); } } public static class Shrine extends RandomlyRotatedPiece { - public Shrine(TemplateManager templateManager, CompoundNBT nbt) { super(SHRINE, SHRINE_ID, templateManager, nbt); } - public Shrine(TemplateManager templateManager, BlockPos pos, Random random) { super(SHRINE, SHRINE_ID, templateManager, pos, random); } + public Shrine(StructureManager manager, CompoundTag nbt) { super(SHRINE, nbt, manager); } + public Shrine(StructureManager templateManager, BlockPos pos, Random random) { super(SHRINE, SHRINE_ID, templateManager, pos, random); } } public static class Skull extends RandomlyRotatedPiece { - public Skull(TemplateManager templateManager, CompoundNBT nbt) { super(SKULL, SKULL_ID, templateManager, nbt); } - public Skull(TemplateManager templateManager, BlockPos pos, Random random) { super(SKULL, SKULL_ID, templateManager, pos, random); } + public Skull(StructureManager manager, CompoundTag nbt) { super(SKULL, nbt, manager); } + public Skull(StructureManager templateManager, BlockPos pos, Random random) { super(SKULL, SKULL_ID, templateManager, pos, random); } } public static class Spawner extends RandomlyRotatedPiece { - public Spawner(TemplateManager templateManager, CompoundNBT nbt) { super(SPAWNER, SPAWNER_ID, templateManager, nbt); } - public Spawner(TemplateManager templateManager, BlockPos pos, Random random) { super(SPAWNER, SPAWNER_ID, templateManager, pos, random); } + public Spawner(StructureManager manager, CompoundTag nbt) { super(SPAWNER, nbt, manager); } + public Spawner(StructureManager templateManager, BlockPos pos, Random random) { super(SPAWNER, SPAWNER_ID, templateManager, pos, random); } } public static class Coffin extends RandomlyRotatedPiece { - public Coffin(TemplateManager templateManager, CompoundNBT nbt) { super(COFFIN, COFFIN_ID, templateManager, nbt); } - public Coffin(TemplateManager templateManager, BlockPos pos, Random random) { super(COFFIN, COFFIN_ID, templateManager, pos, random); } + public Coffin(StructureManager manager, CompoundTag nbt) { super(COFFIN, nbt, manager); } + public Coffin(StructureManager templateManager, BlockPos pos, Random random) { super(COFFIN, COFFIN_ID, templateManager, pos, random); } } public static class MediumRoom extends RandomlyRotatedPiece { - public MediumRoom(TemplateManager templateManager, CompoundNBT nbt) { super(MEDIUM_ROOM, MEDIUM_ROOM_ID, templateManager, nbt); } - public MediumRoom(TemplateManager templateManager, BlockPos pos, Random random) { super(MEDIUM_ROOM, MEDIUM_ROOM_ID, templateManager, pos, random); } + public MediumRoom(StructureManager manager, CompoundTag nbt) { super(MEDIUM_ROOM, nbt, manager); } + public MediumRoom(StructureManager templateManager, BlockPos pos, Random random) { super(MEDIUM_ROOM, MEDIUM_ROOM_ID, templateManager, pos, random); } } public static class Graveyard extends RandomlyRotatedPiece { - public Graveyard(TemplateManager templateManager, CompoundNBT nbt) { super(GRAVEYARD, GRAVEYARD_ID, templateManager, nbt); } - public Graveyard(TemplateManager templateManager, BlockPos pos, Random random) { super(GRAVEYARD, GRAVEYARD_ID, templateManager, pos, random); } + public Graveyard(StructureManager manager, CompoundTag nbt) { super(GRAVEYARD, nbt, manager); } + public Graveyard(StructureManager templateManager, BlockPos pos, Random random) { super(GRAVEYARD, GRAVEYARD_ID, templateManager, pos, random); } } public static class Turnaround extends RandomlyRotatedPiece { - public Turnaround(TemplateManager templateManager, CompoundNBT nbt) { super(TURNAROUND, TURNAROUND_ID, templateManager, nbt); } - public Turnaround(TemplateManager templateManager, BlockPos pos, Random random) { super(TURNAROUND, TURNAROUND_ID, templateManager, pos, random); } + public Turnaround(StructureManager manager, CompoundTag nbt) { super(TURNAROUND, nbt, manager); } + public Turnaround(StructureManager templateManager, BlockPos pos, Random random) { super(TURNAROUND, TURNAROUND_ID, templateManager, pos, random); } } public static class Lab extends RandomlyRotatedPiece { - public Lab(TemplateManager templateManager, CompoundNBT nbt) { super(LAB, LAB_ID, templateManager, nbt); } - public Lab(TemplateManager templateManager, BlockPos pos, Random random) { super(LAB, LAB_ID, templateManager, pos, random); } + public Lab(StructureManager manager, CompoundTag nbt) { super(LAB, nbt, manager); } + public Lab(StructureManager templateManager, BlockPos pos, Random random) { super(LAB, LAB_ID, templateManager, pos, random); } } } diff --git a/src/main/java/elucent/eidolon/world/CatacombStructure.java b/src/main/java/elucent/eidolon/world/CatacombStructure.java index 55b1dc2..fde708c 100644 --- a/src/main/java/elucent/eidolon/world/CatacombStructure.java +++ b/src/main/java/elucent/eidolon/world/CatacombStructure.java @@ -1,76 +1,81 @@ package elucent.eidolon.world; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Random; +import java.util.Set; + import com.mojang.serialization.Codec; + import elucent.eidolon.Config; import elucent.eidolon.Eidolon; -import elucent.eidolon.WorldGen; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.Mirror; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Rotation; -import net.minecraft.util.SharedSeedRandom; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.MutableBoundingBox; -import net.minecraft.util.registry.DynamicRegistries; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.provider.BiomeProvider; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.Heightmap; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.gen.feature.structure.*; -import net.minecraft.world.gen.feature.template.BlockIgnoreStructureProcessor; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.gen.feature.template.TemplateManager; - -import java.util.*; +import elucent.eidolon.world.LabStructure.LabPieceGenerator; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.world.level.levelgen.structure.StructurePiece; +import net.minecraft.world.level.levelgen.structure.StructureStart; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator.Context; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; -public class CatacombStructure extends Structure { - public CatacombStructure(Codec codec) { - super(codec); +public class CatacombStructure extends StructureFeature { + public CatacombStructure(Codec codec) { + super(codec, PieceGeneratorSupplier.simple(CatacombStructure::isFeatureChunk, new CatacombPieceGenerator())); } @Override - public GenerationStage.Decoration getDecorationStage() { - return GenerationStage.Decoration.UNDERGROUND_STRUCTURES; + public GenerationStep.Decoration step() { + return GenerationStep.Decoration.UNDERGROUND_STRUCTURES; } + + static Random rand = new Random(); - @Override - public IStartFactory getStartFactory() { - return Start::new; - } - - @Override - protected boolean func_230363_a_(ChunkGenerator generator, BiomeProvider provider, long seed, SharedSeedRandom rand, int chunkX, int chunkZ, Biome biome, ChunkPos pos, NoFeatureConfig config) { - int i = chunkX >> 4; - int j = chunkZ >> 4; - rand.setSeed((long) (i ^ j << 4) ^ seed); + static boolean isFeatureChunk(PieceGeneratorSupplier.Context ctx) { + int i = ctx.chunkPos().x >> 4; + int j = ctx.chunkPos().z >> 4; + rand.setSeed((long) (i ^ j << 4) ^ 1579937621); double prob = rand.nextInt(10000) / 10000.0f; return prob < (1 / Config.CATACOMB_RARITY.get()); } @Override - public String getStructureName() { + public String getFeatureName() { return new ResourceLocation(Eidolon.MODID, "catacomb").toString(); } - public static class Start extends StructureStart { - public Start(Structure config, int chunkX, int chunkZ, MutableBoundingBox bounds, int refs, long seed) { - super(config, chunkX, chunkZ, bounds, refs, seed); - } - - public void func_230364_a_(DynamicRegistries registries, ChunkGenerator generator, TemplateManager templateManager, int chunkX, int chunkZ, Biome biome, NoFeatureConfig config) { - int i = chunkX * 16; - int j = chunkZ * 16; - int k = Math.min(32, generator.getNoiseHeight(i, j, Heightmap.Type.OCEAN_FLOOR_WG)); + public static class CatacombPieceGenerator implements PieceGenerator { + @Override + public void generatePieces(StructurePiecesBuilder pieces, Context ctx) { + int i = ctx.chunkPos().x * 16; + int j = ctx.chunkPos().z * 16; + int k = Math.min(32, ctx.chunkGenerator().getFirstFreeHeight(i, j, Heightmap.Types.OCEAN_FLOOR_WG, ctx.heightAccessor())); if (k < 17) k = 17; - BlockPos blockpos = new BlockPos(i + rand.nextInt(16), rand.nextInt(k - 16) + 8, j + rand.nextInt(16)); + BlockPos blockpos = new BlockPos(i + ctx.random().nextInt(16), ctx.random().nextInt(k - 16) + 8, j + ctx.random().nextInt(16)); - generate(templateManager, blockpos, rand, components); - this.recalculateStructureSize(); + generate(ctx.structureManager(), blockpos, ctx.random(), pieces); } enum RoomType { @@ -82,7 +87,7 @@ enum RoomType { } interface ICatacombFactory { - StructurePiece create(TemplateManager tm, BlockPos pos, Random random); + StructurePiece create(StructureManager tm, BlockPos pos, Random random); } static ICatacombFactory[][] POOLS = new ICatacombFactory[][]{ @@ -132,9 +137,9 @@ ICatacombFactory roomFor(RoomType type, Random random) { return pool[random.nextInt(pool.length)]; } - BlockPos adjDims(ResourceLocation rl, TemplateManager tm) { - Template t = tm.getTemplate(rl); - BlockPos dims = t.getSize(); + BlockPos adjDims(ResourceLocation rl, StructureManager tm) { + StructureTemplate t = tm.get(rl).get(); + Vec3i dims = t.getSize(); return new BlockPos((dims.getX() - 3) / 4, 0, (dims.getZ() - 3) / 4); } @@ -174,11 +179,11 @@ BlockPos tryPlace(Map rooms, BlockPos desired, int w, int h) boolean can = true; for (int i = 0; i < w; i ++) { for (int j = 0; j < h; j ++) { - if (rooms.getOrDefault(desired.add(i, 0, j), RoomType.CORRIDOR) != RoomType.CORRIDOR) + if (rooms.getOrDefault(desired.offset(i, 0, j), RoomType.CORRIDOR) != RoomType.CORRIDOR) can = false; } } - if (can) return desired.add(-xx, 0, -yy); + if (can) return desired.offset(-xx, 0, -yy); } } return null; @@ -188,20 +193,20 @@ void setRoom(Map rooms, Set edges, RoomType type, Bloc rooms.put(pos, type); for (int i = 0; i < w; i ++) { for (int j = 0; j < h; j ++) { - if (i != 0 || j != 0) rooms.put(pos.add(i, 0, j), RoomType.EMPTY); + if (i != 0 || j != 0) rooms.put(pos.offset(i, 0, j), RoomType.EMPTY); if (i > 0) { - edges.remove(new Edge(pos.add(i, 0, j), pos.add(i - 1, 0, j), 0)); - edges.remove(new Edge(pos.add(i - 1, 0, j), pos.add(i, 0, j), 0)); + edges.remove(new Edge(pos.offset(i, 0, j), pos.offset(i - 1, 0, j), 0)); + edges.remove(new Edge(pos.offset(i - 1, 0, j), pos.offset(i, 0, j), 0)); } if (j > 0) { - edges.remove(new Edge(pos.add(i, 0, j), pos.add(i, 0, j - 1), 0)); - edges.remove(new Edge(pos.add(i, 0, j - 1), pos.add(i, 0, j), 0)); + edges.remove(new Edge(pos.offset(i, 0, j), pos.offset(i, 0, j - 1), 0)); + edges.remove(new Edge(pos.offset(i, 0, j - 1), pos.offset(i, 0, j), 0)); } } } } - void generate(TemplateManager tm, BlockPos pos, Random random, List components) { + void generate(StructureManager tm, BlockPos pos, Random random, StructurePiecesBuilder pieces) { // components.add(new CatacombPieces.CorridorCenter(templateManager, blockpos, rand)); int size = (random.nextInt(3) + 2) * 16 + 3; Map rooms = new HashMap<>(); @@ -271,16 +276,16 @@ void generate(TemplateManager tm, BlockPos pos, Random random, List e : rooms.entrySet()) { ICatacombFactory factory = e.getValue() == RoomType.EMPTY ? null : roomFor(e.getValue(), random); - BlockPos loc = pos.add(e.getKey().getX() * 4, 0, e.getKey().getZ() * 4); + BlockPos loc = pos.offset(e.getKey().getX() * 4, 0, e.getKey().getZ() * 4); switch (e.getValue()) { case SMALL_ROOM: - components.add(factory.create(tm, loc, random)); + pieces.addPiece(factory.create(tm, loc, random)); break; case MEDIUM_ROOM: - components.add(factory.create(tm, loc, random)); + pieces.addPiece(factory.create(tm, loc, random)); break; case CORRIDOR: - components.add(factory.create(tm, loc, random)); + pieces.addPiece(factory.create(tm, loc, random)); break; default: break; @@ -292,17 +297,16 @@ void generate(TemplateManager tm, BlockPos pos, Random random, List { - public LabStructure(Codec codec) { - super(codec); +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.core.RegistryAccess; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.world.level.levelgen.structure.StructureStart; +import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; +import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + +public class LabStructure extends StructureFeature { + public LabStructure(Codec codec) { + super(codec, PieceGeneratorSupplier.simple(LabStructure::isFeatureChunk, new LabPieceGenerator())); } @Override - public GenerationStage.Decoration getDecorationStage() { - return GenerationStage.Decoration.UNDERGROUND_STRUCTURES; + public GenerationStep.Decoration step() { + return GenerationStep.Decoration.UNDERGROUND_STRUCTURES; } + + static Random rand = new Random(); - @Override - public IStartFactory getStartFactory() { - return Start::new; - } - - @Override - protected boolean func_230363_a_(ChunkGenerator generator, BiomeProvider provider, long seed, SharedSeedRandom rand, int chunkX, int chunkZ, Biome biome, ChunkPos pos, NoFeatureConfig config) { - int i = chunkX >> 4; - int j = chunkZ >> 4; - rand.setSeed((long) (i ^ j << 4) ^ seed); + static boolean isFeatureChunk(PieceGeneratorSupplier.Context ctx) { + int i = ctx.chunkPos().x >> 4; + int j = ctx.chunkPos().z >> 4; + rand.setSeed((long) (i ^ j << 4) * 1086585193); double prob = rand.nextInt(10000) / 10000.0f; return prob < (1 / Config.LAB_RARITY.get()); } @Override - public String getStructureName() { + public String getFeatureName() { return new ResourceLocation(Eidolon.MODID, "lab").toString(); } - - public static class Start extends StructureStart { - public Start(Structure config, int chunkX, int chunkZ, MutableBoundingBox bounds, int refs, long seed) { - super(config, chunkX, chunkZ, bounds, refs, seed); - } - - public void func_230364_a_(DynamicRegistries registries, ChunkGenerator generator, TemplateManager templateManager, int chunkX, int chunkZ, Biome biome, NoFeatureConfig config) { - int i = chunkX * 16; - int j = chunkZ * 16; - int k = Math.min(generator.getSeaLevel(), generator.getNoiseHeight(i, j, Heightmap.Type.OCEAN_FLOOR_WG)); + + public static class LabPieceGenerator implements PieceGenerator { + @Override + public void generatePieces(StructurePiecesBuilder pieces, Context ctx) { + int i = ctx.chunkPos().x * 16; + int j = ctx.chunkPos().z * 16; + int k = Math.min(ctx.chunkGenerator().getSeaLevel(), ctx.chunkGenerator().getFirstFreeHeight(i, j, Heightmap.Types.OCEAN_FLOOR_WG, ctx.heightAccessor())); if (k < 33) k = 33; - BlockPos blockpos = new BlockPos(i + rand.nextInt(16), rand.nextInt(k - 32) + 8, j + rand.nextInt(16)); - Rotation rotation = Rotation.randomRotation(rand); - - components.add(new Piece(templateManager, PART, blockpos, rotation, rand)); - this.recalculateStructureSize(); - } + BlockPos blockpos = new BlockPos(i + ctx.random().nextInt(16), ctx.random().nextInt(k - 32) + 8, j + ctx.random().nextInt(16)); + + pieces.addPiece(new RandomlyRotatedPiece(WorldGen.LAB_PIECE, PART, ctx.structureManager(), blockpos, ctx.random())); + } } private static final ResourceLocation PART = new ResourceLocation(Eidolon.MODID,"lab"); - - public static class Piece extends TemplateStructurePiece { - private ResourceLocation loc; - private Rotation rotation; - - public Piece(IStructurePieceType structurePieceTypeIn, CompoundNBT nbt) { - super(structurePieceTypeIn, nbt); - this.loc = new ResourceLocation(nbt.getString("template")); - this.rotation = Rotation.valueOf(nbt.getString("rot")); - } - - public Piece(TemplateManager templateManager, CompoundNBT nbt) { - this(WorldGen.LAB_PIECE, nbt); - Template part = templateManager.getTemplateDefaulted(PART); - PlacementSettings placement = (new PlacementSettings()).setRotation(this.rotation).setMirror(Mirror.NONE).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(PART); - } - - public Piece(TemplateManager templateManager, ResourceLocation template, BlockPos pos, Rotation rot, Random random) { - super(WorldGen.LAB_PIECE, 0); - this.templatePosition = pos; - this.rotation = rot; - this.loc = template; - - Template part = templateManager.getTemplateDefaulted(PART); - PlacementSettings placement = (new PlacementSettings()).setRotation(this.rotation).setMirror(Mirror.NONE).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(PART); - } - - @Override - protected void readAdditional(CompoundNBT tagCompound) { - super.readAdditional(tagCompound); - tagCompound.putString("template", loc.toString()); - tagCompound.putString("rot", rotation.name()); - } - - @Override - protected void handleDataMarker(String function, BlockPos pos, IServerWorld worldIn, Random rand, MutableBoundingBox sbb) { - // - } - } } diff --git a/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java b/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java index 72b9337..8e7d64d 100644 --- a/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java +++ b/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java @@ -1,34 +1,23 @@ package elucent.eidolon.world; -import elucent.eidolon.Eidolon; -import elucent.eidolon.WorldGen; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.Mirror; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Rotation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MutableBoundingBox; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.gen.feature.structure.IStructurePieceType; -import net.minecraft.world.gen.feature.structure.TemplateStructurePiece; -import net.minecraft.world.gen.feature.template.BlockIgnoreStructureProcessor; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.gen.feature.template.TemplateManager; - import java.util.Random; -public class RandomlyRotatedPiece extends BasicPiece { +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - public RandomlyRotatedPiece(IStructurePieceType structurePieceTypeIn, CompoundNBT nbt) { - super(structurePieceTypeIn, nbt); - } +public class RandomlyRotatedPiece extends BasicPiece { - public RandomlyRotatedPiece(IStructurePieceType type, ResourceLocation key, TemplateManager templateManager, CompoundNBT nbt) { - super(type, key, templateManager, nbt); + public RandomlyRotatedPiece(StructurePieceType structurePieceTypeIn, CompoundTag nbt, StructureManager manager) { + super(structurePieceTypeIn, nbt, manager); } - public RandomlyRotatedPiece(IStructurePieceType type, ResourceLocation key, TemplateManager templateManager, BlockPos pos, Random random) { + public RandomlyRotatedPiece(StructurePieceType type, ResourceLocation key, StructureManager templateManager, BlockPos pos, Random random) { super(type, key, templateManager, pos, Rotation.NONE, Mirror.NONE, random); } } diff --git a/src/main/java/elucent/eidolon/world/StrayTowerStructure.java b/src/main/java/elucent/eidolon/world/StrayTowerStructure.java index 6ce6f29..02a4c0e 100644 --- a/src/main/java/elucent/eidolon/world/StrayTowerStructure.java +++ b/src/main/java/elucent/eidolon/world/StrayTowerStructure.java @@ -1,119 +1,77 @@ package elucent.eidolon.world; +import java.util.Random; + import com.mojang.serialization.Codec; + import elucent.eidolon.Config; import elucent.eidolon.Eidolon; import elucent.eidolon.WorldGen; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.*; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.MutableBoundingBox; -import net.minecraft.util.registry.DynamicRegistries; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.provider.BiomeProvider; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.Heightmap; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.gen.feature.structure.IStructurePieceType; -import net.minecraft.world.gen.feature.structure.Structure; -import net.minecraft.world.gen.feature.structure.StructureStart; -import net.minecraft.world.gen.feature.structure.TemplateStructurePiece; -import net.minecraft.world.gen.feature.template.BlockIgnoreStructureProcessor; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraft.world.gen.feature.template.TemplateManager; - -import java.util.Random; - -public class StrayTowerStructure extends Structure { - public StrayTowerStructure(Codec codec) { - super(codec); +import elucent.eidolon.world.LabStructure.LabPieceGenerator; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.core.RegistryAccess; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.feature.StructurePieceType; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.world.level.levelgen.structure.StructureStart; +import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; +import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator.Context; +import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; + +public class StrayTowerStructure extends StructureFeature { + public StrayTowerStructure(Codec codec) { + super(codec, PieceGeneratorSupplier.simple(StrayTowerStructure::isFeatureChunk, new StrayTowerPieceGenerator())); } @Override - public GenerationStage.Decoration getDecorationStage() { - return GenerationStage.Decoration.UNDERGROUND_STRUCTURES; + public GenerationStep.Decoration step() { + return GenerationStep.Decoration.UNDERGROUND_STRUCTURES; } + + static Random rand = new Random(); - @Override - public IStartFactory getStartFactory() { - return Start::new; - } - - @Override - protected boolean func_230363_a_(ChunkGenerator generator, BiomeProvider provider, long seed, SharedSeedRandom rand, int chunkX, int chunkZ, Biome biome, ChunkPos pos, NoFeatureConfig config) { - int i = chunkX >> 4; - int j = chunkZ >> 4; - rand.setSeed((long) (i ^ j << 4) ^ seed); + static boolean isFeatureChunk(PieceGeneratorSupplier.Context ctx) { + int i = ctx.chunkPos().x >> 4; + int j = ctx.chunkPos().z >> 4; + rand.setSeed((long) (i ^ j << 4) * 1556190469); double prob = rand.nextInt(10000) / 10000.0f; return prob < (1 / Config.STRAY_TOWER_RARITY.get()); } + + public static class StrayTowerPieceGenerator implements PieceGenerator { + @Override + public void generatePieces(StructurePiecesBuilder pieces, Context ctx) { + int i = ctx.chunkPos().x * 16; + int j = ctx.chunkPos().z * 16; + pieces.addPiece(new RandomlyRotatedPiece(WorldGen.STRAY_TOWER_PIECE, PART, ctx.structureManager(), new BlockPos(i, ctx.chunkGenerator().getBaseHeight(i, j, Heightmap.Types.WORLD_SURFACE_WG, ctx.heightAccessor()), j), ctx.random())); + } + } @Override - public String getStructureName() { + public String getFeatureName() { return new ResourceLocation(Eidolon.MODID, "stray_tower").toString(); } - public static class Start extends StructureStart { - public Start(Structure config, int chunkX, int chunkZ, MutableBoundingBox bounds, int refs, long seed) { - super(config, chunkX, chunkZ, bounds, refs, seed); - } - - public void func_230364_a_(DynamicRegistries registries, ChunkGenerator generator, TemplateManager templateManager, int chunkX, int chunkZ, Biome biome, NoFeatureConfig config) { - int i = chunkX * 16 + rand.nextInt(16); - int j = chunkZ * 16 + rand.nextInt(16); - Rotation rotation = Rotation.randomRotation(rand); - - components.add(new Piece(templateManager, PART, new BlockPos(i, generator.getHeight(i, j, Heightmap.Type.WORLD_SURFACE_WG), j), rotation, rand)); - this.recalculateStructureSize(); - } - } - private static final ResourceLocation PART = new ResourceLocation(Eidolon.MODID,"stray_tower"); - - public static class Piece extends TemplateStructurePiece { - private ResourceLocation loc; - private Rotation rotation; - - public Piece(IStructurePieceType structurePieceTypeIn, CompoundNBT nbt) { - super(structurePieceTypeIn, nbt); - this.loc = new ResourceLocation(nbt.getString("template")); - this.rotation = Rotation.valueOf(nbt.getString("rot")); - } - - public Piece(TemplateManager templateManager, CompoundNBT nbt) { - this(WorldGen.STRAY_TOWER_PIECE, nbt); - Template part = templateManager.getTemplateDefaulted(PART); - PlacementSettings placement = (new PlacementSettings()).setRotation(this.rotation).setMirror(Mirror.NONE).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(PART); - } - - public Piece(TemplateManager templateManager, ResourceLocation template, BlockPos pos, Rotation rot, Random random) { - super(WorldGen.STRAY_TOWER_PIECE, 0); - this.templatePosition = pos.down(10); - this.rotation = rot; - this.loc = template; - - Template part = templateManager.getTemplateDefaulted(PART); - PlacementSettings placement = (new PlacementSettings()).setRotation(this.rotation).setMirror(Mirror.NONE).addProcessor(BlockIgnoreStructureProcessor.STRUCTURE_BLOCK); - this.setup(part, this.templatePosition, placement); - this.template = templateManager.getTemplate(PART); - } - - @Override - protected void readAdditional(CompoundNBT tagCompound) { - super.readAdditional(tagCompound); - tagCompound.putString("template", loc.toString()); - tagCompound.putString("rot", rotation.name()); - } - - @Override - protected void handleDataMarker(String function, BlockPos pos, IServerWorld worldIn, Random rand, MutableBoundingBox sbb) { - // - } - } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 0afe83c..ace7d6b 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,9 +1,9 @@ -public net.minecraft.world.gen.feature.structure.TemplateStructurePiece field_186178_c # templatePosition -public net.minecraft.world.gen.feature.structure.Structure field_236385_u_ # structureList -public-f net.minecraft.world.gen.feature.structure.Structure func_236392_a_(Lnet/minecraft/world/gen/settings/StructureSeparationSettings;JLnet/minecraft/util/SharedSeedRandom;II)Lnet/minecraft/util/math/ChunkPos; #findPosForPos -public-f net.minecraft.world.gen.settings.DimensionStructuresSettings field_236193_d_ # field_236193_d_ -public-f net.minecraft.world.gen.FlatGenerationSettings field_202247_j # STRUCTURES +public net.minecraft.world.level.levelgen.structure.TemplateStructurePiece f_73658_ # templatePosition +public net.minecraft.world.level.levelgen.feature.StructureFeature f_67032_ # structureList +public-f net.minecraft.world.level.levelgen.feature.StructureFeature m_67067_(Lnet/minecraft/world/level/levelgen/feature/configurations/StructureFeatureConfiguration;JLnet/minecraft/world/level/levelgen/WorldgenRandom;II)Lnet/minecraft/world/level/ChunkPos; #findPosForPos +public-f net.minecraft.world.level.levelgen.StructureSettings f_64582_ # field_236193_d_ +public-f net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings f_70349_ # STRUCTURES public net.minecraft.world.gen.DimensionSettings field_242740_q # INSTANCE -public-f net.minecraft.world.gen.settings.DimensionStructuresSettings field_236191_b_ # DEFAULT_STRUCTURES -public-f net.minecraft.world.gen.feature.structure.Structure field_236384_t_ # field_236384_t_ -public net.minecraft.world.gen.SpellcastingIllagerEntity field_193089_bx # activeSpell \ No newline at end of file +public-f net.minecraft.world.level.levelgen.StructureSettings f_64580_ # DEFAULT_STRUCTURES +public-f net.minecraft.world.level.levelgen.feature.StructureFeature f_67031_ # field_236384_t_ +public net.minecraft.world.gen.SpellcastingIllagerEntity field_193089_bx # activeSpell \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index d394393..4347227 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" #mandatory -loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +loaderVersion="[39,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. license="All rights reserved" issueTrackerURL="http://my.issue.tracker/" #optional [[mods]] #mandatory @@ -17,6 +17,6 @@ A spooky magic mod about necromancy. [[dependencies.eidolon]] modId="curios" mandatory=true - versionRange="[FORGE-1.16.3,)" + versionRange="[FORGE-1.18.1,)" ordering="AFTER" side="BOTH" \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/avennian_sprig.json b/src/main/resources/assets/eidolon/blockstates/avennian_sprig.json new file mode 100644 index 0000000..6cb788d --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/avennian_sprig.json @@ -0,0 +1,10 @@ +{ + "variants": { + "age=0": { + "model": "eidolon:block/avennian_sprig_0" + }, + "age=1": { + "model": "eidolon:block/avennian_sprig_1" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/cistern.json b/src/main/resources/assets/eidolon/blockstates/cistern.json new file mode 100644 index 0000000..0cb259a --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/cistern.json @@ -0,0 +1,16 @@ +{ + "variants": { + "top=false,bottom=false": { + "model": "eidolon:item/cistern" + }, + "top=true,bottom=false": { + "model": "eidolon:block/cistern_lower" + }, + "top=true,bottom=true": { + "model": "eidolon:block/cistern_mid" + }, + "top=false,bottom=true": { + "model": "eidolon:block/cistern_upper" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/deep_lead_ore.json b/src/main/resources/assets/eidolon/blockstates/deep_lead_ore.json new file mode 100644 index 0000000..f8d18d2 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/deep_lead_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/deep_lead_ore" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/deep_silver_ore.json b/src/main/resources/assets/eidolon/blockstates/deep_silver_ore.json new file mode 100644 index 0000000..6a91db1 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/deep_silver_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/deep_silver_ore" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/glass_tube.json b/src/main/resources/assets/eidolon/blockstates/glass_tube.json new file mode 100644 index 0000000..e33b804 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/glass_tube.json @@ -0,0 +1,375 @@ +{ + "multipart": [ + { + "when": { + "OR": [ + { "in": "up" }, + { "out": "up" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_up" + } + }, + { + "when": { + "OR": [ + { "in": "down" }, + { "out": "down" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_down" + } + }, + { + "when": { + "OR": [ + { "in": "north" }, + { "out": "north" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_north" + } + }, + { + "when": { + "OR": [ + { "in": "east" }, + { "out": "east" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_east" + } + }, + { + "when": { + "OR": [ + { "in": "south" }, + { "out": "south" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_south" + } + }, + { + "when": { + "OR": [ + { "in": "west" }, + { "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_west" + } + }, + { + "when": { + "OR": [ + { "in": "west", "out": "east" }, + { "in": "east", "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_straight", + "y": 90 + } + }, + { + "when": { + "OR": [ + { "in": "north", "out": "south" }, + { "in": "south", "out": "north" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_straight" + } + }, + { + "when": { + "OR": [ + { "in": "up", "out": "down" }, + { "in": "down", "out": "up" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_straight", + "x": 90 + } + }, + { + "when": { + "OR": [ + { "in": "north", "out": "up" }, + { "in": "up", "out": "north" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 270, + "y": 90 + } + }, + { + "when": { + "OR": [ + { "in": "east", "out": "up" }, + { "in": "up", "out": "east" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 270, + "y": 180 + } + }, + { + "when": { + "OR": [ + { "in": "south", "out": "up" }, + { "in": "up", "out": "south" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 270, + "y": 270 + } + }, + { + "when": { + "OR": [ + { "in": "west", "out": "up" }, + { "in": "up", "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 270 + } + }, + { + "when": { + "OR": [ + { "in": "north", "out": "down" }, + { "in": "down", "out": "north" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 90, + "y": 90 + } + }, + { + "when": { + "OR": [ + { "in": "east", "out": "down" }, + { "in": "down", "out": "east" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 90, + "y": 180 + } + }, + { + "when": { + "OR": [ + { "in": "south", "out": "down" }, + { "in": "down", "out": "south" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 90, + "y": 270 + } + }, + { + "when": { + "OR": [ + { "in": "west", "out": "down" }, + { "in": "down", "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "x": 90, + "y": 0 + } + }, + { + "when": { + "OR": [ + { "in": "west", "out": "north" }, + { "in": "north", "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend" + } + }, + { + "when": { + "OR": [ + { "in": "east", "out": "north" }, + { "in": "north", "out": "east" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "y": 90 + } + }, + { + "when": { + "OR": [ + { "in": "east", "out": "south" }, + { "in": "south", "out": "east" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "y": 180 + } + }, + { + "when": { + "OR": [ + { "in": "west", "out": "south" }, + { "in": "south", "out": "west" } + ] + }, + "apply": { + "model": "eidolon:block/glass_tube_bend", + "y": 270 + } + }, + { + "when": { + "attachin": false, + "in": "west" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "y": 270 + } + }, + { + "when": { + "attachin": false, + "in": "north" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "y": 0 + } + }, + { + "when": { + "attachin": false, + "in": "east" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "y": 90 + } + }, + { + "when": { + "attachin": false, + "in": "south" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "y": 180 + } + }, + { + "when": { + "attachin": false, + "in": "up" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "x": 270 + } + }, + { + "when": { + "attachin": false, + "in": "down" + }, + "apply": { + "model": "eidolon:block/glass_tube_input", + "x": 90 + } + }, + { + "when": { + "attachout": false, + "out": "west" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "y": 270 + } + }, + { + "when": { + "attachout": false, + "out": "north" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "y": 0 + } + }, + { + "when": { + "attachout": false, + "out": "east" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "y": 90 + } + }, + { + "when": { + "attachout": false, + "out": "south" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "y": 180 + } + }, + { + "when": { + "attachout": false, + "out": "up" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "x": 270 + } + }, + { + "when": { + "attachout": false, + "out": "down" + }, + "apply": { + "model": "eidolon:block/glass_tube_output", + "x": 90 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/incubator.json b/src/main/resources/assets/eidolon/blockstates/incubator.json new file mode 100644 index 0000000..f52ea89 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/incubator.json @@ -0,0 +1,10 @@ +{ + "variants": { + "half=bottom": { + "model": "eidolon:block/incubator_bottom" + }, + "half=top": { + "model": "eidolon:block/incubator_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/merammer_root.json b/src/main/resources/assets/eidolon/blockstates/merammer_root.json new file mode 100644 index 0000000..e589de4 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/merammer_root.json @@ -0,0 +1,10 @@ +{ + "variants": { + "age=0": { + "model": "eidolon:block/merammer_root_0" + }, + "age=1": { + "model": "eidolon:block/merammer_root_1" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/oanna_bloom.json b/src/main/resources/assets/eidolon/blockstates/oanna_bloom.json new file mode 100644 index 0000000..8504c20 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/oanna_bloom.json @@ -0,0 +1,10 @@ +{ + "variants": { + "age=0": { + "model": "eidolon:block/oanna_bloom_0" + }, + "age=1": { + "model": "eidolon:block/oanna_bloom_1" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/obelisk.json b/src/main/resources/assets/eidolon/blockstates/obelisk.json new file mode 100644 index 0000000..2ae3603 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/obelisk.json @@ -0,0 +1,16 @@ +{ + "variants": { + "top=false,bottom=false": { + "model": "eidolon:item/obelisk" + }, + "top=true,bottom=false": { + "model": "eidolon:block/obelisk_bottom" + }, + "top=true,bottom=true": { + "model": "eidolon:block/obelisk_mid" + }, + "top=false,bottom=true": { + "model": "eidolon:block/obelisk_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/raw_lead_block.json b/src/main/resources/assets/eidolon/blockstates/raw_lead_block.json new file mode 100644 index 0000000..3a83737 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/raw_lead_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/raw_lead_block" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/raw_silver_block.json b/src/main/resources/assets/eidolon/blockstates/raw_silver_block.json new file mode 100644 index 0000000..114797b --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/raw_silver_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/raw_silver_block" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/shadow_gem_block.json b/src/main/resources/assets/eidolon/blockstates/shadow_gem_block.json new file mode 100644 index 0000000..4bcfbb6 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/shadow_gem_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/shadow_gem_block" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/sildrian_seed.json b/src/main/resources/assets/eidolon/blockstates/sildrian_seed.json new file mode 100644 index 0000000..624667d --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/sildrian_seed.json @@ -0,0 +1,10 @@ +{ + "variants": { + "age=0": { + "model": "eidolon:block/sildrian_seed_0" + }, + "age=1": { + "model": "eidolon:block/sildrian_seed_1" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/silver_block.json b/src/main/resources/assets/eidolon/blockstates/silver_block.json new file mode 100644 index 0000000..aacdd6e --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/silver_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/silver_block" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/silver_ore.json b/src/main/resources/assets/eidolon/blockstates/silver_ore.json new file mode 100644 index 0000000..ac90234 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/silver_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/silver_ore" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/lang/en_us.json b/src/main/resources/assets/eidolon/lang/en_us.json index b8c71c6..19affbb 100644 --- a/src/main/resources/assets/eidolon/lang/en_us.json +++ b/src/main/resources/assets/eidolon/lang/en_us.json @@ -18,9 +18,16 @@ "lore.eidolon.gravity_belt": "It feels light.", "lore.eidolon.glass_hand": "Risk and reward.", "lore.eidolon.top_hat": "Indubitably.", + "lore.eidolon.athame": "It feels red-powerful.", + "lore.eidolon.angels_sight": "It seems to be judging you.", + "lore.eidolon.terminus_mirror": "Gaze into whirling infinite.", "item.eidolon.lead_ingot": "Lead Ingot", + "item.eidolon.raw_lead": "Raw Lead", "item.eidolon.lead_nugget": "Lead Nugget", + "item.eidolon.silver_ingot": "Silver Ingot", + "item.eidolon.raw_silver": "Raw Silver", + "item.eidolon.silver_nugget": "Silver Nugget", "item.eidolon.pewter_blend": "Pewter Blend", "item.eidolon.pewter_ingot": "Pewter Ingot", "item.eidolon.pewter_nugget": "Pewter Nugget", @@ -28,6 +35,15 @@ "item.eidolon.arcane_gold_ingot": "Arcane Gold Ingot", "item.eidolon.arcane_gold_nugget": "Arcane Gold Nugget", "item.eidolon.gold_inlay": "Gold Inlay", + "item.eidolon.silver_helmet": "Silver Helmet", + "item.eidolon.silver_chestplate": "Silver Chestplate", + "item.eidolon.silver_leggings": "Silver Leggings", + "item.eidolon.silver_boots": "Silver Boots", + "item.eidolon.silver_sword": "Silver Sword", + "item.eidolon.silver_pickaxe": "Silver Pickaxe", + "item.eidolon.silver_axe": "Silver Axe", + "item.eidolon.silver_shovel": "Silver Shovel", + "item.eidolon.silver_hoe": "Silver Hoe", "item.eidolon.top_hat": "Top Hat", "item.eidolon.basic_ring": "Basic Ring", "item.eidolon.basic_amulet": "Basic Amulet", @@ -65,6 +81,7 @@ "item.eidolon.spawn_wraith": "Spawn Wraith", "item.eidolon.spawn_zombie_brute": "Spawn Zombie Brute", "item.eidolon.spawn_necromancer": "Spawn Necromancer", + "item.eidolon.spawn_slimy_slug": "Spawn Slug", "item.eidolon.codex": "Ars Ecclesia", "item.eidolon.music_disc_parousia": "Music Disc", "item.eidolon.reversal_pick": "Pickaxe of Inversion", @@ -86,11 +103,50 @@ "item.minecraft.splash_potion.effect.long_chilled": "Splash Potion of Chilling", "item.minecraft.tipped_arrow.effect.long_chilled": "Arrow of Chilling", "item.minecraft.lingering_potion.effect.long_chilled": "Lingering Potion of Chilling", + "item.minecraft.potion.effect.reinforced": "Potion of Reinforcing", + "item.minecraft.splash_potion.effect.reinforced": "Splash Potion of Reinforcing", + "item.minecraft.tipped_arrow.effect.reinforced": "Arrow of Reinforcing", + "item.minecraft.lingering_potion.effect.reinforced": "Lingering Potion of Reinforcing", + "item.minecraft.potion.effect.long_reinforced": "Potion of Reinforcing", + "item.minecraft.splash_potion.effect.long_reinforced": "Splash Potion of Reinforcing", + "item.minecraft.tipped_arrow.effect.long_reinforced": "Arrow of Reinforcing", + "item.minecraft.lingering_potion.effect.long_reinforced": "Lingering Potion of Reinforcing", + "item.minecraft.potion.effect.strong_reinforced": "Potion of Reinforcing", + "item.minecraft.splash_potion.effect.strong_reinforced": "Splash Potion of Reinforcing", + "item.minecraft.tipped_arrow.effect.strong_reinforced": "Arrow of Reinforcing", + "item.minecraft.lingering_potion.effect.strong_reinforced": "Lingering Potion of Reinforcing", + "item.minecraft.potion.effect.vulnerable": "Potion of Vulnerability", + "item.minecraft.splash_potion.effect.vulnerable": "Splash Potion of Vulnerability", + "item.minecraft.tipped_arrow.effect.vulnerable": "Arrow of Vulnerability", + "item.minecraft.lingering_potion.effect.vulnerable": "Lingering Potion of Vulnerability", + "item.minecraft.potion.effect.long_vulnerable": "Potion of Vulnerability", + "item.minecraft.splash_potion.effect.long_vulnerable": "Splash Potion of Vulnerability", + "item.minecraft.tipped_arrow.effect.long_vulnerable": "Arrow of Vulnerability", + "item.minecraft.lingering_potion.effect.long_vulnerable": "Lingering Potion of Vulnerability", + "item.minecraft.potion.effect.strong_vulnerable": "Potion of Vulnerability", + "item.minecraft.splash_potion.effect.strong_vulnerable": "Splash Potion of Vulnerability", + "item.minecraft.tipped_arrow.effect.strong_vulnerable": "Arrow of Vulnerability", + "item.minecraft.lingering_potion.effect.strong_vulnerable": "Lingering Potion of Vulnerability", + "item.eidolon.spawn_raven": "Spawn Raven", + "item.eidolon.raven_feather": "Raven Feather", + "item.eidolon.alchemists_tongs": "Alchemist's Tongs", + "item.eidolon.athame": "Athame", + "item.eidolon.terminus_mirror": "Mirror of Terminus", + "item.eidolon.angels_sight": "Archangel's Sight", + "item.eidolon.merammer_resin": "Merammer Resin", + "item.eidolon.enervating_ring": "Enervating Ring", "block.eidolon.lead_block": "Lead Block", "block.eidolon.lead_ore": "Lead Ore", + "block.eidolon.raw_lead_block": "Block of Raw Lead", + "block.eidolon.deep_lead_ore": "Deepslate Lead Ore", + "block.eidolon.silver_block": "Silver Block", + "block.eidolon.silver_ore": "Silver Ore", + "block.eidolon.raw_silver_block": "Block of Raw Silver", + "block.eidolon.deep_silver_ore": "Deepslate Silver Ore", "block.eidolon.pewter_block": "Pewter Block", "block.eidolon.arcane_gold_block": "Arcane Gold Block", + "block.eidolon.shadow_gem_block": "Shadow Gem Block", "block.eidolon.smooth_stone_bricks": "Smooth Stone Bricks", "block.eidolon.smooth_stone_bricks_slab": "Smooth Stone Bricks Slab", "block.eidolon.smooth_stone_bricks_stairs": "Smooth Stone Bricks Stairs", @@ -106,9 +162,14 @@ "block.eidolon.polished_wood_pillar": "Polished Wood Pillar", "block.eidolon.brazier": "Brazier", "block.eidolon.planter": "Planter", + "block.eidolon.oanna_bloom": "Flowering Oanna", + "block.eidolon.merammer_root": "Merammer Root", + "block.eidolon.sildrian_seed": "Sildrian Seed", + "block.eidolon.avennian_sprig": "Sprig of Avenna", "block.eidolon.crucible": "Crucible", "block.eidolon.crafting_altar": "Crafting Altar", "block.eidolon.plinth": "Plinth", + "block.eidolon.obelisk": "Obelisk", "block.eidolon.stone_hand": "Stone Hand", "block.eidolon.enchanted_ash": "Enchanted Ash", "block.eidolon.necrotic_focus": "Necrotic Focus", @@ -122,6 +183,9 @@ "block.eidolon.worktable": "Magic Workbench", "block.eidolon.soul_enchanter": "Soul Enchanter", "block.eidolon.wooden_brewing_stand": "Apothecary Stand", + "block.eidolon.incubator": "Vesseler Jar", + "block.eidolon.glass_tube": "Glass Tube", + "block.eidolon.cistern": "Cistern", "entity.eidolon.zombie_brute": "Zombie Brute", "entity.eidolon.wraith": "Wraith", @@ -129,6 +193,7 @@ "entity.eidolon.soulfire_projectile": "Soulfire Projectile", "entity.eidolon.bonechill_projectile": "Bonechill Projectile", "entity.eidolon.chant_caster": "Chant Caster", + "entity.eidolon.slimy_slug": "Slug", "death.attack.ritual": "%s got too involved in a ritual", "death.attack.ritual.player": "%s was sacrificed by %s", @@ -137,6 +202,8 @@ "effect.eidolon.chilled": "Chilled", "effect.eidolon.anchored": "Anchored", + "effect.eidolon.reinforced": "Reinforced", + "effect.eidolon.vulnerable": "Vulnerable", "eidolon.subtitle.cast_soulfire": "Soulfire spell", "eidolon.subtitle.cast_bonechill": "Bonechill spell", @@ -159,6 +226,7 @@ "eidolon.sign.blood": "Blood", "eidolon.sign.soul": "Soul", "eidolon.sign.mind": "Mind", + "eidolon.sign.flame": "Flame", "eidolon.codex.chant_hover": "Chant", "eidolon.codex.cancel_hover": "Clear", diff --git a/src/main/resources/assets/eidolon/models/block/aludel.json b/src/main/resources/assets/eidolon/models/block/aludel.json new file mode 100644 index 0000000..111d2a6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/aludel.json @@ -0,0 +1,177 @@ +{ + "credit": "Made with Blockbench", + "parent": "minecraft:block/block", + "textures": { + "0": "eidolon:block/aludel_parts", + "1": "eidolon:block/aludel_power", + "2": "eidolon:block/aludel_side", + "3": "eidolon:block/aludel_front", + "4": "eidolon:block/aludel_jar_side", + "5": "eidolon:block/aludel_jar_top", + "particle": "eidolon:block/aludel_parts" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 4], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 0, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 4, 16], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 4], "texture": "#1"}, + "down": {"uv": [0, 16, 16, 12], "texture": "#1"} + } + }, + { + "from": [0, 0, 4], + "to": [4, 11, 12], + "faces": { + "east": {"uv": [4, 5, 12, 16], "texture": "#2"}, + "west": {"uv": [4, 5, 12, 16], "texture": "#2"}, + "up": {"uv": [0, 4, 8, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 8, 4], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [12, 0, 4], + "to": [16, 11, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "east": {"uv": [12, 5, 4, 16], "texture": "#2"}, + "west": {"uv": [12, 5, 4, 16], "texture": "#2"}, + "up": {"uv": [0, 8, 8, 4], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 4, 8, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4, 2, 4], + "to": [12, 16, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "east": {"uv": [12, 0, 4, 14], "texture": "#3"}, + "south": {"uv": [12, 0, 4, 14], "texture": "#3"}, + "west": {"uv": [12, 0, 4, 14], "texture": "#3"} + } + }, + { + "from": [4, 0, 12], + "to": [12, 2, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [12, 14, 4, 16], "texture": "#3"}, + "south": {"uv": [12, 14, 4, 16], "texture": "#3"}, + "up": {"uv": [0, 0, 8, 4], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 8, 4], "texture": "#0"} + } + }, + { + "from": [4, 0, 4], + "to": [12, 2, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "down": {"uv": [8, 0, 16, 8], "texture": "#0"} + } + }, + { + "from": [0, 0, 12], + "to": [4, 16, 16], + "faces": { + "north": {"uv": [0, 0, 4, 16], "texture": "#3"}, + "east": {"uv": [12, 0, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 4, 16], "texture": "#3"}, + "west": {"uv": [12, 0, 16, 16], "texture": "#2"}, + "up": {"uv": [12, 0, 16, 4], "texture": "#2"}, + "down": {"uv": [0, 12, 4, 16], "texture": "#3"} + } + }, + { + "from": [12, 0, 12], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [4, 0, 0, 16], "texture": "#3"}, + "east": {"uv": [16, 0, 12, 16], "texture": "#2"}, + "south": {"uv": [4, 0, 0, 16], "texture": "#3"}, + "west": {"uv": [16, 0, 12, 16], "texture": "#2"}, + "up": {"uv": [16, 0, 12, 4], "texture": "#2"}, + "down": {"uv": [4, 12, 0, 16], "texture": "#3"} + } + }, + { + "from": [2, 22, 2], + "to": [14, 30, 14], + "faces": { + "north": {"uv": [0, 0, 12, 8], "texture": "#4"}, + "east": {"uv": [0, 0, 12, 8], "texture": "#4"}, + "south": {"uv": [0, 0, 12, 8], "texture": "#4"}, + "west": {"uv": [0, 0, 12, 8], "texture": "#4"}, + "up": {"uv": [0, 0, 12, 12], "texture": "#5"}, + "down": {"uv": [0, 0, 12, 12], "texture": "#5"} + } + }, + { + "from": [4, 30, 4], + "to": [12, 32, 12], + "faces": { + "north": {"uv": [8, 8, 16, 10], "texture": "#4"}, + "east": {"uv": [8, 8, 16, 10], "texture": "#4"}, + "south": {"uv": [8, 8, 16, 10], "texture": "#4"}, + "west": {"uv": [8, 8, 16, 10], "texture": "#4"}, + "up": {"uv": [0, 8, 8, 16], "texture": "#4"} + } + }, + { + "from": [0, 20, 11.99], + "to": [4, 26, 15.99], + "rotation": {"angle": -22.5, "axis": "z", "origin": [0, 20, 13.99]}, + "faces": { + "north": {"uv": [1, 8, 7, 12], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 0, 7, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [7, 8, 1, 12], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 7, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 8, 6, 12], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 8, 6, 12], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [12, 20, 11.99], + "to": [16, 26, 15.99], + "rotation": {"angle": 22.5, "axis": "z", "origin": [16, 20, 13.99]}, + "faces": { + "north": {"uv": [1, 12, 7, 8], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 4, 7, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [7, 12, 1, 8], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 4, 7, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 12, 6, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 12, 6, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [12, 20, 0.01], + "to": [16, 26, 4.01], + "rotation": {"angle": 22.5, "axis": "z", "origin": [16, 20, 2.01]}, + "faces": { + "north": {"uv": [1, 12, 7, 8], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 4, 7, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [7, 12, 1, 8], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 4, 7, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 12, 6, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 12, 6, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 20, 0.01], + "to": [4, 26, 4.01], + "rotation": {"angle": -22.5, "axis": "z", "origin": [0, 20, 2.01]}, + "faces": { + "north": {"uv": [1, 8, 7, 12], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 0, 7, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [7, 8, 1, 12], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 7, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 8, 6, 12], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 8, 6, 12], "rotation": 270, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/avennian_sprig_0.json b/src/main/resources/assets/eidolon/models/block/avennian_sprig_0.json new file mode 100644 index 0000000..3c5f567 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/avennian_sprig_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/avennian_sprig_0" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/avennian_sprig_1.json b/src/main/resources/assets/eidolon/models/block/avennian_sprig_1.json new file mode 100644 index 0000000..d572048 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/avennian_sprig_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/avennian_sprig_1" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/censer.json b/src/main/resources/assets/eidolon/models/block/censer.json new file mode 100644 index 0000000..2d17f5e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/censer.json @@ -0,0 +1,154 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/censer", + "1": "eidolon:block/censer_cage", + "particle": "eidolon:block/censer" + }, + "elements": [ + { + "from": [5.5, 1, 5.5], + "to": [10.5, 3, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [17.5, 9, 15.5]}, + "faces": { + "north": {"uv": [11, 5, 16, 7], "texture": "#0"}, + "east": {"uv": [11, 5, 16, 7], "texture": "#0"}, + "south": {"uv": [11, 5, 16, 7], "texture": "#0"}, + "west": {"uv": [11, 5, 16, 7], "texture": "#0"}, + "up": {"uv": [11, 0, 16, 5], "texture": "#0"}, + "down": {"uv": [11, 7, 16, 12], "texture": "#0"} + } + }, + { + "from": [5.5, 10, 5.5], + "to": [10.5, 11, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [17.5, 18, 15.5]}, + "faces": { + "north": {"uv": [11, 5, 16, 6], "texture": "#0"}, + "east": {"uv": [11, 5, 16, 6], "texture": "#0"}, + "south": {"uv": [11, 5, 16, 6], "texture": "#0"}, + "west": {"uv": [11, 5, 16, 6], "texture": "#0"}, + "up": {"uv": [6, 1, 11, 6], "texture": "#0"}, + "down": {"uv": [11, 0, 16, 5], "texture": "#0"} + } + }, + { + "from": [5, 10, 5], + "to": [11, 11, 11], + "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]}, + "faces": { + "north": {"uv": [0, 6, 6, 7], "rotation": 180, "texture": "#0"}, + "east": {"uv": [0, 7, 1, 13], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 6, 6, 7], "texture": "#0"}, + "west": {"uv": [5, 0, 6, 6], "rotation": 90, "texture": "#0"}, + "up": {"uv": [0, 0, 6, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 7, 6, 13], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4.5, 3, 4.5], + "to": [11.5, 10, 11.5], + "rotation": {"angle": 0, "axis": "y", "origin": [17.5, 11, 15.5]}, + "faces": { + "north": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "east": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "south": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "west": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "up": {"uv": [7, 0, 14, 7], "texture": "#1"}, + "down": {"uv": [0, 7, 7, 14], "texture": "#1"} + } + }, + { + "from": [11.5, 3, 4.5], + "to": [4.5, 10, 11.5], + "rotation": {"angle": 0, "axis": "y", "origin": [24.5, 11, 15.5]}, + "faces": { + "north": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "east": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "south": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "west": {"uv": [0, 0, 7, 7], "texture": "#1"}, + "up": {"uv": [7, 0, 14, 7], "texture": "#1"}, + "down": {"uv": [0, 7, 7, 14], "texture": "#1"} + } + }, + { + "from": [7.5, 0, 4.75], + "to": [8.5, 2, 5.75], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 0, 4.75]}, + "faces": { + "north": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "east": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "south": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "west": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "up": {"uv": [11, 12, 12, 13], "texture": "#0"}, + "down": {"uv": [11, 13, 12, 14], "texture": "#0"} + } + }, + { + "from": [7.5, 0, 10.25], + "to": [8.5, 2, 11.25], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 0, 11.25]}, + "faces": { + "north": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "east": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "south": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "west": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "up": {"uv": [11, 12, 12, 13], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 13, 12, 14], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10.25, 0, 7.5], + "to": [11.25, 2, 8.5], + "rotation": {"angle": 22.5, "axis": "z", "origin": [11.25, 0, 8]}, + "faces": { + "north": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "east": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "south": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "west": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "up": {"uv": [11, 12, 12, 13], "rotation": 90, "texture": "#0"}, + "down": {"uv": [11, 13, 12, 14], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4.75, 0, 7.5], + "to": [5.75, 2, 8.5], + "rotation": {"angle": -22.5, "axis": "z", "origin": [4.75, 0, 8]}, + "faces": { + "north": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "east": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "south": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "west": {"uv": [11, 12, 12, 14], "texture": "#0"}, + "up": {"uv": [11, 12, 12, 13], "rotation": 270, "texture": "#0"}, + "down": {"uv": [11, 13, 12, 14], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [6, 11, 6], + "to": [7, 12, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 19, 14]}, + "faces": { + "north": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "east": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "south": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "west": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "up": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "down": {"uv": [10, 0, 11, 1], "texture": "#0"} + } + }, + { + "from": [6, 11, 9], + "to": [7, 12, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 19, 17]}, + "faces": { + "north": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "east": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "south": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "west": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "up": {"uv": [10, 0, 11, 1], "texture": "#0"}, + "down": {"uv": [10, 0, 11, 1], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/cistern_lower.json b/src/main/resources/assets/eidolon/models/block/cistern_lower.json new file mode 100644 index 0000000..1010b5b --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/cistern_lower.json @@ -0,0 +1,36 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/cistern_bottom", + "1": "eidolon:block/cistern_ends", + "4": "eidolon:block/cistern_top", + "particle": "eidolon:block/cistern_bottom" + }, + "elements": [ + { + "from": [4, 0, 4], + "to": [12, 2, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 8, 12]}, + "faces": { + "north": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "east": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "south": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "west": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "down": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + }, + { + "from": [1, 2, 1], + "to": [15, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 10, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "east": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "south": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "west": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#4"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/cistern_mid.json b/src/main/resources/assets/eidolon/models/block/cistern_mid.json new file mode 100644 index 0000000..10f2980 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/cistern_mid.json @@ -0,0 +1,21 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "2": "eidolon:block/cistern_mid", + "particle": "eidolon:block/cistern_bottom" + }, + "elements": [ + { + "from": [1, 0, 1], + "to": [15, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 8, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 16], "texture": "#2"}, + "east": {"uv": [0, 0, 14, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 14, 16], "texture": "#2"}, + "west": {"uv": [0, 0, 14, 16], "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/cistern_upper.json b/src/main/resources/assets/eidolon/models/block/cistern_upper.json new file mode 100644 index 0000000..2303b43 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/cistern_upper.json @@ -0,0 +1,36 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "1": "eidolon:block/cistern_ends", + "4": "eidolon:block/cistern_top", + "5": "eidolon:block/cistern_upper", + "particle": "eidolon:block/cistern_bottom" + }, + "elements": [ + { + "from": [4, 14, 4], + "to": [12, 16, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 22, 12]}, + "faces": { + "north": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "east": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "south": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "west": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "up": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + }, + { + "from": [1, 0, 1], + "to": [15, 14, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 8, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 14], "texture": "#5"}, + "east": {"uv": [0, 0, 14, 14], "texture": "#5"}, + "south": {"uv": [0, 0, 14, 14], "texture": "#5"}, + "west": {"uv": [0, 0, 14, 14], "texture": "#5"}, + "up": {"uv": [0, 0, 14, 14], "texture": "#4"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/coalfired_engine_on.json b/src/main/resources/assets/eidolon/models/block/coalfired_engine_on.json new file mode 100644 index 0000000..989d28c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/coalfired_engine_on.json @@ -0,0 +1,115 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/coalfired_engine_bottom", + "1": "eidolon:block/coalfired_engine_on", + "2": "eidolon:block/coalfired_engine_parts", + "3": "eidolon:block/coalfired_engine_side", + "4": "eidolon:block/coalfired_engine_top", + "particle": "eidolon:block/coalfired_engine_bottom" + }, + "elements": [ + { + "from": [1, 2, 0], + "to": [15, 14, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [22, 10, 8]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "up": {"uv": [0, 0, 14, 14], "rotation": 180, "texture": "#4"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#0"} + } + }, + { + "from": [4, 4, 14], + "to": [12, 12, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 12, 23]}, + "faces": { + "east": {"uv": [8, 7, 6, 15], "texture": "#2"}, + "south": {"uv": [8, 7, 16, 15], "texture": "#2"}, + "west": {"uv": [6, 7, 8, 15], "texture": "#2"}, + "up": {"uv": [8, 5, 16, 7], "texture": "#2"}, + "down": {"uv": [8, 3, 16, 5], "texture": "#2"} + } + }, + { + "from": [5, 14, 8], + "to": [11, 16, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 16]}, + "faces": { + "north": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "east": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "south": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "west": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 6], "texture": "#2"} + } + }, + { + "from": [5, 14, 0], + "to": [11, 16, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 8]}, + "faces": { + "north": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "east": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "south": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "west": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 6], "texture": "#2"} + } + }, + { + "from": [2, 0, 2], + "to": [4, 3, 4], + "rotation": {"angle": -22.5, "axis": "z", "origin": [2, 0, 3]}, + "faces": { + "north": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "east": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "south": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "west": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "up": {"uv": [2, 8, 4, 10], "texture": "#2"}, + "down": {"uv": [2, 8, 4, 10], "texture": "#2"} + } + }, + { + "from": [2, 0, 10], + "to": [4, 3, 12], + "rotation": {"angle": -22.5, "axis": "z", "origin": [2, 0, 11]}, + "faces": { + "north": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "east": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "south": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "west": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "up": {"uv": [2, 8, 4, 10], "texture": "#2"}, + "down": {"uv": [2, 8, 4, 10], "texture": "#2"} + } + }, + { + "from": [12, 0, 2], + "to": [14, 3, 4], + "rotation": {"angle": 22.5, "axis": "z", "origin": [14, 0, 3]}, + "faces": { + "north": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "east": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "south": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "west": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "up": {"uv": [4, 8, 2, 10], "texture": "#2"}, + "down": {"uv": [4, 8, 2, 10], "texture": "#2"} + } + }, + { + "from": [12, 0, 10], + "to": [14, 3, 12], + "rotation": {"angle": 22.5, "axis": "z", "origin": [14, 0, 11]}, + "faces": { + "north": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "east": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "south": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "west": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "up": {"uv": [4, 8, 2, 10], "texture": "#2"}, + "down": {"uv": [4, 8, 2, 10], "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_bend.json b/src/main/resources/assets/eidolon/models/block/glass_tube_bend.json new file mode 100644 index 0000000..9b3e116 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_bend.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 6, 6], + "to": [10, 10, 10], + "faces": { + "east": {"uv": [6, 6, 10, 10], "rotation": 270, "texture": "#0"}, + "south": {"uv": [6, 6, 10, 10], "rotation": 270, "texture": "#0"}, + "up": {"uv": [6, 6, 10, 10], "rotation": 270, "texture": "#0"}, + "down": {"uv": [6, 6, 10, 10], "rotation": 270, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_down.json b/src/main/resources/assets/eidolon/models/block/glass_tube_down.json new file mode 100644 index 0000000..e9d1099 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_down.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 0, 6], + "to": [10, 6, 10], + "faces": { + "north": {"uv": [10, 6, 16, 10], "rotation": 90, "texture": "#0"}, + "east": {"uv": [6, 0, 10, 6], "rotation": 180, "texture": "#0"}, + "south": {"uv": [10, 6, 16, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [6, 0, 10, 6], "rotation": 180, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_east.json b/src/main/resources/assets/eidolon/models/block/glass_tube_east.json new file mode 100644 index 0000000..e6ad3bb --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_east.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [10, 6, 6], + "to": [16, 10, 10], + "faces": { + "north": {"uv": [0, 6, 6, 10], "texture": "#0"}, + "south": {"uv": [0, 6, 6, 10], "rotation": 180, "texture": "#0"}, + "up": {"uv": [6, 10, 10, 16], "rotation": 270, "texture": "#0"}, + "down": {"uv": [6, 10, 10, 16], "rotation": 270, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_input.json b/src/main/resources/assets/eidolon/models/block/glass_tube_input.json new file mode 100644 index 0000000..afff280 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_input.json @@ -0,0 +1,24 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "ambientocclusion": false, + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [5.5, 5.5, -1], + "to": [10.5, 10.5, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 13.5, 8]}, + "faces": { + "north": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "east": {"uv": [10, 0, 12, 5], "texture": "#0"}, + "south": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "west": {"uv": [10, 0, 12, 5], "rotation": 180, "texture": "#0"}, + "up": {"uv": [10, 0, 12, 5], "rotation": 270, "texture": "#0"}, + "down": {"uv": [10, 0, 12, 5], "rotation": 90, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_north.json b/src/main/resources/assets/eidolon/models/block/glass_tube_north.json new file mode 100644 index 0000000..06f0e8c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_north.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 6, 0], + "to": [10, 10, 6], + "faces": { + "east": {"uv": [10, 6, 16, 10], "texture": "#0"}, + "west": {"uv": [10, 6, 16, 10], "rotation": 180, "texture": "#0"}, + "up": {"uv": [6, 0, 10, 6], "texture": "#0"}, + "down": {"uv": [6, 0, 10, 6], "rotation": 180, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_output.json b/src/main/resources/assets/eidolon/models/block/glass_tube_output.json new file mode 100644 index 0000000..d6ad690 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_output.json @@ -0,0 +1,24 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "ambientocclusion": false, + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [5.5, 5.5, -1], + "to": [10.5, 10.5, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 13.5, 8]}, + "faces": { + "north": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "east": {"uv": [12, 0, 10, 5], "texture": "#0"}, + "south": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "west": {"uv": [12, 0, 10, 5], "rotation": 180, "texture": "#0"}, + "up": {"uv": [12, 0, 10, 5], "rotation": 270, "texture": "#0"}, + "down": {"uv": [12, 0, 10, 5], "rotation": 90, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_south.json b/src/main/resources/assets/eidolon/models/block/glass_tube_south.json new file mode 100644 index 0000000..993ff5e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_south.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 6, 10], + "to": [10, 10, 16], + "faces": { + "east": {"uv": [0, 6, 6, 10], "texture": "#0"}, + "west": {"uv": [0, 6, 6, 10], "rotation": 180, "texture": "#0"}, + "up": {"uv": [6, 10, 10, 16], "texture": "#0"}, + "down": {"uv": [6, 10, 10, 16], "rotation": 180, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_straight.json b/src/main/resources/assets/eidolon/models/block/glass_tube_straight.json new file mode 100644 index 0000000..6608ee9 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_straight.json @@ -0,0 +1,21 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 6, 6], + "to": [10, 10, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 14, 14]}, + "faces": { + "east": {"uv": [6, 6, 10, 10], "texture": "#0"}, + "west": {"uv": [6, 6, 10, 10], "texture": "#0"}, + "up": {"uv": [6, 6, 10, 10], "texture": "#0"}, + "down": {"uv": [6, 6, 10, 10], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_up.json b/src/main/resources/assets/eidolon/models/block/glass_tube_up.json new file mode 100644 index 0000000..5cb00cd --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_up.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [6, 10, 6], + "to": [10, 16, 10], + "faces": { + "north": {"uv": [0, 6, 6, 10], "rotation": 90, "texture": "#0"}, + "east": {"uv": [6, 10, 10, 16], "rotation": 180, "texture": "#0"}, + "south": {"uv": [0, 6, 6, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [6, 10, 10, 16], "rotation": 180, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/glass_tube_west.json b/src/main/resources/assets/eidolon/models/block/glass_tube_west.json new file mode 100644 index 0000000..9a62684 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/glass_tube_west.json @@ -0,0 +1,20 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [0, 6, 6], + "to": [6, 10, 10], + "faces": { + "north": {"uv": [10, 6, 16, 10], "texture": "#0"}, + "south": {"uv": [10, 6, 16, 10], "rotation": 180, "texture": "#0"}, + "up": {"uv": [6, 0, 10, 6], "rotation": 270, "texture": "#0"}, + "down": {"uv": [6, 0, 10, 6], "rotation": 270, "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/incubator_bottom.json b/src/main/resources/assets/eidolon/models/block/incubator_bottom.json new file mode 100644 index 0000000..facb77f --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/incubator_bottom.json @@ -0,0 +1,158 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "loader": "forge:multi-layer", + "textures": { + "particle": "eidolon:block/incubator_shared" + }, + "layers": { + "solid": { + "textures": { + "0": "eidolon:block/incubator_shared", + "1": "eidolon:block/incubator_bottom", + "2": "eidolon:block/incubator_detail", + "particle": "eidolon:block/incubator_shared" + }, + "elements": [ + { + "from": [5, 0, 5], + "to": [11, 4, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 2.5, 8]}, + "faces": { + "north": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "east": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "south": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "west": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "up": {"uv": [10, 10, 16, 16], "texture": "#2"}, + "down": {"uv": [10, 4, 16, 10], "texture": "#2"} + } + }, + { + "from": [7, 2.99, -1], + "to": [9, 3.99, 7], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "east": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "south": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "west": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "texture": "#0"} + } + }, + { + "from": [-1, 2.99, 7], + "to": [7, 3.99, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "east": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "west": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [7, 2.99, 9], + "to": [9, 3.99, 17], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "east": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "south": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "west": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 180, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 2.99, 7], + "to": [17, 3.99, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "east": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "south": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "west": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 90, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [6.5, 2.98, -4], + "to": [9.5, 6.98, 0], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "south": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "west": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "texture": "#2"} + } + }, + { + "from": [6.5, 2.98, -4], + "to": [9.5, 6.98, 0], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "south": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "west": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "texture": "#2"} + } + }, + { + "from": [-4, 2.98, 6.5], + "to": [0, 6.98, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "south": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "west": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "rotation": 270, "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [6.5, 2.98, 16], + "to": [9.5, 6.98, 20], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "east": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "south": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "west": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "rotation": 180, "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "rotation": 180, "texture": "#2"} + } + } + ] + }, + "translucent": { + "textures": { + "0": "eidolon:block/incubator_shared", + "1": "eidolon:block/incubator_bottom", + "2": "eidolon:block/incubator_detail" + }, + "elements": [ + { + "from": [1, 4, 1], + "to": [15, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 12, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#0"} + } + } + ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/incubator_top.json b/src/main/resources/assets/eidolon/models/block/incubator_top.json new file mode 100644 index 0000000..7ff50e2 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/incubator_top.json @@ -0,0 +1,157 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "loader": "forge:multi-layer", + "layers": { + "solid": { + "textures": { + "0": "eidolon:block/incubator_top", + "1": "eidolon:block/incubator_shared", + "2": "eidolon:block/incubator_detail" + }, + "elements": [ + { + "from": [7, 14.01, -1], + "to": [9, 15.01, 7], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 22, 8]}, + "faces": { + "north": {"uv": [14, 0, 16, 1], "texture": "#1"}, + "east": {"uv": [8, 14, 0, 15], "texture": "#1"}, + "south": {"uv": [14, 7, 16, 8], "texture": "#1"}, + "west": {"uv": [0, 14, 8, 15], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 8], "texture": "#1"}, + "down": {"uv": [14, 8, 16, 16], "texture": "#1"} + } + }, + { + "from": [9, 14.01, 7], + "to": [17, 15.01, 9], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 22, 8]}, + "faces": { + "north": {"uv": [0, 14, 8, 15], "texture": "#1"}, + "east": {"uv": [14, 0, 16, 1], "texture": "#1"}, + "south": {"uv": [8, 14, 0, 15], "texture": "#1"}, + "west": {"uv": [14, 7, 16, 8], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [7, 14.01, 9], + "to": [9, 15.01, 17], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 22, 8]}, + "faces": { + "north": {"uv": [14, 7, 16, 8], "texture": "#1"}, + "east": {"uv": [0, 14, 8, 15], "texture": "#1"}, + "south": {"uv": [14, 0, 16, 1], "texture": "#1"}, + "west": {"uv": [8, 14, 0, 15], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 180, "texture": "#1"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-1, 14.01, 7], + "to": [7, 15.01, 9], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 22, 8]}, + "faces": { + "north": {"uv": [8, 14, 0, 15], "texture": "#1"}, + "east": {"uv": [14, 7, 16, 8], "texture": "#1"}, + "south": {"uv": [0, 14, 8, 15], "texture": "#1"}, + "west": {"uv": [14, 0, 16, 1], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 270, "texture": "#1"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [6.99, 12, -3], + "to": [9.01, 15, 0], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 21, 8]}, + "faces": { + "north": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "south": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "west": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "texture": "#2"} + } + }, + { + "from": [6.99, 12, -3], + "to": [9.01, 15, 0], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 21, 8]}, + "faces": { + "north": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "south": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "west": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "texture": "#2"} + } + }, + { + "from": [-3, 12, 6.99], + "to": [0, 15, 9.01], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 21, 8]}, + "faces": { + "north": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "south": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "west": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "rotation": 270, "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [6.99, 12, 16], + "to": [9.01, 15, 19], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 21, 8]}, + "faces": { + "north": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "east": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "south": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "west": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "rotation": 180, "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "from": [6, 13.99, 6], + "to": [10, 15.99, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [15, 22, 14]}, + "faces": { + "north": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "east": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "south": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "west": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "up": {"uv": [0, 4, 4, 8], "texture": "#2"}, + "down": {"uv": [0, 4, 4, 8], "texture": "#2"} + } + } + ] + }, + "translucent": { + "textures": { + "0": "eidolon:block/incubator_top", + "1": "eidolon:block/incubator_shared", + "2": "eidolon:block/incubator_detail" + }, + "elements": [ + { + "from": [1, 0, 1], + "to": [15, 14, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 8, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "east": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "south": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "west": {"uv": [0, 0, 14, 14], "texture": "#0"}, + "up": {"uv": [0, 0, 14, 14], "texture": "#1"} + } + } + ] + } + }, + "textures": { + "particle": "eidolon:block/incubator_top" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/inscription_table.json b/src/main/resources/assets/eidolon/models/block/inscription_table.json new file mode 100644 index 0000000..b7fc2d5 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/inscription_table.json @@ -0,0 +1,278 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/inscription_table_bottom", + "1": "eidolon:block/inscription_table_mid", + "2": "eidolon:block/inscription_table_side", + "3": "eidolon:block/inscription_table_top", + "4": "eidolon:block/inscription_table_detail", + "particle": "eidolon:block/inscription_table_bottom" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 4, 16], + "faces": { + "north": {"uv": [0, 12, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 12, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 12, 16, 16], "texture": "#2"}, + "west": {"uv": [0, 12, 16, 16], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#0"} + } + }, + { + "from": [0, 10, 0], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 18, 8]}, + "faces": { + "north": {"uv": [0, 0, 16, 6], "texture": "#2"}, + "east": {"uv": [0, 0, 16, 6], "texture": "#2"}, + "south": {"uv": [0, 0, 16, 6], "texture": "#2"}, + "west": {"uv": [0, 0, 16, 6], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#1"} + } + }, + { + "from": [2, 4, 2], + "to": [6, 10, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [10, 12, 10]}, + "faces": { + "north": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "east": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "south": {"uv": [2, 6, 6, 12], "texture": "#2"}, + "west": {"uv": [2, 6, 6, 12], "texture": "#2"} + } + }, + { + "from": [2, 4, 10], + "to": [6, 10, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [10, 12, 18]}, + "faces": { + "north": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "east": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "south": {"uv": [2, 6, 6, 12], "texture": "#2"}, + "west": {"uv": [2, 6, 6, 12], "texture": "#2"} + } + }, + { + "from": [10, 4, 10], + "to": [14, 10, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 12, 18]}, + "faces": { + "north": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "east": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "south": {"uv": [2, 6, 6, 12], "texture": "#2"}, + "west": {"uv": [2, 6, 6, 12], "texture": "#2"} + } + }, + { + "from": [10, 4, 2], + "to": [14, 10, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 12, 10]}, + "faces": { + "north": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "east": {"uv": [10, 6, 14, 12], "texture": "#2"}, + "south": {"uv": [2, 6, 6, 12], "texture": "#2"}, + "west": {"uv": [2, 6, 6, 12], "texture": "#2"} + } + }, + { + "from": [4, 15, 4], + "to": [12, 17, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 23, 19]}, + "faces": { + "north": {"uv": [0, 8, 8, 10], "texture": "#4"}, + "east": {"uv": [0, 8, 8, 10], "texture": "#4"}, + "south": {"uv": [0, 8, 8, 10], "texture": "#4"}, + "west": {"uv": [0, 8, 8, 10], "texture": "#4"}, + "up": {"uv": [0, 0, 8, 8], "texture": "#4"}, + "down": {"uv": [0, 0, 8, 8], "texture": "#4"} + } + }, + { + "from": [3, 16, 3], + "to": [5, 18, 5], + "rotation": {"angle": -45, "axis": "y", "origin": [4, 17, 4]}, + "faces": { + "north": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "east": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "south": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "west": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "up": {"uv": [8, 2, 10, 4], "texture": "#4"}, + "down": {"uv": [8, 0, 10, 2], "texture": "#4"} + } + }, + { + "from": [3, 16, 11], + "to": [5, 18, 13], + "rotation": {"angle": -45, "axis": "y", "origin": [4, 17, 12]}, + "faces": { + "north": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "east": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "south": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "west": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "up": {"uv": [8, 2, 10, 4], "texture": "#4"}, + "down": {"uv": [8, 0, 10, 2], "texture": "#4"} + } + }, + { + "from": [11, 16, 11], + "to": [13, 18, 13], + "rotation": {"angle": -45, "axis": "y", "origin": [12, 17, 12]}, + "faces": { + "north": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "east": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "south": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "west": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "up": {"uv": [8, 2, 10, 4], "texture": "#4"}, + "down": {"uv": [8, 0, 10, 2], "texture": "#4"} + } + }, + { + "from": [11, 16, 3], + "to": [13, 18, 5], + "rotation": {"angle": -45, "axis": "y", "origin": [12, 17, 4]}, + "faces": { + "north": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "east": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "south": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "west": {"uv": [8, 0, 10, 2], "texture": "#4"}, + "up": {"uv": [8, 2, 10, 4], "texture": "#4"}, + "down": {"uv": [8, 0, 10, 2], "texture": "#4"} + } + }, + { + "from": [2.5, 16, 0.5], + "to": [3.5, 17, 1.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [3, 16.5, 1]}, + "faces": { + "north": {"uv": [15, 6, 16, 7], "texture": "#4"}, + "east": {"uv": [15, 6, 16, 7], "texture": "#4"}, + "south": {"uv": [15, 6, 16, 7], "texture": "#4"}, + "west": {"uv": [15, 6, 16, 7], "texture": "#4"}, + "up": {"uv": [15, 6, 16, 7], "rotation": 90, "texture": "#4"}, + "down": {"uv": [15, 6, 16, 7], "rotation": 270, "texture": "#4"} + } + }, + { + "from": [2.5, 23, 0.5], + "to": [3.5, 24, 1.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [3, 23.5, 1]}, + "faces": { + "north": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "east": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "south": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "west": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "up": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "down": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"} + } + }, + { + "from": [1.5, 17, -0.5], + "to": [4.5, 18, 2.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [3, 17.5, 1]}, + "faces": { + "north": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "east": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "south": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "west": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "up": {"uv": [12, 6, 15, 9], "rotation": 90, "texture": "#4"}, + "down": {"uv": [12, 6, 15, 9], "rotation": 270, "texture": "#4"} + } + }, + { + "from": [2, 18, 0], + "to": [4, 23, 2], + "rotation": {"angle": 22.5, "axis": "y", "origin": [3, 18.5, 1]}, + "faces": { + "north": {"uv": [12, 1, 14, 6], "texture": "#4"}, + "east": {"uv": [12, 1, 14, 6], "texture": "#4"}, + "south": {"uv": [12, 1, 14, 6], "texture": "#4"}, + "west": {"uv": [12, 1, 14, 6], "texture": "#4"}, + "up": {"uv": [14, 0, 16, 2], "texture": "#4"}, + "down": {"uv": [14, 0, 16, 2], "texture": "#4"} + } + }, + { + "from": [-0.5, 16, 1.5], + "to": [2.5, 17, 4.5], + "rotation": {"angle": -22.5, "axis": "y", "origin": [1, 16.5, 3]}, + "faces": { + "north": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "east": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "south": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "west": {"uv": [12, 8, 15, 9], "texture": "#4"}, + "up": {"uv": [12, 6, 15, 9], "texture": "#4"}, + "down": {"uv": [12, 6, 15, 9], "texture": "#4"} + } + }, + { + "from": [0, 17, 2], + "to": [2, 21, 4], + "rotation": {"angle": -22.5, "axis": "y", "origin": [1, 17.5, 3]}, + "faces": { + "north": {"uv": [14, 2, 16, 6], "texture": "#4"}, + "east": {"uv": [14, 2, 16, 6], "texture": "#4"}, + "south": {"uv": [14, 2, 16, 6], "texture": "#4"}, + "west": {"uv": [14, 2, 16, 6], "texture": "#4"}, + "up": {"uv": [14, 0, 16, 2], "rotation": 270, "texture": "#4"}, + "down": {"uv": [14, 0, 16, 2], "rotation": 90, "texture": "#4"} + } + }, + { + "from": [0.5, 21, 2.5], + "to": [1.5, 22, 3.5], + "rotation": {"angle": -22.5, "axis": "y", "origin": [1, 21.5, 3]}, + "faces": { + "north": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "east": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "south": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "west": {"uv": [13, 0, 14, 1], "rotation": 90, "texture": "#4"}, + "up": {"uv": [13, 0, 14, 1], "texture": "#4"}, + "down": {"uv": [13, 0, 14, 1], "rotation": 180, "texture": "#4"} + } + }, + { + "from": [13, 16, 13], + "to": [15, 18, 15], + "rotation": {"angle": 22.5, "axis": "y", "origin": [14, 17, 14]}, + "faces": { + "north": {"uv": [0, 11, 2, 13], "texture": "#4"}, + "east": {"uv": [0, 11, 2, 13], "texture": "#4"}, + "south": {"uv": [0, 11, 2, 13], "texture": "#4"}, + "west": {"uv": [0, 11, 2, 13], "texture": "#4"}, + "up": {"uv": [0, 11, 2, 13], "texture": "#4"}, + "down": {"uv": [0, 11, 2, 13], "texture": "#4"} + } + }, + { + "from": [12.5, 18, 12.5], + "to": [15.5, 19, 15.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [14, 19, 14]}, + "faces": { + "north": {"uv": [2, 12, 5, 13], "texture": "#4"}, + "east": {"uv": [2, 12, 5, 13], "texture": "#4"}, + "south": {"uv": [2, 12, 5, 13], "texture": "#4"}, + "west": {"uv": [2, 12, 5, 13], "texture": "#4"}, + "up": {"uv": [2, 10, 5, 13], "texture": "#4"}, + "down": {"uv": [2, 10, 5, 13], "texture": "#4"} + } + }, + { + "from": [13.5, 18, 13.5], + "to": [14.5, 22, 14.5], + "rotation": {"angle": -22.5, "axis": "z", "origin": [14, 18.5, 14]}, + "faces": { + "north": {"uv": [5, 10, 6, 14], "texture": "#4"}, + "east": {"uv": [5, 10, 6, 14], "texture": "#4"}, + "south": {"uv": [5, 10, 6, 14], "texture": "#4"}, + "west": {"uv": [5, 10, 6, 14], "texture": "#4"}, + "up": {"uv": [5, 10, 6, 11], "texture": "#4"}, + "down": {"uv": [5, 13, 6, 14], "texture": "#4"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/merammer_root_0.json b/src/main/resources/assets/eidolon/models/block/merammer_root_0.json new file mode 100644 index 0000000..b25c437 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/merammer_root_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/merammer_root_0" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/merammer_root_1.json b/src/main/resources/assets/eidolon/models/block/merammer_root_1.json new file mode 100644 index 0000000..16150a5 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/merammer_root_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/merammer_root_1" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/oanna_bloom_0.json b/src/main/resources/assets/eidolon/models/block/oanna_bloom_0.json new file mode 100644 index 0000000..291df40 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/oanna_bloom_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/oanna_bloom_0" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/oanna_bloom_1.json b/src/main/resources/assets/eidolon/models/block/oanna_bloom_1.json new file mode 100644 index 0000000..806cdb1 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/oanna_bloom_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/oanna_bloom_1" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/obelisk_bottom.json b/src/main/resources/assets/eidolon/models/block/obelisk_bottom.json new file mode 100644 index 0000000..42559c3 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/obelisk_bottom.json @@ -0,0 +1,113 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/obelisk_bottom", + "1": "eidolon:block/obelisk_parts", + "2": "eidolon:block/obelisk_side_lower", + "3": "eidolon:block/obelisk_top_mid", + "particle": "eidolon:block/obelisk_side_lower" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [14, 16, 14], + "faces": { + "north": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 12, 12], "texture": "#3"}, + "down": {"uv": [0, 0, 12, 12], "texture": "#0"} + } + }, + { + "from": [0, -0.01, 0], + "to": [4, 5.99, 4], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [0, -0.01, 12], + "to": [4, 5.99, 16], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [12, -0.01, 12], + "to": [16, 5.99, 16], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [12, -0.01, 0], + "to": [16, 5.99, 4], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [0, 0, 4], + "to": [2, 4, 12], + "faces": { + "east": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "west": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 90, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [4, 0, 0], + "to": [12, 4, 2], + "faces": { + "north": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "south": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 180, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "texture": "#1"} + } + }, + { + "from": [4, 0, 14], + "to": [12, 4, 16], + "faces": { + "north": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "south": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [14, 0, 4], + "to": [16, 4, 12], + "faces": { + "east": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "west": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 270, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 270, "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/obelisk_mid.json b/src/main/resources/assets/eidolon/models/block/obelisk_mid.json new file mode 100644 index 0000000..e95ce78 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/obelisk_mid.json @@ -0,0 +1,24 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/obelisk_bottom", + "1": "eidolon:block/obelisk_side_mid", + "2": "eidolon:block/obelisk_top_mid", + "particle": "eidolon:block/obelisk_side_mid" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [14, 16, 14], + "faces": { + "north": {"uv": [0, 0, 12, 16], "texture": "#1"}, + "east": {"uv": [0, 0, 12, 16], "texture": "#1"}, + "south": {"uv": [0, 0, 12, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 12, 16], "texture": "#1"}, + "up": {"uv": [0, 0, 12, 12], "texture": "#2"}, + "down": {"uv": [0, 0, 12, 12], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/obelisk_top.json b/src/main/resources/assets/eidolon/models/block/obelisk_top.json new file mode 100644 index 0000000..0dd27a0 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/obelisk_top.json @@ -0,0 +1,36 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/obelisk_bottom", + "1": "eidolon:block/obelisk_parts", + "3": "eidolon:block/obelisk_top", + "4": "eidolon:block/obelisk_side_top", + "particle": "eidolon:block/obelisk_side_top" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [14, 14, 14], + "faces": { + "north": {"uv": [0, 0, 12, 14], "texture": "#4"}, + "east": {"uv": [0, 0, 12, 14], "texture": "#4"}, + "south": {"uv": [0, 0, 12, 14], "texture": "#4"}, + "west": {"uv": [0, 0, 12, 14], "texture": "#4"}, + "up": {"uv": [0, 0, 12, 12], "texture": "#3"}, + "down": {"uv": [0, 0, 12, 12], "texture": "#0"} + } + }, + { + "from": [4, 14, 4], + "to": [12, 16, 12], + "faces": { + "north": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "east": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "south": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "west": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "up": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/sildrian_seed_0.json b/src/main/resources/assets/eidolon/models/block/sildrian_seed_0.json new file mode 100644 index 0000000..bc6b19e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/sildrian_seed_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/sildrian_seed_0" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/sildrian_seed_1.json b/src/main/resources/assets/eidolon/models/block/sildrian_seed_1.json new file mode 100644 index 0000000..5f10594 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/sildrian_seed_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/sildrian_seed_1" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/alchemists_tongs.json b/src/main/resources/assets/eidolon/models/item/alchemists_tongs.json new file mode 100644 index 0000000..8a2632b --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/alchemists_tongs.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/alchemists_tongs" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/angels_sight.json b/src/main/resources/assets/eidolon/models/item/angels_sight.json new file mode 100644 index 0000000..8c0c1be --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/angels_sight.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/angels_sight" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/athame.json b/src/main/resources/assets/eidolon/models/item/athame.json new file mode 100644 index 0000000..be7795e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/athame.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/athame" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/avennian_sprig.json b/src/main/resources/assets/eidolon/models/item/avennian_sprig.json new file mode 100644 index 0000000..58178f6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/avennian_sprig.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/avennian_sprig" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/cistern.json b/src/main/resources/assets/eidolon/models/item/cistern.json new file mode 100644 index 0000000..cc4522f --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/cistern.json @@ -0,0 +1,49 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "1": "eidolon:block/cistern_ends", + "3": "eidolon:block/cistern_side", + "4": "eidolon:block/cistern_top", + "particle": "eidolon:block/cistern_bottom" + }, + "elements": [ + { + "from": [4, 0, 4], + "to": [12, 2, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 8, 12]}, + "faces": { + "north": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "east": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "south": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "west": {"uv": [0, 10, 8, 12], "texture": "#1"}, + "down": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + }, + { + "from": [4, 14, 4], + "to": [12, 16, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 22, 12]}, + "faces": { + "north": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "east": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "south": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "west": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "up": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + }, + { + "from": [1, 2, 1], + "to": [15, 14, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 10, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "up": {"uv": [0, 0, 14, 14], "texture": "#4"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#4"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/coalfired_engine.json b/src/main/resources/assets/eidolon/models/item/coalfired_engine.json new file mode 100644 index 0000000..7ec7dfb --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/coalfired_engine.json @@ -0,0 +1,115 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/coalfired_engine_bottom", + "1": "eidolon:block/coalfired_engine_front", + "2": "eidolon:block/coalfired_engine_parts", + "3": "eidolon:block/coalfired_engine_side", + "4": "eidolon:block/coalfired_engine_top", + "particle": "eidolon:block/coalfired_engine_bottom" + }, + "elements": [ + { + "from": [1, 2, 0], + "to": [15, 14, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [22, 10, 8]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "up": {"uv": [0, 0, 14, 14], "rotation": 180, "texture": "#4"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#0"} + } + }, + { + "from": [4, 4, 14], + "to": [12, 12, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [12, 12, 23]}, + "faces": { + "east": {"uv": [8, 7, 6, 15], "texture": "#2"}, + "south": {"uv": [8, 7, 16, 15], "texture": "#2"}, + "west": {"uv": [6, 7, 8, 15], "texture": "#2"}, + "up": {"uv": [8, 5, 16, 7], "texture": "#2"}, + "down": {"uv": [8, 3, 16, 5], "texture": "#2"} + } + }, + { + "from": [5, 14, 8], + "to": [11, 16, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 16]}, + "faces": { + "north": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "east": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "south": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "west": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 6], "texture": "#2"} + } + }, + { + "from": [5, 14, 0], + "to": [11, 16, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 8]}, + "faces": { + "north": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "east": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "south": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "west": {"uv": [0, 6, 6, 8], "texture": "#2"}, + "up": {"uv": [0, 0, 6, 6], "texture": "#2"} + } + }, + { + "from": [2, 0, 2], + "to": [4, 3, 4], + "rotation": {"angle": -22.5, "axis": "z", "origin": [2, 0, 3]}, + "faces": { + "north": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "east": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "south": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "west": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "up": {"uv": [2, 8, 4, 10], "texture": "#2"}, + "down": {"uv": [2, 8, 4, 10], "texture": "#2"} + } + }, + { + "from": [2, 0, 10], + "to": [4, 3, 12], + "rotation": {"angle": -22.5, "axis": "z", "origin": [2, 0, 11]}, + "faces": { + "north": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "east": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "south": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "west": {"uv": [4, 8, 6, 11], "texture": "#2"}, + "up": {"uv": [2, 8, 4, 10], "texture": "#2"}, + "down": {"uv": [2, 8, 4, 10], "texture": "#2"} + } + }, + { + "from": [12, 0, 2], + "to": [14, 3, 4], + "rotation": {"angle": 22.5, "axis": "z", "origin": [14, 0, 3]}, + "faces": { + "north": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "east": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "south": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "west": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "up": {"uv": [4, 8, 2, 10], "texture": "#2"}, + "down": {"uv": [4, 8, 2, 10], "texture": "#2"} + } + }, + { + "from": [12, 0, 10], + "to": [14, 3, 12], + "rotation": {"angle": 22.5, "axis": "z", "origin": [14, 0, 11]}, + "faces": { + "north": {"uv": [0, 8, 2, 11], "texture": "#2"}, + "east": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "south": {"uv": [2, 8, 0, 11], "texture": "#2"}, + "west": {"uv": [6, 8, 4, 11], "texture": "#2"}, + "up": {"uv": [4, 8, 2, 10], "texture": "#2"}, + "down": {"uv": [4, 8, 2, 10], "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/deep_lead_ore.json b/src/main/resources/assets/eidolon/models/item/deep_lead_ore.json new file mode 100644 index 0000000..079126d --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/deep_lead_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/deep_lead_ore" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/deep_silver_ore.json b/src/main/resources/assets/eidolon/models/item/deep_silver_ore.json new file mode 100644 index 0000000..cc158e8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/deep_silver_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/deep_silver_ore" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/enervating_ring.json b/src/main/resources/assets/eidolon/models/item/enervating_ring.json new file mode 100644 index 0000000..380129b --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/enervating_ring.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/enervating_ring" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/glass_tube.json b/src/main/resources/assets/eidolon/models/item/glass_tube.json new file mode 100644 index 0000000..9b5b2d0 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/glass_tube.json @@ -0,0 +1,47 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/glass_tube", + "particle": "eidolon:block/glass_tube" + }, + "elements": [ + { + "from": [5.5, 5.5, -1], + "to": [10.5, 10.5, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 13.5, 8]}, + "faces": { + "north": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "east": {"uv": [12, 0, 10, 5], "texture": "#0"}, + "south": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "west": {"uv": [12, 0, 10, 5], "rotation": 180, "texture": "#0"}, + "up": {"uv": [12, 0, 10, 5], "rotation": 270, "texture": "#0"}, + "down": {"uv": [12, 0, 10, 5], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [5.5, 5.5, 15], + "to": [10.5, 10.5, 17], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 13.5, 24]}, + "faces": { + "north": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "east": {"uv": [12, 0, 10, 5], "texture": "#0"}, + "south": {"uv": [10, 10, 15, 15], "texture": "#0"}, + "west": {"uv": [12, 0, 10, 5], "rotation": 180, "texture": "#0"}, + "up": {"uv": [12, 0, 10, 5], "rotation": 270, "texture": "#0"}, + "down": {"uv": [12, 0, 10, 5], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [6, 6, 0], + "to": [10, 10, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [17, 14, 8]}, + "faces": { + "east": {"uv": [0, 6, 16, 10], "texture": "#0"}, + "west": {"uv": [0, 6, 16, 10], "texture": "#0"}, + "up": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "down": {"uv": [6, 0, 10, 16], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/incubator.json b/src/main/resources/assets/eidolon/models/item/incubator.json new file mode 100644 index 0000000..ecbed99 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/incubator.json @@ -0,0 +1,320 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "loader": "forge:multi-layer", + "textures": { + "particle": "eidolon:block/incubator_shared" + }, + "layers": { + "solid": { + "textures": { + "0": "eidolon:block/incubator_shared", + "1": "eidolon:block/incubator_bottom", + "2": "eidolon:block/incubator_detail", + "3": "eidolon:block/incubator_top" + },"elements": [ + { + "from": [5, 0, 5], + "to": [11, 4, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 2.5, 8]}, + "faces": { + "north": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "east": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "south": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "west": {"uv": [10, 0, 16, 4], "texture": "#2"}, + "up": {"uv": [10, 10, 16, 16], "texture": "#2"}, + "down": {"uv": [10, 4, 16, 10], "texture": "#2"} + } + }, + { + "from": [7.25, 30.01, -1], + "to": [9, 31.01, 7], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 30.5, 8]}, + "faces": { + "north": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "east": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "south": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "west": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "texture": "#0"} + } + }, + { + "from": [-1, 30.01, 7], + "to": [7, 31.01, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 30.5, 8]}, + "faces": { + "north": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "east": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "west": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [7.25, 30.01, 9], + "to": [9, 31.01, 17], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 30.5, 8]}, + "faces": { + "north": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "east": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "south": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "west": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 180, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9.25, 30.01, 7], + "to": [17, 31.01, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 30.5, 8]}, + "faces": { + "north": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "east": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "south": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "west": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 90, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [6.5, 2.98, -4], + "to": [9.5, 6.98, 0], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "south": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "west": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "texture": "#2"} + } + }, + { + "from": [6.5, 2.98, -4], + "to": [9.5, 6.98, 0], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "south": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "west": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "texture": "#2"} + } + }, + { + "from": [-4, 2.98, 6.5], + "to": [0, 6.98, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "east": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "south": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "west": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "rotation": 270, "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [6.5, 2.98, 16], + "to": [9.5, 6.98, 20], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 10.5, 8]}, + "faces": { + "north": {"uv": [7, 0, 10, 4], "texture": "#2"}, + "east": {"uv": [3, 0, 7, 4], "texture": "#2"}, + "south": {"uv": [0, 0, 3, 4], "texture": "#2"}, + "west": {"uv": [7, 0, 3, 4], "texture": "#2"}, + "up": {"uv": [4, 8, 7, 4], "rotation": 180, "texture": "#2"}, + "down": {"uv": [7, 8, 10, 4], "rotation": 180, "texture": "#2"} + } + }, + { + "from": [-1, 2.99, 7], + "to": [7, 3.99, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "east": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "west": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 270, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [9.25, 2.99, 7], + "to": [17, 3.99, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "east": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "south": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "west": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 90, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.25, 2.99, 9], + "to": [9, 3.99, 17], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "east": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "south": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "west": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "rotation": 180, "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7.25, 2.99, -1], + "to": [9, 3.99, 7], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 3.5, 8]}, + "faces": { + "north": {"uv": [14, 0, 16, 1], "texture": "#0"}, + "east": {"uv": [8, 14, 0, 15], "texture": "#0"}, + "south": {"uv": [14, 15, 16, 16], "texture": "#0"}, + "west": {"uv": [0, 14, 8, 15], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 8], "texture": "#0"}, + "down": {"uv": [14, 8, 16, 16], "texture": "#0"} + } + }, + { + "from": [6, 29.99, 6], + "to": [10, 31.99, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 38, 14]}, + "faces": { + "north": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "east": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "south": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "west": {"uv": [0, 8, 4, 10], "texture": "#2"}, + "up": {"uv": [0, 4, 4, 8], "texture": "#2"}, + "down": {"uv": [0, 4, 4, 8], "texture": "#2"} + } + }, + { + "from": [7, 28, -3], + "to": [9, 31, 0], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 38, 8]}, + "faces": { + "north": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "south": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "west": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "texture": "#2"} + } + }, + { + "from": [-3, 28, 7], + "to": [0, 31, 9], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 38, 8]}, + "faces": { + "north": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "south": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "west": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "rotation": 270, "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [7, 28, -3], + "to": [9, 31, 0], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 38, 8]}, + "faces": { + "north": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "east": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "south": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "west": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "texture": "#2"} + } + }, + { + "from": [16, 28, 7], + "to": [19, 31, 9], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 38, 8]}, + "faces": { + "north": {"uv": [2, 10, 5, 13], "texture": "#2"}, + "east": {"uv": [0, 10, 2, 13], "texture": "#2"}, + "south": {"uv": [5, 10, 2, 13], "texture": "#2"}, + "west": {"uv": [5, 10, 7, 13], "texture": "#2"}, + "up": {"uv": [3, 13, 5, 16], "rotation": 90, "texture": "#2"}, + "down": {"uv": [5, 13, 7, 16], "rotation": 270, "texture": "#2"} + } + } + ] + }, + "translucent": { + "textures": { + "0": "eidolon:block/incubator_shared", + "1": "eidolon:block/incubator_bottom", + "2": "eidolon:block/incubator_detail", + "3": "eidolon:block/incubator_top" + }, + "elements": [ + + { + "from": [1, 4, 1], + "to": [15, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 12, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#1"}, + "down": {"uv": [0, 0, 14, 14], "texture": "#0"} + } + }, + { + "from": [1, 16, 1], + "to": [15, 30, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 24, 9]}, + "faces": { + "north": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "east": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "south": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "west": {"uv": [0, 0, 14, 12], "texture": "#3"}, + "up": {"uv": [0, 0, 14, 14], "texture": "#3"} + } + } + ] + } + }, + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.28125, 0.28125, 0.28125] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.25, 0.25, 0.25] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.3, 0.3, 0.3] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.3, 0.3, 0.3] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.1875, 0.1875, 0.1875] + }, + "gui": { + "rotation": [30, 225, 0], + "translation": [0, -3, 0], + "scale": [0.46875, 0.46875, 0.46875] + }, + "fixed": { + "scale": [0.375, 0.375, 0.375] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/merammer_resin.json b/src/main/resources/assets/eidolon/models/item/merammer_resin.json new file mode 100644 index 0000000..427ffc0 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/merammer_resin.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/merammer_resin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/merammer_root.json b/src/main/resources/assets/eidolon/models/item/merammer_root.json new file mode 100644 index 0000000..f377de2 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/merammer_root.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/merammer_root" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/oanna_bloom.json b/src/main/resources/assets/eidolon/models/item/oanna_bloom.json new file mode 100644 index 0000000..18edd28 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/oanna_bloom.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/oanna_bloom" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/obelisk.json b/src/main/resources/assets/eidolon/models/item/obelisk.json new file mode 100644 index 0000000..6fc371c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/obelisk.json @@ -0,0 +1,124 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/obelisk_bottom", + "1": "eidolon:block/obelisk_parts", + "2": "eidolon:block/obelisk_side", + "3": "eidolon:block/obelisk_top", + "particle": "eidolon:block/obelisk_side" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [14, 14, 14], + "faces": { + "north": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "east": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "south": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "west": {"uv": [0, 0, 12, 14], "texture": "#2"}, + "up": {"uv": [0, 0, 12, 12], "texture": "#3"}, + "down": {"uv": [0, 0, 12, 12], "texture": "#0"} + } + }, + { + "from": [4, 14, 4], + "to": [12, 16, 12], + "faces": { + "north": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "east": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "south": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "west": {"uv": [0, 8, 8, 10], "texture": "#1"}, + "up": {"uv": [0, 0, 8, 8], "texture": "#1"} + } + }, + { + "from": [0, -0.01, 0], + "to": [4, 5.99, 4], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [0, -0.01, 12], + "to": [4, 5.99, 16], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [12, -0.01, 12], + "to": [16, 5.99, 16], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [12, -0.01, 0], + "to": [16, 5.99, 4], + "faces": { + "north": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "east": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "south": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 10, 16, 16], "texture": "#1"}, + "up": {"uv": [12, 6, 16, 10], "texture": "#1"}, + "down": {"uv": [12, 6, 16, 10], "texture": "#1"} + } + }, + { + "from": [0, 0, 4], + "to": [2, 4, 12], + "faces": { + "east": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "west": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 90, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [4, 0, 0], + "to": [12, 4, 2], + "faces": { + "north": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "south": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 180, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "texture": "#1"} + } + }, + { + "from": [4, 0, 14], + "to": [12, 4, 16], + "faces": { + "north": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "south": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [14, 0, 4], + "to": [16, 4, 12], + "faces": { + "east": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "west": {"uv": [4, 12, 12, 16], "texture": "#1"}, + "up": {"uv": [4, 12, 12, 14], "rotation": 270, "texture": "#1"}, + "down": {"uv": [4, 14, 12, 16], "rotation": 270, "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/planter.json b/src/main/resources/assets/eidolon/models/item/planter.json index b14b8bf..7d5bb2a 100644 --- a/src/main/resources/assets/eidolon/models/item/planter.json +++ b/src/main/resources/assets/eidolon/models/item/planter.json @@ -398,6 +398,5 @@ "down": {"uv": [6, 10, 8, 12], "rotation": 90, "texture": "#0"} } } - ], - "display": {} + ] } \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raven_feather.json b/src/main/resources/assets/eidolon/models/item/raven_feather.json new file mode 100644 index 0000000..035c1a1 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raven_feather.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/raven_feather" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raw_lead.json b/src/main/resources/assets/eidolon/models/item/raw_lead.json new file mode 100644 index 0000000..a62d763 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raw_lead.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/raw_lead" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raw_lead_block.json b/src/main/resources/assets/eidolon/models/item/raw_lead_block.json new file mode 100644 index 0000000..7b9b0e6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raw_lead_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/raw_lead_block" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raw_silver.json b/src/main/resources/assets/eidolon/models/item/raw_silver.json new file mode 100644 index 0000000..d6b0781 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raw_silver.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/raw_silver" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raw_silver_block.json b/src/main/resources/assets/eidolon/models/item/raw_silver_block.json new file mode 100644 index 0000000..5f59fee --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raw_silver_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/raw_silver_block" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/shadow_gem_block.json b/src/main/resources/assets/eidolon/models/item/shadow_gem_block.json new file mode 100644 index 0000000..c639d05 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/shadow_gem_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/shadow_gem_block" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/sildrian_seed.json b/src/main/resources/assets/eidolon/models/item/sildrian_seed.json new file mode 100644 index 0000000..8503cb0 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/sildrian_seed.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/sildrian_seed" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_axe.json b/src/main/resources/assets/eidolon/models/item/silver_axe.json new file mode 100644 index 0000000..cf7d6ca --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_axe.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/silver_axe" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_block.json b/src/main/resources/assets/eidolon/models/item/silver_block.json new file mode 100644 index 0000000..ede2af5 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/silver_block" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_boots.json b/src/main/resources/assets/eidolon/models/item/silver_boots.json new file mode 100644 index 0000000..42ee629 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_boots" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_chestplate.json b/src/main/resources/assets/eidolon/models/item/silver_chestplate.json new file mode 100644 index 0000000..88be3dc --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_chestplate" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_helmet.json b/src/main/resources/assets/eidolon/models/item/silver_helmet.json new file mode 100644 index 0000000..6c51f91 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_helmet.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_helmet" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_hoe.json b/src/main/resources/assets/eidolon/models/item/silver_hoe.json new file mode 100644 index 0000000..f927c1d --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_hoe.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/silver_hoe" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_ingot.json b/src/main/resources/assets/eidolon/models/item/silver_ingot.json new file mode 100644 index 0000000..fe20e71 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_ingot.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_ingot" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_leggings.json b/src/main/resources/assets/eidolon/models/item/silver_leggings.json new file mode 100644 index 0000000..52e841e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_leggings" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_nugget.json b/src/main/resources/assets/eidolon/models/item/silver_nugget.json new file mode 100644 index 0000000..e34cf80 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_nugget.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/silver_nugget" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_ore.json b/src/main/resources/assets/eidolon/models/item/silver_ore.json new file mode 100644 index 0000000..ada6b94 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/silver_ore" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_pickaxe.json b/src/main/resources/assets/eidolon/models/item/silver_pickaxe.json new file mode 100644 index 0000000..4f3f43a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_pickaxe.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/silver_pickaxe" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_shovel.json b/src/main/resources/assets/eidolon/models/item/silver_shovel.json new file mode 100644 index 0000000..85822ef --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_shovel.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/silver_shovel" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/silver_sword.json b/src/main/resources/assets/eidolon/models/item/silver_sword.json new file mode 100644 index 0000000..e655f29 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/silver_sword.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/silver_sword" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/spawn_raven.json b/src/main/resources/assets/eidolon/models/item/spawn_raven.json new file mode 100644 index 0000000..38194e8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/spawn_raven.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/spawn_slimy_slug.json b/src/main/resources/assets/eidolon/models/item/spawn_slimy_slug.json new file mode 100644 index 0000000..38194e8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/spawn_slimy_slug.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/terminus_mirror.json b/src/main/resources/assets/eidolon/models/item/terminus_mirror.json new file mode 100644 index 0000000..ca2d9c6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/terminus_mirror.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/terminus_mirror" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/unholy_symbol.json b/src/main/resources/assets/eidolon/models/item/unholy_symbol.json index 7d1ee7f..98ceefb 100644 --- a/src/main/resources/assets/eidolon/models/item/unholy_symbol.json +++ b/src/main/resources/assets/eidolon/models/item/unholy_symbol.json @@ -1,6 +1,47 @@ { - "parent": "minecraft:item/generated", + "parent": "builtin/entity", "textures": { - "layer0": "eidolon:item/unholy_symbol" + "particle": "eidolon:item/unholy_symbol" + }, + "display": { + "thirdperson_righthand": { + "rotation": [-18, -180, 0], + "translation": [0, 4, 0], + "scale": [0.55, 0.55, 0.55] + }, + "thirdperson_lefthand": { + "rotation": [-18, -180, 0], + "translation": [0, 4, 0], + "scale": [0.55, 0.55, 0.55] + }, + "firstperson_righthand": { + "rotation": [-15, 135, 9], + "translation": [-1.5, 6.5, 3], + "scale": [0.7, 0.7, 0.7] + }, + "firstperson_lefthand": { + "rotation": [-15, 135, 9], + "translation": [-1.5, 6.5, 3], + "scale": [0.7, 0.7, 0.7] + }, + "ground": { + "rotation": [0, 0, 15], + "translation": [0, 2, 0], + "scale": [0.625, 0.625, 0.625] + }, + "gui": { + "rotation": [0, 165, 15], + "translation": [1, 4, 0], + "scale": [1.25, 1.25, 1.25] + }, + "head": { + "rotation": [0, 180, 0], + "translation": [0, 13, 7] + }, + "fixed": { + "rotation": [0, -15, 15], + "translation": [0, 4, -3], + "scale": [1.25, 1.25, 1.25] + } } } \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/worktable.json b/src/main/resources/assets/eidolon/models/item/worktable.json index 5b51021..a89a787 100644 --- a/src/main/resources/assets/eidolon/models/item/worktable.json +++ b/src/main/resources/assets/eidolon/models/item/worktable.json @@ -131,58 +131,6 @@ "up": {"uv": [0, 8, 6, 14], "texture": "#4"}, "down": {"uv": [0, 2, 6, 8], "texture": "#4"} } - }, - { - "from": [13, 6.5, 7], - "to": [18, 11.5, 9], - "rotation": {"angle": 45, "axis": "z", "origin": [15.5, 9, 8]}, - "faces": { - "north": {"uv": [6, 0, 11, 5], "texture": "#4"}, - "east": {"uv": [11, 0, 13, 5], "texture": "#4"}, - "south": {"uv": [11, 0, 6, 5], "texture": "#4"}, - "west": {"uv": [13, 0, 15, 5], "texture": "#4"}, - "up": {"uv": [11, 0, 13, 5], "rotation": 90, "texture": "#4"}, - "down": {"uv": [13, 0, 15, 5], "rotation": 90, "texture": "#4"} - } - }, - { - "from": [7, 6.5, 13], - "to": [9, 11.5, 18], - "rotation": {"angle": -45, "axis": "x", "origin": [8, 9, 15.5]}, - "faces": { - "north": {"uv": [13, 0, 15, 5], "texture": "#4"}, - "east": {"uv": [11, 0, 6, 5], "rotation": 270, "texture": "#4"}, - "south": {"uv": [11, 0, 13, 5], "texture": "#4"}, - "west": {"uv": [6, 0, 11, 5], "rotation": 90, "texture": "#4"}, - "up": {"uv": [11, 0, 13, 5], "rotation": 180, "texture": "#4"}, - "down": {"uv": [13, 0, 15, 5], "texture": "#4"} - } - }, - { - "from": [7, 6.5, -2], - "to": [9, 11.5, 3], - "rotation": {"angle": 45, "axis": "x", "origin": [8, 9, 0.5]}, - "faces": { - "north": {"uv": [13, 0, 11, 5], "texture": "#4"}, - "east": {"uv": [11, 5, 6, 0], "rotation": 270, "texture": "#4"}, - "south": {"uv": [15, 0, 13, 5], "texture": "#4"}, - "west": {"uv": [6, 5, 11, 0], "rotation": 90, "texture": "#4"}, - "up": {"uv": [11, 5, 13, 0], "rotation": 180, "texture": "#4"}, - "down": {"uv": [13, 5, 15, 0], "texture": "#4"} - } - }, - { - "from": [-2, 6.5, 7], - "to": [3, 11.5, 9], - "rotation": {"angle": -45, "axis": "z", "origin": [0.5, 9, 8]}, - "faces": { - "north": {"uv": [11, 0, 6, 5], "texture": "#4"}, - "east": {"uv": [15, 0, 13, 5], "texture": "#4"}, - "south": {"uv": [6, 0, 11, 5], "texture": "#4"}, - "west": {"uv": [13, 0, 11, 5], "texture": "#4"}, - "up": {"uv": [11, 5, 13, 0], "rotation": 90, "texture": "#4"}, - "down": {"uv": [13, 5, 15, 0], "rotation": 90, "texture": "#4"} - } } ] } \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing.fsh b/src/main/resources/assets/eidolon/shaders/core/glowing.fsh new file mode 100644 index 0000000..d7da70e --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing.fsh @@ -0,0 +1,15 @@ +#version 150 + +in vec4 vertexColor; + +uniform vec4 ColorModulator; + +out vec4 fragColor; + +void main() { + vec4 color = vertexColor; + if (color.a == 0.0) { + discard; + } + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing.json b/src/main/resources/assets/eidolon/shaders/core/glowing.json new file mode 100644 index 0000000..ef91b7e --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing.json @@ -0,0 +1,19 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1" + }, + "vertex": "eidolon:glowing", + "fragment": "eidolon:glowing", + "attributes": [ + "Color" + ], + "samplers": [ + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing.vsh b/src/main/resources/assets/eidolon/shaders/core/glowing.vsh new file mode 100644 index 0000000..19d3fdb --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing.vsh @@ -0,0 +1,15 @@ +#version 150 + +in vec3 Position; +in vec4 Color; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out vec4 vertexColor; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + vertexColor = Color; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_entity.fsh b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.fsh new file mode 100644 index 0000000..c46a768 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.fsh @@ -0,0 +1,23 @@ +#version 150 + +#moj_import + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; + +in float vertexDistance; +in vec4 vertexColor; +in vec2 texCoord0; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; + if (color.a < 0.001) { + discard; + } + fragColor = color * linear_fog_fade(vertexDistance, FogStart, FogEnd); +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_entity.json b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.json new file mode 100644 index 0000000..58464f2 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.json @@ -0,0 +1,24 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1" + }, + "vertex": "eidolon:glowing_entity", + "fragment": "eidolon:glowing_entity", + "attributes": [ + "Position", + "Color", + "UV0" + ], + "samplers": [ + { "name": "Sampler0" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_entity.vsh b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.vsh new file mode 100644 index 0000000..e0277a8 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_entity.vsh @@ -0,0 +1,21 @@ +#version 150 + +in vec3 Position; +in vec4 Color; +in vec2 UV0; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; +uniform mat4 TextureMat; + +out float vertexDistance; +out vec4 vertexColor; +out vec2 texCoord0; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + vertexDistance = length((ModelViewMat * vec4(Position, 1.0)).xyz); + vertexColor = Color; + texCoord0 = UV0; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_particle.fsh b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.fsh new file mode 100644 index 0000000..95ab1f5 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.fsh @@ -0,0 +1,24 @@ +#version 150 + +#moj_import + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; + +in float vertexDistance; +in vec2 texCoord0; +in vec4 vertexColor; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; + if (color.a < 0.001) { + discard; + } + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_particle.json b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.json new file mode 100644 index 0000000..e3257be --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.json @@ -0,0 +1,27 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1" + }, + "vertex": "eidolon:glowing_particle", + "fragment": "eidolon:glowing_particle", + "attributes": [ + "Position", + "UV0", + "Color", + "UV2" + ], + "samplers": [ + { "name": "Sampler0" }, + { "name": "Sampler2" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_particle.vsh b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.vsh new file mode 100644 index 0000000..f6a6cbb --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_particle.vsh @@ -0,0 +1,23 @@ +#version 150 + +in vec3 Position; +in vec2 UV0; +in vec4 Color; +in ivec2 UV2; + +uniform sampler2D Sampler2; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out float vertexDistance; +out vec2 texCoord0; +out vec4 vertexColor; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + vertexDistance = length((ModelViewMat * vec4(Position, 1.0)).xyz); + texCoord0 = UV0; + vertexColor = Color; // unlit +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.fsh b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.fsh new file mode 100644 index 0000000..7b99ac3 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.fsh @@ -0,0 +1,18 @@ +#version 150 + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; + +in vec2 texCoord0; +in vec4 vertexColor; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor; + if (color.a < 0.001) { + discard; + } + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.json b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.json new file mode 100644 index 0000000..915460d --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.json @@ -0,0 +1,22 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1" + }, + "vertex": "eidolon:glowing_sprite", + "fragment": "eidolon:glowing_sprite", + "attributes": [ + "Position", + "UV0", + "Color" + ], + "samplers": [ + { "name": "Sampler0" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.vsh b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.vsh new file mode 100644 index 0000000..1ed8e40 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/glowing_sprite.vsh @@ -0,0 +1,18 @@ +#version 150 + +in vec3 Position; +in vec2 UV0; +in vec4 Color; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out vec2 texCoord0; +out vec4 vertexColor; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + texCoord0 = UV0; + vertexColor = Color; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/vapor.fsh b/src/main/resources/assets/eidolon/shaders/core/vapor.fsh new file mode 100644 index 0000000..f619104 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/vapor.fsh @@ -0,0 +1,17 @@ +#version 150 + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; + +in vec4 vertexColor; +in vec2 texCoord0; +in vec2 texCoord2; +in vec4 normal; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor; + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/assets/eidolon/shaders/core/vapor.json b/src/main/resources/assets/eidolon/shaders/core/vapor.json new file mode 100644 index 0000000..d2d9299 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/vapor.json @@ -0,0 +1,24 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "eidolon:vapor", + "fragment": "eidolon:vapor", + "attributes": [ + "Position", + "Color", + "UV0", + "UV2", + "Normal" + ], + "samplers": [ + { "name": "Sampler0" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/vapor.vsh b/src/main/resources/assets/eidolon/shaders/core/vapor.vsh new file mode 100644 index 0000000..96201fb --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/vapor.vsh @@ -0,0 +1,24 @@ +#version 150 + +in vec3 Position; +in vec4 Color; +in vec2 UV0; +in vec2 UV2; +in vec3 Normal; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out vec4 vertexColor; +out vec2 texCoord0; +out vec2 texCoord2; +out vec4 normal; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + vertexColor = Color; + texCoord0 = UV0; + texCoord2 = UV2; + normal = ProjMat * ModelViewMat * vec4(Normal, 0.0); +} diff --git a/src/main/resources/assets/eidolon/textures/block/aludel_front.png b/src/main/resources/assets/eidolon/textures/block/aludel_front.png new file mode 100644 index 0000000000000000000000000000000000000000..79e5c170e42f21285e5b3d2ad13cb8eb4677d2ea GIT binary patch literal 399 zcmV;A0dW3_P)Px$Nl8ROR5*=&lQC<;Kp2J}Tc^XA3k0&b2o7B;xOVR3pYx}5HLHKXLKP88!J*o~ zQIlM_#i1SK4lfscr@N2$p7+Z~zTRT7_{*{kfTAc^F5du%q9JiS1fZ&Fw5|cj^Hq-< z^@R{(z&rp_U zHk%KkXy_8{c{Cb@9qe|WUcs2!dkmoUwbnTUDP;@r+xe{)5&+sWI3B+O(>(<<=t{rs zA^@CD3Lyjlm&+pnP1AG&27^He7>~!;UC>&y-@gZ@dvd$bPHK12l@8DcFvhrDn9W|8 tPN$y91}LS%AISm$Y&Uj0Z)NAy)<5weuX$X$3}65N002ovPDHLkV1kpRtSJBh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/aludel_jar_side.png b/src/main/resources/assets/eidolon/textures/block/aludel_jar_side.png new file mode 100644 index 0000000000000000000000000000000000000000..2b4def4035424c4daf3f1f68d572d72fc4060ade GIT binary patch literal 529 zcmV+s0`C2ZP)Px$%Sl8*R5*==l1*zGQ5c0Er5>r8P@^qrqxn4RaKI4J)==B>~DpH6-hp=U4H~<{ru+r z>D&l_y@Thm@hD#d;5d(oUk(Y#mjQZaucjME#oURi0(}4c#WT{2M%S5IXz{Rv4iC7_ z)aseN8h~|KkNrNo@q$g+LbfEw+UOt%>c-J6)MJYiR81`bWHdtdmjbslyZrJvkLygW z$zU?coxF`s1`~n{1Q2aIBoO&<)}D_pXPd-Bl`?jD|K`<7jFI}>ng8z($m}=82Ve?+ zF~V1I$8bQ^Zdxq~s+y|4E+r}eKhFIXOyYa_ctrsi4yd}$)EbY*zwU?L#ZD%A2oxcK zXxnVN+t&K)N;0mCw!Ls*H?5W=1Kbb2i$sc|Y`*G_D(eFMh9G6^qL{)*k|g-g0jBUn zOIxqyb|h&h6FtlpvZZuh&pk$5jv^NV6s7H8_D>3kw#}$JTbZ%n5cC_1+@GqyUh%Px#*-1n}R5*?0lD!JTFcgJPN)WN3>R^N_IQ3Eb3cg!k!NCX6$;DMShb{_ju?~_* zt)+-MNFf+gU7Y;3+>?9m$q$*t;_kT?hG?LU2qnVghVh_7)H+q0r|V*VJ)P6+kY&{d z#u=lI-S2Yvo@;5wv}*2=Cec)dU?pZDZvJcCswUUw2XH-|(|2_%LTMCL)MIH0OyW1_ zxAH3k#u+mjm_!xo*nOjcNmS`_Xio?L6aX%{@Pn0@)qNrWNVY;ZSS*i_yBrd^Hlc_m l5KHVg&vkp$`V{mpc>pSDPp4wNiS_^h002ovPDHLkV1mWMc?$pl literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/aludel_parts.png b/src/main/resources/assets/eidolon/textures/block/aludel_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..136a893b62c70f3a5aa6e9be3f515233073172c6 GIT binary patch literal 318 zcmV-E0m1%>P)Px#_(?=TR5*?8lCf&TFcd|PTN#H3Y8FAU<_!Hu51#yw9Rl7I3Wi1z2&*ZiLnC7s zC;5S%@jh|i<>?k}+g_}-XswwOLclpkN(q1%<6+rmYp2?ar<`sbB@e}XA0N8F{$h!9t5m`N=h^!~@{xl^hOO3Vm<~J4q zUDsWVF^ewreNWRg#oYsN?SY7(wI+lxZJPhaLj(A2Ugln@Rt+9C@t^zr0Fn-d=6o{D Qi2wiq07*qoM6N<$f|{j-Pyhe` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/aludel_power.png b/src/main/resources/assets/eidolon/textures/block/aludel_power.png new file mode 100644 index 0000000000000000000000000000000000000000..858b396252b0c1c3cff7e94556fd752148a4c2fd GIT binary patch literal 550 zcmV+>0@?kEP)Px$;7LS5R5*==lQC=CP!xr~5Mjgv1-ZN+M=b%F3^EtL{ydqLMTHzsCt#`Lhtg#xmV}hcka6z!{PARaU7~h)08aB z5JF&C)_*ZW2!T?HEXx28Lg?bE2+){PN{b00FskHgWLefAEsCOnH3%xzq9`bef;f)J z^SnW5nkE3PR;wXmgkeY=#{lGcj_1AN=;$*K4|ffM-Q6xHCttb04>Vc3-Nxv89q>AY zvqz#x(eLkbeEbC|9ejTRz~0_#Mx!$h4?hq^3MnQ1{yqRkID2d;sreKs%c&&EQsYuO zsQDCtC{m0@XC=YytzWy-FW$XY}?j`*>-nr z8mr;DU0rXQCL5=x-=5Wcsy&d>(dT%44#2^|`?Z|AvyIbviE(xHzG=KOsq$JUwj!o23Vy=TYs##RY_6Ise5XUQ2mPx$gGod|R5*>5lRacRx^K?38ba(gT2|z#I1MskG zPU@PbaR6Lh&8VvDR|S*xdeytI_UIq#K`DhXhMSx3F(3Hd&X7nc zDa-O`Uu){R#yN*l3Ty4jk&WNHEK7R3P!vV9DujqhYb{k(0T6zxlrru@;Ku;HkY~*31o=VF4-W2|&>Cj#D{kSY8yZE3-dz-m^W}488|HZ@ObupoPx$b4f%&R5*>blD|s=VHn3h=79#Ux#;9U=hWnnLU0hm&E>$Yy~({T2wH@eXzyQ$ z28COM5($C?K`RHFyg(-#JUT&#xQ647(?gMG zck)7?xF`W{Sl)}ns1XlEiy+G~rfDLjQ!!uRIt(EMjmDF2 jJ6o$zII{lS{BQaN-b#;yT2c9M00000NkvXXu0mjf1f;-w literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/censer_cage.png b/src/main/resources/assets/eidolon/textures/block/censer_cage.png new file mode 100644 index 0000000000000000000000000000000000000000..b4b0a72ceb6a69561db6b78c18e87c0839bc8883 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|`aNA7Lo9le z6B?R6o7(-~AHU*f{k~(*?U|)4;vawhf4Hq=O%acQ?|=K8fBk3v*DYiVHq>Ld%)=~i zw&Z{N%^qLdO%}p-&7!_bIJ+L3KKM6tdCO6d8T&8XXL|RXU;0wu50~cFe`5a=XI*^y z;V6^xCPss@KgWc7UT|fyZ?Ke{Z((&nn!CiXA<2LvsS)VhtdPY2C;u;w0y>Ss)78&q Iol`;+0K`I7(*OVf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cistern_bottom.png b/src/main/resources/assets/eidolon/textures/block/cistern_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..5636b5ea9bb3c9273051b832cc83263f36655e2e GIT binary patch literal 416 zcmV;R0bl-!P)Px$T1iAfR5*>rlFdp2VHAcRbs);0ra;A?AaKM@Z44tQ+obDgQHv0|fbODes0$EU zxry4kt3_eZrey^Njo}zMqn}o&*`_h6Ns@xz&3Aae^S{M_4j?okek%B!YmWwpZ=zrGHzWK85`fF+aslzW zQNI9~o)2&PLh?L-rs{=a;cjoBfzX67#Q>7W=|9@do&qdwZ3YL9a8-K!Lbhv-vQ=!N zUn5z$3QdTa#T7H|@$PYV{C(Vy4xqOKrskA&B^BFwDC${R@kh*8NyT(;8`_5HNN})XS@Mw^NUPx$0!c(cR5*?8l08qtU=)R)LXpINKux5Rfq7BrK}{0000Px$CrLy>R5*>TQ?X9NFciExl`_Pk&CsB<3=GXimJD4$S@?$z2#F8ici;mmF){K9 zEJz)?WDG+FT8n^`l(<7A0xY;P#+9(dO;1mE=l7n@o!e#g`SQ5AVHvvzfTnCyXkdF* z1OP!8B!jVYJ{|Qt06=tP6A%F41?PVis9X{b&4-XR1OTW{sj-V}po8sMkvNv{nIhm(U#f7G7mNB?JH{N*zu|EL3 z=G9CbP)_DICmxKQp9Z=h?TWMt;}oeYkX2rpdO+6v&u21;vU;yCRG@RDUyQv{00000 LNkvXXu0mjfRnD3o literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cistern_side.png b/src/main/resources/assets/eidolon/textures/block/cistern_side.png new file mode 100644 index 0000000000000000000000000000000000000000..98c5936a414ebf1ab701440636a475e2e9ec072b GIT binary patch literal 500 zcmVPx$u1Q2eR5*?0Qp-xiKomV~gP^7w1sjYN#iqFFrWHk~y0CUFE_5M+|Kd0J0|i%I zSn5hBZgin21VJ}a3lW+~;%kzbwmur`YGQrj-m{rIXE^8HnKOaBL0WMoh$uSn7gX_# zviXXYAt?X=Lc4hT^s&@*YnIT{Edv0#v?`J+$J!10BFM&-puZQmIKO|lRXI8EG6J1dR!tWDQ@rE zX6%CjC#gd1St>${qxT_b$w%526G=?t%ZKHM8l zi4jr!FaZE?a(F^rRu{%MZgrBAR5`|1bzyvii+RKxfxJOl4>n3ow`Ls`irzr9AF;{V zQ03&n0mc5oa4FmX0000DBu230?N}e`@#+w^;K4!6P1?Af9yw ziefX)#>dtE43b+luk-v*)8cbWjP4{RBp6I+kv{OH<)JvUU3xO}_W6ICH_!CA*ui^% z_rR<4ARYy=4;>#r1f(z=)mw0a!86p;TFfr5FvU=ejm?8Ac?WZEy3H(*{VYcXIyv$V ze9xDU0XlD?CNJXz=APF6Xqja{Z#MH6nDz+w+5Pzc@u7K8&7lMO=ULDDF!M7={Py** U`>=5jFlZP&UHx3vIVCg!0ERAnA^-pY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cistern_upper.png b/src/main/resources/assets/eidolon/textures/block/cistern_upper.png new file mode 100644 index 0000000000000000000000000000000000000000..a6669bee4033a0ebc537f47e33b12b29b6212db1 GIT binary patch literal 427 zcmV;c0aX5pP)Px$Wl2OqR5*>bkiSa;VHn51o<|M7i4NV-DHy5SHJnfcR}CG`(bCZ3Kh-}VG&v+T z1<_JNVQ>Vtgb6q3$%*0p5>q^Dh|@C}r0oE3b$4quMRo=0(YkXKL%I&@_NBgjmL8$F`#9 zSEIpg0O)s|%DfePCs@Sjiu(P_vPx#@JU2LR5*?8lfi1jKomufA+{2j%%liH7X>$(h3=$(VLzxJ&=1nT2)c?3+l}Bx z3SuT15UOCiNR!5zhOD~sEbqJb&4YQbF@Adf1TfK-TW5(7E@c>#@Uiz1UK@bv% z7fpk~ur!=84~`d_{l0nwz)^RV;f&0mHyA$N5XT9d%?z!5;y5V{O6hVuEqUnQBc)3a zrn;q+hcRjBuW+$uOoCEgu3NR{uHf1LEUlw_`=l)2!eUJb7pPx$VM#Em1f|j)h9PZ(VLTy(AR3JV zn|KxP>MvLWa$Z`h%>)ePaHV0Md9QOQhYQd8ONcX>PO;(M`t@*ldxvB?^%DT#3oE!i z3Xw<@RaF*-RMqOaJ<7}y0l3~CU+hDzRwa`;u-AA(uRowxtFpGf$F%<+i*G4^h0Yly R=0N}e002ovPDHLkV1hhqv}ynV literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/coalfired_engine_on.png b/src/main/resources/assets/eidolon/textures/block/coalfired_engine_on.png new file mode 100644 index 0000000000000000000000000000000000000000..618cafcdb6a2cf37c9e7732c31a073f33e152820 GIT binary patch literal 525 zcmV+o0`mQdP)Px$$4Nv%R5*?8l2J<(Q5?m8ZiBJegpM<;qpYz(EsEM=>Wk@P1c@6OguV3ASBUxu z^$C2*hhBCGYH54Zr3ZZo5^1*{mQ^mZvaVY0Ff%Ze52E&P*>Q*T8+70g|NB4Zo_o*b zw!QtdaSHJMO^(;Eo&b=~=jb&J0QUA9q|b*hzbCO!ZNX*zH<$f?XtkJ9RP~O5+lPyTw3{nrpaqMj?MAZ6vbi*fSszvZ{IsJ z0MK*|-?b5|YHvC7(E1h|T(YZphDkDidKmoW#gz*Ylh#xbAY zAyqFkA3eGF4Vn?uenoD6FaWm<*sMY_f%)({YQI9OHi+QZP7py=J797^GBe|6s+&6M zVLNd8k4a>7dV&tM6M)#!PdQB{p!2b;&1&exc;W`5(-YwcMqEej(pkB7A7OP%#(O6# znLt?Ge2=D3yY$c}0#LrKtp|%tHVX?2@WT&@z8o85vRT?M-=$Um9}<57Z~CF$t_Lkw P00000NkvXXu0mjf%ERp@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/coalfired_engine_parts.png b/src/main/resources/assets/eidolon/textures/block/coalfired_engine_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..2dc2093603fd3f7d1f85fe2265b9a6a1754cbcbe GIT binary patch literal 448 zcmV;x0YCnUP)Px$dPzhDlD|s=VHn3h#*G>ZZ@m406XXV`$bTRl3WtIqTy$s=TN<4jifHMd zi6CeR9h`$Gs-Ynogi~L9K~48-u=l#Nv!w5IcklE4y!U;cCw6gh?(OaE(`vl~VA~n4 zudg^hK8-PltXyt`YV`o6GyqZxPEO9|@dB`*x~^{qP)eh^?%V+DuYyXY>?M;agpi@{ zS}O*F{sbVU2t|mJ)++iB+MOPU)hcp%Z4#mD((d&90>{ac%WXuOA08gD3^`~D-nP23 zgl%X1DH+*z2Gw=3gpj6(02mDVI8K&IrR+IQHUyqlyVE09C~SJ;@tAl#9y%G_5AuV*uX;qb#h7eY=VBod1NTwdP90E)$3ZyI)g zf5&L_ZEiLjBod3P?(Se2qmg;9)sB9EqV($`nFglQX@rn8n+*W+`7N|ov^%}ofT+zg qaf4%?2{0W8FsmGdYOO*w|JEmrh?sQCglxS40000Px$Ur9tkR5*?8l21zlQ5400iPWN|MtLFzY6-Qf78x#O77lHqMYM0z$7<6)T11=B zK-wi)LK0!3q0=96P-kAPYau;mbUs3Ncg{WU+;iW1Gp84KKLBSZ=d7?y=jaX8s zUf3(_eZKMj(Py%PxIhB{+wKJlmlLsIgV(1f1ACw*2@#(%5hAWqblWYy<;b5PDx%1t zO|$uou16S+hEtQq+yYS%_3@!eVZHu1bvTIg8T_pPU>F4)$HlTNEX%@iTnwY2`d%$S zXkZU~vC8EVQo0ID=~6D2e22Uyq3wK*c}-V@rY%mz^m5774BPpf!eM||QlPa3@I^YE z22dBN>k);ui12+PfbjiIMS;Jav)LS5n;XFRX{*%=Qo78}t>D%F*SLNGJkgXD((rmv P00000NkvXXu0mjfIGnXL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/coalfired_engine_top.png b/src/main/resources/assets/eidolon/textures/block/coalfired_engine_top.png new file mode 100644 index 0000000000000000000000000000000000000000..a27a025a3970d1a9f0e52ff44fb422eaa6ba70eb GIT binary patch literal 483 zcmV<90UZ8`P)Px$ok>JNR5*>rlf6zGK@^2QEQ>T=jHO8ifrTQ=v9?&F7$LgdN1#CTG_<@%o`QxR zQKYAVA|i^wvbTr~T98?O7Dnviod%jvgdMMOqR{13ckZ3J_nbL16Wd>Z`~uk7+U3Lh zb3E6j)Ah+?q3N)HaKP=|N7go00a#yIngA#Sy^zDbHfgNzT-O{*l9(ik&DwKa(pYi0 z*CyzNCSN?-|2{IU)AjNFE?R2(ZAtYLVGaIzl z2q6Iw@``d0@R=19|liH(GO z_xbr60M%-BY;sn6jl!F`{{_WACBrZraUp+cV+^93ON5YE))c^t3)*bRyI@&U2qB4X zE{6;{U4P`k{0pb2KT#?gHt3y{fih{V0E`QH3E2S^&GPspxV_6s*!;4=qPGk{zaJok z#BrL~wvBDuI8GBGB>n#H*SF{`oBse%ybkWEHL4s{1OTnpXO55CMt7D2uquLDW8C8Z Zi)Vusomsb`8@2!d002ovPDHLkV1i0i))@c* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/crimsol.png b/src/main/resources/assets/eidolon/textures/block/crimsol.png new file mode 100644 index 0000000000000000000000000000000000000000..dc0e7bfe59f302af429bb7e9104609c67bee6749 GIT binary patch literal 9203 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 JPDHLkV1he$Zx#Rm literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/crimsol.png.mcmeta b/src/main/resources/assets/eidolon/textures/block/crimsol.png.mcmeta new file mode 100644 index 0000000..ae24a2f --- /dev/null +++ b/src/main/resources/assets/eidolon/textures/block/crimsol.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/textures/block/deep_lead_ore.png b/src/main/resources/assets/eidolon/textures/block/deep_lead_ore.png new file mode 100644 index 0000000000000000000000000000000000000000..4360a4635c20027533744a96cd69dcee2b83c421 GIT binary patch literal 777 zcmV+k1NQuhP)Px%!%0LzR5*=QlFe@$MHt3^Ydc>gS=l=~UcBVs7^`-Zw6cPdf)Wr!9H1OPMI1O) z;=jnvclaZE;l!nvszQRQGzZjFgaZB8Heu`H#3G&r9CjsU1sW|P|K9jzl=*9IUH1OZw{L{T3A+n#z&$QYA|xvrg@PlYl< z2!s$wDG7oAJGX+J&9eLK24UDDiu%;v`HJFPnNCY%=MK34+YgCIdU7&Xx2yp{5HdPe z!}AL`zRO5yVB2t$xud%wioIEa_n_=tDCet|=ts}N>Z6@_X$>G-Z+w{7c z>6}ZYGD`+PDaFhE9oD}1knrg)#c~P9cWFFw2)AznpVD}=Lq~TKhX>ueWYRY2YPDK7 z#xON`$i0n!7#kT&+$^qK!11--83_~?*wWq@T3h8WLc^77#L%dgGb(H+vf zjhAoZ<%iv$Jb9L2O-uP!J)65kqwy!LR-5sW0*fmbDU=+pefxbf@80eMENeisxla`J zdGX?ylamNnrTK*C-K!G1fB<2pRwehR>arJ<|FPDm#Gn3>tnXzYY6%*UjPb7kyo zHc6H-hK2bU-!r_oD#*F&|3CR)nXZ=nb#F*UDMi{IFV#Q3@)3UVO~S`LvZBHt_kUqx zVw7gHiPjO;K(O-3yZpYf#UQqroO+Iw@i2*BURkZ*{xRV0&l?;c9a4M$65Y1N-tGfN z$7;Mh8Yh(s`1PlNL2TjW+dO>uH~s$MFo{YjygV$-OIrKlRmyb2dphS*tqPPuQ_cVi4f3`PF~6wo^FtDx^>00000NkvXX Hu0mjfA3b!C literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/deep_silver_ore.png b/src/main/resources/assets/eidolon/textures/block/deep_silver_ore.png new file mode 100644 index 0000000000000000000000000000000000000000..7483808645a1c9e23b05b4ab38b9c37f64834e42 GIT binary patch literal 755 zcmVPx%tw}^dR5*=QlTSz#0Tjl6n@jF)>$Ej9HEvs*UeqiUVb|28zZB&q34%!aD;G z?IHlLp4|B_UlLpg&T8>kz#FP7(m|z5${;b_3Af+`zN!CKD`v_ugMD02YOGQLkWi% zOMwz?Wv4&lvhZmcI+{8Gm|a|8>$mp+cwUa>?bpLY{QUKu!qPkdmyh3dHz?r{$tl(4 zqJ%@d9v)(UDTA)-R9U-f27j2-bo#3)f19J_NIxNe5G5QU-dM-O7mq0>-_UX90>K&| z_n+RTYFhxWp;aujdCKU&ZN|nv5$_wIy}5z&@mc_`K6pl9X&%jIlblkS%#K$6VK&9; z_vMO(L?U53H{g68z>Jo3K`PN!+B{`G+tuv!M_l=`ELR{pwZD|%vt8}7P@=7Fw0drw lHd%&JhIBfOD2nL1&OZPWJ$Asjl(PT;002ovPDHLkV1jPrS(5+& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/esprit.png b/src/main/resources/assets/eidolon/textures/block/esprit.png new file mode 100644 index 0000000000000000000000000000000000000000..de62f046b18d751d7c3de8483eac8323d1161453 GIT binary patch literal 7513 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/esprit.png.mcmeta b/src/main/resources/assets/eidolon/textures/block/esprit.png.mcmeta new file mode 100644 index 0000000..ae24a2f --- /dev/null +++ b/src/main/resources/assets/eidolon/textures/block/esprit.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/textures/block/glass_tube.png b/src/main/resources/assets/eidolon/textures/block/glass_tube.png new file mode 100644 index 0000000000000000000000000000000000000000..7db37ed51538c8e04d4a2c7c24a6941183c0be73 GIT binary patch literal 364 zcmV-y0h9iTP)Px$CP_p=R5*>Lk-bjCKoEpKBfC1=v0QLOE?f{&A|($1Rq__pDe^oN)RepdR8UfY zLX+fS@mjG2sHXC`Px$H%UZ6R5*>rQol>XP#C<#fM9;TfF`647MgAfnxRW1i^Ti`PC@99#nC^-!NIk= zlcUZeIOyQm4so!-AT(`bil9CRNlmnYMg(vAIPUJ<_xPAwI-=*N;mK1FcQ6N*>!iKA zryp!F5(5BixBotmuYkOVt?d4W{}14@VNqGwcp1FiWpiFs#uoze0==o*>MCggK=cq_ zhushWAj+aCsDe-$FeN2kJ3H=N0l;?KtL4p{#B0sk*XA?-;C1x;n4j}6w>DYlM+0JL z4fKHVaC`#*Nt7h()=s7oGV_YT?*qj<-~eEf#ttzwp!Z2;L82_0Nt7hS&>E98cKSh# zK}0ST71I{X(Pcn~_vx%nN+GW;;n1ox1=9CD>iZt8l!U)HB-gbm01%@5F2QweYFTFG b>KQ%&O=V*8u{Ob(00000NkvXXu0mjf)7GkX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/incubator_detail.png b/src/main/resources/assets/eidolon/textures/block/incubator_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..ab541ed8b805a75e3153d70d0689ca8fda2104fd GIT binary patch literal 539 zcmV+$0_6RPP)Px$)k#D_R5*=wlfP>dVI0OkkwYw{a0zd?)FhSOkfHvdu{4Y5;25=2^g(F=Y;&A57^o;&87Cz$BC@H}~`e%WB5cXjx4>&;6Id;a-z`S#aFx#RGI6)#^Hy6`9Qbh4%c} z!??^ZZF_p_{taF{efhsA@H{suFn>9+Bj=^8NIl%F-DWVbPx$hDk(0R5*>DlffPyl3jWAADWOza6)SyS3Q3 z?4MQNna(EwhyutnhlPJa`As_vV`x|ygk4n_Nj;hTX7C?2H`j&1Una`}nmIGC^d*cR z4O*++ikUO>0Gck|K&4XoGElQdrnkR$GR#1R2eXN}_Av#Z;oFv)H9lY37qVbVU&3hk zwpA_L^u*PIreoEsx>#U${{iRH$HBKi=t-K_j_Al1aPX~$A1AI3hz05gMeeS|&w6rg zQrZOosg$VI;^K0o)3Ih|mjbt5qvPOTm|s{406qYJm!y1Hd6g9a0000 CTFZd| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/incubator_top.png b/src/main/resources/assets/eidolon/textures/block/incubator_top.png new file mode 100644 index 0000000000000000000000000000000000000000..68ae4b9f5cc48096604fa649b1ced9ee3db5cd40 GIT binary patch literal 392 zcmV;30eAk1P)Px$LPrkuggGVHn4McS;SS>C$mWLf~CZ4dqx!5Jn#$mzLJXK2EC;4ie2$ zI26*TL6f3eT_}`#_X-)tHOLFsc_mH$mgjx{&+~uYhxbv+F9XjqQ~=gk!p}3GgmL%q z&iU@T0-!WJ$7^>Yt^G`71K|4c<96bVx}qmU(3mu}Olp<9WvFZ`2?ZbuAkF3bw@U!g z6T%(3^_i#J02&zNrKHNS=b8a`=++1AZpW{wa_o8L-%tT2&Zrwr#I&TTWdPDyvk;8w ztXa@4Jr~+Q^n_?uD|W3|vUN+(HLDd{xAdI6*NP>(RxH`kL`<7$AXl|{aAZi)f0pc> zo*2z)#SZF9!*jfwtJe!DxI?!dUy1Joqd#|ete^c@qfCzbUrzwz{vb3iry^USe=seY mn*SoKMhz?c4~uWGc)kH`VxF8^8ZHU|0000SGAhxr*IBe$ zGNfi_)TVVMbbUCQDYl4H=Fa5@Ix5mHB79~kmj5l0-y^8hy6W1V1?uk#z2g}e>U+{| zCAjXH!^H3-KiHxvCA<1S^yHlBj~~P>{xi*Q$%Pc#L-k21U6&6nQoOh&U#y`vw?1=S b%3Px$Wl2OqR5*>jkiSa;VHn3hr?(_D2#RTOln6m*5rGngLxD634XwJiw71mM-_R7) zKOkI_yF;LZHMV7xzq#`+icW&JK~6k9L%q`TW|kxFOqqFO1FN@u86 z%H#{Dl2hMKs-kqLqSrgfPD7*Fbq&X&VIoV*Xj;)#Z=Ib8z1~5ucL0z|rF&7UJ$gC- z$mNa!*w{!)01pRyLbq(zRu(a>0kYHB>$P2jp-{vXWt^`sfoToUEgQMrdY>A01Vf?7 zXtTpx>)R#do7^_;AQlZz)dPW{o^IIy$c<*#vk{m&EP(&&5><(hqREc^Ns&gg>lsZ^ z;@sR^v$dHdUpSR~o~vh|X+^Txqmetg-#38a(VX`z&d)DgM;(23cC!M&{xn%%uqjra zq{(3~WJO5`!{}mvn!LU|6AXsw`}}i9k_}^+<-^obR@VWrfAqNpJlR(h;%^H7$uIU+ Vk{-_Clu7^q002ovPDHLkV1gVo!L9%R literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_mid.png b/src/main/resources/assets/eidolon/textures/block/inscription_table_mid.png new file mode 100644 index 0000000000000000000000000000000000000000..51dcfffd5181603bea215ef059f337742208eb5c GIT binary patch literal 348 zcmV-i0i*tjP)Px$7D+@wR5*>jlR<97AQVKO4GzSXRn^O!qj%_GdhIIeu8}OoU<1y=u`vmivg)jW z0shQqD84>F=C+mOU`)uaPg9^bf#5;5t>pV>feD}ILwxsn%a9_r}r zk{rKs7J6&cXyO1wcM}A0^?GCg^YgmCbc_C z-kRmGaZAJYRQ#w)c9!J_$OqtF`4z}%T3+Eg`Y3TMHrW8yhJ^2k z{mJHFt^QXI&b{SC13+0-(eJPx$g-Jv~R5*>5lRa+SFc5`5QIseN5aIwf0yi$Vw41|VrqGgJS?d6P6*+I_%@2pk_b;FKbu9tV+SBel*V~GVJmnaV#&P$dr!ECW zA!yqXJ%Y?K!S6o?0Hp-O-~srx({$cPflrxY7(9i9r_BgJZydr}k5Xcm?b%s6?`djF zQ`=|*&{J%T5diDf(i=xz3X~Fb-gB>X6uehcHA)HUQqUX6x}5|i!0M_5plv7lrnY=k zSrkx8(Bu|{z*^7hszhr~^LIdQJI}*Jf%7v-m8Y?l*LaJUC%q5l7E&!re~p+SxSUkE&H#y4N!e|&QM7iKMJkG0ctW!ZdFgFXI*$Mv`n7zQ6RR(ZNu z_uwOf+ItZa$gowtaf@kRp5*{MYz*vP>|wD0{s9RZ)4a}-m@fbT002ovPDHLkV1n1c B%OC&% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_top.png b/src/main/resources/assets/eidolon/textures/block/inscription_table_top.png new file mode 100644 index 0000000000000000000000000000000000000000..06e1b669c70f4639d8184c879c05bfe5ac7e89c7 GIT binary patch literal 386 zcmV-|0e$|7P)Px$JV``BR5*>Lld(?2Fcd{k>@+cj3I!?Z#$E|AGP1DpG5jLGz>*Cl7K9=ZkWmvS zvCELUt=oc%dY4!)=iTHzT}Kc1Hw&c%08Qi2wd1ayFv}zWMP&hasT-azI`S+I*jOon z*8NcI!5Bx`TBrzgCPzRQu$Ar*P2*OO8qCQP$+q%DV$3cpyxZopZ0(MLmuI|UT|10% z7&8>+%jUf%ihynGg82Gt95C;lAwQLrt>xQxtNHUpa;Zm5N9h`lKy1$I8xB3^i5zxt zjE*vxW&ikteM>DWi`aZIgyrya*;?YK^LgNEjN{7f!g(Tj6b-M*dWj!(Pdqsh=-LG) zzXfTWNYZpYwQ8f~UDz`4U;Il!lzqV$Z>P!LrZg2R&PO^ftDZ`C0a#QvxX!aoQdE|= g&lV*kV2Clm59T4D!fnpR+W-In07*qoM6N<$g25Q6XaE2J literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/merammer_root_0.png b/src/main/resources/assets/eidolon/textures/block/merammer_root_0.png new file mode 100644 index 0000000000000000000000000000000000000000..5b8ff46e78bcdc809a9c495e013c9ba72fe0dc51 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|j6Gc(Lo9le z6C_v{Cx|>?ZGX4*fBQuPGqVFN-j6Q+P3Q6c_UvE##*<86xepiK^0~lzgo&X|T7-kC SPn83xox#)9&t;ucLK6Vw(I%V# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/merammer_root_1.png b/src/main/resources/assets/eidolon/textures/block/merammer_root_1.png new file mode 100644 index 0000000000000000000000000000000000000000..100058a62b58f989b5feb7ad69daf42c2a3da161 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|R(rZQhFJ6_ zCrGe1i~RZf|Iz>Z|MmYZ-n@}fEk@{k{JoSP|LY$8f3BZ@h*$NdsDGTypMIaoDGbca z%+7xg6*SF?*uZ)3ugS;%m(A}>$la}XyCAeCvEa`aS+-0;JvJa{bN+to|NXxv6Sp|@ z6wW)d;>`5(Ck`AqprCu`C`j2Hy#udUQy7dpRKyP)c&omiW9IpW%U`mEbN_Xp@-Q|4 kf;Tt*wkVbz3tW@M_{Si~?OS)C5YX8Sp00i_>zopr09ssT=Kufz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/oanna_bloom_0.png b/src/main/resources/assets/eidolon/textures/block/oanna_bloom_0.png new file mode 100644 index 0000000000000000000000000000000000000000..812ee1ad8081f88754689824a3fad8e754d7f346 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|f;?RuLo9le z6C_v{Cy4Oy9q91AumdKI;Vst0LacT%K!iX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/oanna_bloom_1.png b/src/main/resources/assets/eidolon/textures/block/oanna_bloom_1.png new file mode 100644 index 0000000000000000000000000000000000000000..62313e4f90dc9653b376db49d44d01994300859a GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|4tcsbhFJ6_ zCrGd^ZkYDq|26IZoq@+&g5Bnc=biYkcc(2;;=`IRH~;&7JpSL<<`2(v;|ybioG$x+ z^0OT!*gU%SB^wA%PEXj;rBX4KQE8cP3%6PP-!lrDzxp2j%vRi?cs`!n5TxqHo>#_g zj6El0c60UrKQzgR2Lw8wPg30GbZ}-kzvMINv#Axo|8O2&*eBZ)!J7aC1}C@t*I&Kx z)Bzy)@a?B?TfY2$;Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/obelisk_bottom.png b/src/main/resources/assets/eidolon/textures/block/obelisk_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..5e3fd4a16717a0b84db9f36b4d8dcc061b14dc02 GIT binary patch literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|7I?ZihFJ8z zo#e>HtjOc~zeC_e*0p(8lq-VzKO79*J)3on${IAt2as!skoxlhp1LWpWeOzWLphd+^;`8?Uf! zd*2AVzSWWYl@rgQu&X%Q~loCIANbT~7c2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/obelisk_parts.png b/src/main/resources/assets/eidolon/textures/block/obelisk_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..69dc7d3689bcdd60b5204745b44bad530b3ad7ad GIT binary patch literal 311 zcmV-70m%M|P)Px#@kvBMR5*=|Qo*W(FbtesN|8XpLqYV@{1rdKvp*;ZJqUpudf9hM$=d4Mx!Bsy zWG2mP+qO>#0U-n^m>JBBloFO@dEo(0$;@0G#u%Tt0DyOktb6O~R^a-BnIR$&k$=em z;Ix{4E%9duEiw@``*Q2Rf{4CcS*+{&8HS-mbtxsp7%@##xn!TQC9c9mg!ed(&1Zbd zZ=3A8uKTKN*Ba$Y*6JbxH_!9qq_v>J=Xut1@C#Yv^?eU_y`WvT&}jR<0|1WWC})*` zlCMn_5qR$_N0q?cC=*f1ZW~z%q?C|z1^{^P%UTIa&N+jK@CT73lSuvP$FTqa002ov JPDHLkV1iD+i248k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/obelisk_side.png b/src/main/resources/assets/eidolon/textures/block/obelisk_side.png new file mode 100644 index 0000000000000000000000000000000000000000..6c32417766dca3376dd818e5d0cc87f4366410a8 GIT binary patch literal 324 zcmV-K0lWT*P)Px#{z*hZR5*>rl1-|GFbsvyy;zli=%C;d+<>cbf$mKxSP2BRgZD-a^_Mq$8O5|G zJzwHy9LJxks_>U!W(>pdNo!duW@a!mj4@g(%M$U<-9y<~3;-d7%f%;`*;xz#A_4#) zB7_jM;iH3fT@PaKz2??hobROZO+TD-5E1l!kFM*q_J;9gW`qzRB4B1%YZWQxB62$y zMToprRVjZ&D2f6^bSpj}7-K+0sOuWeIXLIgwymB4I1KvYAX;3OMF%%c6Pl(`#Ml2I zS|*|cM%>5~Miz$@hnPkxO1E)w;Jrtl=UUwNUGr_*F6V~^B7%9IFV<76*ywE={};bN Wtfw!2X$}1V0000Px#*-1n}R5*>DkvpoyFbqY{guw=bNtHS)%4)NkY#@-@Ah2A#S2-w7JTP+`e`FtB zNw0NX|Mq<+#>lp9%<~LDDTNp#$8j)@BLLGhu`J6AqjyRP5dpwCM=9kDrj$;YJzEU` zAq4FDjfVE3y7>tpBBzTA5|NM4n}hbVs(vi(5zqs60oA6eULN=M7l0j2&iV4NwcZ`0 z%@9I(Y+Tnt4Yu94dmC@{22j;oKvi+hk#p{rbSc3?TA*|8G5hJDW)Ts*_m`}-4DbCT lU}zg=KU=jEx|Q&&{sDELnSniwa;^XX002ovPDHLkV1iixc47bk literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/obelisk_side_mid.png b/src/main/resources/assets/eidolon/textures/block/obelisk_side_mid.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f825a3529052fe816d19c40c32b04b5d328b4c GIT binary patch literal 291 zcmV+;0o?wHP)Px#-AP12R5*==Qb7uYFbo`pN+<+Ro_&$8^)-G#5WE#a(ZlX3CDyjit!X-)nWS6S z^|$Xkm>Ju)VV-9IzH3?e3w9qR%5kW*=4VsJ1q^O_Px#^GQTOR5*>rkwJ=vFbsv?FIGdKxG9Jy@B*I31A4kHgg_{CF|%r@PCLwQ-YUkt zwBPIJx~?zpJ^msQ!Fisax;NHl5rK%nIcGg0LYZkDG``IMkaPYq*t_NUHUogF0sxp9 zIcHngy+KOpVZQI%>JS3nGqr~LBgP0-#c>?i_uYEGVGJUIoHJAvB7zWtA(dKHo4FW5 z;q~4de?ge%8O+=?KMGf$(xJ5H%N1QJ2dMmo9^#@`$I$-LXX}x zG*)Wrcv0Tak#KukYvZC-E-YKa`W`bZxOVIOXB$C5mliRTO?~|HPT07HRu`q^RarIe zuJ_G9v*+j;y}67oDXY%DDQ=qoSh#EV^11J;!V>5HozWB7%2fG$cOG}?%mfpgiIrY1 n3s(KjUdGD7{-4y&e%9OE<)nJav>K{%nm`_v_nvK z=_Ygv0_);&FB0S_I<=?pB6|>`PTf?ZOBXvSVrd-;HFkB!U5woNrrA$-{&W~-Y^_7j z<^5jx-sk=EJj&f`m&0$4$JthmI085|AL)llo*uhFj7)zzd4H<_Mw3Dubxq}8Fin$8 ze;U&?>Fnyo-ai09(>0aW7Ko#vfuX55H9skKYCb*P9dvf}0?^lY0f0)mglcG@X9meW zo9Fty`{=rgJU77O`4>EW{t`Vi2*8!AqW}m;lFL0IpPyr6^COzBt4w7dGBYzxP~4?` zWSEJGJIu^X1Aj0%`GC32M@dH^1V4WK1fWnTpc;nC>dG>yR2%Ih!;FoNlF!c(6n6nw zUw@yhA{>e9x}?+55mTu)G$A||7MBp{N5; zuLljEzYFhV1tI>DR}(TSkba2tj*wn6buU2rVItva>{WlA5LkvvPe(ICctA6jr6Gie zQ&WI5bhqmW8Bi&ga9tOGw;w($F@XwT9~?&`$^aoeEK5WBAx4vekO7vVCeAZWt6>@? zo1F?x({oDv9lNbkE+HIArBcCl1-aa;Qms})+uj49SlnTJ{I;T*riE#m*!u@qmWBO? z?(xWRSKHoWb!8cVt?fc|1J@O}u4pJYA!xjM?1hNbj0keMS%v>ZrCefbyU;-V8*lXx Uq3L0l&Hw-a07*qoM6N<$g6P*F;s5{u delta 462 zcmV;<0Wtoc1@r@uFn8S{5QRTGX0x$!iCBU7lhzUi&%h(3qN0a3 zZ$KIzf`%44q|opJX+i~}fDXwUHrXtvnwdL3bI;sk>-CFg zwMc>JiZm~II^H6hUy$Y{x~#do?Evuh^C19HG~?UXBMj`(Xn%m{sx6F01JuxN^KKkP zGXU;CcuaIM2f#T!z34TXyo)q1iJ}?P=`jG~@e=@&IK(jx-AU`<`x6chKC)b%;dvgt zuhP5(=t=6vNgN^~ESF~h1VMl;Qe11i36g5EEW`6W0Csk6HxdkVSz`$QtsDJWCj377 zf-Y-5egA2#6@RXa^Og1Ot&KKr35@==5=5@m9HU*AHM%%QwA1D{5ziKXt_al7=Fz>u zrS<_zIfxXbxdm+U@XjqnS0r&rmSq4O{`h6}Bt-MZJfbT^3Y2otWzBHILUe^1+O6|k zSM_dVeR%(_hQ^+&ki;PXFJJ9hi^ZZgcAid;+1-6^IY*M}X1YIFxg@2oCU$=$e-d0S zQKZ!d%{v>ouIil`FEnRvL$JU9rd`PYki;SWB0one@0?q=EF@Fe2L_t(IjqQ@bPJ=)cMNcVI1{oS48XMC@>nHf}euqnUx-d3P z!9p2^nNEufV|U=*c(yn1n{8B1>RC0;0i6MrXn#P@=6L91H=uSdob zncb4iQ*@&MF#eRzHorH3p6u!#-4xV7Fr5KlwL0%HgxBhpJX-)D;`|&KRk11G=?;2a zkjNCP6-HG6B=Z!bDvHe;LP)YC9~Jn%7cdi-9C`;wOS3L0$`6=&q{%h=lLKCd1pt*b s0O;+SvM%`fiyyM7an6i3_~%dX1*Yk54~(%#Pyhe`07*qoM6N<$f-MVyHUIzs delta 288 zcmV+*0pI@40>}c8F@FL{L_t(IjqTFSPJ=)chT)gtccwro)u=IX=Y@E$UW#k)qm9U) zoq+*b7sT$sz46M42tL^n3i$JR_`+W+4jMa6}pE?djh3U;wcU~dS zHdt+8f^ZX&ZY9;Bp*U736%hsAI^YQx5efh<&V}lup{N=N1iNjFD}Mn19DfGNW680s m`T2`+nlPW;DjD#fKap>_)@C2h!Fm$_0000Px%dr3q=R5*=YlfO?>Q5?lT{XrBG3|xw)TJ7`EzF>z20cB{Eriq4-C=IeX8I6B{ ziHnQfG3??%99T(pFicHFScp_$sL7*wDN=*TY(?^?Xmy}9>$&iS76y{-oj zUp0hJphZFy^98g>2msv(kV$7rB;x?gOilyP-suBC_yp3Hc%5QEfdCZq1*9zju*}k# zLM;;F^M_9Wc=~SMPjz$)#d^J0V`VYN@1I*79Uf5LtkZ?2|M6=hlg{$^#W(=7Q*%nm=7vdorw`#1N?~(*S|o(mGD}EXGCMT~fV3sr>Eq1} zQ%R1EMA^0^mRZ6wOK6c0x)H#m1qM^CZLNyITwQ}>7yG-C@u!byxV->u6?TZ+(zq77 zM2owHZ(nk(Eavb^Thg3DFl?y3Ul+NnI&QcySJ&w1>LQVh zQ{MYSN4H?Bu*1Z}5Celf3=H-#HJDjjD4oU%+$Wyq>C8Ygpe4$_sz+ z3iWD@` nJ5r@B;lJPM09$4W-3ag(l9e%iZdL$c00000NkvXXu0mjfs~11~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/raw_silver_block.png b/src/main/resources/assets/eidolon/textures/block/raw_silver_block.png new file mode 100644 index 0000000000000000000000000000000000000000..0073e160c8de4b3fcce56c9dd629cedd57770eb8 GIT binary patch literal 668 zcmV;N0%QG&P)Px%R!KxbR5*=olg~?&aU92A%N-^-+l;kmd#q)GYfd2~TS{cVPC3Fl2-Ts3ARU4Z z{sHN!Q-_X@hNn905FI9zNNym-Jcz+&O`H#p^gMfp(VnRwsj&|0`>>gx+xK~Yzn>qk z_vf)qOfOU;;UMv3jGm4m>SI3jird$p5eWw|bhANI%Ow_9-eS)xX|hV1o{k{`Zm%UC zjhp=;R<$CAZX)?zNPZXdsV(foeWOTzS3`wJI7lX!$Kmpz8wE1|zIV$$x@8}$TG7&N zS*2QC)rtUC_Dn8MR!IY3Ry58_5&Tl8l^o#Zo99eCnyMuL=#pzy)-;%zOIa5U-DGw- z0YF=GI{?4-egH5Q9mlr6UrPY+eyK=28DlIuZao%Ej&hn^PSDoej{WhAxYeF$Tg(Yq zzyfY>1FPY_QD&DDoB+^`0$C-Ep{`(7G-l>fj9m8dWF&N~8zS18+iB{(ad&bcG)R{( z%qgjdweO#BI6N$^Z*%taIXtaSwsv;OZK`}+ddC@GkQS$d+@{Lc^$*w*i+WYGB^(f4 z0soCBKyDZ{bM2X2-XfmK<##nT`K@7OP=thBV*=IRXuS{|EJ4vPv4WqH*=&L;eDTeja-41Ve=Y0000Px$Z%IT!R5*==ld)>TP#A?juSo+b6p978kikI6B8bqTn{@Fd`T|ZJe1*P6-=K4y zY?rQ51QA?HK!?!aAcCL}B-$alX`)GcAYAU{Kj%OHxw)0c?)T9V5<3Lf1c0v{Ddq;H z@D2f*BP6{R7!LtBIslEQn?k~3mKVp62mqtA0sr#%yt643$dMBWJIw4pF5=JHrXp%x z%!dLZV2Fc3Z5R|AnEQUE5o9q-a@w1i>;JH5?lKRF*^6)kgz z?|Q&G^i#4b9PKC6s`ay6#5(lTS?w^s+cIRGDlrYf+l|4zWh9o=s+Jx8!Z-~etF fpdAOi8w2nI48@eJF7aJu00000NkvXXu0mjffE&Br literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/sildrian_seed_0.png b/src/main/resources/assets/eidolon/textures/block/sildrian_seed_0.png new file mode 100644 index 0000000000000000000000000000000000000000..9808106f91a3c62d82729889512874276effe8e7 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|tUX;ELo9le z6C_v{Cx|>?^_*?{UwCm}r^MMGJjn;uRw#4`s67#KixC1z+_(QfvoWx3W@7v$$2qSU Yq^}5U+|-=F2sDPl)78&qol`;+0JOR&^Z)<= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/sildrian_seed_1.png b/src/main/resources/assets/eidolon/textures/block/sildrian_seed_1.png new file mode 100644 index 0000000000000000000000000000000000000000..1754bfff656f74011c39268db34c7c4af9971662 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|9(uYshFJ6_ zCrIpDaR2PH|6M89|F>K*d^qXBqts-J!l$;W>t;y4`Lh51S+@1s1-lMp&iniSwZENV z!N*M#-!mOooBiMK^Bc}K=CBD{Zcf%X8?pC7$&v5-+c#+({;yuo8P#%?fmhMd;xbP0l+XkKgcgAF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/silver_block.png b/src/main/resources/assets/eidolon/textures/block/silver_block.png new file mode 100644 index 0000000000000000000000000000000000000000..ce9e02e350729540cce834db638696f4b1c26dda GIT binary patch literal 404 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

#kn)Tux*X6=ZgGV}+k)-+)Ms za?M8Gbs^m z709;k+2=HviW^8Qqry$D&y7YDJuf6$m)e*gT4SbGs%=;RsNQLtx>OeCdN-d-IWk~9 z`nKLhndX>{Xa=#;=u}_b9+wke0+0ig>hHK)i-h%i@CE!MS^{d-6Qnjb zX|O$st+76~9}tW-eBISLmhE}bl*)tQqEf%wIi{3>(ecuS{D~n(QQK=VUL;!NE(%0F zV(X5RU~F6XxVO{i-*{PzBF*rp5W6P^OuPW;2yNF3FIdU8IvXoLuI&MTzff+FYLX(=}o=rcd&-IE2(aLgL9` zkNSBk#qBSBwYP4al~BE$`+PCO>}Ku^iM}+tbo7fx)uVDDIl~sBZAt5eB@dE)E=V@r z!qhTUI@>H<@3sI6fxlTihtYkl_3xaXZ3ppeCoS?E5<()2ChU&wfRD;6!~$B01W3cR z{+DPyBK5?|!0p<$4QdnHZy6HlANXSbhrM2#z*}iV_S?CBk>sa#*ww7WWP$kged;hp-8lApOz@+YuJ7y3A5?nkb_BT}| z{(E3;%-CeM=4>NSkO`5!X@G~i2u;~UI`KXWZvK$03AU2@^9ox|eZ9mxueO+a+9)h$ zJmjUu8pz=8C)*#u@Tz``6(0jPZ573DlNl47Ue^)C5~b#7hQFXvpMvGVv(396ze+Xs ztc{(RH_v;!H|@zj-tq@9raYQaOz@u@W%f1(d1zE;)hN6Cp;Fp0bnx^J(zUB<-tSK7 z#J>$+Z%f;1{OUgZ$ed$6M7FqUe#mab)hizyHUMs`MFF29CiyyOdKO;67*f}UYlZA; zZeo-KJ(IR$z?a#xe)#Wlc_*WHGh>p9D+)Oo(OW1`braFm&xr0u8fAd1}hF>y|kd5EVUv&*&`2Nc)W z+Edc*ROAF?T95*JZ(NHS+P}H-YjC&Xe116v9jod=FYaU__8ON^~f)D$jB9G{iD^exnd@^Uh z<-dUKuDH^n&1*d%ezMS*y(!j+vL-pObU(>BL4>U`kEp5i>AYtxclGStV6KLbOJ$d5 z5lww^J=wH4yM?1^&@J6?(fZhs>WytOISCcu5;k+`EVA;j`@QnU+Ly8ae3Km5z6g82 zf8hDrR-qXu2JAIia~nI!O{>a#!-32gDHmz07&VjvX(M+jeoD{ic%4 zojIp$kvPIp*C_2Hcx0b!tk_~CO~_d<5Xh~wA}`XdVHu=hB6cw1#|0F2GI67tQ|3J_ z6PQM5${MQmyjR{+C;4~eWGM3ig`HUF_0#KHf>_j@xkpJHeW!2*yOXhE&BFs z-4xlTeXeX8^KB69@bPX7oSqgJeU4Sul7m_fm5@?YWuW-qr!&VYvy|1JaDXw4^w{mz zA9~oi2RT*SJs{pfCCOIyFh1t#DIrXzY#C%zvPZ&i#I$*L~k-MQK9`e+q=5jV{=RW-N|@ z-V`RbbA^h7=$J1Ho?b{V`o~>JlCQj3JfS_YD(-s45z3_OTTi<@tz-SR&%k5%Q`}d< z5!p60yR(0_bJgmcX|S|huCL@3<^2Hfbv2jz#dIYE)FYUk+w7^O2qd*z@Su~}k%r8ML@c>g@~UFQwqaE9CvIY(V)Tyb!{zM=vY+P@Ln!xR z3LB}kw?g}hE;6=zWui0aSIFaZ=hNru(bnq`v3sIiwNsmNA^qQmhmWJ@W@hlI5_jAk zCdJdC@7x{c>Veb}0z^pun&xLFgrfo1)tzMT$15{Skdse~f$No=OthTG)_t?^-ED@t z`w7)x)ldgG9Degn`lSLsR8k~zJ-Vzjbob1zrUpkWc2qyK2t%j8V&tX{C-EI7YzrPX z>ZUwZYQ1QfguQ##Ux)qfS?MGz;a zGK&HHj{{|?@6@g@y%!?j1Qo&SElwhofq@CEv!f%zlPRd}d_fRpWtDh0xR(B*ye*#i z84GE{;BBIugdKDvxN+zvSk%3PhWz*L-Rokt@Z+MGWs3^;MuvRFtafkofoa zpCvPOfZA(>^3CXr%0xs+Z@rV9omvwexfIDu9vT{_)eyD@ z?OMgkHowF(;Za?+>m4?BcKI|Kt!N~sfWO5RZ-K+@m7?S~&-qe$9Ii1}*j&%@t-b|c zj7v!UUGtlwd-F6H9)R_h_4sl31Ix#Mt4(&qizyuH1Z#Gp{+T5QV9P$&N zVaIz_6;2JlWQaY;+NRUlHbIIX4+MdhyEw{GMF59F_4M@IfJTiJH8lKUu7xO`Bb7_i zEdn3;Y0KL3d@{QkdPp#SU!LD5$W=$jQdjM>p2GbpkqAAV)~PcseDtl7v*3flp`jA>e}hZdtbsaM)RyRRAg^0Ktw6ZK25$oZpu7O! zdcEZe#6L!>CF))QU-k-g_xx0iTbgUFycEI)qU32!asp!c4tWvYKn@YIA;P-X`z>$^ z^70jtQ79$+x)rD+F_9-9jfMKFPlf+q>3-vtZf~z;hg-&;#8&nh|7Z;YR`3KNPEZV~ zHnvY`zev%C5Bl@MZi*cj+*Z;4ik&ZXclLQysO+DR`gHa^g0H%!#yrWuz#wm#p?&n( zA)IXCc&D3b_NbdU!A(e-z!f~IC>p6aDS_ZSW!aM0nt=Mi`<~k@PrOsPy7cZ(!ye;_ z?bBZnX*(;3l<-%dO+cZPZ<%I)Zj}PGp98>N6#!^WI>}d|sr_HcdcNDM@BYj=XHQs8 zOV|)Dh`S$+DE zoU^+hqE0QzMKOLwLwo0OK$t!M6+;9!HNy;# zUWt*~X}|aj5n6PH9v!9e6axWTMSx~)zW=!-(1cb0_|VhTKX9(cVb2QBouMH*6KFXx6$b9)V|EYL;r1{~z^zI%*;8>5A_Ht}huw z3d%JCng^OV8*bcItJe`SCvSE!-?+ved-191`mqR7(-`spp9R(a?A1#Lo*&3mPF>X3WrKxDl2N?oTA23&Hb$H5G)^qnKT z+cWxa$mTDW3q_`$1H%vaE>->(<2Aj<^ z9&Ds8$34X17d(L27#ZMwPg5oKHRsi!sQCJV{4Xf_+vuu3_Jpv z@zj5obim2VkfR$(fnYwYWSb3(%$bTSoNYhYAAWm6^=$BT{d{_EdXsII$(Z`;3aKnQXWrvnC%@Un z%)USyzqwg0I%ONTS;ybDW{#<4!DvHJArrN+SOaeIr@n$1`FmHbF_*dJsQA0VLIWk> zb{n3#z1&=cNwIv^He}vkj_Ro!=5pCpLsY!~x$JL`JOJM{y34H1y=>6R%I9Zxy(V|K z=HHV~IvP{Dr=GDFcsT?=)Ljn2u&M)Bx{C(3jN(HdW%oJyq)6EzD|L>cow++ZSlX?d z-VNbG%4ji7kI*br!|=|b!jf02yGt9Z3}?nz0yZLB_7Oz8<_m+Jvgs2R>{Ne|AInN? zb}GTIFOY*92zPd1Ao}ZH)sM33Ar<#m3LjcEO~98cjC~ptZU?b$jCl=L6x`GaJYQmH z^HnAqtQsDQcYaXUiC^$`{d!&Ggv+@riIm>eUZsn$Lv}OyxpGk9t6ez-0E6@KrdO8Y zYLH@ST-eV=;tn=8;?arknh>7U_Grq&rlMHibU5#>mIv#>4P;696~ss_Iw{l8zL3%W zQ8(qj=)2or?>3BX6ePnWV3Ujb_Jtl)V=K2K^SO!jmb^kN_3}0tr#H|L^Jdd4xLXI9 z7qhFaB+$31kWt4QT4+PG1Fty3hk{=tX-`n^Nh6(vGMx3GdP&gyEfRkyFFU-V&2xe( z*yrI;}Ti_}4~6QC{$;Y~& zR??Gw7`|I2Xjx$Pc-xtYj0S5)U5oM)neEdJ8D}@W(s&*A_+bj4mEbQE9}8@!K>zs> zAoh^L-@sEz0EorZc**`8;%`6U5illM2nScW9673a`UCEqv>4GJ+%i=VeL`KMv3nj2 zBj@R5nu!hq8C|ldQ)YD{sYSRmb|in=3?i*c(j>#4yT}3q@*b@HaWKMN)N!^^D@`mT zn*9lNXm`TG&iR@$y5yszD44sLr-Bx{n^IT?18-fTP!0VMn&@F$r_3Rccl9H_K%3V% z@13eD4tupW!>_5P;U-d7y#{qGwnne1E$(c})%Hr)Mz(nlvV?aBSCEaiE+;j6>S#VY zBwO2itav;N*{Febu(m(WQ-yPv;cAGTLCwDmO6M_X$!baXdut)(t1}&fs5|_9sf$#O zf-)RCjp;3zvx@=cmEC-H$Fr%Z=-!OgB^lD5F^5{5n!7CwJr$YtMJ0VVQKf%W-+H(6 z3;|w|x9kaSA5_RmM_Nx#@Y@(uN`WPvcO%UyLc*=e%RkIty_6{Q<_r0veY?g*Mu;>w zY!>5dxH>Hd?@Ow%MyEf(-dVHghnh;AF-jUF2SFnPJwT1|@51(B&;vHWW$}kh{?t<= zBr6l-_h_g-xxAE2`h8gZiK132k(SNVfS*1RPYYZx_VwyeSzou}8JnbH6JvU!pCuc4nQTQvS0Jx-V zTKd(z!6efzYLJ@7`S@Z&y>?Fbt2?{1=sRw`qySLq9_;a@mX+fFsiv8-ly zCHCpYnSZ*GP&+M8P#GT=6G0$so!ovCOq)&dGLG&*Q+hxQu$SwXmEek8) zbyWiE$Ep4g63tk(7N;L#+}|NI+2Xk-R)|7wqaN3!OAK$jfjX6z)YMgqIibi5rd@vf lI}VdID+~O0px$grgWRikzOPI7_W${VHnuc+d(rjp{{URMc`5(^ diff --git a/src/main/resources/assets/eidolon/textures/item/ancient_armor_plate.png b/src/main/resources/assets/eidolon/textures/item/ancient_armor_plate.png new file mode 100644 index 0000000000000000000000000000000000000000..aa7da0c1b83f85680391cb244a6ce6e696cc8c6a GIT binary patch literal 432 zcmV;h0Z;ykP)Px$YDq*vR5*>bkTFZcKpe$?mCijWN+>jj&cRTS;t;wN1O>;Aj(!DK=Yq4}z`;RX zR1^f4(8b_jY!;VtO`(*Q()tC?q1@5476kFZaml;?d;H&nKO(p4A#CiapZNCklcmY8 z64#rDxPfc&Z?`W1YSCoLAZ+X@zqYd^1~@w23B5nskQ?^`{B{dnqB>%sx%4U zdKK0;Hm$;@s5^Tcj2#45JG9w af5R7;4Vt%>x_&UtP)Px$3`s;mR5*>*lCes|P#A^3h_eNkA|!EhDUE`}MY0H8q;4I22H(KNH|Sb32wfZ; zG8PxdOcDy^%AHGc10o5M_yTc|hL)I1M?Kr+{@>yJ=U({tGIW>c7lUg3T;v&2EH;>3 z9qf&USdIliziaUPl7K(0)=hTW;GTPmo5>wL=cG>7NU(yBug+@l z`p5?0b{rt1IVxW2SJ*#1KnYdHm!;zI;gu)Px$;Ymb6R5*>Llh0}zQ5431cjk_1%p{5=F^kDU5EpfsE)s&!7bt3L*0~~#pS~J&i8%i+;ibSLu8lx(`x|sMa)W> zY8QB4#A2mP0NUe+Ey4ZiHMS8EBvJv?3kzBoWnDNJ&KZtk`kMm)Y$FmuB598wkQpdQ zq^cJd+}t*>&QAace@yV6$JCrdY7Vr3Zf{C|bD%PDnH~`llAGHG0HZH1-QF~3zjA2M zY#hn1vE|C~~B;P*Sp@ z999!ZBNiP$HRDuG4V;CNStvEJQ%$$9<4dFwZ};FO5?ZPCwg9ZDER$UCH7DK7&SN_M ztVYk^*hF+!sE^;KG%cG;dxKLosT`#*(f+)|4FjrXkz*6_^G_GL(GN%O2$B#>z%&VW pex|ZviBN%USbXxo?}Ge${00L;yOh5kW48bR002ovPDHLkV1iT|^?LvS literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/bone_stake.png b/src/main/resources/assets/eidolon/textures/item/bone_stake.png new file mode 100644 index 0000000000000000000000000000000000000000..549c7f6d37ce2d8b662f4e687f5326dede0a2c86 GIT binary patch literal 427 zcmV;c0aX5pP)Px$Wl2OqR5*>Lkv~g9Q5c6GEs4UYOEg%2>S+tXwVlB zB9O-ZY#{^@v=o7r4rVkMNI@V7Y7V)C!D)zlx#XqHe$zRe_dGoB`w|KV#a=urXfei8 z=@qZr#eX0qj$@)&xNphC2#~&e1YmV-lf-dMgu=nU+w8@o;-g*>AN7hzCl8v2v?&MA zm8G+lb+rIhWb0O*ajn4m+9zF0E6}t3I|2N?*qUw;^F4@LTzt*Ysb*|{To1m zOihddV6*lCkbTIL%H)Xe9yQeKQr9<@#KQb6<#H9T+XX=4EUCV0ZH#(=`0kP6^!yrG zmdHNj0dU$a1pGdnb_?18x9b5ENbRjAoTJ0YvV<&46p9tRZWpOcPOZ~5P;$6`Vt9Uf z0lwxjGd-soH3d*oE?04kcmULy{Mv%n0uZt+VYBu%80c<6FUu>70>IpD)?H`I`2=ig Ven89N1jYaW002ovPDHLkV1fdxyj%bP literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/bonelord_chestplate.png b/src/main/resources/assets/eidolon/textures/item/bonelord_chestplate.png new file mode 100644 index 0000000000000000000000000000000000000000..002f9a3bd482ed7edc5cc3012641b5a46ba138e3 GIT binary patch literal 643 zcmV-}0(||6P)Px%JxN4CR5*==l21rfQ5431S7+tuybxY*kuxR1Y#b#M+=wuwZUhyiRXb@Tt_xfZ zvkY2i?IH?klMAIkn=mjpifKw;j!e%x4Kq1U6Rg)_e7Bie^sUZ4=X~FH&fyBq z(baP;pbpZ_@x4+J00TEh8fxXD!m+mmKm;IW7{S=|6eYKSv%aAPVulffgt6%<;yv+N z&6e=!ap2fnqA663_r%HX=KSOcKDub=L|egH~tp_a1*qaz7DO(YEFGY=^j6*F@g z<})?da!~;=GnYZyl5R_IFY}^)o0`D&xW$KaS7}QO%hC;oWg%^ey|PZpE%5%;5+Mg5 zl1?Rq+3YaSo^G?5J7RPs!QGn!05}!Nwih66NyYPUogL!stvq?21>nx@`+-QOl7aGl zCdYeOSk5yum*H=`e6T>p^XP2*LFW|%fR(qqDBmaYZf92jut-3g`471s`8|*Po`>>% zoZNu`XaY#5l7ShG0`PHZt$`$MspF2T7K1}c%xIK!Dj8@2<@*c{CE-Z1`udF~Nn28K z3v?tpC>Ir*_7?^Q6U=6ZQN9m=2-UkfFX<^%Qwx{7QUJKl4glt_V?r}Pub}^d8I3ZV z9R^@^WuJw`WdJ6}dzrX35ni3slNgnsCB2rOAe_*rg2Px$Qb|NXR5*>z(y?m7Kpe;MZ;HE86e%RSb&1tNsf(N7BrbI+eS_i)baw45^btBp z7uzY2MY1SDjkt8v1msAN_yp-tawJW3>C)eH2lxN*zyBTlF-m;XYInlG_W&pqOIW6% zWLCwJix)o(ANd%)p;lDRs}}&FWg5yUI2YIMFDqOP`>aF=K=9%vV1Vx6PQoeRd2FH8 zH2{{AS)$daVIMuO@%ptT>LvkLrlADB7gqHe2O$W2kG1`&wA!7}u^p&uti(12Cpst; zOLPZ!EGIMEtqTwazQ=U@PJUVj;2^|t0Kl;w8oeg&$d#ymdqbnwlvi8N7xMhsZy-X{ ziV8sBdo+4Y9NUq2doOhY*c!G5y?psLrh8cZZLgXlF1#S;1Q&*1i( zUG%Xe9_8p))$7+`w2lS|u%0jE6Q2Z*VSp_DANdCD+n-Gq`ydVg0000igP)Px$#7RU!R5*>rlRrosVHn1L@giDIIsfFWR#J?XfS3w#(3Yaj;O;0wg>I!TrGp?y zA%lZp90Wl+xC-KAyL3=&69ma%AXo|+l8{5OoG2H(!y@tP5OaFH+Z_6C-}~qJp7(p6 z5B_)fypjWVARf?X&LrYCHR8)7sT&19DV%`04<*e zAP|i5Y7`1Z18{=W-3L%**>Q8Qci6%1&Gd8Ex^)1tNLWma4v8Aw%#Y8m#u^h(0NphC zlz5NQ+Qiz*0sE;ET0U*BV86j_#3Er4i-d(^h3$=P0E~-EvWF+!&o9PzNbTkb_70=U zGMjr_=%#tcK$T^(hbI^pmn7C_860|I1Eh9y03_CDSzVZCE3}*NPtj}LZN7o$>tr7bOCfV z2e7Og02HNKuCZx&RCd|fPx%8c9S!R5*>Tk}J&(HiV-K^YQiL!g`!UEtccj0+I70mo&>8y!4(Fd^$2+;m;Q+qetq8Y|>wxm*Dt{_!jM z<&>p!IW-#U!ELr0->VI>Pu(3mR)WPPK_VN)?bwsY(>dm2S&GH2{TbZ3d=U}bVKt}7 zKvRY5!@a0oZg@CN_(cYFY!Bbhc46t5S2=q`O^{-mX>vmXamwXTRQhRtP|BZC9Ci z`;LzDXRxJHYgR>?q4WCjE1qsbHsN6Slmy`Ayx_~$Hr-W)$=K|^%&ZJFL#LcE=^r@F zrHo1Fd7Ar?-@;}^5%HbcfyNYoPcxr+bnh9tl@$5q6kbE8H(@fb}a7+N6U_gWn%GbZ^$8Gy-|4|PE+gLGzt upC;1f)JP`Q$rsABv>Xw|;^v|7f0-ZMBh}=?x|Xg000009U*f7 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/deathbringer_scythe.png b/src/main/resources/assets/eidolon/textures/item/deathbringer_scythe.png new file mode 100644 index 0000000000000000000000000000000000000000..c0ec619e072977aaa706fe9de5d94e5521679e9b GIT binary patch literal 486 zcmV@P)Px$ph-kQR5*>5kIw+-6{S9$tD{Y zLJwUnY@i$yFbLR1i;RD*3I4ugSE0)Dl(8$U8}2FcyL_kM5=_ukh) zO?5s_NNoo2^JKrlD|dyFNV~i=6=J$Vr0XdFt1}qkj97+@Sccfn&h2SCJF>KpmaUC>F_W5j zc3>todHt#f^-0K;XQ$rq`*4%>wO_YczzZImcmcrMi4~kmh1|C}3I{g1-9xNli}xRM ztbO@`Q>omCmlo2ZtBUBVBGviLyZY_|t6|^8_|3buF)!np!TMpYzj1POmS;w^UiPkP cXRfFI1IvN0(Eors8vpPx$21!IgR5*>*lFLfNKoo|*NG}i@LK1Afft&7iE%*j5eF0z6o#4`q8jwmC0V(ui z7tI(Z9cZ(Ns|*t-+O7VpIhXI}9Ol5km$R$k_WH7{-ZEPQpj5%#)0+d(+64}d26#cQ zR+A!Uo~_F`nK+igZ=fG_cpptkQ>k;UCh&9^S`+yPed32_(p2hIw872Qc^QTt;b9*? z>R90MNx+6rFKBU^2mCSyiMt}@k7+~)wxKgoEWUDQJ1=kGB5lywbE>h%;Fc_D3F+3~3 e7fm(6e?wn7hkZSxcH8Ix0000Px$ZAnByR5*=|lR--YK@`V-8+`$5lR(5v;3d%xqDPNG9jaUR2qNeU1jYt^fgprs z@7}6IN#LcMm4{W#ZGY-0JHsqp=-g)vKGwt z3&L}8Y)irb=}eB{$RjqvaO45t*cRzb4&k}d=hzkif3|R0Jr9b7Ea^-x0y(xtw>QA| zC%=nm=vt89-ipBP_zNMXe3+jA=(T!O#LMb=2%dqBW=qECwYt1mS%iy)EUC?P0Nn8x z?M@%xpM;=!lOh_r762g_h=t)tL_^mCRZYktnZb=_D;5S=HFPc5-#e830+dS?9NS`J zV=ayiw*b)X4WxMUFA!V7aOCm!{`#-rUn{t|zEj$rK8DjUT dzRLsz_y*@sqe4YWw`BkT002ovPDHLkV1m#_!eIaa literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/goblet.png b/src/main/resources/assets/eidolon/textures/item/goblet.png index bf7a70610666245fc57a12b65de80185a5e2891c..8d3395a09dd74dbc0ef96f37bf42364985596252 100644 GIT binary patch delta 415 zcmV;Q0bu_70>%T7F@JzbL_t(Ijir-0O9N39g}>*x1SA1*iQmQNi22!##&{?!8ao zQZt%nx#3H?E}WPI%xIbw?DjA?&{BaXQ+d*cDTxRtITBXs8-LT-oj)RNm;eO3J&aC< zh_9bXA~jA2PBK8+Fp009F}^S&#gYU{nH&=b2_j(?zfZyMQ;39BqMNgnGC4`0Rzd*r za!hD(htN0dB|gRV>FwVH$|7dw#CGLImLhcZc*Sz;#3q)jOx`=p(%RfmG589Bn@j@X~U$g(@ULIaJI`40PZiJt+|b`{hp2u z@t7^R{*S6_yx7<28`FMVVO4>zL0W7ZHWun_6i+$Rtr-1(^$7{dnl8rqP-_4H002ov JPDHLkV1nm~#*Y91 delta 339 zcmV-Z0j&PU1N#DyF@H5lL_t(Ijir(?OT$nUg})d#X(yo+10pUC)@Bggvbbi{!NLBA zIyh7c1)+n#qPmG46kO|G=nxWzc915}P7Sn0gp?w2dZEorTA_D(?{LrIo^vm3SV|ID z(e-ff{kw!|8I`(aN&VYN(<2gMqpyvfl#&c}P zr`j;7=z5qc05Ee$T)(z3j6AulN-nEn7pdJEt2twfV1fu+MjSiail;B=3E zXNc|iv_5}$`b=`9{zL&Ga(=u6kV=LXA!->_91lG&NNY>ZKpd2)+uE6QKx-%HHZ6`W l^pz`wH5n}a(=yn&{s2a|fsI^y%jW<9002ovPDHLkV1j~!oGAbR diff --git a/src/main/resources/assets/eidolon/textures/item/grape_candy.png b/src/main/resources/assets/eidolon/textures/item/grape_candy.png new file mode 100644 index 0000000000000000000000000000000000000000..097edaff3dbeb2cb30f17f24198b9d0685f5a46a GIT binary patch literal 410 zcmV;L0cHM)P)Px$R7pfZR5*>Lk+DkxVHn1LCrySJILHZ-hJ%BNVyl8R90ZNsA0SOZOVE=4Kp-?Z zHMpk`fgrdToRg3k+Hjy`5nMO~%7N=OsE6VwT=-1)eLU~)eeU^SOG!?Rs#3KU-{tz5 zJ?C-?&<%}TEKM$!CVqHh!*-kk0EQEj;dDeakO8o|y@Iq6upC)8Gyq<{-^d0Ngx!Ao zP6$wys#Um76FBk$kiU}o{QW^UG+O;40N&j=ASh8)s#eG+b1X;Li$F^CV!TeMRZQ+0 z7kquxS7w9>!frnRowiA*ZIVoRNTxi{SoaEF;q=_Y$?Yuua600tIbb{xIRyaS(5O{R z+U3b?>s+PxrVt>(dgIYRhD8sH;a0!6_Wv;NKsPiVF7u2BP@11x{VtD7M$xbh0Jwi{ z67tDpgNcpXL~;Ridj&~1G`s!(Xl2X(fns;zG{M&T130;Sn2e(D-2eap07*qoM6N<$ Eg80F)`2YX_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/imbued_bones.png b/src/main/resources/assets/eidolon/textures/item/imbued_bones.png new file mode 100644 index 0000000000000000000000000000000000000000..87e4fdb972e9c77dcd975fb8528db4e994dd82af GIT binary patch literal 503 zcmVPx$u}MThR5*>TlCf(OaTLctsdcbdDHVd?S@2T0oe_ZUx9`0BxU1~xE8y4}c~x8k;Qp=Yu-*v*nr^$Ne?X<$I`|Nh9xvRc zusTONl?a_haUuH1CQXU!qxdb4i?YY?r6JbWs{9C!nJ+By`BRmFfCcZ%*C*$k!6@0D zG;wkc$E_Lwjh!P#Mu#buYPjAkORry2-kOg7`AY!6$vHfK_J-4wfK=uhm#=6TH%6Gr zPq6&reK=ZQfw9C*4)+(aCrwhO`1|zonv!-lg7>w0DFf%O}8Dh3|&-NP>vHF#j!JD8T#Kjh>8HjH4W&W#6Q}x t3|-Qx1OTA^1F@JhVL_t(Ijm?tHN&-{ZRC4f`RRlpjAZB1$Yb5 zq8o_zT|u<#5-MmDMMx9`p%nCkfrO)ClrfAslY`P?TI39x3GM1#opU~(hwuA1@YfNY z3bAP1IeVoZOhdN-q<}1pvPSZ5w_VT)0*K7c0q~HzY>|lHK!0P?ApmmeM@Qn7B%wYP zaSe=)@RBcB0H&e0LCtA?yGk5eL!n6_V$ry@wz*C=Q|z>kmP~|)0mx>G>}_r1vMp#Xute$nOj`9(>| zpsCuAJFp>BuVCsG)Ph2{+amx`el6juSKnz!EC@qm6e$oyEhqq(dWCMcM|{+40DRPI z+~-e##!rkzeYA41^_%hNz|%_(}@lJuY3YGrV_62%xXVt00000NkvXXu0mjf Dk!8Q8 delta 338 zcmV-Y0j>VP1Ns7xF@H2kL_t(Ijn$GpOT$nUhMzztCkcfj1hhp172;+PT>L=L%^{=U zB>o^L(Vq|m7ZHMpf*>sjwIxC+O(O*nLNpPwUWal++7#=k?{x0rKJWS9z`v1Y+QKqz zF`ieaK{BqbuE|i;TaF?h%5R{B;aQ)2FeVwn5u+UM~fiyWf-T~n3)XkvuGa7-)6=T#O3L~_VM&IjlbF1T=UrYo6 zW@a_~W&kI>)JH!*5~w3x+N4gdfE07*qoM6N<$f*~21t^fc4 diff --git a/src/main/resources/assets/eidolon/textures/item/magic_candle.png b/src/main/resources/assets/eidolon/textures/item/magic_candle.png new file mode 100644 index 0000000000000000000000000000000000000000..dae7698e42af0e7da702d44b7bb0dd5bba4a18e2 GIT binary patch literal 358 zcmV-s0h#`ZP)Px$AW1|)R5*>TlD$g9P#A`v6YWW?n2J@iRQ!R0*wqfAUWc3D9k}R4xVd@}-hhjP zqv#+7H!ba=O#=puZ6f_#YzxgX0ri~@hwpuO_|AbpMwu?pylns;UE$8|Np;|;dRKA! za+{j9Oyxz_0+7v6$l;dn&Xc?0PB@Gj&=$>cSR=Wr%gKuny+|!H9R0`bpUvJXk%KL5%3nqaMKu{ zfgtPyPClR`HbK~<Px$iAh93R5*>LlD$hKaS(=|-x@a`l2xK6&8mb$B1FA_R|r~YFQl>+to#dXv=Ivn ztt_=mZJX+@vCu-4BM9PIhzJqHgovw{O*A_e(ZI%CPH@U$-e=x-82Dx>ujXdr7XbeZ z;cw8EK_{Y8Wu2|N!%wrCm)HmkfQ(p5`g^)bm38S4H&~8O{T~2eRh6Vo;m@$ncCXIN zfK92|Azrhd0Dy_9A8hyP03^+*-Pw&U*rU?r0Qkanx@uGB`M&@TC2y#Zd#jU_KV(|Z5_002ovPDHLk FV1lAH)Xx9_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/magic_ink.png b/src/main/resources/assets/eidolon/textures/item/magic_ink.png new file mode 100644 index 0000000000000000000000000000000000000000..7471c40a00518afb0b62b5dbdc2cbb73c656ea40 GIT binary patch literal 417 zcmV;S0bc%zP)Px$TS-JgR5*>rl08d;aTLXWz61`I2#WNSgrZ@E^a8acM3W6ILC_{hLt7O11ss}! zzCpREU?4a|ErOFnltW?B3l^z^1<7M-S^94i#K&suj_00x?zxu(|6QtH4Zp`FEJOVO zWU{ZET-+&g)k`66vtz z3q-~8_7VV#lCF*CX^@EI0Z7L~9LILsb6O=APD#zi$|eBS_b&j}_xHF;6}z}yKX6KF z5|KPN_Z4!_I!YBig+iUHRFSa->30EuWH^S#Zlh(=(=zGN*li@kF(s<<3C(I5F=qfk zb=^Sy@@iKVHmo}Bf00000 LNkvXXu0mjfHpaR% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/magicians_wax.png b/src/main/resources/assets/eidolon/textures/item/magicians_wax.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bd50bc6e7b48ab33f27ef655a5865b5bba7246 GIT binary patch literal 469 zcmV;`0V@89P)Px$k4Z#9R5*>*lFd%rKoo_)nK%xyNm3%9n?i(&Kx(B**<{m7ux8yC=%#Owr|2_u z!z=I%NL`dAQj1zu2(vH-BRh%n<9MbE<4Hp3t{Y}~?|kQ+xp&~%AMv=*-F(kRH6s|7 z^i#m9oQl4(_;Pa!fHmLz^rFN1sv_u@^x@WsX1!v1VLZn3Gk#56U1nm8t$BEVqr{IO z)1TV{n8A&@O`~oDJ@5y7>)X0WFN;gBT+PoQ)7=AS0o*%k^YX)6qIg1*EWgSm@CHJE ze4P=+lLt3wwl+zx0?tlwT&L4qTU=nu5DI=njsrC9SF!#Cd7qCwAO7xtp|z z)YR;(yS)PBa7{|lQ;L)L`?A1eA%LxlU=$e>r~v(DSBHZCltu00000 LNkvXXu0mjf#KG9~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/notetaking_tools.png b/src/main/resources/assets/eidolon/textures/item/notetaking_tools.png new file mode 100644 index 0000000000000000000000000000000000000000..81e5654f2c5e3cef3b8c9873e0ac871986eeb806 GIT binary patch literal 709 zcmV;$0y_PPP)Px%e@R3^R5*=&l3hrXaTLaX?{Y9^rbF>#YHNLfudpGBS&FT?2njzfBZ3SDby0}o zKrFn-ZqgJZ`Vc|7v6dE@#=IyI#dIK*W}sfo4cFAR{J@V*TgcnR>xSa!fdhZe`9BZm zoaYGapxInRe5{(K)qs>|)bT%zOw1A=s}`140|>hd&E_I0##T7W9q7@57{W%T7+ zMkZ!C6s;7ZLiw7z4U!Kybu|YLCPgGJJDsfieHcp%aQ|9lX>|)lh+J(kV-WRhZFnJ4 z?7%zW0l?$)1E2_zrzWTQG35e~MIu0*7)_^boQdus05<<@6Sez8wZ%+bV;k3Vf*j7; zFA(tgNlVwzX&a~M7duv4}e~; z#pRl(@^%@u9c}_Xe>fUOj67^=L8%FH@71If7U;CL3ZdD>%nbB;Ej_)%066U5Se#$r ziQ^0cf@som&GK3TJ`%cOeVBsktl} za}C^hG{lTkUf!{z$MG&Kpi7lS-gUGiWh5g^2l@WA1<_Q;9v2d{DYRDPQgvF1YShk* z(?NHImbAVH0K}|qa^Uka+fElz!PRhg3Xrc#ofr*3oGt}`j_1X=zRc~h@bB91eYPq> z-nQIt4<~PxpQSAO4q29)c-FV+v3k%XBoUX8OpJ1iRNWD#2ImR808n)?UrI~Y>`@;Z rm<7OhvXDewHon=f0O5D4yHEHB=r09#*#eK|00000NkvXXu0mjfJyJv0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/parchment.png b/src/main/resources/assets/eidolon/textures/item/parchment.png new file mode 100644 index 0000000000000000000000000000000000000000..9081ad9757ecf6becb325de4c8671241d3918f5c GIT binary patch literal 523 zcmV+m0`&cfP)Px$#Ysd#R5*==lD}`$Kmdh5w}IMDgq5_!fYL^(DmJW6P=)3X0D-a~F(9!ZF|aW* zv%|{5##E3HDljmxAhlUqRhg?)#a4q&h;bU*P5EIK+p+7YJn1CgyL;c=Jy{^s^9Q$> zRb+lRUQpMnoTiQTKC_A}+<&%4E;8p;1>JOlx>iMNHV`jplhZ>Jc*90}KLCUn5Cj2r zt;*GVcc7q74E8%64qXea+2HH99spC(x-3q|CPOnjLYZv?0K;+t#!u+|^pM4PI#F^t z&)SEblou!b(Qo>L(W!t)QHdu2e=-}7!mEn~m7}4Fxwi+v!10C54U!=-EKy99DHc@J z8dT}lsesY)Zw$JF-U;3R6ayg$0cwys*u9bmJ0VpMf z^F=8DGU24B)@qXhPTvW%YgaII8_#kxqy6qnDkRNJrvU&9%S$|bbc5Z^?Rc?w&}DaX z8?D)(chJSNTq@-}(#*K~9E|^}%d6L6b$n83aWS6HU2~B03sQ>O{pjeMt2Z<{{UNlw=8YqABX?| N002ovPDHLkV1lxI=WhT2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/pewter_ingot.png b/src/main/resources/assets/eidolon/textures/item/pewter_ingot.png index e1cf45e087f6fa300dd43c876efc2961c4d11305..1e63be3423a6d8b631c271eb3302a67d0e27fc54 100644 GIT binary patch delta 399 zcmV;A0dW5H0=5H?F@JDLL_t(Ijm?tHN&-<7fWI3q26X&up;-vJ8bMtMiXrt1we4Yo zpr}pJW3(-L0y9YzTBr*b{)9}E16De^a5pVfluAzv67d@-nTP{Wt$)>RiPPy4?e+_fXe2_r z(=h=I!&rglWB%^$?%s^W6d`iClzDu7g5G;wH;#n}1h)x?qg2WTPR}lI0O-9}0>N#p zd>P1Q_W{r}l}fq5_4Ot3cmiN5sMhKvfplh%a5xG;D70fsG)?8|>Ks*7S2}W7i8Y{u z!=vdRZ*O=g6n{`vmGOAI04a*HC>RVr@p^q!Yjx6@?`q2+fXn3~pMRWnxg|DaSr&~( zgTdevfNr<_Bc$tnbiGfj^@1cx0uY+^Hr)eRmKlvkrlKf#y*^uJRRWMCNlYda``m1H tf!QX`O8|7e4}izx5yRnd1^Qp{1$AAba&(G(8UO$Q00>D%PDHLkV1iqVwL1U+ delta 333 zcmV-T0kZzK1N8!sF@G;fL_t(Ijn$IBPQp+WhrcF_3}w=w>A=(h7@9z8ZgeA#y7~b4 zA{t#JJcg@20#+h{#G&n2jA^coO-Sg#UI)AdS|X16o6bGS_d9>?fqx?*tW*dq&F4$I zAQjv8kqXn{@KsX}?Ke=fQ3t^Fd;mtH7nDh97qqVRTpZ8RAb$uoO$aN!>~?WIe=C&N z-u?lGQDZW8xVpYw?V!^+T{?e$6ad>k0U(Mbld(g;e@DIEAREE;e40S3eT-q$0H{_E zGm|Ki^m;c)DGMEC9jFDJonHX(_;AmY;~=GEu~=+CrfF^(B*`3Iui$zPx$>PbXFR5*=wl1p#eP!NSbQv#M9z_md);U-E+gitoHVA1|+q%PWZrLd?_yC98< zs;a3h$ioduq12YaD(=GaEw9e%&Y3%}b4Fu_)f?^j+1}n7_9u$?`sJgx`F9JbH`;Nf z(d5O;<2C&An-BPp-d2&!X0quBEGd|b77Cw?78qrL=?LnLcKqK00M%9#fZP5h&e;LZ z*#WoxO8|_r*jiVOb9{0hAGcm%Nx}8SJN(&{=jB5Heva=j3nlE+a{z|@_YB>E29RB? zX33<3Kbr#ZWAqJxJ>9^cO|iH7udHAeN?1oZ6^O!M=i8D3vryX2!BwY=b(F)AwXIH$ ztYJyPsMp)(AZ0)N^#p)@dQLF*l&=?);aB}s(rl{x?;97rX!CgU9j*s!T%_jDrZ}?3 zavoA?Gy&pF7zPAmk9~Q71=dlH>x(Boy?sp-2HbnDmI1i;TrCO% yCJ%R9b-GH*p*zrq?m$aV_^Q)o@^Gh;0saEd``4b0%ki}U0000=Z8F@J$cL_t(Ijm?lxOB+!X#eZ)mFL^WhH;5&R2yGW3D;FhDXjk3z zL-d1n?FVpI=*o>yaHVu1h()Ma33MP1)x?)KGcWVHh>lLIZtYp#%kSKC4?MTTQ_FWB zKM}M#03`9byPd!2zZN^&p8=>n1=m$T5}&(py+^p-D|gqac7M0W|CwO(%?DIFBDa~l z53XwO%a-s~hlAk=fNApE0q9ALp2Wiqz2R zzbwIMqmG`$RfEBBgy+}D)42;;U9wb@r5e>)djKDO-DhL8DPX0I2ev7iUpqMJ7YA>b{ExITbibZ`Roz^UrK^zBy46l z{Ju+>z}lQzO;%uYm2f>>g3Wdpfe--q;nE<_4A$l-6#{TEJ_SIjkfJEW!dg_&s(=*( zo23pQHyWuzlnSvn7dOc`Io^K&Rt#<=gy$pfUgG4(!5O3A|D(ThN1-(=BvP~h0000< KMNUMnLSTXlpv6!C delta 312 zcmV-80muHw1K+pufP$#Yrb|aMFSB0VBsJ_;> zR~MRFE9eh~%5vPo{^i-Ju~x7OUY2aHDjpmjD}Xo{1F%RFntz=xwzmgBIC=qK>nGUr zd#Y5fvPcu=QBZ*EM=dQbT*32us@`---)8_+8V;7@=HQ!?b3I7oJ1nG0mb@XPNvT|= z+3D(f9E_Pq0T1`rnk&p;8i&*@n@Yn0VDkLL>*TXtA%jASD$5cL&!d2890E|Y z>;hO2wA%Yh2r-F}rUr$Oj2`cPeQE<>*KX@ywj<<5U@pso|CbM^Y+x{{FrGR90000< KMNUMnLSTZ2U6&I8 diff --git a/src/main/resources/assets/eidolon/textures/item/raven_wings.png b/src/main/resources/assets/eidolon/textures/item/raven_wings.png new file mode 100644 index 0000000000000000000000000000000000000000..83490530591ef61b661f12b75971bfbe62364dae GIT binary patch literal 607 zcmV-l0-*hgP)Px%8A(JzR9J=Wls#|SP!xtAqXaAyKH^xig0b9Wilqp~q(jv%*}8VW?5KzkP5Zx=NaA>Cv^*i~V`|-Tz_}mMbGG)s2zf1d@#jfXzVyU9W zU%y;w04JyCLdM3UA>HfnkI&uN29gjNGmm|$jxAvV;P}NW00vPE?GV@Vg)||}r5W4k z^yKthn8!WgMql6I() z*=oS`d~x6$QEN6-Y!Jl?KA%k#0N}2FL$OpLUoeyjX%3(lw788r8!M38WB_1#pFEcI zH+Zg~lP?$weAmALQ1In!%A_B!?Va8yX_(Ch8ZTdKUWS*?bL2{Jzu!ZbDo{K48G6l1uYEgv8+iuL@%2v zGx@#RH??MiYCX@l4_&&!RqD-1HE{9f9o_Jw7>|Y&OBL1W?e~{!a48vET_^YM?&{j- zPnR1xsXg#>u|Np4VyS{&HmTP0^nw-uhGnCdO~#`k?!9=&W*EL9NV z>9;0z^7+ME9{M*df%_y@56yvdw06~iwJUlXb<`PU)7El8TJ}#Gka9hLbtqN`J3G4? tz+&-ZExvkg_d48$$doBlrcD1Cf002ovPDHLkV1f$q8hZc$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/red_candy.png b/src/main/resources/assets/eidolon/textures/item/red_candy.png new file mode 100644 index 0000000000000000000000000000000000000000..5b8178e878e83e98c1bce37307d25774277fa3b6 GIT binary patch literal 465 zcmV;?0WSWDP)Px$i%CR5R5*>Tl08VnU=W6%s8m~85d{Nw$QH8*0T*=;mrM>>1qDSM#Yw@%Q9(yR zK@dc6a4py=i|Ak%<)cL`#i1!!$RcW_N}$A{8lx%xpf`QrareCM9S465Dg0T`r~SA0 zrr4LF<&DtcJAE}3E`fV2RJ zYEBZ>oMb=Wp{A3_Gn3q3U9x2^2F(e50CQq6GFDsoV?Q_~^f6qKCv$j?p~V1#Q4W^( zB7l}=%M#f$l$1y5<}qkKUEM)RdEWzSqJZr-l=bmpT#^5vY(F?(1GX;ejlx$*=I}gF zwwyRhr;MqYzNwjhWCx;}lK`LIe$+&rnkWRYQmqyH`3|Ey1;B3kng}2aIRSRd?|G$D zM(OCHR0BhP3i3a?cW7MeoYD@!N}=*56m{@btQ0C?m;Vzl+Y^$18#nZk00000NkvXX Hu0mjf#yQ5_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/research_notes.png b/src/main/resources/assets/eidolon/textures/item/research_notes.png new file mode 100644 index 0000000000000000000000000000000000000000..42c83b78ddb48561e0390d0c19dacb3152377218 GIT binary patch literal 648 zcmV;30(bq1P)Px%LPtV1APIs~0c2q6eOM6lFFDDpZ4wH%uR_iDL4ncJSZUWd2$YASti|Nrmz{r-Nx zFJBi;JiakOpU=xry=sn$F#p4fnx)U@bzOh-f)4w0K=!ev>E@USBPPdj2gLF0iUusO zqGnCNoW$G0TcejkDCXpi%^56Gb1&ZY=UUvtE-e6&N-kKPYkcEP#CIQG5 zilo-^Ef+ZgHRFJtU4yAaoKP(4G`PEE0{ibi(=~VoEt5Gs zk2U~bua8rHj|pJt4Qq>yG&IQo#^zV#NaTn>2Y|k#n__gB)Z81S{vcAn6`Y6D05a*- zb)px}IV4Y4d#iwL-psAbq*vDg93RTrZ7X>jX(WOur%zC=AG8YCsTxYeAz>9p?2hJJ z>fdunwc7q6fvpnr51w=7>iL!s*{C)LynVGqYAufvJn7V&K-|3)H>FeBL0UJv0{p0000 z*`Pz@m2#I=!rY!g%g*h+0OJif+ivOu=JQT|hKUnv7H{dIwf$q^E>{Q&&f zixZpOv1J_ve}89tc^!y7BAVZqMV#1&)s0vr9D0uugB6GI?loz#dK=qI}Eg8}j zR+9w+sz>Bai=(rW<279`VV~Dc-n8UEkN;h;O%PB$wlUgmn(`)W6V#rZKCiq9+ulHL iZIA$Mn(}V=L*@@2GP0rT!)lZO0000= delta 294 zcmV+>0onfF1I_}FF@Fe2L_t(IjbmV-5HJ!_pdT6VADMq~`38b|P&7|kb?yJJU;qFA z`t|=mx?v0q3=AyzG$#kPF*uoOGR)X;ok2oM0INDCd@gV@)nwRr`Z@yx0|Ud0XCD}( z?jB{x@RLJv1x^D#J$b;uz`y{v`S|r?44x$i84g@{%b;j$0Dm_GXMi9p()jt5LBPA6 z;obKq4Bkdz4E>X%815gwz=+oc_YYrSynpxtqsGst4Du434Cm+OGYE0YFg$$!5=9-} zDDgBC{qJBX#4vyR6NaDiswjpNG{DnL^uN3WC&PgYZy9bp`ifH>RtaJ?MoG~~F+*Gvfj0HKa_YP)Px%c1c7*R5*==kxNLFVHAd+Z?qCk$8MTB*=VQ{h6XBHSdzJI5?r~6HYL(f?nFye zDBTEZXejLrTu7*+;6{{*K}x6`8wD@uOgdWQCH<>ksRq9m_W$03&gyVD=Xu}n{RDr@ z`k+K>QPm9q;*!iPd6%R%H=Ya=AK#4u(A(1qfY6T5rzSDsoYa>;dFD84j-|Y@R0kJX z?gL;-h!@`JS$caq2?U5uIKzZRY5KAzlF6 z07w6jY_&D(%Uy3?k)KsSN}dIP5aTgn3=gHLtXgWIj`|h}2!lo+u)6?A&q&u5NBeE0 z9G3aDz$p?TA*j*azczCcF?Y9w?k_o?m$)KPhxqmlM3#FsJ zMOtes8Sd)CG3eyctulLwY1h&GS&Tzdv(Rw z+HC;R<`@#dZgrvf7Iz#N);t^yKweId;M8h2Q(EeepEB~g6+kL$%Un#27B1%^_OU6Q zWB`bc2?M}VXuPx$kV!;AR5*>Ll21zlQ5400(;q4#1}rm51u-Tfqv&7M%aoKp= zUlyiWQ2^Rn5vywbKegS1*Xxr_85nv@0)+gX*mk{%xZdN`e>E`lm^Ad5OlRT%_(C11 zs=`#H>j%fxAQ{zUIuobQ(+kvR&gW{(E`~|2&Xdp8SV_$Qzl0bGjYxonxoHYTo2BIm zHr5URczOR|B{f4r53;>^Mu(fheW9#`1DZTKexk4QldG)C>D{4Ie}1}QcWWP02=@-c z0Zont1_7v4E&PMsq%(1@vLyhr=MR`da9=1Zt{J@5Y${cY+s8+0A2yS*VFm)z7%787 z(RReH8F;-u8T9l6P_n9+W<^OxH3?t};f&beD{kVFRRwUa?Jp=$UmJiw?BnG6p($Yl z?a8PnclOqK7q47g<|&q6nid1JnL@C;wNFA1wxauqNN7Yhj;B?81J=-&%bj$ZssI20 M07*qoM6N<$g5;9QKmY&$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/withered_heart.png b/src/main/resources/assets/eidolon/textures/item/withered_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..0e3ae0af99c7dd46075e7c37f82d9b839cd0bab3 GIT binary patch literal 525 zcmV+o0`mQdP)Px$$4Nv%R5*>5lg)0^P!NSbCjm!}+-pTvozQ|IM2SpMDz$s({vjvGAl*mIoUd5!Zwo_Bbsb9qTBhLbmt6UvBml(G z3`;NLby_6xoJdA=dXE7xL`V|PvGg*`)<}5SLpu&92+IV(ml02&>~n9o!z>Q}kkt74 z{l|I_-h3u+nF4?de~j1J0pR51-3>r;dAZrd>sn1=-)J<2O@A1$9F^sVIGQ0W6FKrR zL`@OB|L{qzcY2ksC-7y2>sT0~MiS5I4+AWHtaRH|ok1e$JSc0yWDP->W*{T1Xr@*e zWebdw#vqXZJlegjUBrKVP}lYB@D9V#V&zzhXg4d`x8(OvhG%k9+yBQe=$Nnj-IiWR P00000NkvXXu0mjfMBnP? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/wooden_stake.png b/src/main/resources/assets/eidolon/textures/item/wooden_stake.png new file mode 100644 index 0000000000000000000000000000000000000000..82ae9e3a4bfd4feb7e33273189c47592b6209132 GIT binary patch literal 409 zcmV;K0cQS*P)Px$Q%OWYR5*>Llg~>6Q4oN?HO*yB%i1i&A0d0u1)%~jA$1F)2>O@1NDx7!hgyn;ltuYv4ToTL=^caBP?A!xNWRrvMm_&j4Z(NC2SPXh~+bN2PKLz;04;P~bK`9%VR zZS`>-kDa7SbbXD?FfFD{XsRSVofP@}o(}=Atv;{K_QaTHTGrD^v8iqV5LIN9hzu|R z2~2-JbkZ?DhSgmU*YN;QJB;_m!7KD~|uw=MJ!NDQO z-6A-+p9meg6}!cyQ#)kM+`&O`xcUbO$)IGgL!j*tFb+LZX-IGhmfX`Jm$!G`g$#YB z_kH<2pZC3&_h4GJ`s{UnL8~vc`Vx(&#%Cfjx)B-O%*0eCl7D~T^nPCCMY2hKTVyZ) zpib}S;nm`72++t`t_#3!_(WrXdJN^_6W=r0zpQE?YSO?2-M_5jduBG|dnN@-apE20 zS67)kD5nlPcTmQ!u5#iXQ?OJ5%S{k#eVJY$;(Mmpu0g#qNI~_+0NXY2JyUvth_$|~ zF$17rDT1#*#ec0`|LZz>mVy9^P7~J|kG~wgmV%{}K2a|av0a03SRou%XxB_;g*shU+Y}a6A%hvOy?HzpuI{m)%SqDCxl_@$+ zy60;&UY-NcZLd*un*90kCXt=g1d6{W0SJc`icXW=FlJhfklTwZGJ3|)$M56xyXT2# zML4YJ@u+hbM~L?&K5bf!I(M@oz@wM_Ka~mHUR+H*N&ac}-l?B9x+gh&Yi2fmI{FQu j;`fsY#j(t-GZ28kiNM6CD%`Gno7UAr27-J6MuHl18Bw8&HFb#ClH$y{CHb75h%- ze0=Y7-t%z|Oj4!IPW3lb+LB6J4%ZXgr$S`^PRjn>RG9FD1b-em>dZ*_dfX%~=GX~5 zilfd9yqTL00uXc%Uhv%-Vx)@OwW z46}@GXf*3mMt@coR5EQyr~d7iG|aNg?4@wBgpq`ky|*$H5ki6NBvv;~zj{wCUu1o4 zmIDW1eQlN-bCqa9=gEtw=!Qn|I#=3d^SeG;S6NCrk9M-eYE4kbgZKJwt&;-;)Hex@p4665H0W zI)vD19G(H_;BwHtzclu&u)1lrwr4jg+c$Q#N$OYc0bCHLd|t&`zNi5ID;Fph_X{)I zng}zqEn;!M>yNq$`%6AzaX+`$J-PQGNZ|S4tjmWApI@IbqJUUJ!u4rf}!c Um|t5901E&B07*qoM6N<$f`Whg{Qv*} diff --git a/src/main/resources/assets/eidolon/textures/mob_effect/undeath.png b/src/main/resources/assets/eidolon/textures/mob_effect/undeath.png new file mode 100644 index 0000000000000000000000000000000000000000..1413465394de24dbdd24fbb2ae49d70e8c9832d5 GIT binary patch literal 521 zcmV+k0`~ohP)Px$!%0LzR5*>Tl)p$igPXG;P731ENgcX~ zpo2)jsV$j%bk!jSK?2?jr-Dj;mVjVE?;FRrH0*qow>ojOKaH}r9*G|CRr5ybO0$>zN zDW{2O(v4I;XKF$Bp%3(;1F>|aK#zZ(a26cGKoACkoMG{~w3vXLHx3B{p`6!`x6_UQ z!a#6ZZ{d4wMza^JenrI$nhkcpeW%-rFzo`fH*8LYV_e$Dsh z=Z!=9qYcYqD*tKYB?=kKK9hN$LDVYz{Bgm@i4OproV3V~2aM$nt}lP%R$W>*58U2A zY{Hw(o|&GE0d}?>a)zbWK*pB6wRIPOtD8IhX3K#!w*;VK_1ALN4@rTfM6IIs$0(K( zwWw8epP>CE%uG+lmRY3RiPTLU?42>19YOfbl$(Jd3Dfm;kpHT`1=zic-OM5M00000 LNkvXXu0mjf8%6Og literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/absorption_ritual.png b/src/main/resources/assets/eidolon/textures/particle/absorption_ritual.png new file mode 100644 index 0000000000000000000000000000000000000000..500e3f03dc18164d3830a948a77bf4fb8d431e2b GIT binary patch literal 491 zcmVPx$rAb6VR5*=Q(=khzQ4|L7-~0N{v@FD+OdJZNXicMrkd}tlhT0n=XpKgvzCg`_ zgU}afaA;}JB_vvcpoAz3gdokdzn+HoG3&tLo_o&o+rf_ z<~O#mjh$eqDpfU9RhO!2u{v9=sw?r;jyhfRoak8F@>@0*w0vh&v}>|3w9I(y|g`<;%)>yg$ai? zk=#x&Z8-fl3(Tg?9?oM98v(Y7=ThqhJByJPgLsT_T*W*-r}dNZN^U-w@o)xvQGXn_ zv)hF@+|79IpX1!XemG5=$vT#zGCai$ZpLSl6UmM9D!z`d_~HNGcmij1>c5X~H2Dj?v^IpZx_kc^9pISm hDjR&kFWqD6{{eFWr?R*9P1XPa002ovPDHLkV1l=J<9+}D literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/aura.png b/src/main/resources/assets/eidolon/textures/particle/aura.png new file mode 100644 index 0000000000000000000000000000000000000000..08ac11d106c3e103d4ab6c5deefc22772f8e52ef GIT binary patch literal 878 zcmV-!1CjiRP)Px&C`m*?R9J=OSIdr^Fc2)j^9r-8Wf! z03&7w4%YVo8q93$Cfgo>0zgf>(7Bf2h_noQ0D49(yCE&tug?Ow()kwyapAof5ePX~ z5)O>ErFpVW0DeCMphz!teg*JqpibE4ftO*=s2fHc_>I^RLk|HcI)Qiv@EyPl8BkJ+ zR%gJMKwwJ(yV=}#SUxxaMXxo#F!C3gmP0~x;J7hkpyhj2M8{`hU?89sfC?$e0aPSK7DVsFNqah!E)2YHI7aUWvju>%+j}t~HpGaS5XB>-jF^*5fNnPauwx4V*Y+y= zNPq$-ssVgOO3c8C8UQ~?`+&7($g0eiC2(z5W|ua|fhjS+Va^M!^%1E8I&+fGF9BNt z$hBSO&z%J&X3b|KzmH_1LCOy~^Ritv<$yc(R%F*@7FG3ulYGvNa{*9IR@u7=>l$~x zf49iB?s~58^7e2q813bRj~#cIDLz`{17_8Wn9Ho+89Qcv7JvasKzdHBk9ELsk%^eI zUDpB-0sJI5)w)0rSOZuwApoLLeQ&+&j=9bytqqdYN^m0INrYUW`4gg4N zDh682$#p_n8trN-Kb4kf6$=f3H=3f?0i`vco9(zmQZ&hQX~^@9$j^jgAky9#fEd_4 zALam*OsU3UhQaBXIdMg9~3h+fV|8|=H9@<7d(K#p$MCg!H?0hlmTr|j10 zR@ai;{75Ff$g^Ec?6%^`ubKZBIQ@Ia@(HP$oPiDP08kY3@Mk|JN*pDa1IU}0(3po& zdkZl}gb)xySpBhN6HDDZ0lkgZcd$C&YvZ`LSN*T;4}yGj6{)CHE&u=k07*qoM6N<$ Ef|tU9PXGV_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/basic_ring.png b/src/main/resources/assets/eidolon/textures/particle/basic_ring.png deleted file mode 100644 index c805d11d452e8857585aed0e3e44fbc15c024b68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmV;40e1e0P)Px$LrFwIR5*>zk+DlcVHCxGWuKfw2 zLqU_0EtcU>gOH%T8lohHoRWABp+<09;-x;HYn}0)d(U^y`QWeNaw1|%N&hTfD%ti& z`v-~jMF9wDUS>BHV}XTVGQ2N?M0$=Tn-yt2i5S;nrgUkQ_QXu-Vy1Kv^Gy1kjo4I{ zW&n6SpJFl`p;LXcsAfLHR>V&Ybs|BC{!0Evyx%&^26~nPOyMrI-8)@rh zryZMst9jK^TK92GDe-ySHb*_`(V!-YVw`3^L;9%9W36p*K98GX{nO^iW-l7lWOsWS nz$y@M>|$WP?tdN>=YQcFcs+?wKD!t&00000NkvXXu0mjfma?ef diff --git a/src/main/resources/assets/eidolon/textures/particle/beam.png b/src/main/resources/assets/eidolon/textures/particle/beam.png new file mode 100644 index 0000000000000000000000000000000000000000..282c13fad36e50b81899bc393342e0a15a4bb6ed GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ii4<#ArY-l zFI#gpIEXl3TydF0?375|xBX^Eowi6^aGTfKy~A}=qYTqZB_&RuNmp(#M^!uI^S^k* z$jp1fBw-1oFz<}a15V5rq_3sy{GuO_alnh&tonc-GoMt!C5At377sSD+n799#<g literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/death_sign.png b/src/main/resources/assets/eidolon/textures/particle/death_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..500e3f03dc18164d3830a948a77bf4fb8d431e2b GIT binary patch literal 491 zcmVPx$rAb6VR5*=Q(=khzQ4|L7-~0N{v@FD+OdJZNXicMrkd}tlhT0n=XpKgvzCg`_ zgU}afaA;}JB_vvcpoAz3gdokdzn+HoG3&tLo_o&o+rf_ z<~O#mjh$eqDpfU9RhO!2u{v9=sw?r;jyhfRoak8F@>@0*w0vh&v}>|3w9I(y|g`<;%)>yg$ai? zk=#x&Z8-fl3(Tg?9?oM98v(Y7=ThqhJByJPgLsT_T*W*-r}dNZN^U-w@o)xvQGXn_ zv)hF@+|79IpX1!XemG5=$vT#zGCai$ZpLSl6UmM9D!z`d_~HNGcmij1>c5X~H2Dj?v^IpZx_kc^9pISm hDjR&kFWqD6{{eFWr?R*9P1XPa002ovPDHLkV1l=J<9+}D literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/eye.png b/src/main/resources/assets/eidolon/textures/particle/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..b411c1ee4670b7473ede958cb9f80bceeb8e5b1a GIT binary patch literal 405 zcmV;G0c!qPx$Pf0{UR5*>r)4gg`aS#RY-+%XNvUeqg2mx_Ltb73l3vKcMmiiDWC3UdU2M~M& zQ>96}wib3Nf|x>yy+Ux^Z2TAtkGKS^QaCUSckVgo&e!FCTZ5`vejdiVGuZF=5ie-1 zX(2ZZup06OjFW?(nBiLlPLiuZ2%`{stm7Vba2Vf7ZatWBIKx&|Juc?OZEWLOa^qAm z!yNDN6mReqr-Ss`;|`wTDxPB(pX0lDftz>|Y>!S=O{(faRqa>RQB`eL)%~hEsK0iQ z+-5NQ;Y2JZqZbN(81j&h!uQDuaF3s%kC6 zx{kX6FK`KuBJdJlu#$>j;|R0mEsQY1EquZUzmMln3pa2XZ&UFcr>&}nQSK5~u$DgO z5g27{$Ej`+@x{L`v4yyrc#>GoT;jR^g>&04RvMjl8ck2C00000NkvXXu0mjf?MJW` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/feather.png b/src/main/resources/assets/eidolon/textures/particle/feather.png new file mode 100644 index 0000000000000000000000000000000000000000..c8359a911b0b03cd23c5ff98f24a7446f2d12a8a GIT binary patch literal 446 zcmV;v0YUzWP)Px$cu7P-R5*=&)4OVwQ4j^-Z=d|Rn0SdwKqG3QHj0hc%2EV7eHhT5F&?jG$r) z$8Zjhv4@wK#d?yzB!_m8WG>11Bu|rkN%AwvN|Faj&LkOBrxOV-Ci#$m<4ux#Nfwi| z!2}8Wl}}dQz<1oiBP^hsL@*wESgG?}y?+x4It=u#!&hwTr*pb;`)>+m%oOHv8EZxM z9?O^;|I0Xdx{BuYdbjWqySQClts_V`2429aD!NwZ9|gXGv)INv3^D9RX4w_sNp-MO zMcXCiei6UL^CBJ&%8agbHyp&OFb5=A5E2 zBBEMez@=ROLLW*g%`4*q5z&r_xrlh4b1q|J`JFS|Coqq_+<(tw9|sX}isF<&jyAej z#74#z@fC*{)RS9hxL?lX_c;$UHqppE5oowC;7z&>a=nme?J#QBU-fVzy3ERbd)SxRYWlc!sw|&Gb0)KH#QN zdH-TqJ>dY`*nh%Ztl@iJeux)%jYo*2oviQ*rf>tBDcH?-ui#bUALZF6+`>2XJBfTX z75DHI_cM9jr~=pV055S5JGh4Z5)rdl#XEe&pCl^znZp#jm{eU{N#Z9Wq8AZAiavn|xFeRAU_YiF3HFgqz zoY-zKGi!R^27eRhOSGd?elLEL+@yz}i8zQqpYKr$4=xDU#|%&!-Ap$^G{!aTV>5Rh z#@|nFtXrlHES6g9I-cSx?%=IX@k4w~_Z!h>g!}jq!sn&dy4BO+E}jJN<$}OB)8GZ( z>o!!WwJzt-Vgab002ovPDHLkV1hPM(iZ># diff --git a/src/main/resources/assets/eidolon/textures/particle/harmony_sign.png b/src/main/resources/assets/eidolon/textures/particle/harmony_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..d18dbd48416b9cb4e272a0b2aa783559014ddedd GIT binary patch literal 515 zcmV+e0{s1nP)Px$y-7qtR5*=g)6I*GaTEve&vWO_ow+VGW4vY5D1)^mDW$NoB4nYID8*L(0{?&= z3wAaviIR;--jZU28M7L1VNl$AXWV-%?s;-Gr=EU2=bYd7obUJiP7x7MLCsohwNe}cA?1p0!o0Pyfl%)&FPPfjpI?qI~dHEN`h>_8ob2~ zyi9-sBiNS!XYmCq@Ee^<@;#8;@1>Zt_>68A8OyxaSdZO!hGtdoku1T}OgfKixP|X} zBObtBY|8d$aUb)g2Bk3dtgsyq(pTCvZYTFaH2Xy?on0)X+7o!(2QY(`eR|EHRZUeJ zDa;ghB=3&i!#RSVdUKz|maJYYr_jvSPGUcXlTsaraT-_f6{|CUs%)!>h@lkfD9-3@ zUy-!hxPZ&qP0hcpokO#Th)VJwws>_r_^7wK;eVS)_b<*(rY7HZUR3}9002ovPDHLk FV1l}J?lS-Y literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/magic_sign.png b/src/main/resources/assets/eidolon/textures/particle/magic_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..c75d11982287cd83497a09f3b1091ab354da4786 GIT binary patch literal 494 zcmVPx$s7XXYR5*=g)4hvRQ4j_2-%VoNtnQbBC>Vqqc53JbD+B++D(v3QeBHcmBf?!9NuIWw=AiioIZx(9(8X0p~s zA5lsHjfhyl0JCUjUdR4?cns(97fmT0|U*h{F-_D8}(1 zB9GNgL=vzHjJZ>11Y1P@>)2Ei)m&DFYyIk3~SlFht&i+osyPt4p$Oz6K8Q3 z%gLyW7_{*a_izKplhHgr;(a#xj+F$zgKo)jG*xpyg9}N01MBHQH<=#6yKH(A8zTnW zD(BzgQ%dNoM%m8uMgnc(Xqu@}N)Zvmywp!7w-b0Jjgvks=3_emc1H_0aX-KNc%1C^ z;rhhgCgyAYkLE-^ryA=5PT_KbuBoQAxU-gN<_u2YR_5!fHQzEevaXs)2lZ)yqFUS8 kEdMe79|llL8Eq-}2aNHebS|k)8UO$Q07*qoM6N<$g8P5hG5`Po literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/particle/mind_sign.png b/src/main/resources/assets/eidolon/textures/particle/mind_sign.png index 5c80bd503a47461f6fbe6d70b27ca96003ab6acb..691c8d7b9ad7009789911936673b5ef63fc4425c 100644 GIT binary patch delta 466 zcmV;@0WJRV1Nj4xF@Lj3L_t(Ijb+nMZ%ttk2Jqi|d)jJ>#?`2ViY_F&5=)g33wGi= zNF+90@&&|>q=|(DiCD3)v-1r^bm31L-4N}m0kLA z6w|niCs@NU&S(4+X3>XHEI?CW7$MWMgO;w{9 zOyXGnSJVxRTf|qDp`y9>Gv5x{N#7aT=>Qp5NvTR@j3{ ze8;g|Qsa7#5e=zI$LG@JS?tDpT-(y^ zB5vVjsyUmSl`1YeaatK1!WaBfAI&_j;4}`a4@+kPXK)p7@D06Y3%l?+3v}@U zPt${aTRd9AO+3#=N<@sS*S1(n`H-jGhn;Bq|FoAIZ%Qft02!&W4T-TCSO5S307*qo IM6N<$f=4UmmjD0& delta 458 zcmV;*0X6>l1MvfpF@LK`L_t(IjdjyKYgAzn1>oo2y_=06D29OI2WTOfN-Qi~3$f5n z^e-p~HYwddAa)i33qc#Lw6OCp1jI&Akwps?jNmFH7>y>x-LbfH&AQ+;_wvq}cjlaV zPXQ4DC8n_#ZCkO40oE}pilV{S5fLJyjEI?txEK+G_%{Z5K7W%q5z&o^?Ge$g@}4%1 zVIKGJ1Z&uV3wiz(&oRpX<9JczI5W76Pk4rv1XkFClQ@9;d435`@vcnnQ<%*T%NXWV zv*_SWYSYO}_vM7chC+!JHV`@bY23=92RT8BBC$h6l>k|I6x(v5Yq*;o=dp?t`E8=p zaGb-B6lNM%v44O^2^``ky7-kk%%NY6-4>Zx#i69LnYl0cI7avHL#R^mK2D{GyYK-w z#=2d>ZM@8B&SlL?m7SXCCx!RwEi7dI4j!vFv>WFWzfn!9ir;vJhpEdjX{}|^)Fg$L zdTpPxc!Z@CcL_hUpipn<2)-pwY3sEuW|wum#dVy)VM83u!n5e%HNImcBHC$;?wGOm zM?~*G#_DCh6%iUQfHAAKuv6`kNoy}R+7w0M4*+T4BHqJDkN^Mx07*qoM6N<$g03Ch A9{>OV diff --git a/src/main/resources/assets/eidolon/textures/particle/recharge_ritual.png b/src/main/resources/assets/eidolon/textures/particle/recharge_ritual.png new file mode 100644 index 0000000000000000000000000000000000000000..1931fa75f584eb41eff0139bf5e9380c598bd492 GIT binary patch literal 494 zcmVPx$s7XXYR5*=|)6I*GaTEve&+mGaw=|(kl(*Q>tx;^O`~k|s#>y-u#op$Y1-4Tx zWFg5P;AKga)T|U1O2%6lH05Q?+;Ha}i|0HuH>){y>Uo~u`JQvW-|z1!5mB%f%dx@I zVj6$(vr6!J9Krk&8!W>uoUIb{38(N91-;DSSeY5vi9P67S$G=XE?@8-hw%W9@f(-%7MDsy ztivQuXV*#W#WA(8-2}cy3mvsvSFyRm#uVo{=CC_yR5|%0zUSFNyuwtTkGB3(dL~t# z&xt2+1zU4SQ?n2izNXrp{PqmHa@{TIz!=u!QEuEx@t;;|yDnlJXVg};u^rcw+D&{I z8a$43m=zHvB1R&j8xb=R@gpMcM#Ra8Xh+1Rh`1IJ6A|$)vzwSwB0{da3Tv=B`R-TW zP)X%UZu={94ub+iO{yVncHmIHKg1i0H?xmHDWwLKQbfcc`8Uo?sqJf?`wg(cQ2#g! kk()HpvS?ke0S<%VALE;<*APx<{7FPXRCt`_n`u)V$q|O1fni`c#3h8aM$$@QM{KPB|4*?aHXK^Kl2&U#0>Qv= zgFjThRCZ3)Tp)khim2$GrmHLSt<0=Eiq`%8Jx|zL6aKEXNYtp`Q@8dLeWz8puU$)H zpw8sIy&Hd*#!TEE3qWMN74GBj(imtm;u($i9*ideVp;%djL*D+*>y83)}$L z;aR+Ik-^b7CIVqx0BWo5`>gA2paaa?wPVlP?%h%oV>i~XtY6yo#@?A>5QMwJ_eKIS z4gj@PkBp1y1)ytJ^+kI&PX@tDfnWU_WB45C0~fBJ+tq_{>*$(T8b$#yjCs%aoH4oN z`Wmnbtk~Zc?7dlGK?ERhNv> zXTTQl9N4hmE5Nb=p!x1-imjI@NUM7RoEiWpz#;GjIIubA42Vky#Lc82j3WV_`O>P3 z@lD_*unoKb{z8&~MaP^(_ri!4!TO#+>NtS0AKCB9$6Y7OG5;q*lGa8 zJ=-%sXMM>STm^mr{%Y4(2Ev;AzQnmtTD4QMEYHM zQ_dJvt7sSpfG7bFogA<8Vt&OK-!O(>TYpPh{Uw|Hk}SSQBoRI%88bMjI|lZ)G5(6IA~MKgP%G~HjGL<} z0i#5Jku3IajQO7(^E0GX{{Z~ku6qW+H)A|HG+s2lFL6Ycf-M_=Lb4mLjgD=y{zLX2 zz3W^Gs5IYw1VDd?%(qG6DZQ7@Yvs3W>@n~w@GoQj6G;Um^4@{*1jc#2Lv?E3Juv{! zZTvg3BtmweuH77Qo(KjWfKp)NSAU7L8b8p~`OU!mKY?A~Kcp4Z7IjYc+Ps+hra9&M z_TAV^1MtR;69}8+tySKl+-NTmcVty~umvR*@XWW#d;KP9tCO|&VlU=@wSHjF&nkrY z)$sFcZtw43lWoRr80SHFLz0+tnhuf=qKYa|T74P54te!ok|aQ4->xvfPtw^_va?en zq6C1aL#uV`#+MwLcccZ{CP~Z*N%G`tT!e2lq@bn(l7IyRV9O?WMcR@&Hqi%?&hG~1 zdx3eaT-3$bBn8o$LvxS!@3u*+zhJcOkar#V9M{IrfD}X(h^XJZJX>W%kk+P6|d)Tg{WP^UB{v`bP^AD3(!O=~1c?KrwTpZC!QcnO%d30Cc+ zs|MI5Nz^})q+p-4GH29vzP9qQm7+E|FpB%Jx#n!{XU6C{Ir*Y6{F(7EPf~?}w49uX zk`0gqtdL`R$e!L;>k_eX#D19m$G^uUs5gjL?ZN>p0dUHM2FN-`9==_6vQ6}cY)aSOi0JAuEzBD0HQXJ-yvcY2*ddr zP=P;P^8gH6NuQ|jHNH}TgUYkVw%R-~d>4)4ZK#BnUh-lsF;{_8Ue!D~WR7vf_im-Q zMM+h8uX9GT)B`Hpb5sG(xYzR;a^7B9S@{P=7qf6bZ7Y2*Zq>?JcFEad4}ed=HY6gd zK=i$3@UV$|?XOD~H=j)T9?}rMtGQx5L0wVqs6^=lN@{*LH@Qzlx0S}99hRRN`!m6<)Y!K&45J0N0#BJL2=fDoCF2Cq#%cc8`CBIg7Y zx15qg_3OyI2cYC)%BxbK(YJS$aoMy%Ad@doMIs_- ze!MDED`c^M8<@W{+J3YCyZzSA6~lKJLj@$VDo&n}bnG+DL}}Xy^B~AYT_A~Km+8yn zIx(VM=QT;}#XQFBF7TdwZb&ClhOWK`0RNDtDzwOn$2RFqjt_(&8AySkY_cjg2jtyi z+yfHxZoKM}GI%;5p_P9R{6ex%A896RYjui;R#E}odk~a!DZpt#PbBz^j%2>S~Nj`oMvv3E426Ih)WscKKYp3iV>`> z>(Kf*$K*C>9*LW`_l`(*WtVL5K9X17m*vMQ&ekL#ssc36E907FINby zg5?(D9h6j3qvPh2hxdtO=)A%6D_=VmGQfNdfYOU4e?ErJXGZ7|X&=@WsoLC(yYDjm zsH}VtN!2mg!`mm<|7GxeouXEsEM}@lofY6)cot}A_GeN6qCM~+c=y*=XXHA6A?bcREk5aSd4F2mAD362qO|H0 zRi;~G{NG?LKKCA*kJjV^e6N3)&^GEBFIoGM%#RB|1VPuC(Ep$RG80$47HExL-3kA5 zbeJ@FApBL~>{I>IR220`9mbdx0H{ktjOI%B!*YbtxW)q!@xJKWGXe839RM(x!HHR% zaeAr6ZL8LYR(mF5xwI9;E>$A5{nah(KyV=-fH;*{n$PR>lQ&EzbGGw#HceXK{qHm+-SqL;f6Y&$vY z;f%VPrFox(d3?qpE@`$A&R{oYUQEH~7?v#3JnrBYo@#dgDDuSUInCR+k2iRU?~_&T z;sS2scJw_PYbI&Gp g7_WwrRZpJtKO~ueMs>BbRR91007*qoM6N<$f|^6scmMzZ delta 435 zcmV;k0Zjhg1KI+e20LIg&@cxq_z=k5e18#Z5gB6zuOsjfztIc% z1Yc2iQpGuJ;6_fUF+e|akk}-cjc`gQC*Hz#lxy6>o_}L6u{xOTaF#nMYZC`KVGGZ& zgWH)qiERaQ5Kga3)B1Rm(_Y|7{GTND1E}qRa zaWojE)6IYJX@7Eyah)W7VLfH;;;i{Kwqqr+-C)+knRe2Y5gy0FTk~sMOUd2r2gy~z zjxedrAI*E*!6kf3Uply%3dZ=DYOh7`CC06VLk#i2{67vb6BXR2^MUN>ECcHsa3002ovPDHLkV1l^U(qjMs diff --git a/src/main/resources/assets/eidolon/textures/particle/winter_sign.png b/src/main/resources/assets/eidolon/textures/particle/winter_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..cbc2925d8b046b9cd94a98b920553e7e1d77c183 GIT binary patch literal 518 zcmV+h0{Q)kP)Px$z)3_wR5*=o(%);(Q5?td$NBnLU(_&C*w#>U!3C2G_1(&(l;nmhvQlovwZB2! zD>dc9kK8O*67ek;Gh8b!7PU4_w#M2QZx`S9+FIUqI_JFJ&-Xd!^ZL9?L=>#I5`R!( zBQ~V=3qSE2>sGO?3R|!>5BZB(L~17!e1?*v3pKRxy~0sk!i9wI;yD(Z&E^0!8jWex zaRQfOBdLp8;!Y*9Qc`|P})ND4pt%^pYu|1cQIG8?-mWb#^FZvTWjdOY1 z*VJ}n6p!&VwU3yrVLneC&&0!=`|%}5|C-!**34Jw<{liwC+)T!!wtO8f*Yw#X}9+f z-pJp082hwa`bZYM!x<}Gx2!c*?GK<{BBBGE(1B&6dT|O@bAMC2y_Ze?h9xYB2oX_> zh$0l}J(((N6#t2QRTs{u^a!)1l%=)oKbEtuBP2HMBLDyZ07*qo IM6N<$f~{cbn*aa+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/rune/crimson_rose.png b/src/main/resources/assets/eidolon/textures/rune/crimson_rose.png new file mode 100644 index 0000000000000000000000000000000000000000..db7fa8aa0a6c796bb3a8bf506558f6dfda4ad003 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Hh8)?hFJ8j zoovY8qQKKCFU}saX!HJWd+fVs8yW_(_ws$6J7tHX_yULDUjxr^^+42$iM0oN&UqfIW$&EW`rtoTkB9CJ@hdI04noh31SQ^||ChTsS2Z~F trM=T)vq@xdviq3vf-w$kmGh7!0@RWT8x|+e$)z4*}Q$iB};4@z! literal 0 HcmV?d00001 diff --git a/src/main/resources/data/curios/tags/items/body.json b/src/main/resources/data/curios/tags/items/body.json index d9b8239..b03c63d 100644 --- a/src/main/resources/data/curios/tags/items/body.json +++ b/src/main/resources/data/curios/tags/items/body.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:warded_mail" + "eidolon:warded_mail", + "eidolon:raven_cloak" ] } \ No newline at end of file diff --git a/src/main/resources/data/curios/tags/items/necklace.json b/src/main/resources/data/curios/tags/items/necklace.json index 4b1620c..19e0156 100644 --- a/src/main/resources/data/curios/tags/items/necklace.json +++ b/src/main/resources/data/curios/tags/items/necklace.json @@ -5,6 +5,7 @@ "eidolon:sanguine_amulet", "eidolon:void_amulet", "eidolon:glass_hand", - "eidolon:terminus_mirror" + "eidolon:terminus_mirror", + "eidolon:soulbone_amulet" ] } \ No newline at end of file diff --git a/src/main/resources/data/eidolon/loot_tables/blocks/magic_candle.json b/src/main/resources/data/eidolon/loot_tables/blocks/magic_candle.json new file mode 100644 index 0000000..f4b5c1c --- /dev/null +++ b/src/main/resources/data/eidolon/loot_tables/blocks/magic_candle.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "eidolon:magic_candle" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/loot_tables/blocks/magic_candlestick.json b/src/main/resources/data/eidolon/loot_tables/blocks/magic_candlestick.json new file mode 100644 index 0000000..74a41da --- /dev/null +++ b/src/main/resources/data/eidolon/loot_tables/blocks/magic_candlestick.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "eidolon:magic_candlestick" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/loot_tables/blocks/research_table.json b/src/main/resources/data/eidolon/loot_tables/blocks/research_table.json new file mode 100644 index 0000000..1d673f7 --- /dev/null +++ b/src/main/resources/data/eidolon/loot_tables/blocks/research_table.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "eidolon:research_table" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/arcane_seal.json b/src/main/resources/data/eidolon/recipes/arcane_seal.json new file mode 100644 index 0000000..3a6345d --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/arcane_seal.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "group": "eidolon", + "pattern": [ + " w ", + "www", + " w " + ], + "key": { + "w": { + "item": "eidolon:magicians_wax" + } + }, + "result": { + "item": "eidolon:arcane_seal", + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/death_essence_withered.json b/src/main/resources/data/eidolon/recipes/death_essence_withered.json new file mode 100644 index 0000000..5f8d564 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/death_essence_withered.json @@ -0,0 +1,27 @@ +{ + "type": "eidolon:crucible", + "steps": [ + { + "items": [ + { "item": "eidolon:withered_heart" }, + { "item": "minecraft:rotten_flesh" } + ] + }, + { + "stirs": 2, + "items": [ + { "item": "minecraft:bone_meal" }, + { "item": "minecraft:bone_meal" } + ] + }, + { + "items": [ + { "item": "minecraft:charcoal" } + ] + } + ], + "result": { + "item": "eidolon:death_essence", + "count": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/deathbringer_scythe.json b/src/main/resources/data/eidolon/recipes/deathbringer_scythe.json new file mode 100644 index 0000000..9bdad8f --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/deathbringer_scythe.json @@ -0,0 +1,33 @@ +{ + "type": "eidolon:worktable", + "pattern": [ + "bwb", + "brb", + "bsb" + ], + "reagents": "gege", + "key": { + "e": { + "item": "eidolon:death_essence" + }, + "b": { + "tag": "forge:bones" + }, + "r": { + "item": "eidolon:reaper_scythe" + }, + "s": { + "item": "minecraft:skeleton_skull" + }, + "g": { + "item": "eidolon:shadow_gem" + }, + "w": { + "item": "minecraft:wither_skeleton_skull" + } + + }, + "result": { + "item": "eidolon:deathbringer_scythe" + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/enchanted_ash_from_block.json b/src/main/resources/data/eidolon/recipes/enchanted_ash_from_block.json new file mode 100644 index 0000000..447cb03 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/enchanted_ash_from_block.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "minecraft:bone_block" + }, + "result": { + "item": "eidolon:enchanted_ash", + "count": 6 + }, + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/glowstone_dust.json b/src/main/resources/data/eidolon/recipes/glowstone_dust.json new file mode 100644 index 0000000..611d711 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/glowstone_dust.json @@ -0,0 +1,23 @@ +{ + "type": "eidolon:crucible", + "steps": [ + { + "items": [ + { "item": "minecraft:glow_berries" }, + { "item": "minecraft:glow_berries" }, + { "item": "minecraft:glow_berries" }, + { "item": "minecraft:glow_berries" } + ] + }, + { + "stirs": 2, + "items": [ + { "tag": "forge:dusts/sulfur" } + ] + } + ], + "result": { + "item": "minecraft:glowstone_dust", + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/magic_candle.json b/src/main/resources/data/eidolon/recipes/magic_candle.json new file mode 100644 index 0000000..ac8a362 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/magic_candle.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "group": "eidolon", + "pattern": [ + "s", + "t" + ], + "key": { + "s": { + "tag": "forge:string" + }, + "t": { + "item": "eidolon:magicians_wax" + } + }, + "result": { + "item": "eidolon:magic_candle", + "count": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/magic_candlestick.json b/src/main/resources/data/eidolon/recipes/magic_candlestick.json new file mode 100644 index 0000000..820a992 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/magic_candlestick.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "group": "eidolon", + "pattern": [ + "y", + "x", + "y" + ], + "key": { + "x": { + "item": "eidolon:magic_candle" + }, + "y": { + "item": "eidolon:arcane_gold_nugget" + } + }, + "result": { + "item": "eidolon:magic_candlestick", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/magic_ink.json b/src/main/resources/data/eidolon/recipes/magic_ink.json new file mode 100644 index 0000000..cf8cd66 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/magic_ink.json @@ -0,0 +1,34 @@ +{ + "type": "eidolon:crucible", + "steps": [ + { + "items": [ + { "tag": "forge:dyes/black" }, + { "tag": "forge:dyes/black" }, + { "item": "minecraft:glow_ink_sac" } + ] + }, + { + "items": [ + { "tag": "forge:dyes/blue" } + ], + "stirs": 1 + }, + { + "items": [ + { "tag": "forge:nuggets/silver" }, + { "tag": "forge:nuggets/silver" } + ], + "stirs": 1 + }, + { + "items": [ + { "item": "minecraft:glass_bottle" } + ] + } + ], + "result": { + "item": "eidolon:magic_ink", + "count": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/magicians_wax.json b/src/main/resources/data/eidolon/recipes/magicians_wax.json new file mode 100644 index 0000000..2890d88 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/magicians_wax.json @@ -0,0 +1,31 @@ +{ + "type": "eidolon:crucible", + "steps": [ + { + "items": [ + { "item": "eidolon:ender_calx" } + ] + }, + { + "items": [ + { "tag": "forge:dusts/redstone" }, + { "tag": "forge:dusts/redstone" }, + { "tag": "forge:dusts/redstone" }, + { "tag": "forge:dusts/redstone" }, + { "tag": "forge:dyes/red" }, + { "tag": "forge:dyes/red" } + ] + }, + { + "stirs": 2, + "items": [ + { "item": "eidolon:tallow" }, + { "item": "eidolon:tallow" } + ] + } + ], + "result": { + "item": "eidolon:magicians_wax", + "count": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/notetaking_tools.json b/src/main/resources/data/eidolon/recipes/notetaking_tools.json new file mode 100644 index 0000000..dfb5e67 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/notetaking_tools.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "eidolon", + "ingredients": [ + { + "item": "eidolon:parchment" + }, + { + "item": "eidolon:magic_ink" + }, + { + "tag": "forge:feathers" + }, + { + "tag": "forge:nuggets/arcane_gold" + } + ], + "result": { + "item": "eidolon:notetaking_tools" + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/parchment.json b/src/main/resources/data/eidolon/recipes/parchment.json new file mode 100644 index 0000000..ecd1280 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/parchment.json @@ -0,0 +1,28 @@ +{ + "type": "eidolon:crucible", + "steps": [ + { + "items": [ + { "item": "minecraft:leather" } + ] + }, + { + "stirs": 1 + }, + { + "stirs": 1 + }, + { + "items": [ + { "item": "minecraft:paper" }, + { "item": "minecraft:paper" }, + { "item": "minecraft:paper" }, + { "item": "eidolon:enchanted_ash" } + ] + } + ], + "result": { + "item": "eidolon:parchment", + "count": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/research_table.json b/src/main/resources/data/eidolon/recipes/research_table.json new file mode 100644 index 0000000..530d168 --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/research_table.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "group": "eidolon", + "pattern": [ + " c ", + "xxx", + "zzz" + ], + "key": { + "x": { + "item": "minecraft:red_carpet" + }, + "z": { + "tag": "minecraft:planks" + }, + "c": { + "item": "eidolon:magic_candle" + } + }, + "result": { + "item": "eidolon:research_table" + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/recipes/soulbone_amulet.json b/src/main/resources/data/eidolon/recipes/soulbone_amulet.json new file mode 100644 index 0000000..228216d --- /dev/null +++ b/src/main/resources/data/eidolon/recipes/soulbone_amulet.json @@ -0,0 +1,32 @@ +{ + "type": "eidolon:worktable", + "pattern": [ + "bab", + "bhb", + " c " + ], + "reagents": "cege", + "key": { + "e": { + "item": "eidolon:death_essence" + }, + "b": { + "tag": "forge:bones" + }, + "c": { + "item": "eidolon:ender_calx" + }, + "g": { + "item": "eidolon:shadow_gem" + }, + "a": { + "item": "eidolon:basic_amulet" + }, + "h": { + "item": "eidolon:wraith_heart" + } + }, + "result": { + "item": "eidolon:soulbone_amulet" + } +} \ No newline at end of file diff --git a/src/main/resources/data/eidolon/tags/items/zombie_food.json b/src/main/resources/data/eidolon/tags/items/zombie_food.json new file mode 100644 index 0000000..be58446 --- /dev/null +++ b/src/main/resources/data/eidolon/tags/items/zombie_food.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "minecraft:rotten_flesh", + "eidolon:zombie_heart" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/items/raw_materials/lead.json b/src/main/resources/data/forge/tags/items/raw_materials/lead.json new file mode 100644 index 0000000..2161e6b --- /dev/null +++ b/src/main/resources/data/forge/tags/items/raw_materials/lead.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "eidolon:raw_lead" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/items/raw_materials/silver.json b/src/main/resources/data/forge/tags/items/raw_materials/silver.json new file mode 100644 index 0000000..07b42d6 --- /dev/null +++ b/src/main/resources/data/forge/tags/items/raw_materials/silver.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "eidolon:raw_silver" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/items/storage_blocks/raw_lead.json b/src/main/resources/data/forge/tags/items/storage_blocks/raw_lead.json new file mode 100644 index 0000000..8538c23 --- /dev/null +++ b/src/main/resources/data/forge/tags/items/storage_blocks/raw_lead.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "eidolon:raw_lead_block" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/items/storage_blocks/raw_silver.json b/src/main/resources/data/forge/tags/items/storage_blocks/raw_silver.json new file mode 100644 index 0000000..2192248 --- /dev/null +++ b/src/main/resources/data/forge/tags/items/storage_blocks/raw_silver.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "eidolon:raw_silver_block" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/fence_gates.json b/src/main/resources/data/minecraft/tags/blocks/fence_gates.json index bd96de8..d7e30bd 100644 --- a/src/main/resources/data/minecraft/tags/blocks/fence_gates.json +++ b/src/main/resources/data/minecraft/tags/blocks/fence_gates.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:polished_planks_fence_gate" + "eidolon:polished_planks_fence_gate", + "eidolon:illwood_planks_fence_gate" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/illwood_logs.json b/src/main/resources/data/minecraft/tags/blocks/illwood_logs.json new file mode 100644 index 0000000..1b1dc9b --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/illwood_logs.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "eidolon:illwood_log", + "eidolon:stripped_illwood_log" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json b/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json new file mode 100644 index 0000000..04f6216 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#minecraft:illwood_logs" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json index 59c3691..c69c5d8 100644 --- a/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json @@ -8,8 +8,18 @@ "eidolon:polished_planks_stairs", "eidolon:polished_planks", "eidolon:polished_wood_pillar", + "eidolon:illwood_planks_fence_gate", + "eidolon:illwood_planks_fence", + "eidolon:illwood_planks_slab", + "eidolon:illwood_planks_stairs", + "eidolon:illwood_planks", + "eidolon:illwood_log", + "eidolon:illwood_bark", + "eidolon:stripped_illwood_log", + "eidolon:stripped_illwood_bark", "eidolon:wooden_altar", "eidolon:wooden_brewing_stand", - "eidolon:worktable" + "eidolon:worktable", + "eidolon:research_table" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index c328ca0..882fcbe 100644 --- a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -23,6 +23,20 @@ "eidolon:smooth_stone_tiles_slab", "eidolon:smooth_stone_tiles_stairs", "eidolon:smooth_stone_tiles", + "eidolon:smooth_stone_masonry", + "eidolon:smooth_stone_masonry_slab", + "eidolon:smooth_stone_masonry_stairs", + "eidolon:smooth_stone_arch", + "eidolon:mossy_smooth_stone_bricks", + "eidolon:elder_bricks", + "eidolon:elder_bricks_slab", + "eidolon:elder_bricks_stairs", + "eidolon:elder_bricks_wall", + "eidolon:elder_bricks_eye", + "eidolon:elder_pillar", + "eidolon:elder_masonry", + "eidolon:elder_masonry_slab", + "eidolon:elder_masonry_stairs", "eidolon:soul_enchanter", "eidolon:stone_altar", "eidolon:stone_hand", diff --git a/src/main/resources/data/minecraft/tags/blocks/planks.json b/src/main/resources/data/minecraft/tags/blocks/planks.json index 252f89a..10223f0 100644 --- a/src/main/resources/data/minecraft/tags/blocks/planks.json +++ b/src/main/resources/data/minecraft/tags/blocks/planks.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:polished_planks" + "eidolon:polished_planks", + "eidolon:illwood_planks" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/walls.json b/src/main/resources/data/minecraft/tags/blocks/walls.json index 14d2864..299d0bc 100644 --- a/src/main/resources/data/minecraft/tags/blocks/walls.json +++ b/src/main/resources/data/minecraft/tags/blocks/walls.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:smooth_stone_bricks_wall" + "eidolon:smooth_stone_bricks_wall", + "eidolon:elder_bricks_wall" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/wooden_fences.json b/src/main/resources/data/minecraft/tags/blocks/wooden_fences.json index 95c6a40..8ee6f2c 100644 --- a/src/main/resources/data/minecraft/tags/blocks/wooden_fences.json +++ b/src/main/resources/data/minecraft/tags/blocks/wooden_fences.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:polished_planks_fence" + "eidolon:polished_planks_fence", + "eidolon:illwood_planks_fence" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json b/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json index 9d694ea..730595d 100644 --- a/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json +++ b/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:polished_planks_slab" + "eidolon:polished_planks_slab", + "eidolon:illwood_planks_slab" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/wooden_stairs.json b/src/main/resources/data/minecraft/tags/blocks/wooden_stairs.json index 32121a4..28cf8f7 100644 --- a/src/main/resources/data/minecraft/tags/blocks/wooden_stairs.json +++ b/src/main/resources/data/minecraft/tags/blocks/wooden_stairs.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "eidolon:polished_planks_stairs" + "eidolon:polished_planks_stairs", + "eidolon:illwood_planks_stairs" ] } \ No newline at end of file diff --git a/src/main/resources/eidolon.mixins.json b/src/main/resources/eidolon.mixins.json index b8e7a4a..e1b2a21 100644 --- a/src/main/resources/eidolon.mixins.json +++ b/src/main/resources/eidolon.mixins.json @@ -4,13 +4,15 @@ "compatibilityLevel": "JAVA_8", "refmap": "eidolon.refmap.json", "mixins": [ - "LivingEntityMixin", "ZombieVillagerMixin", "PotionBrewingMixin", + "LivingEntityMixin", "PlayerRendererMixin", "LevelRendererMixin", "AbstractArrowMixin", - "StructureSettingsMixin" + "StructureSettingsMixin", + "AbstractContainerMenuMixin", + "LocalPlayerMixin" ], "minVersion": "0.8" } \ No newline at end of file diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index c79a362..7719e8f 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { - "description": "examplemod resources", + "description": "eidolon resources", "pack_format": 6, "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." }

+K|vTCCRqrtRd-Sbbvg9X5+vokU?lw5Z`b;~L=y;kB1&5Yj;rM7bb zq4OFry@PR$121!JBtNZ0mvNMG>}fs6GS|r~E4+V5XZu;Q;`be!>W3mcIyUX&eH0TC z-PQW^9~Zm9YWnwakt8#7cJ}h9EK%)_*_j=qPI5&84rX(aL!EP`2Sr9G{?8FAM1v~1 zIFuo4ytT~yw?2GFt(8$l_Qq;|ff1b)0Pl*4=e5iOs)UamT!KT|$n4B*UTLdOgi3Abhg7V{Xoa>~| zGywEk9YJrj-uo1zTz3v|V4aCo7rqKJ9`-EL-xDfiKOvu25SihbP&MNuf7zNc59CZ& z>f0K(9)MBRdLG|RF1l9s8>UB3Za`3PO4vX|d*aEjD*~-;)5VcvBIfnnZ_w2D+`)?o zmv(1_+RPY;k+BG5~T131b$6-eQ1I6Yq`VCh3=dt?VE;Ix*HAm4|&)N`!toIbufO77qIqhAy zz{qNICyYVFq`9-(LJxG!JKhZ_E33rs0Dk3|W_cRuhnQzRQ@uUWdnhXkG|z5TANJC> zGr3u<*^xH0YDM227>g{|Qg_k$y_O1h@3-FjnRWE{I@EW+;A+Oa^P{o44+qTI!Dn$v zrvBXaUkBKoWQ)Qby)|!DU^*R?|)Cl(y#}6?P?+LlT(j-LgtTkJcxWtzGVF zKy9pk$PC8A;cUSqRm;pr6M*{b1-!(AJ?^?O7p$pQWai%xIln0jIl?xHcrJ42YD@5x zA5`})6zT#LbB8JIFC?S)?(r#5F5Rm9m-=Jj&B4jrdivf7z3E&TsUxKugpv*BA0!9UUNI#zttiQ-C zP9{$8K(Sl6_`g?eAgRJ7o};m2@QS=3vDfm?;z>XE)_ect@13bPW^Yoc^TC{>4Q7fq z_I|Rv5-<82&OD$qD!E#9>vIksCTV#351Sk6>?ha0=>!xH-p)*9jmzJ8Q5@te?)0|n zn8yGXTOB~f%N;k7R zQ74Y^SJ@uUaOS=07p}ksqej$eB8I6#+KK0kGyIK4TpjMW6diice_9(z9lbyIgkB z6HSB9@)1|@=jM>jc;*8XkK%7rd1UOZX}7%#$EN7`2F)dKOg4I0y>e7?t3LN9YNvZ? zsHi$v6^hyZ4P%|aZJsf~l+c_S6D=6)Gz+RC|1=0;jMDx8#MmS*E)BpttFd(3PmEPN zV35@=g}S7!HIf{hdXoIiB4Q5ISF;vb=Nx88l8NLuH;{i{-uy-JN1F0@B=nYJ9oG}D zx5#2@U0D3UCI-tVaI_dMiO2ghnnX6Df}m|o;vpNh^YB5r!BzZ4QG zg+rJyK^4kFb~gc))Vd*lPq+>=a|rVio=vQgZkE3}8i^pwjv zaU%I$>F?`;1&+q<#xt|_OB@%#XfTbN*UA5(qfY07LtCmhQ{<$u^dnaQ-#m4OR{)OZ>J@r$NZYFp349*TD zNgmMD_eJM2hq7K6|3?lI+FgpJ?U_0GOR;;_BFC%r0o}-*TwIQ1!e%iZ{FHMLBNLmc zm^c<$W(AekYQ6)7`yNPoL(*Obm3{uU<*JZA1URexV3iNdteV(iZ7}sv=A-w1UA3(* z!bo&0@idtLcGDW}p4I9a3%s*4c|+2rPG^11z+)n_d%txpy7^&~Ot^ffQ6GF!#y;@7 zBe~S~&i2uCu8^ZNh)3s`!+J1hGa4&;s`&=0BJ()JB$UaSo1`;&?G3RGp#4AUC!&SV SFsi!%0000JL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/vapor.png.mcmeta b/src/main/resources/assets/eidolon/textures/block/vapor.png.mcmeta new file mode 100644 index 0000000..1c15072 --- /dev/null +++ b/src/main/resources/assets/eidolon/textures/block/vapor.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/textures/block/worktable_side.png b/src/main/resources/assets/eidolon/textures/block/worktable_side.png index f464f4c90d3dcc6183c4262f29277537afb6e045..303089ecf5890f898f504312641153bcc3e6168f 100644 GIT binary patch delta 426 zcmV;b0agCt1JMJJF@K9mL_t(Ijg68$PQySDg+JTtcoVb`^H*{O8pIW7sAxC?LP&@v zXNZKj1QIP>ZjmMjh!CPc5Qrm`khPr+#j<800r4u&%$wOa;}@JC?$7aX|D;)OUa?VY z_-S7939s1&jatOoN(jJcY!CoNVNgl{kgAy1?1E9!X00Au;(vR=Ot(l?%vNf7&%+YH z4p2%|2}c;dwYbY$0Ibg2q$)<$!-^*bXbqw$3{qN2S{t5+C0nUL)kE%|+5qfqCjh*? z8?-hgNm#8WoE#|tLbNtKJmzdR1&vx%5eJ!lIY~mKfNA+TU^F&N@)`jwVU>i$q8%kY$FROnW;CA-+_VHU? zEMh@!1KTZZB~A`t=0`{-ptKZ*S=L@A$3m5S$+D&7F;x zt}-%%q#!#0k;Fb Uq$k-(r~m)}07*qoM6N<$f{Av@~ delta 442 zcmV;r0Y(1N1K|UZF@Kv$L_t(Ijg6AOP8&fG#(%fBcegfLg+oT7i0D(LiFk!HsiH`E z1rS2YgX96+Bhk{)rJ<*xp+ixW0%9vZ%QAO+cV4I1+q ze+-AcZN`n@T^<8)Gg&Z5EW@&(pT@k|5&%r+76H&S7NrDA34d~(Ff0oOiRJRX=JLMw z$+=E=yO*N1q-tG5381xPG;yBYTmmqh6?{o|+`Ifst`l@mc%G7A49KoKfH9WQq-8gk z=$_z5IRjw7mjN&spPgatZgz4P!P%n6j zae?nNE?UnCxqtmMChCmO2k)2FV)Y>^j_7O^J6agOxVnzKgsz&3BbV43m(UvjelGr~ zz+hX_PhNT1sM8z9*Cq%z4RC&b z#_jD-HpM$c#~(i|wce)A;%bZfO0x_ kj)!{j;p5m+%VJg)si14l&rViMB3E!px|ne(=a6yzeFN%a`EvXun-r3IVvgH`Ku;nUoBK z0AQ#!10fh{O`#Nv?FAca5dhXUMAkOwal=SkUV?M>HYJ5plz*nep)4!Z*pf-f_0t*E zV@@i1)OAA$c=EQ~qBIq9xyLNza*xtfY|AZPf^$aN0uZX##*+d1ae^A#Z=)Y40KQ3O zJ_wEvui8vXN>kB~6Rw|b07&C?M&|iTzPGvKYYU|aGuh1y_;ns8YcnZ{20}~;md5M9 z=1vo!6LAtF^MCBG`%~^P5aMft{~{V{J+<-I5uh_!2%yIH-y=9q=+p%KIuDbzg;E43 z2fOXPJ)1JpPtWQ60&uGySZ#Acxe~J4=G>|W0B_~*VwRl53!Mh3==mnj%Cm4*cH~ra vK8W7lp{^T}cmYgKq4K%k*_~Y14FI3@iT3g2K5(W0015yANkvXXu0mjf`1ij( delta 486 zcmV;G#eZI73-Cbz8M(gFQmQDVin!v^CFPY7 zO&ZF49O~5f2~yHhq&dlDniL^Mm;i?J?s+$b{w1VFY^Oj|v^9`A_*hjg!4sj4b~l@g?TMI1ORwvuV9 zN48S{h@ZLUrZHf#m5jQ+1po|vm!a>Ty^XrQO>&SW&gZKuljMdtsPrzjl3Z(^2W{^1 z1Az4dAuLIa5q~Qs7)QUEbFBeLWoaeUey+8xWE}adl)(A&_KkV0`4oI=wH$!Z(+n>> zL^Ns`07f%&#S-vLwk3(ZE6QM0>h~Br6$Sc!Zw*ZwWOx$x1}%Y3565 zKLR2CV5|K=2un0yN;kl3k0*{#%|bYU@A-7 zk5lld>vQ|CrtQ1c6#5;{CP{L0){`^Mx#6Px$ut`KgR7i>Kl)q}*P!z_0b_I$hL~3EBT9RymjKvu;WQu7Yz*~ndoiq7CGW7xa z1RgRPN_P{;QZP*jK{gcsDUyw_+(3#l$meox2S-Ud=3DOJ-mCMS^W9IU08p>j)1%{a z8YkTXOK3G~>27%ofFK(3^Y_)lxqQ=V)>44MI0oSJm-b4ohfoC4AP8ujbg5RW=|h*? zl8IX~0q`te?d$Pi95WcljFLX1q@RZyfWogIpHjDE63%XMOD5jow}r~(93Y(C(!RM? z1fJzHO8R(~uR1>cx|4dA&%3t{03Yk$*D7JecT-$UWL?Hy*@DgY08}Oyv~TitCQtDg z4Czc?S1`Fyp>!s3)_GU$WuEAg7skPdv$Yca`TH+-vgg3ab4ipDFX$?~6ve#c3xzl~ zu4Dg~0t)i~?v}SQ!?7s)vM)phfXc=j04}41AQ}Rh`9z_?IDT{<6s40O8gdyWDzPNj z2_@Fgb#loiGa(O*POs1Ywoe#O38EoEl&K+z@1}(DbROF{hD|s_6|IVMY&yNC4I!AD sP>Rq=1wyW3&40QNI=!b6zv2~wdkVw7vBptI+W-In07*qoM6N<$f-U{vVE_OC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/brown_slug.png b/src/main/resources/assets/eidolon/textures/entity/brown_slug.png new file mode 100644 index 0000000000000000000000000000000000000000..5a36a2e74109f1053be34298ebbbee7dc2ad08c6 GIT binary patch literal 479 zcmV<50U-W~P)Px$nMp)JR7i>Kl(A02P!xv0YZ{9+O#?DOf+BBV!sO=YjPIbMK7os)i>tnZiKD?u z7se)Rj8ZkR1J*ReA|&QI=qW82EXI+4x##xWd;W7y|8o^UqtVbCQNUUAPBDS={au~h zcOKqTez_y(o?eFloLt^c#rg>bpgqsy%5|yN>)LhQ)WxEc;>WfX{l1QEfe?!?D^&A% zM>}g4;Y)9r+E0R0ihvI*lj@V!M(zd14sb2bbvzf6~#+1olpEW?l%Q zaGrQ`!^m<-IwM+;|N9?U%1WNJi;kX}j=w_5{8mfv)Yi*Dy6uy?kS+ietS{N#KR)C6 zx%j&Xu#z`_oq{E)#Pf69KR(BSC3uoh?4&|!Z7$Ob6`r5N^Ixf! z#;@Jmz@!&`6AV6BT^Yt*`63>Zx4WacA0h)ll1P#YdZC)I$G)Tv+TGDy#0xAS_yh~> Vxjjei!0P}2002ovPDHLkV1lVC-f;i` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/necromancer_eyes.png b/src/main/resources/assets/eidolon/textures/entity/necromancer_eyes.png index 48b20acfa8c074d5e55a8ba566374a4a3f0571cd..3f01aa696b31f76be4a6bfae00ff2c7ac40f6219 100644 GIT binary patch delta 246 zcmbQoG@ogLVf{@{7srr_Id89Q%wlpBX?+;KA&RA2mrc=yr);CAZj{F?5l!aT&QEe{ zIDUUoR4Lu1>uSic>8KdvMn6?S?L?=TFaLK%pGkanAZCJ!=cFavA=Y16`wTrks~uS6 z$aUdn08`DBz3*?lIVEo3@%h=ihwWCtI$4!5kZp;rqea}X1 r|0mW1?}co>h>V5Vf_tH7srr_Id89Q%wlpBX?#BN=djoY|7&Sn`l`uXC#2dv^1INw)neZ^FEKxRNFX8aXOIp9+wsrF>kE~S zg+?Aw;6B{$XS9#EM1jGe%4gm_?t3SgUe6K_sAM|3`;VQ^BrylW`}qug&)1)SSAD0W qF!l@Qyj8#ddQSpcj*Pyz%QATXF*L}Zb9WL05O})!xvXP)Px%qDe$SR9J<@SI>*uKp1^l1Di|~t+q&E8!xV<2Pv{36g+t8*=ze3w%49}@lYrf ziWCn^cYCoGWa+kB(M%#m(nI{laW;t)f6#ZCB$N5RH*dZli2(`iPA~MmDQu^R$@oe< zACE2#XrkHbh5#@e^tINUs1IzX2mr7wwlV6W;xf!g5 zV!Ogjny^?w1f;z4L&HqkL9=`o($14oOIB`Ih=2pu=T5t)jG%jYPKIv8$3YxHz-M^y z=nMdG_wxsWfa9+e(ehjziM@xf+$=)y~N|jpSH%eyrkj5U3?S3HQ2Tk`Y~l zgo@ihyVKjcCNT|xsPK^Etf{Em6;l;ZL3Liej)U(_wK`*}0y&!jD_Yk z?`ji>!;6=%LjaiHPK5mP+X;q)zR~XV!hM{|NGwDYWVTZTt5n4`DF9?I&v8hs19avp zp`6XI^!WynqYxkxRMF_KiGnl#@G(BVf3x>7r1k>Yc^r|W9)bD^X0d{B4n#+hKfn?E acl-kg^kpoTGX1Ck0000Px&xk*GpR9J-sz{Jou!HT+qdHTVz|PiLWShDq(JWOG z-vJyRZ)jQM=0&;aLKU!Cs$iSC1eztI-aixzJpusR)DuJmm>{%Xtu3@);SK;a4J-Z> z7^auZ*R4eUvl3XZ)pH3I&3_UB04GRRCV=wtMMBF;3L)91E;oDmY9({+>Hf7;yc2l1 zqcFan4CPeJi;@7G1y?JXtxyg1yDadBMzRda`Bhb2Bvg{lWQe-o>~&ViF%(R9kJ_3u z8PfF!g$Ou-M|aSd)gK;jXggbHQBgC>Wp}c79;wy+@bfo?G|=@293F3I2iu*fhz?Rl zB$#*o0o_3#n6K*81l(Ko?onGSqJspxgY8bFDqjV0Ms+FVItMo}CaOz()}{**lNA{y?5^01YFgWr&J~fQ3t}2WK+G zrY5`6FhW|jcCfc`Y*I0cvz6XXj@cyqSK%MTOPqS2sD>ma! zO^HIwsL%_>bB!xS0H!T%n@?G_Zt*UvSl>+m@Lrc#eKy4XbGptQh4CMKpw4r134phw zv7DU31XR_x>j9o$v(wjT*L|G9 zEr0wzHK7;PfKFeN_d;|oeQZ;wZ9WB{Gx~R7L2ByDlvnptuJ9~I&KsK zUapCiRgXX2zm6J4h^;T-hSOFyjF7eE8m>78EWZ7*_27v8^J^~xu(epYc}A5mA^|Qc zZx~@_E-%yqtgnagF@Cz=uY8Fcj_CzDr~B8DFuRwpRT zKFa&g^1EL?Mk;_+^|64<8-tcn;kOSCZ-^J$rcQSda~4ZdHA0J`g{SSU|`(oz!)P;|XuLyt$KAH;j;`VPzg_Wj6}3H9cnoyl^~C@H002ovPDHLkV1oW*-E;r| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/silver_armor.png b/src/main/resources/assets/eidolon/textures/entity/silver_armor.png new file mode 100644 index 0000000000000000000000000000000000000000..7887d2bbdf49e4ee27c4d5f60f08afb564689d05 GIT binary patch literal 1502 zcmV<41tI#0P)Px)m`OxIRCt{2T0LkZM-=`P#DP26jaRz{V+1ym-JXq2z{v$-NaZw!GzsAXNtMQp zAw`rbY0|hlLqf^}HE|WVKqL(24xL(Qg$zO%ysLF%sWV(NDfZrIW_F~NPg?7T{lHk> z8Lj8NnR)N~-b?}^`0AHGm}z9Ny12}rU3YE)0It`>%b&kXguP>$kqql#8X4?tZXjo+ zv2OX#uAD52m3q`;dlY;$OefiR|F>bLq8ihqB6J1N(!X*5+i7dtW*I}RfO$sf3h)D7 zR(j^SU7>BZ5$XT{C|2rov*%TWI>7as0Q}jeJujxgSx4gFB+s_i_5mPZV6}CDrG*vj zX7^y2Ddem)4}_lE#hdzT+}+<`(DwlhY=8Azexf`gaaypMxV#Uy(*S_;w{4Vb4XiFM z2aE^gIIy$1A$?En0|e71wf%UMo2Ubl;$W^jw>;% z?edwQru3Nv3)KRSXGe)z2^s%X(rNX7l0N**qN^iDRL)C0CO^!&a0nPQAFpUiF zK(nhu&Pu~`yL@)VplBMIK(M^KzX1R&Ev$^!iV={cK&1|f3^L3Vsx8L0))LYxsJ0lh zoi^UoUrP?_wO<6DQNTMm$uj`BYu${?jt>SmiUy^_(!vT%BZJ?+|1<#r$7dzxdQCo~ zI!rpc4~wA&+0Qw%V&ovqoB_vYB_;+}T9qG)p{VdQVP|s#0N(SG(dl`t1}8m$hk}Tf zNUTP|$T8sfti)(p5_8mXd{J{eq`yj*hBSv<>X~Aa11;qWiZUNu? z`X>P3r>~z&11#4XaJ?pWvwL{2~|XI~&^rBSTZCFc0-X;v!Fty{e^ z9eoztRsNzPbPG_<2Ox0)6|UEWrwot`Cy+rRW3-(%4!6@d+jCO#5h4@x2b~TKs@DcBbLRU9ZXaHUNIMP_8us?-naiQ6f>ebQ$eU!VibOK`+jG&nQ^wK!Z2TlvekPe^Vdo zufBso{h}_IBmsZsD81yYbl~u#Tx)RFHK?#bZQ_!)op!)6Vt@KSlPbCn+EwDV6K@UYjl$XHZz@+2e zQKzY>5g7cq_4c$Qzyrpux2GL(JwSahZoNJ2NYEW1N{4DXqG!9=JuN*|4^8PkY7XC8 z+vjZ$=^ynSq$D68hR{JM&?{JohaBpvkXc`fOX6Z>IY@zpb4Ia0okFR)zgStu%P6gf zvIWEd2>1^8_VZ6Ts|%y6bW#M6p2%`qO?;x?Ns}+AvVpruQA2V74ZhzXJ-5r1AHhEt z^hFanh-v~lh!k1pP}N~kgF8U3(xm!2!FJk`(4q1c0GJ(r8yRLQP|7mQ6s|kBvKCPK zi=h5dgF8SJGNcIrNQQ{*gjpv_+JXoLs=xm287`Kd<_Q5JL@8>J2+CRMfyd^v1Z@nU znRdNqfEQeMZs+QnT#OhoV#J6MBSs`RJ}a?mi}9brrOR}Osgp!xS7hkCVci0rJn=6n zR9lQuTfghKbAi)>&B)ky?--wP`dn=>c3QBfVkJaY71mvl7^dy95s3qa5lPb`q#}y} zFV5>IT)OPa>BR&3EZ#eqG$IW|{UZLXSCL}Gh%rC-AM??Zh4W!K<^TWy07*qoM6N<$ Ef^u`qumAu6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/slimy_slug.png b/src/main/resources/assets/eidolon/textures/entity/slimy_slug.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a4289a118d371bc6aaf7678753532fc09bd31b GIT binary patch literal 475 zcmV<10VMv3P)Px$l}SWFR7i>Kls`+uKp4hXQzUTi{L8megeONtI)+S z;3{=@ad2=EwKSoMF|@>DI>kZnOw!V(boGHFZ!T}{dES3l0cbXxso3k&I%-!a;QZzw z&A#70zvjN{f3#l^#sHk{UyYqL2}?lQ>2zovwP`dO=_Ds zIW-g2hyDiu`dNhMD%NXj0QiF*Jie5QOqXI7s%4z~LC@GaGHn-YJ*khT3Ye9mD30bi zZ*G*zz;N^hfMYEK`7A7orLyE%J3AGNqN3+_Yo(6oD&QyWSz;Y|aZd^fKsO9>O{^PG zxnlMdNZTSxM&HxeYpG3*XI7f+(v@Mf~Y}A^3o=XURn^23;C=%;>N6E;nVjpB9|HnV(!8g-xzyHD} RQ;7fo002ovPDHLkV1oLH&@%u4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/tranquil_soul.png b/src/main/resources/assets/eidolon/textures/entity/tranquil_soul.png new file mode 100644 index 0000000000000000000000000000000000000000..0b5905996708d0863358a3ad150681c04bec7710 GIT binary patch literal 1078 zcmV-61j+k}P)Px&@JU2LRA_@zzfY2`GItv&dE@$5V^t9|Bq`#kzPjLG_oUb>ip#ha zpwjZN+7?1EG2O>^Wzq~iEV8x0v#cMPv)wIa5jzUEysRM^VyLZ_bv|Y;<$CmlMnwj54nps zcM@jPnBM4-U8jM*?pm+t>nbIiQ|AEcOzkL072Bx$DHe0`X_B>Oy!hL1@q90k_FBr_neE$7MUY3{r zfK9e;NNt-iy%7_1V^_wVM!U2T+O!|A6uJr?5&r(|xyN+++9*-XU!T}4^MxuQTxM>P z{UsF2DDg_!EPx3Spy@tO6gB(0OAcrovmRax&c$=mJ@ zL$#MHnKL^u7h=sMt*^Lv z@!V#AXO&fM>OgM_S66|Y$6H#PUx^LoW3Lj}vF_$`;3)56se5x3DQkCSk39tU9j##P{o=M^lAv^H(y@ulr>k_g z=O(Tw1M)+NG7}!;_Xue&a}IVJF@6|^hS?3Xr0;*ZZ48H>fPlKWRD`DH#+o4&hq-IA(ZyiwU+!X>azb2 w5cht--6JVZ?iXYHK42Sl{tkDz!yPu^KQ_WH6tkbCi~s-t07*qoM6N<$g1ssa+5i9m literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/zombie_brute.png b/src/main/resources/assets/eidolon/textures/entity/zombie_brute.png index 6eee2d17f8938d11346f0ac869f495bdb7573283..bcbf85d737eb6376c4807248efebd6cd5a8cefab 100644 GIT binary patch literal 2754 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 FV1h_zj1>R? diff --git a/src/main/resources/assets/eidolon/textures/gui/codex_crucible_page.png b/src/main/resources/assets/eidolon/textures/gui/codex_crucible_page.png index 0536f77bb12b68ddb9a326c175a75c74c10e1b4d..96460538ff672ff8ce614f5d5037f227fbf3251c 100644 GIT binary patch delta 2500 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 diff --git a/src/main/resources/assets/eidolon/textures/item/alchemists_tongs.png b/src/main/resources/assets/eidolon/textures/item/alchemists_tongs.png new file mode 100644 index 0000000000000000000000000000000000000000..60cfc0448857fb15ee690276bf0988fea9cb053f GIT binary patch literal 384 zcmV-`0e}99P)Px$I!Q!9R5*>LlD$d;K@^3*l{`R9p{@u+N|`rMtRxsVPcR{n1YbfdEG)z~5GxhL zG=g1FM685>ov>gRhKP!V3OoI^&{@pSCJ|3{xpVKwIhTQdD)2>AjwC-@0N|{38f0!{ zNoy_7wj+lp2U0aP`O~6b_zj85(NvHb=NzV9p=xRp$8k`KHd&m{V|#Wg137@Z&LgH? z;q&8N04~mNan7N&mN<^b-Xj1|N{MMUC>9q0=yqRudwOARDdeGZ4?z2}Jra~Ql~QTu zFbqkO1m_&4*#O7{<$PhSP2Cjo1(GDeS{t;Ejs;+Qck6quXZvF17|;($)=L`z>G0mp zz5opNhX7gf4sWinWOZe&4>D3pDXE&8Xsw6-gHlTT&8BuR%FS4Szr`fGV;y*iUe=kA ei4i;`>-`IO51b>w)5OyN0000Px$-AP12R5*>Tlf7yiK@^2Q1wDZ5Mp+j-tk)n3S4Kq!F9vls7?FCLSZeYEfwU%R zLLR{cj4Mf%(mNqirw|m@7-0wqWx?{YTWIXY)*DQUcqfvjB1H}i++xnT=l*55hm=yM zu~LdSjx+o#q?G!kb*#14dJ+fvq;;%?5L!w(_m*+9Qc7KabwIVU1%PEgVJ#ow*J}Vc z&SLJCILI}Me&<}nAFc?Kl zZl+vCmjKuWmn0lht!(l9*-JcGzbGhVj)cA@givYA6O#r5MxBLvwdFof`|M>pL z0f1#$0IWM3*aer<-UXg4^7_T08Rx9+Z=L?%DWpN#?IawVjI$lLEQ{RAs&P5j#90yl zVBd@|g%Cnl_I4M@a{}qO$|c7%HC-mZUZdCPnlgu@p>dZ52!bG^l+u2^#vmU7uvyv! zAh)t=$d$ca6E8T3<2ci9G@0B?u?w#GklJ2%Ht2P_3wN?`FhU6JZSR;Rn%><4FdPj{ lqS^mTFYe*GE+hUo{06@|;u|8mGfn^i002ovPDHLkV1gR|^*{gs literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/athame.png b/src/main/resources/assets/eidolon/textures/item/athame.png new file mode 100644 index 0000000000000000000000000000000000000000..6ce7512172228f4e04b9459cbe0523d5ab73c662 GIT binary patch literal 374 zcmV-+0g3*JP)Px$FiAu~R5*>*lCetyVHn1Lbq+-b*$|ZuIfM=$fi1Z?1d&`wOA+l+1ku_OlH@_F$iP$Dw`y;0yZ>09Z>X zS&Xdm@n&;zc}`?0O!4~GH~pau^i)y+((9YlEQ@G#g>Ls1Ghgu283y%KQnYwX62+=$ z@tC)P(X~w+aPuXyd~zmQJSMJ_Am!b`)!{Dl8(RQ;K0XD$G_TRMJ-ZP8)qp?OH=ROl UwDe^c>;M1&07*qoM6N<$g39NhD*ylh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/avennian_sprig.png b/src/main/resources/assets/eidolon/textures/item/avennian_sprig.png new file mode 100644 index 0000000000000000000000000000000000000000..0b71fa4ae3471af9340309311354b14ccc42be0a GIT binary patch literal 468 zcmV;_0W1EAP)Px$j!8s8R5*>rld((dP#DF3QE4p*N}sl_LU9%Mw>%Ku z?&JLt<*k7r+KwfVC7^=}4h^AI8kaQEa2>=;Vzt9tJlo~m-}w%F_riBenPgV?x5a!h zC(nT&VmDhUX67?cZ`1`qS<6tb{z!R$iaC)C8f&08>Y}V=I6vA1;CJ&zdbfSS`l5nm zMY7G*N7yj3oF8rS&+gIbKT|2?X}cpTr953f=C&^|jI3m2fU4JoVPrYk-=Ncf2H>jY zv08e&Y}$`(sWaR=FSOlJIzZKHVr^%MN+~bFz3LKecf?i8<8ZftV+L4OL|MzQQk))d zaJXB*v>yTFgvg6&yCcqi-C;LdO5lgwJ1=zoI33_#bd;Z`t~4Sqrt$Y0!^rY**-Ndi ztYwJ2nBgE~YzwMh69>o3SXP98^Tc~NyuFEnHb>;eOkAU?*F+M0hqd}Vju|ie#?bP~c(PyF(J@MpMzv5^cKIrB8=<@7khc zKX?w$1E25n{r$erBPJ&&sl?;>+8yM#jwE&Eaoa>;SFb@r8 zIP7D3d5Y=fDTc#73cI=lYRm1hGj=i9AfVVQWh{poS@cg6IxpZA%%xTC-0%_^3ZZ8U z0IaWU5RK(zSBF!K5oB>qGaMWzH8~viF@OIITvFhg%1wVe@r4w&z9+1&Yyc4G_cC$2 zlP}*6WvI_xbAO@$gdX1||MDWf2d4nM&2HhUS`74iQ3qcD(CvTD1Q3noWSeRgH35LB zkDs~qJy7fIgNQH~f5^G(VUm#%(pr(;U@P52AqKP}iA+fXLIFt5&NDOaCBBdXASoi; z>zQMH1)`6hHViGTy{9+WN+MG-X5hMVLA-vK$L9Aix_^{lbSc5i_!}^+;%l=BKme@f z%Iy89G{$&vECA561yYd__N%r{cvEZPY?G(~+xsV^wc;NEtJPZD1p2*3&$IIYU7p}1}JAg)!!gZczgc@fXkhB5}6V$E{l=Esl$QWV;9j_PEG)3 z4)styymFc=1F%;zB3CM^O6qHgt`4V&#&U9?8kgzfZ#aK&fM-D6oDXZs#PR1C20a?wYV%|uXIX1{9o!f+%N;r T7NLJ)00000NkvXXu0mjfj^8k$ delta 370 zcmV-&0ge8i1(^eoFnYC}^TS_5 zvTB?J0>W5}=5m(vI^tz$T|7mC;wu*sJ<$|B(G;SV7G|Q7k$-%47=;Z7e6*;ylDgq3 z?<}YL8J&{}?ZA@94hM?>+}yfxZU!l2%fo)BSYbElChU`kPHfuke%XZ@n;>0;1xLUB zqEtD*Dgm&)GL2t$>0H^gkL8^JcJCWU&Mg4ysTcr>yds5tvUo4GfvUBD-MdEpK0_fJ z=Q^VTqvR8LMQbt(QI|ox_yEBC>KtmLs|!nex21p)15(&03-`<<0C%rV5_x4PEEx&$ zWQb0&Lh9m~{>>w(jjoP7CNK~=-tz$cAEPx%1xZ9fR9J=Wlrd-%Q5eU6F%BlAa(xEQ!@CPoC}cQH!BZ%J7pG}3U&|*7V78}5*LloNQOY6ifJSU%6XES=n&4K+!2%9MJJd0ZSQ>_@Bh93 z|M4IsBqSu{KNATmu4OV#t2^NNem&x@-P(Gs78&gwt=*k79Cao-);r9}paC|&{o>V~ zIe38saPz84rf~1Ln0@592d`x^&Xdw(0BXf&w7LTa;Nk5Q*EaWqB>WvP7P5|Rm{{!= zPcL@?IDhdRI~yM;Hc#kb|EL3`mzMyjZg2Sx;2VK$b!e0; zq?eZvii*{4c?S>rJ^DYs^C15bfd1(-#D;_cgra)G+g8Ur8P|#G_7-j| zgMN?p!5#pLHcvDb_v{|-x2+BbpBuh9CxQl$giNlO_imyaCU6`@G#2;zhV9o4(~B%u z%p(aoNFvw)V=OV literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/enervating_ring.png b/src/main/resources/assets/eidolon/textures/item/enervating_ring.png index d29019b25cc4e45ac24c6fb8095cf2a077198083..c12d58f450de73d05ca3cc9dcbf4de8674181632 100644 GIT binary patch delta 513 zcmV+c0{;D>1E>U$F@NGoL_t(IjjfWgYZFl%$3L%0Y_L7r(oD%ga?Q|yUJRJUNwA}J zO9nf{(Jff(lF3f3n^6CNLY7dwSjcDuI|zY_snJ0s+yyR3(_$+@xSAZ#p}Dikx#@3t zj~~D9=Y8MzJ^05G?&i_tJqd6$kc1L#R3+dW-e@$$crWORwSPd5;wgEoh z|A2by2bwYiz~qe*usK{ImDpq}8-uk!5CKp~>auUfS&4$C*Z|bb0RV=hu)Y&zZ~Kt6 z9wC*>@bc+vYJZ=8Qf@Ux5I|J|T3SRT zY>T2MhnAov!Wx~57MB_#*Puxd3NCHPp}d2fG%75*E94sF?0%GSDWj^kw|H06ByY~=HfQ(RFgHyo+OpHfF#zsQHGkBtRZP7ENo+4fasyVv zp8y1-Z;b74W9lU=z0oZmk|)?n7KBLz+TqB&9hZI7TEhT5KEIPL#so<1x=uE4aPm-* zgcUNXYOh^wc8Zi70CCwzDx%?+jZQo>%B(Uj++e^Rn0l$(ITSFvd8b>|Fez7>{g3Dz z3^dZk7^#Q`KytoakQ_+A&j^62B^66=VCfC~^6#DiiLlaR?peVr$CL;wb}%pqz~$YC z0G7Ol+}R?Q-r)S`ma1V2z^7JQF!ul)$j0&{0Od-P*OzYqZt7n>=Dq;;=x+5h{}25D XxOI|vh$i9;00000NkvXXu0mjfd~L1? diff --git a/src/main/resources/assets/eidolon/textures/item/essence_of_crimson.png b/src/main/resources/assets/eidolon/textures/item/essence_of_crimson.png index d2252a4a36cea7041fcfca1ffefbb67dfa70359e..581e4e343160cfc94fbb74f034d05c2654a99c71 100644 GIT binary patch delta 384 zcmV-`0e}9S1E>R#F@Iu7L_t(Ijm?oePr^_bhM!X!E?u~29GEao7`P0E$f}bo2@Guf z0o+U+jI)D@f5M%is}lDX%ua e{>JeGe?DJCB9PG6U;rKf0000kLrXyy4{Cov>Egj- zKcH)Wr*qMvOGm*@!Ttk90>wjwN-HaY%Pu6-LC03pJO#a%89u)EnRn(J_}6M!LhkE1 z_|05T=BUD6$X2scEX&bFMLNZ@RFG}39|;|c%Ysc6WJ%;WAt84H zRP0JkaCbkTH}M!urvQ{hj;qQMH^s9xh!!=U264v5obzNFXXbLAOp`ZFTKxfqlpt@K z+`jbycplE^;A^@vXV5961WY^}T!58%Y|Iz+nM*c^(Kf5O*|gFkCk~1pdha#=-_MW zp=>KoJ(k(vbk)siA!bPCT+8zrV))A9b5GDo!a~?f2uFv*Ne_M SX&dzb0000l0*?cbF@H%(L_t(Ijm?oUPr^_Xg+GXCD)m8Wn<4@shQMNi1B-EI<6rs% z9NZm^|3IS?f-xGbB`*&eN%I`EwSkJ0iD!9v$vr3Mei#0=4)%Th+e~qrxn!9*w!JkZ zHy|S;(`*iN2#G&*7yyyH0rL9mPCmI1VB8VDh@lz+02+aPNOs5Fhw*S0WC zgL=bdFz6zL&>I0s?Zn*a?{RtYz;rTW9x6^wy8uilGirV{4Jl^L&6YJ686+hIHoSg44FiYQqoPmixiwItz?!f)947-QsNt~B_0>Hk%UnO&cY~}P z+ty!!2qARMucmuv>u)f~0$s(imQohh+hol@DtqTY*9YWPn6^6Xvi<-7002ovPDHLk FV1lF4q09gP delta 323 zcmV-J0lfZ?1M32iF@GgVL_t(Ijm?po@=aln$2jpnoc5oxZ67gAdag%K4dha5P*5EX+)trU!FfudWlj>Yzb`B zLa#_WiGvq<1wbtfSm>35T>?AdIH|h^8CJJ|;jqg**Sx-c;SbSm;WN(#VAe%p8;sIR z049?WcehXYGd!{-_Fgt=HbSJ7rrm0~-|*vaCD`4@x+siNO4u~^yAS_Z{+|E5z5y+b Vkbvt16OaG^002ovPDHLkV1kwbl5qe4 diff --git a/src/main/resources/assets/eidolon/textures/item/holy_symbol.png b/src/main/resources/assets/eidolon/textures/item/holy_symbol.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f80fa46517c2c7364b0f86b82598daa242e0c2 GIT binary patch literal 614 zcmV-s0-61ZP)Px%AW1|)R5*==lf6q@VHAg-n}p(cqp2Z~AZE&<Ua_CZFH+c2#t$l!7c%% zLp!v8fp|eE*zIBy5Hc2|LPAYirB)X|NI;U?S_=&Z^?Eu;uJI%EOfQGu?>X;z&v_L( zL@w=@V9*Odt>*B={H=7--ZAFVesLN}5$8a}IS{9jlve(~=9Zz535e53%Gvgqdlu)Q zGo)oMWCCL9s^rpsIbGA_bWM|7+ApTAN+A=t1MvWux+>!fWr}md02tH#)T`Hp>Q%v* z?gyYaH_Z4#8BgVr- zesu%j9NKvM9$o_g%F9K!g_LD*R@%flwC``BR6&~>xu%=CDrehcV(O~cmUd(A?R#Nc znzU zY|JCGF^|}mCQc(MP9rI{rAaG)Ti=m%TimJYKNYhx51)t<8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/lesser_soul_gem.png b/src/main/resources/assets/eidolon/textures/item/lesser_soul_gem.png index e26bdedeb27d0313232dc31aeed52839201fb926..a9e518568dd7eb951cce68e57b7b6daa5697877d 100644 GIT binary patch delta 326 zcmV-M0lEI>0`3BkF@GpYL_t(Ijn$GrOT$nU#eWe&rv$RJLqILT4h1O=-MWbm1(7bn zFJN)>19a*t1P2M79L2@Wp}|GksZ(hYX;WzhF|H|C7vVX?KYfXfs~&j6IrpA(-+Ns6 z_fV3G2YXjymIqG*F4{+l9?2|vEg@VtJg=S*y_T>FwiLQB&wpI6Y2Z&op|}PtfAbkE zMg^;2i~6<#<_efIh2|X$-+m7OsJMcB_kqKW2^3W@Q$Lzx0an2l$K_p&l24@?;GmHi z>+Ecec${QEy86jCFiJj{De`IPJO`mTXF5bavGdZ#IR(x zmCM0MHgDeJbU)Qtfb@j^?YRPo8!zPL^(r}i3Ct;tYlD+!?X%|#iCdM;?Mq7&HUAB~ Y10;xN=c8QPv;Y7A07*qoM6N<$g1n`Y!~g&Q delta 318 zcmV-E0m1(60_FmcF@GRQL_t(IjbmUK@_-SaWLm)1|H%B0&u%fSJXMHS4~pjhmyi7a zziSr+f4}|z|K%h9!_E3p3}wQld1f;|1Hl{+ zBG15}f+TVHIs?O41X%(ST$o95N_80zbD9# zLB{(zLwfB;hUpCa3`!4#7~Ea%Gd%gE4pns%#Q=;jknw&Fu@MUHeR_w}b_@e9d_Bc5 zeJTS3!~EL}L28N^ie>n2Vu)e5;KGZK3_BkvFs!?EA62u_U54qG_%IAW34@zgmoqXj zF#JDw8^RA#t2brP7Gh^$Q2EBNbB_$e#KX-nHE@78RjF%7q9hu0&4U8~0KsKvvi!8n Q8vpP)Px$qDe$SR5*>@lD$h?VHAfSV<1MsCXpaFv|@=L;o=}ju%vWKm*}84sDD6LFOD74 zshgmaqo6}6u9C&g8Wj;KEtlGt2ud_u^Ko;bH{=${+o_ktFAz7+bm0B{&Uwx`FFfx^ z&#N*$ugZrs-iOR{OEc8ZEdZJRqPIP&^AEW!YtokA)@SAM{=&T^-kZis&SYvaNt6$q z6+ROP`=|Z2T45TR#CXt{leRMi`z@IoiGC>&gzNCpO9H*W^W+&9x(54)(YN zZ2($ak%^SbuiphKIg?N{NNh+Uo6!kHgYN9vj7}n@lFjI>92QzXmKIl}7FXo|ym?VK e-)`OVDe(_10JktkhuFse0000Px$rAb6VR5*>TlQC=CKp2J}HU+n} zT@bh0c` zJU5}^yNfKAG@U<`_FMVwo|`ZTB2KSnOeeqT_$~kqTcSFu zWCgpa7bNuFzD5lKR3r$8lQnZGgVj$~MS{`U4SSwNuPcboYpdQeU|D$=3?aO$vG?-n hM)O~5(@*x_^au1QxGHu60u}%O002ovPDHLkV1i#H-gN)~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/oanna_bloom.png b/src/main/resources/assets/eidolon/textures/item/oanna_bloom.png new file mode 100644 index 0000000000000000000000000000000000000000..3ed4934aafaff7217e8a9074f06e3f2666a00fa0 GIT binary patch literal 521 zcmV+k0`~ohP)Px$!%0LzR5*>bkuhi!Q5eU6S1XZ&oTw1IgYpO*BAh3pnZr381@WMrij!oilcVE7 zp>&C(lP;1iEjUGl;&M1R1qag`)Rgv7Y04EcG*HO&9A54`X$ube!Q*|r@BM##|L=qU z6|0LKbzc5gqSeKYQtchJvD{S~%Uz|~JE~kOYv#-1wYwq0?5dXAWONMjbPB-e_&Vhp zbkv*erv|`WnPvxLT5gkmCIJv;1z}bI=x36a+r$pWe{?+u5c;taW(87;4>_cq+rb!8 z4G#TS6&C7_i*E`2JJr|wqwlAgJU)t3)^9IP8gPQ3^M zTqp)806C=YxCpa?ZwUq`vRK>TL?Tb8>>UmZ@fkoFbl!Ve_|M`Oqb0fES3D#W00000 LNkvXXu0mjfB|7SG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/pewter_nugget.png b/src/main/resources/assets/eidolon/textures/item/pewter_nugget.png index abe6f7fe60e83b2ad1e4961e861096e1c568ded4..2ffe1b95d361b2eac68ba18884921531182aee31 100644 GIT binary patch delta 201 zcmV;)05<>P0rCNmF@LN{L_t(IjqQ;!3c^4TMW14sB0^xh6p~^KwXn@0va|@HtyUYQ+=2>kAV;4Or%AcZu%iR*J5qsWoOc{)|xP!1JHFJ z;L`gfUI9Rs?Q!oH0Jr-Cr6R0t{E(+XYVO|%x2`rTyU(ZtLskvjQxq{j*E3z l@HR*?B|q*u7I@$Q1H=6b`dc+-eUoDV0#8>zmvv4FO#sAtPD}s* diff --git a/src/main/resources/assets/eidolon/textures/item/raven_feather.png b/src/main/resources/assets/eidolon/textures/item/raven_feather.png index 24c4b47dd14d3f525d6dfb8119b88343add07489..f70a2e2d72bb3ae5ed7603f4af9fb7f503cdbe78 100644 GIT binary patch delta 312 zcmV-80muIG0^kCWF@G9KL_t(Ijn$GdOT$1IhM$PS_1e%jw8TJ4v5*D_2kBHNm;Q+U zBf)>+pufP$#Yrb|aMFSB0VBsJ_;> zR~MRFE9eh~%5vPo{^i-Ju~x7OUY2aHDjpmjD}Xo{1F%RFntz=xwzmgBIC=qK>nGUr zd#Y5fvPcu=QBZ*EM=dQbT*32us@`---)8_+8V;7@=HQ!?b3I7oJ1nG0mb@XPNvT|= z+3D(f9E_Pq0T1`rnk&p;8i&*@n@Yn0VDkLL>*TXtA%jASD$5cL&!d2890E|Y z>;hO2wA%Yh2r-F}rUr$Oj2`cPeQE<>*KX@ywj<<5U@pso|CbM^Y+x{{FrGR90000< KMNUMnLSTZrj+Z?E delta 330 zcmV-Q0k!_%0`dZoF@G#cL_t(Ijn$GdOT$1IhM%Yq3L&w{px71-O@|IC1}qd8Gqiue zu|L7Jo8S*{@Gm$zI=Z;%CMYO4WUwVdTel{*6s*%Zh(}|r?IwQHao;@;-@SM6*QG3a zu+eOZul42GiR9)A8qJm{l#8kT)1w1ru3#2CEm@h>+}Ya~0Ds+}1Hfb$QL0th+I9eV zerN-*^b_oQzQ||>lVL>M4^!~2yDY`2E4ZF7RySPx%C`m*?R5*>Tlg(=rQ5400lT1t6&IElFrX!(^V~8ZBMJfq}f@tfa-HFtdg>J-+ zJD2@8#D(a-E1^q4Eu|o|0c%xEu?}fkLeof`iuq`W8J>$_rVYiF-qn5Y-E%ni-231k zLpgiMj?Dwm6Y1l3>qMS?b9?GarTP_s(!t(&g6!Bl`b9zQ*pUFK%p^|LK@182-oAMX zKsc-_uG+sr?>8^~N;S!3tRDpB1asv8Up=zOzt5>P?_{dyDtD;Wb|`p!)NOiNJME#Xuh zQlrz%-Ft{(T%*yb1>`C~v-V4-GLsZ`OBC}qRx*ZZ3EsW>L@{qOaU%=B)_RT)+sj>3 z2>FRqb=X?ZasRO=Jw0Mj%-h7%39Mv{V%`Qo(*)NiX3rB;_I442f^xxO=2j{wn3^3A z@=9f!sBUmUT}o=#9Mcz4zB2OO4nFwGG*H%{9K1E_tj)FYRW zNJ46qt@j15_o;DAOYmgr1=}BAqG^Kt{m-=9C#Y(#^7Ht|=@{v6qV$A=zT@cxt1D|b zRVOg6UU&RzrPFD92|#T4veYzzIh3H$sL|gWquDNz8l7fyW0|OKa9G|6>fv;q6@a*P zl}@KEeV6@ZDIeJZI1WS!2c!w0OzLK)+3Ukq5uE@07*qo IM6N<$f)ZgMe*gdg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/raw_silver.png b/src/main/resources/assets/eidolon/textures/item/raw_silver.png new file mode 100644 index 0000000000000000000000000000000000000000..f116579a8fe7c4121e96839cbb8baaac732d0056 GIT binary patch literal 603 zcmV-h0;K(kP)Px%6-h)vR5*>Tlg~?&aU92AUtO(X&TX{$xCui|a3Z*iNl_pc9b$)h)I$(LbPLZN zI_WLKKcI`ax~T{0WTmW(;bp;o>C$Jyrt=y2tOZSF@pM@G&L_Lo`}BOiJnvs0zF+u9 zi1WknWEgvU7nSda#`$xn!zc7|LC#;^tXvcro($9D8$vB4jKP5rUZqd|w6;Dkzdi1L zp_Q^y#3TS1(-U*->qnB{cXpz99RS3V+pMk6-U9#B$k2?W}4H4urTF zxFtyq6c5S(?CVD?EzST4H5$j_ardK@vPSK!isBEF%B=0>7MsEr zt&}zHjXgC*eGz$1uQJN=ySF@hI8FFQ7XUj2m|b{fN+yOU!$xFonfF_1fD0mkTV&v;Z6wcTK%w$!*3*0zA4uhT?T_T+K`8gt~#t z*4Iu`Ybup|4o8QNKhdb9 zCAPTK)-I@DJOPMf?Q1R#I)6J)!cZ87pHmtxUASl*m@rKkxD1BKs*@`T3~c-X+)NydvxA9$ z!kwY36AKH*xWGa}bZ|1IVn{5f5$b@{a&re_C7gv2u?!c|2_AYDU8&HND#xKuI%9`iI7lrYqtdnkczKhw=?lfv zE=DMv7C66ur7LG*bNKpjkIvZf;HWZLf5Pp}Bc{+W>=4<|l-k(=rqHOgZA_tgaBDF8 zec^;6x|`im*>H6~FsuNj#Dr>8NQuQtE_#_R#I)AZC0&x__KWBmm-q4kDN|T*Kf|Emp&cfBy;1c-@ughT&8 zv^Is1YYl=gW{2J^IFU+Q(H^0y4ecyZVud9+)#cw^4O>lk|!+?#F zwSr1o6{qnOWj#YRn+qiC5=Ga+S9=El3>=5v#HO0fp?Idq&wpaLAnG8k6|BO#Ch^#} zvE&7oH>Os|(YFNj0ox2Dk?*js1#&ETK`EXG;sq?T1{Ypct@d$D;=T;fE`?X@x5m< z9L+<5&=;1mTnrHPuOPx$UP(kjR5*>jl1)njQ51%sO4Rg@BNLSqlZv#ckaj}gs)h6iT=xt61JOGASc>4s zBCy0Uq_J@>lL|5|Vg_>j2!h_#g?pa&oO9m`f7Hfr3#-|J=bx`%o&#>Jfe#wGMox`W z@4eIP4Y{-W8vv1Y@R^aKT-jsL^?0ZcLp7VL;7TbU!0pC>oEi`A%UZ@;YT$Q1Dn2S>`~EBM`AXG+H&b7G_dSP_DR z5~bE1VM=%T8z@5HNJ&nOqo%hoUq7*C5fVz2rq35KrmW?FRYF^Uj$>~RSGF+o|&cvlyvyqOk?5CGJB?*KG= z-}%qOFqeXw-a<|9Vt>qdYMCp+g$B2eU2>@yH_iT9aG}at#`AyJzv&CU%APr$n$6?@ O0000+65}U5PwEp!35-oqe03#mp?D zGdBw6Iy!kVthQ3C(JL^znsTH3mlZP*9PUn+mss*nF7?ER$UTpBZx$o-(kh`7h)udr#w|iSXa|2^vQX>VFHj&HuDY zqfOZ4z-6B=`}eS@A8zE%m&~*I)fFro#+hXLc*{=X*uVSRWX#-Q(O3x%`GM=qOmUJ!2kID|Nj5~`ucypYjpGf7mvcPx$YDq*vR5*>rlD$hpQ5c6G!=+7Ix*vf_gK)2)4dD>dC8RB|p}>Y9f))ptHg~7M zL1_qFf@o+ks4=1lv}mXxlO_$!bW;2WZiC&E-P>&n`c3D&?|Yv2>%f1@0}x3iO}pdq z=)^O6cZ(UbE(s&UVXjOzz2}-Oo8IFvS0-U(giQc;w+-~^FW6|tNGfS2j0~&uG60)P zh5&f2L*clNr1-e4y%5tw1pGNlU;=Ed}B#2luW3faQ%@8rKiv zo!1`l{PvEf%3`3FYR#d~E(gGZT-^0}?R5bN_$QGR-;WhJ0Hw2i!odZe8dt*h)PQjB zyUi6aF+N4WKS{v9CMp>9{R$Wkr)VnD3^6@~r1-?zUVB|`&Wqm$2(~R)3dW<3fB%)> akM#jnOm*q2s?-Mn0000Px$EJ;K`R5*>@lFv#4Q5eO4M(fCxlLQt$fYLSs!B)1>MS(8b_yBF%1ucSnfZ7SO z5h@rLBUJ8`Ae~tV{eg5K2q(~SS|z@~ZDGMo_x1pF;BG$7`Q3B*F8p~#RKsK;CsgyN z%evApg^ji+gb?C+Fgr%u6Q@RBsKE0-!=-$gosA`WF0{H109t$zfUWdC)1fN{caISz zU^;XGIH=s>`LA3Yl>jIn>%_G+6498{I0RT&Ucq*(uV9*5XAHpM-VAh7)g{1Ou>N`3 zB%jH0R&yj{tLu=@WVxz7u)3KN5&)n-8smEtY{#PKg4t|fHX8ugj)m_{=#R$g1_1hX zMY{PL{F^7V*JL3lv_y*S^T%TXNkU`x75dWw0IguMB;(hk|Dv$ z|58PFmar?GdB!Y$@6cZ#)7c+)HRzcomomoY9%BH?J;`3i!oV=^dP3$)XZ5o{?=X0} L`njxgN@xNAC}D1q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/silver_ingot.png b/src/main/resources/assets/eidolon/textures/item/silver_ingot.png new file mode 100644 index 0000000000000000000000000000000000000000..5a3358879e426550f34bc36b7def1b9b780190ab GIT binary patch literal 411 zcmV;M0c8G(P)Px$RY^oaR5*>*k}*ibKp2I;K!-XRg<{$YMI1CmXqUPw#j!&iYLvE$M<;mbMSAJ(KRolYu?~I@*Cv) z^mL(bbi8`WkiHEFLJRY20Hj97X!p8b(?Tdj8ibY?H&GHY08YmhU@)ZP+;M)ija4-z zDWhxN#_CR}h0}3E=U_-MytuX0e}dC-$>&r6n)V|~LKY!PLJr+sT;GZoVh8PBmvRmA zIhAxW4uCcr7Y&TdK6q;G^Wi@CgHze?68(@BO%>q!?gl8C~;~RF;{EIT}_)K)!-dP@$p!AKo7Be}w*)J^^);nNG3J)-3=4002ovPDHLk FV1iG5vLFBe literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/silver_leggings.png b/src/main/resources/assets/eidolon/textures/item/silver_leggings.png new file mode 100644 index 0000000000000000000000000000000000000000..3bcc1f2ead2998c145bb56dfd1280dcc44e4dcfa GIT binary patch literal 308 zcmV-40n7f0P)Px#?ny*JR5*>zlD|sBP!z_0inHkCU#Lz+Gw33nir^EJZiT!=o}{3!kSRjmL3GLH zkXAC3BoNbPO34e{PLbxGo06@5{|!A@h};ww&E&Fh(EtYPovrU%2gOE zp)gkJ)tjr^;bY^0BOP*obpgQJ`%l9^zdYgP>5i#ZF8~1Z-=*+Y`P!IT0P5znEbv_i zfU!MgVD-BJf>{KB?>c`A^Klfm9=-)Iu=*nI@%4?-2RJlh4eGpudW3CNSwdPCMu14r zwk&|&>DlfCRhAIUBJ$Nj6o&B!@GShsS?X6-|3aJpKePd!~cH|xh2{R9$t!> zYunoh1P_mH=I42K>y<@p=VjK{-}90qB4(aB00afEHU0kX;N9{4k&1JTHS^)!@BJl8 zMBWxkHC*KupPrvkQ~K0|83>vMmhRn!0g literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/silver_pickaxe.png b/src/main/resources/assets/eidolon/textures/item/silver_pickaxe.png new file mode 100644 index 0000000000000000000000000000000000000000..180c34bf4e017ad3dd7696d92ed51cffddf91ec1 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|o_V@BhFJ6_ zCrD%*=d>&DTi(gmxIU)b~N#OD9|>;C?)e`?3#A65Exe_hIfdVk}K|0U~+ z3J!nV_2BYk_JVz_-h9ndT8x@+?Br?td3(OWor*701=lmaIB?nL%YXajIc$o4l5N7( z%M9+=*ECLS1cJ_pv!8_K@bFJBH8ubOmZM*cHEv1$Q9s21GMul?iHBWpPwI}3FSH+b z+6D(a`6$J(S@P!j7Yxf8UzjPMo|(P+v3bLUv- ui1ixG-e@^nLE%{19tY>X*)?aUFffR4=5fd+7We^u%;4$j=d#Wzp$Pz!(tt() literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/silver_shovel.png b/src/main/resources/assets/eidolon/textures/item/silver_shovel.png new file mode 100644 index 0000000000000000000000000000000000000000..786011b0f4620dc340efc50d07ff3d2d683d187f GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|ZhE>nhFJ6_ zCrD%*@aRhVd!pe#4-m|sXOpm_{s)t1mE;#?=70Zxef|G`efc04v`UH+FZTmAp~gvV|ltxwL9l#r0vka_GSkH7K7 z|DS~B@UZLcN!{`Bg?46OTb{99L!!}2v%{hlvpWB!CnO{k7>Fdz*#DRF;<+@ZXA@RQ jGH0A96n>h&iizQzd;C*p&aEGTo@DTJ^>bP0l+XkK5bk;T literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/silver_sword.png b/src/main/resources/assets/eidolon/textures/item/silver_sword.png new file mode 100644 index 0000000000000000000000000000000000000000..3619509512645811c4d6c46cd5ec2b20c89d7deb GIT binary patch literal 344 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D%zg*;sxLo9le zQxuqAxU>CHcbAX(JoWeg|M5Hj|KGo8?ZJArAk+DAJLVIG?1*A#N*48*?C%bo|brKWbo(ur4NY~ zb$=zAr?eQwoz>9WQU8M}`TrA*wxzkRCGXYNGi{%#@*q>~m;GV?zAr19GT-@x|6i|o z{BQilYY*x_p84w{d5DAC;`I9G5_~Zgrwblm40i+BG9#_#UwT3V+oEZ0{D;rk@=Lt4 ouVM-J@lfUp0Q%(a`2Yrn`L`BLI>+ZM3=Ap;Pgg&ebxsLQ02+sv7XSbN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/terminus_mirror.png b/src/main/resources/assets/eidolon/textures/item/terminus_mirror.png new file mode 100644 index 0000000000000000000000000000000000000000..85cd1f0199019c16fe93d3665b9a6c915d8fc3aa GIT binary patch literal 633 zcmV-<0*3vGP)Px%Gf6~2R5*==l3hrXaTLaXuXGX7MFf5j=CUm9qEyD_8;V3D7uF_;SOjTVWR!?O zA}l|m(x5KV>Lv(b87h&X)s@3J6k%#(#)M3YIm_0(dZmjlPZ#pOZMx`O9sbXAp7Z?A zIST)YhQ=n*^QVuym5un8e~}|g%b50L;p%B2?o9yRy?vu>5@={_5?4QuVjN{SG~qco7`VO8FsCDN>82NG&$3HAxs5qRJ0+6DEW4;go z7OTY&{^%JY|9AyDdD=gvq@|@Z>78SBHMV&M05db6xZU1|ULb52-Q`9ufbkE9vr?*W zTqWq4#a4QNv57?h>duwX+ds;X+l{^Mvf*snKcxUDu7UzXIoGrmbLSHx-phm~AGv?I_WZ*C6#izlSL|BiRVnhq#csi|m^(=_v6q(Ep1^ zmXisj%*_4RfLQ7_x>k}10Juknu$d1N4fP}t3bW0WojAkw^tGf8j5~;Y{z+*`4Z(20 z0Lz`t1j7NoEG$!TF`rJ~UE+tH5LVSL^YgQ!X`1ZZaZs$PT{KM-P17XUdP=n6deMgK z<@a2x#ET>x(!=gSs;g8SRpkIo`8~XP?MKEVFc3-FIAJAL)h@Ab;Z3BCtBa36vBB#! T2;2x|00000NkvXXu0mjfVB93h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/unholy_symbol_base.png b/src/main/resources/assets/eidolon/textures/item/unholy_symbol_base.png new file mode 100644 index 0000000000000000000000000000000000000000..382686d99f1ad6a96db7fb8b303e9872a84a43f1 GIT binary patch literal 555 zcmV+`0@VG9P)Px$_g)o-hEY)#}8= z2ZL7z0J&VAKtj2^&wSsE^gu?cOfzZJc)TtRi-Hc7dnIdj#)aaFTIl)WSdjU^1C70Eoq6 z#<_1b8w>yr4lAV9Y%o)wILWxuKYA}LG|=naC|980qb^pf)yblV=`XP4hsFfm02k-+ zvL>vxwe`>hy&}0>UQ}&!b9?Cu5I)Zw{eD+Tcz%9SxcpTAhl#l?B^YroM-?5002ovPDHLkV1n*W{O14w literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/item/warping_mail.png b/src/main/resources/assets/eidolon/textures/item/warping_mail.png new file mode 100644 index 0000000000000000000000000000000000000000..c87f5ebd026d832ce819f18ac64323c3f20bad0f GIT binary patch literal 568 zcmV-80>}M{P)Px$@<~KNR5*>Tkw0h}VHn1L7gW@c)BI_S4uO*rDUo1_!+}dFBq4)~AzQZ6PHu&e z7Fsg3rO++y651{Z{s^Vj7^UenVRgl_$+j@8u2|3I zHA>TIeEx_qb=lnk_OwZo1CyAX;@BvQbAa`kEvnvgszVcZYq}%>+`5~#-c3DbzkdQi z-E6QitMa*f3c&4Ph{9Qgs7Dd|C$)!kYr5pJJ5;^rymiN^3`{be97%bN?8FTKDt(h@ zMwyM9Du6H+PXKt+d`-c%EG|^HhswYdYnubm>eK~Kq&=>LEr1uP_hb`4;Ap}51{|?bM0gyv+E_+RU{s@=7rszB@zSdyaWE7*~|AJpnNxxzUQObw_0000}M{P)Px$@<~KNR5*=|lQC;rQ5c4wW3SmHQBsR3SSp65q(e%EyCmR{DR?uaWXLWAI+QMf zZcd%Dh}(s38ACIe`~V>i5eGY1l0cG1p%oiYgNwv^PY1oHdhZqcPUn1l?{nVsaSlvU zrOi(DH&oh^N?Q)s6WgakWdBae{@qlV@Pq^&IqJ+v`Fh+WF6P(?Jc^^v47{0}4gwV9 z*w+AH+j^#8fN+9*qnlhR$nJSY0fr_8u%Wx>8FHzhccNS>NGKv`)}^#-TOWV$b@>W_ zci&%;%e+*^P(+AkU9$D1^)FE_6(q80nX|%!>(*z52Mn`}ZfG>?Qbtx5 zR5EQyr~d7iG|aNg?4@wBgpq`ky|*$H5ki6NBvv;~zj{wCUu1o4mIDW1eQlN-bCqa9 z=gEtw=!Qn|I#=3d^SeG;S6NCrk9M-eYE4kUbndLxD!$lLWB3X~M}8+t#o;gxF~uo&o6Ka?riM zH1@2px@onxXE!R_H+Hp2>R0apTo9*xUd39zr~v;f7bq6@3p3lA2s5)SVsXFgkGcx` zOFm+8KeyLCx%VMR;Q8RJ&QD80Zm)Y|^YH{ZVa~K(5P-j?aOcsOUt0?R0000Px%Gf6~2R5*>zlRrpXK^(_Fm!<_VDai}5w#i^>nm>z}#yA9oh~Q>I2Sps53bjS2 zpmY$2Qi`;6%g`ZHC$UT0u}~reI)wbu>G{&y7V#BD)S`k74P1vNucmp04juZ18}9eJ z``mr+%fbI90gz0kvANuw9_-6zz?Yq^!b2PIQ!!jT|qMU(z`g2|~EcW;f;(V+-M z@k@YkBq-F1W(s)y>L~ygo6C(_(d1%go~4CR0$wKo_4+q-y})8-9<`#$a3n~rb_^h! z!{&06Or?KD0J+t5h9~;*#}ioTkUgQB;@SP#Up_1s00?-UEG>*0x3#(4i0HtO zu2bC zfwAZ`YH1s-oMj}IHTqW5Oigrlc4$^MTv&eZPx$5J^NqR2Y>7!NE$yFaQA1XhUEXl|k7}amWVAAkZBOr3`ji_XYcnUi_0@yMGvX zu;@j+?G}3I#qO}$4F^>d(+)P)MBf9H(*Art_obAtRaL!l&L4}S2%{*PP)hqS2!gxW zZ1y08NI2(tmSro15b}M03IKRM6GA*mDc@VIR!1pyNRs4*F}A@NcZS2^_}nmz3(k42 zlsW(awANaeWqI6gx56~d8`w0>ZteXrNM0ssJ5*Yz49gcxI+ zvMi5jn(kfKy(Wa*o=&H4gAmeqo;OxX{Xhu+FvgdTPx$gGod|R5*=&(>rSwQ4qlK-`TsX7hE#Zo?r`8xRKmKL@bw5wyTUbNazLL;2iq+hJAR7+qi(s zxQ;3$g1XXc zjT+zaZoJH~lB>>V4+o6yOg)j<4L3N5ZjhUDlFg{j!!7N zg7i@4W;q$nJN2Swi zyG(tfz1ZxOzBj>ne8L=-cfH(y*16TSN$dOzZjQ~;04Tu#00000NkvXXu0mjfg_p;w diff --git a/src/main/resources/assets/eidolon/textures/particle/burst.png b/src/main/resources/assets/eidolon/textures/particle/burst.png index 990356fb2e7bffa5ad656bb5e12c2a89f89115a8..fe6e417634bd560e70eed3e95067f149ff3ce2e8 100644 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|CVRR#hDc2H zJ!hTO`wMk8xh|8O!EUT@ zQtPDE$>d3nldh}0_xxpglEc~N0jIc4a&yomo(%`2?KZgci`rk6-}a*5kp8iVq@pqCwzC{@28Y6Dzp46hZ0FwjN!RL1mx`F*cxU%?$tyi| Qpz|0!UHx3vIVCg!0KG_4XaE2J literal 454 zcmV;%0XhDOP)Px$fJsC_R5*=w)6HsBK@bJtukXynMAV%Mg2sgkW-o#Sf)60L^d)rXL%8z|glxpM zPap^)ZrlW2NI(&H{w6U_#yjm|&K+98g3Il$uBvnDRCj?|t5`uTr3}6fYdJf_yp*D~ zt_eJjQy9fpa2ikWIP21Y84?Rl;w~QHO8gxz;u@}EJ-)weoc{=0xQ)YI*U7S9}iMsFUZGI;2`~8z^zPcGPK=AxR-c=cPTQ) z`LO6M?nS{J+{=_ot<^aFK1}dlP|rk*Pxv0%yNTTiLxR-fNA@+o_4M8+xW{w6&VFAW w-M?cLs%t59FbLK>Fhg?dSla&rTcFnW2fLz>`DP&%OaK4?07*qoM6N<$f=PJKzW@LL diff --git a/src/main/resources/assets/eidolon/textures/particle/flame_sign.png b/src/main/resources/assets/eidolon/textures/particle/flame_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..339fc6cbdd9719d7265576c4425ff9252c624d68 GIT binary patch literal 466 zcmV;@0WJQCP)Px$j7da6R5*=Y)3HueQ4j{;?_93nvS28-(!!t^3*r`rf{2NY4`F3v?IT$62-Y@K zK77?I^z+<%uFrnz%w{`u#gf94cDtF^)$=F#9ZsTOBA!K9Qj zt7$G2w-{oC)ez0cA0^iYdrr{nyo5EZ<0xIv;;$#Sgt;k66Q^Jiw*%V4agX3Qv9(|p zQEIKTE3~+RF+Sk{HSsq7L2~0@+i79J<=nH$@1FJq?AuW=tN4Y}DZv8n;SGLZIifA3 z@GlON+rD_<27~?f1KEEFf(g<-v$%s zOSGd?elLEL+@yz}i8zQqpYKr$4=xDU#|%&!-Ap$^G{!aTV>5Rh#@|nFtXrlHES6g9 zI-cSx?%=IX@k4w~_Z!h>g!}jq!sn&dy4BO+E}jJN<$}OB)8GZ(>o!!WwJzt-Vg Date: Wed, 15 Dec 2021 17:59:43 -0800 Subject: [PATCH 2/3] Untrack forge files. --- .gitignore | 1 + CREDITS.txt | 65 --- LICENSE.txt | 520 ----------------------- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 5 - gradlew | 234 ---------- gradlew.bat | 89 ---- 7 files changed, 1 insertion(+), 913 deletions(-) delete mode 100644 CREDITS.txt delete mode 100644 LICENSE.txt delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100644 gradlew delete mode 100644 gradlew.bat diff --git a/.gitignore b/.gitignore index 80173c3..b477375 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ logs forge*changelog.txt changelog.txt LICENSE.txt +CREDITS.txt diff --git a/CREDITS.txt b/CREDITS.txt deleted file mode 100644 index a70c53d..0000000 --- a/CREDITS.txt +++ /dev/null @@ -1,65 +0,0 @@ -Minecraft Forge: Credits/Thank You - -Forge is a set of tools and modifications to the Minecraft base game code to assist -mod developers in creating new and exciting content. It has been in development for -several years now, but I would like to take this time thank a few people who have -helped it along it's way. - -First, the people who originally created the Forge projects way back in Minecraft -alpha. Eloraam of RedPower, and SpaceToad of Buildcraft, without their acceptiance -of me taking over the project, who knows what Minecraft modding would be today. - -Secondly, someone who has worked with me, and developed some of the core features -that allow modding to be as functional, and as simple as it is, cpw. For developing -FML, which stabelized the client and server modding ecosystem. As well as the base -loading system that allows us to modify Minecraft's code as elegently as possible. - -Mezz, who has stepped up as the issue and pull request manager. Helping to keep me -sane as well as guiding the community into creating better additions to Forge. - -Searge, Bspks, Fesh0r, ProfMobious, and all the rest over on the MCP team {of which -I am a part}. For creating some of the core tools needed to make Minecraft modding -both possible, and as stable as can be. - On that note, here is some specific information of the MCP data we use: - * Minecraft Coder Pack (MCP) * - Forge Mod Loader and Minecraft Forge have permission to distribute and automatically - download components of MCP and distribute MCP data files. This permission is not - transitive and others wishing to redistribute the Minecraft Forge source independently - should seek permission of MCP or remove the MCP data files and request their users - to download MCP separately. - -And lastly, the countless community members who have spent time submitting bug reports, -pull requests, and just helping out the community in general. Thank you. - ---LexManos - -========================================================================= - -This is Forge Mod Loader. - -You can find the source code at all times at https://github.com/MinecraftForge/MinecraftForge/tree/1.12.x/src/main/java/net/minecraftforge/fml - -This minecraft mod is a clean open source implementation of a mod loader for minecraft servers -and minecraft clients. - -The code is authored by cpw. - -It began by partially implementing an API defined by the client side ModLoader, authored by Risugami. -http://www.minecraftforum.net/topic/75440- -This support has been dropped as of Minecraft release 1.7, as Risugami no longer maintains ModLoader. - -It also contains suggestions and hints and generous helpings of code from LexManos, author of MinecraftForge. -http://www.minecraftforge.net/ - -Additionally, it contains an implementation of topological sort based on that -published at http://keithschwarz.com/interesting/code/?dir=topological-sort - -It also contains code from the Maven project for performing versioned dependency -resolution. http://maven.apache.org/ - -It also contains a partial repackaging of the javaxdelta library from http://sourceforge.net/projects/javaxdelta/ -with credit to it's authors. - -Forge Mod Loader downloads components from the Minecraft Coder Pack -(http://mcp.ocean-labs.de/index.php/Main_Page) with kind permission from the MCP team. - diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index b0cbe2b..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,520 +0,0 @@ -Unless noted below, Minecraft Forge, Forge Mod Loader, and all -parts herein are licensed under the terms of the LGPL 2.1 found -here http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt and -copied below. - -Homepage: http://minecraftforge.net/ - https://github.com/MinecraftForge/MinecraftForge - - -A note on authorship: -All source artifacts are property of their original author, with -the exclusion of the contents of the patches directory and others -copied from it from time to time. Authorship of the contents of -the patches directory is retained by the Minecraft Forge project. -This is because the patches are partially machine generated -artifacts, and are changed heavily due to the way forge works. -Individual attribution within them is impossible. - -Consent: -All contributions to Forge must consent to the release of any -patch content to the Forge project. - -A note on infectivity: -The LGPL is chosen specifically so that projects may depend on Forge -features without being infected with its license. That is the -purpose of the LGPL. Mods and others using this code via ordinary -Java mechanics for referencing libraries are specifically not bound -by Forge's license for the Mod code. - - -=== MCP Data === -This software includes data from the Minecraft Coder Pack (MCP), with kind permission -from them. The license to MCP data is not transitive - distribution of this data by -third parties requires independent licensing from the MCP team. This data is not -redistributable without permission from the MCP team. - -=== Sharing === -I grant permission for some parts of FML to be redistributed outside the terms of the LGPL, for the benefit of -the minecraft modding community. All contributions to these parts should be licensed under the same additional grant. - --- Runtime patcher -- -License is granted to redistribute the runtime patcher code (src/main/java/net/minecraftforge/fml/common/patcher -and subdirectories) under any alternative open source license as classified by the OSI (http://opensource.org/licenses) - --- ASM transformers -- -License is granted to redistribute the ASM transformer code (src/main/java/net/minecraftforge/common/asm/ and subdirectories) -under any alternative open source license as classified by the OSI (http://opensource.org/licenses) - -========================================================================= -This software includes portions from the Apache Maven project at -http://maven.apache.org/ specifically the ComparableVersion.java code. It is -included based on guidelines at -http://www.softwarefreedom.org/resources/2007/gpl-non-gpl-collaboration.html -with notices intact. The only change is a non-functional change of package name. - -This software contains a partial repackaging of javaxdelta, a BSD licensed program for generating -binary differences and applying them, sourced from the subversion at http://sourceforge.net/projects/javaxdelta/ -authored by genman, heikok, pivot. -The only changes are to replace some Trove collection types with standard Java collections, and repackaged. -========================================================================= - - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59536 zcma&NbC71ylI~qywr$(CZQJHswz}-9F59+k+g;UV+cs{`J?GrGXYR~=-ydruB3JCa zB64N^cILAcWk5iofq)<(fq;O7{th4@;QxID0)qN`mJ?GIqLY#rX8-|G{5M0pdVW5^ zzXk$-2kQTAC?_N@B`&6-N-rmVFE=$QD?>*=4<|!MJu@}isLc4AW#{m2if&A5T5g&~ ziuMQeS*U5sL6J698wOd)K@oK@1{peP5&Esut<#VH^u)gp`9H4)`uE!2$>RTctN+^u z=ASkePDZA-X8)rp%D;p*~P?*a_=*Kwc<^>QSH|^<0>o37lt^+Mj1;4YvJ(JR-Y+?%Nu}JAYj5 z_Qc5%Ao#F?q32i?ZaN2OSNhWL;2oDEw_({7ZbgUjna!Fqn3NzLM@-EWFPZVmc>(fZ z0&bF-Ch#p9C{YJT9Rcr3+Y_uR^At1^BxZ#eo>$PLJF3=;t_$2|t+_6gg5(j{TmjYU zK12c&lE?Eh+2u2&6Gf*IdKS&6?rYbSEKBN!rv{YCm|Rt=UlPcW9j`0o6{66#y5t9C zruFA2iKd=H%jHf%ypOkxLnO8#H}#Zt{8p!oi6)7#NqoF({t6|J^?1e*oxqng9Q2Cc zg%5Vu!em)}Yuj?kaP!D?b?(C*w!1;>R=j90+RTkyEXz+9CufZ$C^umX^+4|JYaO<5 zmIM3#dv`DGM;@F6;(t!WngZSYzHx?9&$xEF70D1BvfVj<%+b#)vz)2iLCrTeYzUcL z(OBnNoG6Le%M+@2oo)&jdOg=iCszzv59e zDRCeaX8l1hC=8LbBt|k5?CXgep=3r9BXx1uR8!p%Z|0+4Xro=xi0G!e{c4U~1j6!) zH6adq0}#l{%*1U(Cb%4AJ}VLWKBPi0MoKFaQH6x?^hQ!6em@993xdtS%_dmevzeNl z(o?YlOI=jl(`L9^ z0O+H9k$_@`6L13eTT8ci-V0ljDMD|0ifUw|Q-Hep$xYj0hTO@0%IS^TD4b4n6EKDG z??uM;MEx`s98KYN(K0>c!C3HZdZ{+_53DO%9k5W%pr6yJusQAv_;IA}925Y%;+!tY z%2k!YQmLLOr{rF~!s<3-WEUs)`ix_mSU|cNRBIWxOox_Yb7Z=~Q45ZNe*u|m^|)d* zog=i>`=bTe!|;8F+#H>EjIMcgWcG2ORD`w0WD;YZAy5#s{65~qfI6o$+Ty&-hyMyJ z3Ra~t>R!p=5ZpxA;QkDAoPi4sYOP6>LT+}{xp}tk+<0k^CKCFdNYG(Es>p0gqD)jP zWOeX5G;9(m@?GOG7g;e74i_|SmE?`B2i;sLYwRWKLy0RLW!Hx`=!LH3&k=FuCsM=9M4|GqzA)anEHfxkB z?2iK-u(DC_T1};KaUT@3nP~LEcENT^UgPvp!QC@Dw&PVAhaEYrPey{nkcn(ro|r7XUz z%#(=$7D8uP_uU-oPHhd>>^adbCSQetgSG`e$U|7mr!`|bU0aHl_cmL)na-5x1#OsVE#m*+k84Y^+UMeSAa zbrVZHU=mFwXEaGHtXQq`2ZtjfS!B2H{5A<3(nb-6ARVV8kEmOkx6D2x7~-6hl;*-*}2Xz;J#a8Wn;_B5=m zl3dY;%krf?i-Ok^Pal-}4F`{F@TYPTwTEhxpZK5WCpfD^UmM_iYPe}wpE!Djai6_{ z*pGO=WB47#Xjb7!n2Ma)s^yeR*1rTxp`Mt4sfA+`HwZf%!7ZqGosPkw69`Ix5Ku6G z@Pa;pjzV&dn{M=QDx89t?p?d9gna*}jBly*#1!6}5K<*xDPJ{wv4& zM$17DFd~L*Te3A%yD;Dp9UGWTjRxAvMu!j^Tbc}2v~q^59d4bz zvu#!IJCy(BcWTc`;v$9tH;J%oiSJ_i7s;2`JXZF+qd4C)vY!hyCtl)sJIC{ebI*0> z@x>;EzyBv>AI-~{D6l6{ST=em*U( z(r$nuXY-#CCi^8Z2#v#UXOt`dbYN1z5jzNF2 z411?w)whZrfA20;nl&C1Gi+gk<`JSm+{|*2o<< zqM#@z_D`Cn|0H^9$|Tah)0M_X4c37|KQ*PmoT@%xHc3L1ZY6(p(sNXHa&49Frzto& zR`c~ClHpE~4Z=uKa5S(-?M8EJ$zt0&fJk~p$M#fGN1-y$7!37hld`Uw>Urri(DxLa;=#rK0g4J)pXMC zxzraOVw1+kNWpi#P=6(qxf`zSdUC?D$i`8ZI@F>k6k zz21?d+dw7b&i*>Kv5L(LH-?J%@WnqT7j#qZ9B>|Zl+=> z^U-pV@1y_ptHo4hl^cPRWewbLQ#g6XYQ@EkiP z;(=SU!yhjHp%1&MsU`FV1Z_#K1&(|5n(7IHbx&gG28HNT)*~-BQi372@|->2Aw5It z0CBpUcMA*QvsPy)#lr!lIdCi@1k4V2m!NH)%Px(vu-r(Q)HYc!p zJ^$|)j^E#q#QOgcb^pd74^JUi7fUmMiNP_o*lvx*q%_odv49Dsv$NV;6J z9GOXKomA{2Pb{w}&+yHtH?IkJJu~}Z?{Uk++2mB8zyvh*xhHKE``99>y#TdD z&(MH^^JHf;g(Tbb^&8P*;_i*2&fS$7${3WJtV7K&&(MBV2~)2KB3%cWg#1!VE~k#C z!;A;?p$s{ihyojEZz+$I1)L}&G~ml=udD9qh>Tu(ylv)?YcJT3ihapi!zgPtWb*CP zlLLJSRCj-^w?@;RU9aL2zDZY1`I3d<&OMuW=c3$o0#STpv_p3b9Wtbql>w^bBi~u4 z3D8KyF?YE?=HcKk!xcp@Cigvzy=lnFgc^9c%(^F22BWYNAYRSho@~*~S)4%AhEttv zvq>7X!!EWKG?mOd9&n>vvH1p4VzE?HCuxT-u+F&mnsfDI^}*-d00-KAauEaXqg3k@ zy#)MGX!X;&3&0s}F3q40ZmVM$(H3CLfpdL?hB6nVqMxX)q=1b}o_PG%r~hZ4gUfSp zOH4qlEOW4OMUc)_m)fMR_rl^pCfXc{$fQbI*E&mV77}kRF z&{<06AJyJ!e863o-V>FA1a9Eemx6>^F$~9ppt()ZbPGfg_NdRXBWoZnDy2;#ODgf! zgl?iOcF7Meo|{AF>KDwTgYrJLb$L2%%BEtO>T$C?|9bAB&}s;gI?lY#^tttY&hfr# zKhC+&b-rpg_?~uVK%S@mQleU#_xCsvIPK*<`E0fHE1&!J7!xD#IB|SSPW6-PyuqGn3^M^Rz%WT{e?OI^svARX&SAdU77V(C~ zM$H{Kg59op{<|8ry9ecfP%=kFm(-!W&?U0@<%z*+!*<e0XesMxRFu9QnGqun6R_%T+B%&9Dtk?*d$Q zb~>84jEAPi@&F@3wAa^Lzc(AJz5gsfZ7J53;@D<;Klpl?sK&u@gie`~vTsbOE~Cd4 z%kr56mI|#b(Jk&;p6plVwmNB0H@0SmgdmjIn5Ne@)}7Vty(yb2t3ev@22AE^s!KaN zyQ>j+F3w=wnx7w@FVCRe+`vUH)3gW%_72fxzqX!S&!dchdkRiHbXW1FMrIIBwjsai8`CB2r4mAbwp%rrO>3B$Zw;9=%fXI9B{d(UzVap7u z6piC-FQ)>}VOEuPpuqznpY`hN4dGa_1Xz9rVg(;H$5Te^F0dDv*gz9JS<|>>U0J^# z6)(4ICh+N_Q`Ft0hF|3fSHs*?a=XC;e`sJaU9&d>X4l?1W=|fr!5ShD|nv$GK;j46@BV6+{oRbWfqOBRb!ir88XD*SbC(LF}I1h#6@dvK%Toe%@ zhDyG$93H8Eu&gCYddP58iF3oQH*zLbNI;rN@E{T9%A8!=v#JLxKyUe}e}BJpB{~uN zqgxRgo0*-@-iaHPV8bTOH(rS(huwK1Xg0u+e!`(Irzu@Bld&s5&bWgVc@m7;JgELd zimVs`>vQ}B_1(2#rv#N9O`fJpVfPc7V2nv34PC);Dzbb;p!6pqHzvy?2pD&1NE)?A zt(t-ucqy@wn9`^MN5apa7K|L=9>ISC>xoc#>{@e}m#YAAa1*8-RUMKwbm|;5p>T`Z zNf*ph@tnF{gmDa3uwwN(g=`Rh)4!&)^oOy@VJaK4lMT&5#YbXkl`q?<*XtsqD z9PRK6bqb)fJw0g-^a@nu`^?71k|m3RPRjt;pIkCo1{*pdqbVs-Yl>4E>3fZx3Sv44grW=*qdSoiZ9?X0wWyO4`yDHh2E!9I!ZFi zVL8|VtW38}BOJHW(Ax#KL_KQzarbuE{(%TA)AY)@tY4%A%P%SqIU~8~-Lp3qY;U-} z`h_Gel7;K1h}7$_5ZZT0&%$Lxxr-<89V&&TCsu}LL#!xpQ1O31jaa{U34~^le*Y%L za?7$>Jk^k^pS^_M&cDs}NgXlR>16AHkSK-4TRaJSh#h&p!-!vQY%f+bmn6x`4fwTp z$727L^y`~!exvmE^W&#@uY!NxJi`g!i#(++!)?iJ(1)2Wk;RN zFK&O4eTkP$Xn~4bB|q8y(btx$R#D`O@epi4ofcETrx!IM(kWNEe42Qh(8*KqfP(c0 zouBl6>Fc_zM+V;F3znbo{x#%!?mH3`_ANJ?y7ppxS@glg#S9^MXu|FM&ynpz3o&Qh z2ujAHLF3($pH}0jXQsa#?t--TnF1P73b?4`KeJ9^qK-USHE)4!IYgMn-7z|=ALF5SNGkrtPG@Y~niUQV2?g$vzJN3nZ{7;HZHzWAeQ;5P|@Tl3YHpyznGG4-f4=XflwSJY+58-+wf?~Fg@1p1wkzuu-RF3j2JX37SQUc? zQ4v%`V8z9ZVZVqS8h|@@RpD?n0W<=hk=3Cf8R?d^9YK&e9ZybFY%jdnA)PeHvtBe- zhMLD+SSteHBq*q)d6x{)s1UrsO!byyLS$58WK;sqip$Mk{l)Y(_6hEIBsIjCr5t>( z7CdKUrJTrW%qZ#1z^n*Lb8#VdfzPw~OIL76aC+Rhr<~;4Tl!sw?Rj6hXj4XWa#6Tp z@)kJ~qOV)^Rh*-?aG>ic2*NlC2M7&LUzc9RT6WM%Cpe78`iAowe!>(T0jo&ivn8-7 zs{Qa@cGy$rE-3AY0V(l8wjI^uB8Lchj@?L}fYal^>T9z;8juH@?rG&g-t+R2dVDBe zq!K%{e-rT5jX19`(bP23LUN4+_zh2KD~EAYzhpEO3MUG8@}uBHH@4J zd`>_(K4q&>*k82(dDuC)X6JuPrBBubOg7qZ{?x!r@{%0);*`h*^F|%o?&1wX?Wr4b z1~&cy#PUuES{C#xJ84!z<1tp9sfrR(i%Tu^jnXy;4`Xk;AQCdFC@?V%|; zySdC7qS|uQRcH}EFZH%mMB~7gi}a0utE}ZE_}8PQH8f;H%PN41Cb9R%w5Oi5el^fd z$n{3SqLCnrF##x?4sa^r!O$7NX!}&}V;0ZGQ&K&i%6$3C_dR%I7%gdQ;KT6YZiQrW zk%q<74oVBV>@}CvJ4Wj!d^?#Zwq(b$E1ze4$99DuNg?6t9H}k_|D7KWD7i0-g*EO7 z;5{hSIYE4DMOK3H%|f5Edx+S0VI0Yw!tsaRS2&Il2)ea^8R5TG72BrJue|f_{2UHa z@w;^c|K3da#$TB0P3;MPlF7RuQeXT$ zS<<|C0OF(k)>fr&wOB=gP8!Qm>F41u;3esv7_0l%QHt(~+n; zf!G6%hp;Gfa9L9=AceiZs~tK+Tf*Wof=4!u{nIO90jH@iS0l+#%8=~%ASzFv7zqSB^?!@N7)kp0t&tCGLmzXSRMRyxCmCYUD2!B`? zhs$4%KO~m=VFk3Buv9osha{v+mAEq=ik3RdK@;WWTV_g&-$U4IM{1IhGX{pAu%Z&H zFfwCpUsX%RKg);B@7OUzZ{Hn{q6Vv!3#8fAg!P$IEx<0vAx;GU%}0{VIsmFBPq_mb zpe^BChDK>sc-WLKl<6 zwbW|e&d&dv9Wu0goueyu>(JyPx1mz0v4E?cJjFuKF71Q1)AL8jHO$!fYT3(;U3Re* zPPOe%*O+@JYt1bW`!W_1!mN&=w3G9ru1XsmwfS~BJ))PhD(+_J_^N6j)sx5VwbWK| zwRyC?W<`pOCY)b#AS?rluxuuGf-AJ=D!M36l{ua?@SJ5>e!IBr3CXIxWw5xUZ@Xrw z_R@%?{>d%Ld4p}nEsiA@v*nc6Ah!MUs?GA7e5Q5lPpp0@`%5xY$C;{%rz24$;vR#* zBP=a{)K#CwIY%p} zXVdxTQ^HS@O&~eIftU+Qt^~(DGxrdi3k}DdT^I7Iy5SMOp$QuD8s;+93YQ!OY{eB24%xY7ml@|M7I(Nb@K_-?F;2?et|CKkuZK_>+>Lvg!>JE~wN`BI|_h6$qi!P)+K-1Hh(1;a`os z55)4Q{oJiA(lQM#;w#Ta%T0jDNXIPM_bgESMCDEg6rM33anEr}=|Fn6)|jBP6Y}u{ zv9@%7*#RI9;fv;Yii5CI+KrRdr0DKh=L>)eO4q$1zmcSmglsV`*N(x=&Wx`*v!!hn6X-l0 zP_m;X??O(skcj+oS$cIdKhfT%ABAzz3w^la-Ucw?yBPEC+=Pe_vU8nd-HV5YX6X8r zZih&j^eLU=%*;VzhUyoLF;#8QsEfmByk+Y~caBqSvQaaWf2a{JKB9B>V&r?l^rXaC z8)6AdR@Qy_BxQrE2Fk?ewD!SwLuMj@&d_n5RZFf7=>O>hzVE*seW3U?_p|R^CfoY`?|#x9)-*yjv#lo&zP=uI`M?J zbzC<^3x7GfXA4{FZ72{PE*-mNHyy59Q;kYG@BB~NhTd6pm2Oj=_ zizmD?MKVRkT^KmXuhsk?eRQllPo2Ubk=uCKiZ&u3Xjj~<(!M94c)Tez@9M1Gfs5JV z->@II)CDJOXTtPrQudNjE}Eltbjq>6KiwAwqvAKd^|g!exgLG3;wP+#mZYr`cy3#39e653d=jrR-ulW|h#ddHu(m9mFoW~2yE zz5?dB%6vF}+`-&-W8vy^OCxm3_{02royjvmwjlp+eQDzFVEUiyO#gLv%QdDSI#3W* z?3!lL8clTaNo-DVJw@ynq?q!%6hTQi35&^>P85G$TqNt78%9_sSJt2RThO|JzM$iL zg|wjxdMC2|Icc5rX*qPL(coL!u>-xxz-rFiC!6hD1IR%|HSRsV3>Kq~&vJ=s3M5y8SG%YBQ|{^l#LGlg!D?E>2yR*eV%9m$_J6VGQ~AIh&P$_aFbh zULr0Z$QE!QpkP=aAeR4ny<#3Fwyw@rZf4?Ewq`;mCVv}xaz+3ni+}a=k~P+yaWt^L z@w67!DqVf7D%7XtXX5xBW;Co|HvQ8WR1k?r2cZD%U;2$bsM%u8{JUJ5Z0k= zZJARv^vFkmWx15CB=rb=D4${+#DVqy5$C%bf`!T0+epLJLnh1jwCdb*zuCL}eEFvE z{rO1%gxg>1!W(I!owu*mJZ0@6FM(?C+d*CeceZRW_4id*D9p5nzMY&{mWqrJomjIZ z97ZNnZ3_%Hx8dn;H>p8m7F#^2;T%yZ3H;a&N7tm=Lvs&lgJLW{V1@h&6Vy~!+Ffbb zv(n3+v)_D$}dqd!2>Y2B)#<+o}LH#%ogGi2-?xRIH)1!SD)u-L65B&bsJTC=LiaF+YOCif2dUX6uAA|#+vNR z>U+KQekVGon)Yi<93(d!(yw1h3&X0N(PxN2{%vn}cnV?rYw z$N^}_o!XUB!mckL`yO1rnUaI4wrOeQ(+&k?2mi47hzxSD`N#-byqd1IhEoh!PGq>t z_MRy{5B0eKY>;Ao3z$RUU7U+i?iX^&r739F)itdrTpAi-NN0=?^m%?{A9Ly2pVv>Lqs6moTP?T2-AHqFD-o_ znVr|7OAS#AEH}h8SRPQ@NGG47dO}l=t07__+iK8nHw^(AHx&Wb<%jPc$$jl6_p(b$ z)!pi(0fQodCHfM)KMEMUR&UID>}m^(!{C^U7sBDOA)$VThRCI0_+2=( zV8mMq0R(#z;C|7$m>$>`tX+T|xGt(+Y48@ZYu#z;0pCgYgmMVbFb!$?%yhZqP_nhn zy4<#3P1oQ#2b51NU1mGnHP$cf0j-YOgAA}A$QoL6JVLcmExs(kU{4z;PBHJD%_=0F z>+sQV`mzijSIT7xn%PiDKHOujX;n|M&qr1T@rOxTdxtZ!&u&3HHFLYD5$RLQ=heur zb>+AFokUVQeJy-#LP*^)spt{mb@Mqe=A~-4p0b+Bt|pZ+@CY+%x}9f}izU5;4&QFE zO1bhg&A4uC1)Zb67kuowWY4xbo&J=%yoXlFB)&$d*-}kjBu|w!^zbD1YPc0-#XTJr z)pm2RDy%J3jlqSMq|o%xGS$bPwn4AqitC6&e?pqWcjWPt{3I{>CBy;hg0Umh#c;hU3RhCUX=8aR>rmd` z7Orw(5tcM{|-^J?ZAA9KP|)X6n9$-kvr#j5YDecTM6n z&07(nD^qb8hpF0B^z^pQ*%5ePYkv&FabrlI61ntiVp!!C8y^}|<2xgAd#FY=8b*y( zuQOuvy2`Ii^`VBNJB&R!0{hABYX55ooCAJSSevl4RPqEGb)iy_0H}v@vFwFzD%>#I>)3PsouQ+_Kkbqy*kKdHdfkN7NBcq%V{x^fSxgXpg7$bF& zj!6AQbDY(1u#1_A#1UO9AxiZaCVN2F0wGXdY*g@x$ByvUA?ePdide0dmr#}udE%K| z3*k}Vv2Ew2u1FXBaVA6aerI36R&rzEZeDDCl5!t0J=ug6kuNZzH>3i_VN`%BsaVB3 zQYw|Xub_SGf{)F{$ZX5`Jc!X!;eybjP+o$I{Z^Hsj@D=E{MnnL+TbC@HEU2DjG{3-LDGIbq()U87x4eS;JXnSh;lRlJ z>EL3D>wHt-+wTjQF$fGyDO$>d+(fq@bPpLBS~xA~R=3JPbS{tzN(u~m#Po!?H;IYv zE;?8%^vle|%#oux(Lj!YzBKv+Fd}*Ur-dCBoX*t{KeNM*n~ZPYJ4NNKkI^MFbz9!v z4(Bvm*Kc!-$%VFEewYJKz-CQN{`2}KX4*CeJEs+Q(!kI%hN1!1P6iOq?ovz}X0IOi z)YfWpwW@pK08^69#wSyCZkX9?uZD?C^@rw^Y?gLS_xmFKkooyx$*^5#cPqntNTtSG zlP>XLMj2!VF^0k#ole7`-c~*~+_T5ls?x4)ah(j8vo_ zwb%S8qoaZqY0-$ZI+ViIA_1~~rAH7K_+yFS{0rT@eQtTAdz#8E5VpwnW!zJ_^{Utv zlW5Iar3V5t&H4D6A=>?mq;G92;1cg9a2sf;gY9pJDVKn$DYdQlvfXq}zz8#LyPGq@ z+`YUMD;^-6w&r-82JL7mA8&M~Pj@aK!m{0+^v<|t%APYf7`}jGEhdYLqsHW-Le9TL z_hZZ1gbrz7$f9^fAzVIP30^KIz!!#+DRLL+qMszvI_BpOSmjtl$hh;&UeM{ER@INV zcI}VbiVTPoN|iSna@=7XkP&-4#06C};8ajbxJ4Gcq8(vWv4*&X8bM^T$mBk75Q92j z1v&%a;OSKc8EIrodmIiw$lOES2hzGDcjjB`kEDfJe{r}yE6`eZL zEB`9u>Cl0IsQ+t}`-cx}{6jqcANucqIB>Qmga_&<+80E2Q|VHHQ$YlAt{6`Qu`HA3 z03s0-sSlwbvgi&_R8s={6<~M^pGvBNjKOa>tWenzS8s zR>L7R5aZ=mSU{f?ib4Grx$AeFvtO5N|D>9#)ChH#Fny2maHWHOf2G=#<9Myot#+4u zWVa6d^Vseq_0=#AYS(-m$Lp;*8nC_6jXIjEM`omUmtH@QDs3|G)i4j*#_?#UYVZvJ z?YjT-?!4Q{BNun;dKBWLEw2C-VeAz`%?A>p;)PL}TAZn5j~HK>v1W&anteARlE+~+ zj>c(F;?qO3pXBb|#OZdQnm<4xWmn~;DR5SDMxt0UK_F^&eD|KZ=O;tO3vy4@4h^;2 zUL~-z`-P1aOe?|ZC1BgVsL)2^J-&vIFI%q@40w0{jjEfeVl)i9(~bt2z#2Vm)p`V_ z1;6$Ae7=YXk#=Qkd24Y23t&GvRxaOoad~NbJ+6pxqzJ>FY#Td7@`N5xp!n(c!=RE& z&<<@^a$_Ys8jqz4|5Nk#FY$~|FPC0`*a5HH!|Gssa9=~66&xG9)|=pOOJ2KE5|YrR zw!w6K2aC=J$t?L-;}5hn6mHd%hC;p8P|Dgh6D>hGnXPgi;6r+eA=?f72y9(Cf_ho{ zH6#)uD&R=73^$$NE;5piWX2bzR67fQ)`b=85o0eOLGI4c-Tb@-KNi2pz=Ke@SDcPn za$AxXib84`!Sf;Z3B@TSo`Dz7GM5Kf(@PR>Ghzi=BBxK8wRp>YQoXm+iL>H*Jo9M3 z6w&E?BC8AFTFT&Tv8zf+m9<&S&%dIaZ)Aoqkak_$r-2{$d~0g2oLETx9Y`eOAf14QXEQw3tJne;fdzl@wV#TFXSLXM2428F-Q}t+n2g%vPRMUzYPvzQ9f# zu(liiJem9P*?0%V@RwA7F53r~|I!Ty)<*AsMX3J{_4&}{6pT%Tpw>)^|DJ)>gpS~1rNEh z0$D?uO8mG?H;2BwM5a*26^7YO$XjUm40XmBsb63MoR;bJh63J;OngS5sSI+o2HA;W zdZV#8pDpC9Oez&L8loZO)MClRz!_!WD&QRtQxnazhT%Vj6Wl4G11nUk8*vSeVab@N#oJ}`KyJv+8Mo@T1-pqZ1t|?cnaVOd;1(h9 z!$DrN=jcGsVYE-0-n?oCJ^4x)F}E;UaD-LZUIzcD?W^ficqJWM%QLy6QikrM1aKZC zi{?;oKwq^Vsr|&`i{jIphA8S6G4)$KGvpULjH%9u(Dq247;R#l&I0{IhcC|oBF*Al zvLo7Xte=C{aIt*otJD}BUq)|_pdR>{zBMT< z(^1RpZv*l*m*OV^8>9&asGBo8h*_4q*)-eCv*|Pq=XNGrZE)^(SF7^{QE_~4VDB(o zVcPA_!G+2CAtLbl+`=Q~9iW`4ZRLku!uB?;tWqVjB0lEOf}2RD7dJ=BExy=<9wkb- z9&7{XFA%n#JsHYN8t5d~=T~5DcW4$B%3M+nNvC2`0!#@sckqlzo5;hhGi(D9=*A4` z5ynobawSPRtWn&CDLEs3Xf`(8^zDP=NdF~F^s&={l7(aw&EG}KWpMjtmz7j_VLO;@ zM2NVLDxZ@GIv7*gzl1 zjq78tv*8#WSY`}Su0&C;2F$Ze(q>F(@Wm^Gw!)(j;dk9Ad{STaxn)IV9FZhm*n+U} zi;4y*3v%A`_c7a__DJ8D1b@dl0Std3F||4Wtvi)fCcBRh!X9$1x!_VzUh>*S5s!oq z;qd{J_r79EL2wIeiGAqFstWtkfIJpjVh%zFo*=55B9Zq~y0=^iqHWfQl@O!Ak;(o*m!pZqe9 z%U2oDOhR)BvW8&F70L;2TpkzIutIvNQaTjjs5V#8mV4!NQ}zN=i`i@WI1z0eN-iCS z;vL-Wxc^Vc_qK<5RPh(}*8dLT{~GzE{w2o$2kMFaEl&q zP{V=>&3kW7tWaK-Exy{~`v4J0U#OZBk{a9{&)&QG18L@6=bsZ1zC_d{{pKZ-Ey>I> z;8H0t4bwyQqgu4hmO`3|4K{R*5>qnQ&gOfdy?z`XD%e5+pTDzUt3`k^u~SaL&XMe= z9*h#kT(*Q9jO#w2Hd|Mr-%DV8i_1{J1MU~XJ3!WUplhXDYBpJH><0OU`**nIvPIof z|N8@I=wA)sf45SAvx||f?Z5uB$kz1qL3Ky_{%RPdP5iN-D2!p5scq}buuC00C@jom zhfGKm3|f?Z0iQ|K$Z~!`8{nmAS1r+fp6r#YDOS8V*;K&Gs7Lc&f^$RC66O|)28oh`NHy&vq zJh+hAw8+ybTB0@VhWN^0iiTnLsCWbS_y`^gs!LX!Lw{yE``!UVzrV24tP8o;I6-65 z1MUiHw^{bB15tmrVT*7-#sj6cs~z`wk52YQJ*TG{SE;KTm#Hf#a~|<(|ImHH17nNM z`Ub{+J3dMD!)mzC8b(2tZtokKW5pAwHa?NFiso~# z1*iaNh4lQ4TS)|@G)H4dZV@l*Vd;Rw;-;odDhW2&lJ%m@jz+Panv7LQm~2Js6rOW3 z0_&2cW^b^MYW3)@o;neZ<{B4c#m48dAl$GCc=$>ErDe|?y@z`$uq3xd(%aAsX)D%l z>y*SQ%My`yDP*zof|3@_w#cjaW_YW4BdA;#Glg1RQcJGY*CJ9`H{@|D+*e~*457kd z73p<%fB^PV!Ybw@)Dr%(ZJbX}xmCStCYv#K3O32ej{$9IzM^I{6FJ8!(=azt7RWf4 z7ib0UOPqN40X!wOnFOoddd8`!_IN~9O)#HRTyjfc#&MCZ zZAMzOVB=;qwt8gV?{Y2?b=iSZG~RF~uyx18K)IDFLl})G1v@$(s{O4@RJ%OTJyF+Cpcx4jmy|F3euCnMK!P2WTDu5j z{{gD$=M*pH!GGzL%P)V2*ROm>!$Y=z|D`!_yY6e7SU$~a5q8?hZGgaYqaiLnkK%?0 zs#oI%;zOxF@g*@(V4p!$7dS1rOr6GVs6uYCTt2h)eB4?(&w8{#o)s#%gN@BBosRUe z)@P@8_Zm89pr~)b>e{tbPC~&_MR--iB{=)y;INU5#)@Gix-YpgP<-c2Ms{9zuCX|3 z!p(?VaXww&(w&uBHzoT%!A2=3HAP>SDxcljrego7rY|%hxy3XlODWffO_%g|l+7Y_ zqV(xbu)s4lV=l7M;f>vJl{`6qBm>#ZeMA}kXb97Z)?R97EkoI?x6Lp0yu1Z>PS?2{ z0QQ(8D)|lc9CO3B~e(pQM&5(1y&y=e>C^X$`)_&XuaI!IgDTVqt31wX#n+@!a_A0ZQkA zCJ2@M_4Gb5MfCrm5UPggeyh)8 zO9?`B0J#rkoCx(R0I!ko_2?iO@|oRf1;3r+i)w-2&j?=;NVIdPFsB)`|IC0zk6r9c zRrkfxWsiJ(#8QndNJj@{@WP2Ackr|r1VxV{7S&rSU(^)-M8gV>@UzOLXu9K<{6e{T zXJ6b92r$!|lwjhmgqkdswY&}c)KW4A)-ac%sU;2^fvq7gfUW4Bw$b!i@duy1CAxSn z(pyh$^Z=&O-q<{bZUP+$U}=*#M9uVc>CQVgDs4swy5&8RAHZ~$)hrTF4W zPsSa~qYv_0mJnF89RnnJTH`3}w4?~epFl=D(35$ zWa07ON$`OMBOHgCmfO(9RFc<)?$x)N}Jd2A(<*Ll7+4jrRt9w zwGxExUXd9VB#I|DwfxvJ;HZ8Q{37^wDhaZ%O!oO(HpcqfLH%#a#!~;Jl7F5>EX_=8 z{()l2NqPz>La3qJR;_v+wlK>GsHl;uRA8%j`A|yH@k5r%55S9{*Cp%uw6t`qc1!*T za2OeqtQj7sAp#Q~=5Fs&aCR9v>5V+s&RdNvo&H~6FJOjvaj--2sYYBvMq;55%z8^o z|BJDA4vzfow#DO#ZQHh;Oq_{r+qP{R9ox2TOgwQiv7Ow!zjN+A@BN;0tA2lUb#+zO z(^b89eV)D7UVE+h{mcNc6&GtpOqDn_?VAQ)Vob$hlFwW%xh>D#wml{t&Ofmm_d_+; zKDxzdr}`n2Rw`DtyIjrG)eD0vut$}dJAZ0AohZ+ZQdWXn_Z@dI_y=7t3q8x#pDI-K z2VVc&EGq445Rq-j0=U=Zx`oBaBjsefY;%)Co>J3v4l8V(T8H?49_@;K6q#r~Wwppc z4XW0(4k}cP=5ex>-Xt3oATZ~bBWKv)aw|I|Lx=9C1s~&b77idz({&q3T(Y(KbWO?+ zmcZ6?WeUsGk6>km*~234YC+2e6Zxdl~<_g2J|IE`GH%n<%PRv-50; zH{tnVts*S5*_RxFT9eM0z-pksIb^drUq4>QSww=u;UFCv2AhOuXE*V4z?MM`|ABOC4P;OfhS(M{1|c%QZ=!%rQTDFx`+}?Kdx$&FU?Y<$x;j7z=(;Lyz+?EE>ov!8vvMtSzG!nMie zsBa9t8as#2nH}n8xzN%W%U$#MHNXmDUVr@GX{?(=yI=4vks|V)!-W5jHsU|h_&+kY zS_8^kd3jlYqOoiI`ZqBVY!(UfnAGny!FowZWY_@YR0z!nG7m{{)4OS$q&YDyw6vC$ zm4!$h>*|!2LbMbxS+VM6&DIrL*X4DeMO!@#EzMVfr)e4Tagn~AQHIU8?e61TuhcKD zr!F4(kEebk(Wdk-?4oXM(rJwanS>Jc%<>R(siF+>+5*CqJLecP_we33iTFTXr6W^G z7M?LPC-qFHK;E!fxCP)`8rkxZyFk{EV;G-|kwf4b$c1k0atD?85+|4V%YATWMG|?K zLyLrws36p%Qz6{}>7b>)$pe>mR+=IWuGrX{3ZPZXF3plvuv5Huax86}KX*lbPVr}L z{C#lDjdDeHr~?l|)Vp_}T|%$qF&q#U;ClHEPVuS+Jg~NjC1RP=17=aQKGOcJ6B3mp z8?4*-fAD~}sX*=E6!}^u8)+m2j<&FSW%pYr_d|p_{28DZ#Cz0@NF=gC-o$MY?8Ca8 zr5Y8DSR^*urS~rhpX^05r30Ik#2>*dIOGxRm0#0YX@YQ%Mg5b6dXlS!4{7O_kdaW8PFSdj1=ryI-=5$fiieGK{LZ+SX(1b=MNL!q#lN zv98?fqqTUH8r8C7v(cx#BQ5P9W>- zmW93;eH6T`vuJ~rqtIBg%A6>q>gnWb3X!r0wh_q;211+Om&?nvYzL1hhtjB zK_7G3!n7PL>d!kj){HQE zE8(%J%dWLh1_k%gVXTZt zEdT09XSKAx27Ncaq|(vzL3gm83q>6CAw<$fTnMU05*xAe&rDfCiu`u^1)CD<>sx0i z*hr^N_TeN89G(nunZoLBf^81#pmM}>JgD@Nn1l*lN#a=B=9pN%tmvYFjFIoKe_(GF z-26x{(KXdfsQL7Uv6UtDuYwV`;8V3w>oT_I<`Ccz3QqK9tYT5ZQzbop{=I=!pMOCb zCU68`n?^DT%^&m>A%+-~#lvF!7`L7a{z<3JqIlk1$<||_J}vW1U9Y&eX<}l8##6i( zZcTT@2`9(Mecptm@{3A_Y(X`w9K0EwtPq~O!16bq{7c0f7#(3wn-^)h zxV&M~iiF!{-6A@>o;$RzQ5A50kxXYj!tcgme=Qjrbje~;5X2xryU;vH|6bE(8z^<7 zQ>BG7_c*JG8~K7Oe68i#0~C$v?-t@~@r3t2inUnLT(c=URpA9kA8uq9PKU(Ps(LVH zqgcqW>Gm?6oV#AldDPKVRcEyQIdTT`Qa1j~vS{<;SwyTdr&3*t?J)y=M7q*CzucZ&B0M=joT zBbj@*SY;o2^_h*>R0e({!QHF0=)0hOj^B^d*m>SnRrwq>MolNSgl^~r8GR#mDWGYEIJA8B<|{{j?-7p zVnV$zancW3&JVDtVpIlI|5djKq0(w$KxEFzEiiL=h5Jw~4Le23@s(mYyXWL9SX6Ot zmb)sZaly_P%BeX_9 zw&{yBef8tFm+%=--m*J|o~+Xg3N+$IH)t)=fqD+|fEk4AAZ&!wcN5=mi~Vvo^i`}> z#_3ahR}Ju)(Px7kev#JGcSwPXJ2id9%Qd2A#Uc@t8~egZ8;iC{e! z%=CGJOD1}j!HW_sgbi_8suYnn4#Ou}%9u)dXd3huFIb!ytlX>Denx@pCS-Nj$`VO&j@(z!kKSP0hE4;YIP#w9ta=3DO$7f*x zc9M4&NK%IrVmZAe=r@skWD`AEWH=g+r|*13Ss$+{c_R!b?>?UaGXlw*8qDmY#xlR= z<0XFbs2t?8i^G~m?b|!Hal^ZjRjt<@a? z%({Gn14b4-a|#uY^=@iiKH+k?~~wTj5K1A&hU z2^9-HTC)7zpoWK|$JXaBL6C z#qSNYtY>65T@Zs&-0cHeu|RX(Pxz6vTITdzJdYippF zC-EB+n4}#lM7`2Ry~SO>FxhKboIAF#Z{1wqxaCb{#yEFhLuX;Rx(Lz%T`Xo1+a2M}7D+@wol2)OJs$TwtRNJ={( zD@#zTUEE}#Fz#&(EoD|SV#bayvr&E0vzmb%H?o~46|FAcx?r4$N z&67W3mdip-T1RIxwSm_&(%U|+WvtGBj*}t69XVd&ebn>KOuL(7Y8cV?THd-(+9>G7*Nt%T zcH;`p={`SOjaf7hNd(=37Lz3-51;58JffzIPgGs_7xIOsB5p2t&@v1mKS$2D$*GQ6 zM(IR*j4{nri7NMK9xlDy-hJW6sW|ZiDRaFiayj%;(%51DN!ZCCCXz+0Vm#};70nOx zJ#yA0P3p^1DED;jGdPbQWo0WATN=&2(QybbVdhd=Vq*liDk`c7iZ?*AKEYC#SY&2g z&Q(Ci)MJ{mEat$ZdSwTjf6h~roanYh2?9j$CF@4hjj_f35kTKuGHvIs9}Re@iKMxS-OI*`0S z6s)fOtz}O$T?PLFVSeOjSO26$@u`e<>k(OSP!&YstH3ANh>)mzmKGNOwOawq-MPXe zy4xbeUAl6tamnx))-`Gi2uV5>9n(73yS)Ukma4*7fI8PaEwa)dWHs6QA6>$}7?(L8 ztN8M}?{Tf!Zu22J5?2@95&rQ|F7=FK-hihT-vDp!5JCcWrVogEnp;CHenAZ)+E+K5 z$Cffk5sNwD_?4+ymgcHR(5xgt20Z8M`2*;MzOM#>yhk{r3x=EyM226wb&!+j`W<%* zSc&|`8!>dn9D@!pYow~(DsY_naSx7(Z4i>cu#hA5=;IuI88}7f%)bRkuY2B;+9Uep zpXcvFWkJ!mQai63BgNXG26$5kyhZ2&*3Q_tk)Ii4M>@p~_~q_cE!|^A;_MHB;7s#9 zKzMzK{lIxotjc};k67^Xsl-gS!^*m*m6kn|sbdun`O?dUkJ{0cmI0-_2y=lTAfn*Y zKg*A-2sJq)CCJgY0LF-VQvl&6HIXZyxo2#!O&6fOhbHXC?%1cMc6y^*dOS{f$=137Ds1m01qs`>iUQ49JijsaQ( zksqV9@&?il$|4Ua%4!O15>Zy&%gBY&wgqB>XA3!EldQ%1CRSM(pp#k~-pkcCg4LAT zXE=puHbgsw)!xtc@P4r~Z}nTF=D2~j(6D%gTBw$(`Fc=OOQ0kiW$_RDd=hcO0t97h zb86S5r=>(@VGy1&#S$Kg_H@7G^;8Ue)X5Y+IWUi`o;mpvoV)`fcVk4FpcT|;EG!;? zHG^zrVVZOm>1KFaHlaogcWj(v!S)O(Aa|Vo?S|P z5|6b{qkH(USa*Z7-y_Uvty_Z1|B{rTS^qmEMLEYUSk03_Fg&!O3BMo{b^*`3SHvl0 zhnLTe^_vVIdcSHe)SQE}r~2dq)VZJ!aSKR?RS<(9lzkYo&dQ?mubnWmgMM37Nudwo z3Vz@R{=m2gENUE3V4NbIzAA$H1z0pagz94-PTJyX{b$yndsdKptmlKQKaaHj@3=ED zc7L?p@%ui|RegVYutK$64q4pe9+5sv34QUpo)u{1ci?)_7gXQd{PL>b0l(LI#rJmN zGuO+%GO`xneFOOr4EU(Wg}_%bhzUf;d@TU+V*2#}!2OLwg~%D;1FAu=Un>OgjPb3S z7l(riiCwgghC=Lm5hWGf5NdGp#01xQ59`HJcLXbUR3&n%P(+W2q$h2Qd z*6+-QXJ*&Kvk9ht0f0*rO_|FMBALen{j7T1l%=Q>gf#kma zQlg#I9+HB+z*5BMxdesMND`_W;q5|FaEURFk|~&{@qY32N$G$2B=&Po{=!)x5b!#n zxLzblkq{yj05#O7(GRuT39(06FJlalyv<#K4m}+vs>9@q-&31@1(QBv82{}Zkns~K ze{eHC_RDX0#^A*JQTwF`a=IkE6Ze@j#-8Q`tTT?k9`^ZhA~3eCZJ-Jr{~7Cx;H4A3 zcZ+Zj{mzFZbVvQ6U~n>$U2ZotGsERZ@}VKrgGh0xM;Jzt29%TX6_&CWzg+YYMozrM z`nutuS)_0dCM8UVaKRj804J4i%z2BA_8A4OJRQ$N(P9Mfn-gF;4#q788C@9XR0O3< zsoS4wIoyt046d+LnSCJOy@B@Uz*#GGd#+Ln1ek5Dv>(ZtD@tgZlPnZZJGBLr^JK+!$$?A_fA3LOrkoDRH&l7 zcMcD$Hsjko3`-{bn)jPL6E9Ds{WskMrivsUu5apD z?grQO@W7i5+%X&E&p|RBaEZ(sGLR@~(y^BI@lDMot^Ll?!`90KT!JXUhYS`ZgX3jnu@Ja^seA*M5R@f`=`ynQV4rc$uT1mvE?@tz)TN<=&H1%Z?5yjxcpO+6y_R z6EPuPKM5uxKpmZfT(WKjRRNHs@ib)F5WAP7QCADvmCSD#hPz$V10wiD&{NXyEwx5S z6NE`3z!IS^$s7m}PCwQutVQ#~w+V z=+~->DI*bR2j0^@dMr9`p>q^Ny~NrAVxrJtX2DUveic5vM%#N*XO|?YAWwNI$Q)_) zvE|L(L1jP@F%gOGtnlXtIv2&1i8q<)Xfz8O3G^Ea~e*HJsQgBxWL(yuLY+jqUK zRE~`-zklrGog(X}$9@ZVUw!8*=l`6mzYLtsg`AvBYz(cxmAhr^j0~(rzXdiOEeu_p zE$sf2(w(BPAvO5DlaN&uQ$4@p-b?fRs}d7&2UQ4Fh?1Hzu*YVjcndqJLw0#q@fR4u zJCJ}>_7-|QbvOfylj+e^_L`5Ep9gqd>XI3-O?Wp z-gt*P29f$Tx(mtS`0d05nHH=gm~Po_^OxxUwV294BDKT>PHVlC5bndncxGR!n(OOm znsNt@Q&N{TLrmsoKFw0&_M9$&+C24`sIXGWgQaz=kY;S{?w`z^Q0JXXBKFLj0w0U6P*+jPKyZHX9F#b0D1$&(- zrm8PJd?+SrVf^JlfTM^qGDK&-p2Kdfg?f>^%>1n8bu&byH(huaocL>l@f%c*QkX2i znl}VZ4R1en4S&Bcqw?$=Zi7ohqB$Jw9x`aM#>pHc0x z0$!q7iFu zZ`tryM70qBI6JWWTF9EjgG@>6SRzsd}3h+4D8d~@CR07P$LJ}MFsYi-*O%XVvD@yT|rJ+Mk zDllJ7$n0V&A!0flbOf)HE6P_afPWZmbhpliqJuw=-h+r;WGk|ntkWN(8tKlYpq5Ow z(@%s>IN8nHRaYb*^d;M(D$zGCv5C|uqmsDjwy4g=Lz>*OhO3z=)VD}C<65;`89Ye} zSCxrv#ILzIpEx1KdLPlM&%Cctf@FqTKvNPXC&`*H9=l=D3r!GLM?UV zOxa(8ZsB`&+76S-_xuj?G#wXBfDY@Z_tMpXJS7^mp z@YX&u0jYw2A+Z+bD#6sgVK5ZgdPSJV3>{K^4~%HV?rn~4D)*2H!67Y>0aOmzup`{D zzDp3c9yEbGCY$U<8biJ_gB*`jluz1ShUd!QUIQJ$*1;MXCMApJ^m*Fiv88RZ zFopLViw}{$Tyhh_{MLGIE2~sZ)t0VvoW%=8qKZ>h=adTe3QM$&$PO2lfqH@brt!9j ziePM8$!CgE9iz6B<6_wyTQj?qYa;eC^{x_0wuwV~W+^fZmFco-o%wsKSnjXFEx02V zF5C2t)T6Gw$Kf^_c;Ei3G~uC8SM-xyycmXyC2hAVi-IfXqhu$$-C=*|X?R0~hu z8`J6TdgflslhrmDZq1f?GXF7*ALeMmOEpRDg(s*H`4>_NAr`2uqF;k;JQ+8>A|_6ZNsNLECC%NNEb1Y1dP zbIEmNpK)#XagtL4R6BC{C5T(+=yA-(Z|Ap}U-AfZM#gwVpus3(gPn}Q$CExObJ5AC z)ff9Yk?wZ}dZ-^)?cbb9Fw#EjqQ8jxF4G3=L?Ra zg_)0QDMV1y^A^>HRI$x?Op@t;oj&H@1xt4SZ9(kifQ zb59B*`M99Td7@aZ3UWvj1rD0sE)d=BsBuW*KwkCds7ay(7*01_+L}b~7)VHI>F_!{ zyxg-&nCO?v#KOUec0{OOKy+sjWA;8rTE|Lv6I9H?CI?H(mUm8VXGwU$49LGpz&{nQp2}dinE1@lZ1iox6{ghN&v^GZv9J${7WaXj)<0S4g_uiJ&JCZ zr8-hsu`U%N;+9N^@&Q0^kVPB3)wY(rr}p7{p0qFHb3NUUHJb672+wRZs`gd1UjKPX z4o6zljKKA+Kkj?H>Ew63o%QjyBk&1!P22;MkD>sM0=z_s-G{mTixJCT9@_|*(p^bz zJ8?ZZ&;pzV+7#6Mn`_U-)k8Pjg?a;|Oe^us^PoPY$Va~yi8|?+&=y$f+lABT<*pZr zP}D{~Pq1Qyni+@|aP;ixO~mbEW9#c0OU#YbDZIaw=_&$K%Ep2f%hO^&P67hApZe`x zv8b`Mz@?M_7-)b!lkQKk)JXXUuT|B8kJlvqRmRpxtQDgvrHMXC1B$M@Y%Me!BSx3P z#2Eawl$HleZhhTS6Txm>lN_+I`>eV$&v9fOg)%zVn3O5mI*lAl>QcHuW6!Kixmq`X zBCZ*Ck6OYtDiK!N47>jxI&O2a9x7M|i^IagRr-fmrmikEQGgw%J7bO|)*$2FW95O4 zeBs>KR)izRG1gRVL;F*sr8A}aRHO0gc$$j&ds8CIO1=Gwq1%_~E)CWNn9pCtBE}+`Jelk4{>S)M)`Ll=!~gnn1yq^EX(+y*ik@3Ou0qU`IgYi3*doM+5&dU!cho$pZ zn%lhKeZkS72P?Cf68<#kll_6OAO26bIbueZx**j6o;I0cS^XiL`y+>{cD}gd%lux} z)3N>MaE24WBZ}s0ApfdM;5J_Ny}rfUyxfkC``Awo2#sgLnGPewK};dORuT?@I6(5~ z?kE)Qh$L&fwJXzK){iYx!l5$Tt|^D~MkGZPA}(o6f7w~O2G6Vvzdo*a;iXzk$B66$ zwF#;wM7A+(;uFG4+UAY(2`*3XXx|V$K8AYu#ECJYSl@S=uZW$ksfC$~qrrbQj4??z-)uz0QL}>k^?fPnJTPw% zGz)~?B4}u0CzOf@l^um}HZzbaIwPmb<)< zi_3@E9lc)Qe2_`*Z^HH;1CXOceL=CHpHS{HySy3T%<^NrWQ}G0i4e1xm_K3(+~oi$ zoHl9wzb?Z4j#90DtURtjtgvi7uw8DzHYmtPb;?%8vb9n@bszT=1qr)V_>R%s!92_` zfnHQPANx z<#hIjIMm#*(v*!OXtF+w8kLu`o?VZ5k7{`vw{Yc^qYclpUGIM_PBN1+c{#Vxv&E*@ zxg=W2W~JuV{IuRYw3>LSI1)a!thID@R=bU+cU@DbR^_SXY`MC7HOsCN z!dO4OKV7(E_Z8T#8MA1H`99?Z!r0)qKW_#|29X3#Jb+5+>qUidbeP1NJ@)(qi2S-X zao|f0_tl(O+$R|Qwd$H{_ig|~I1fbp_$NkI!0E;Y z6JrnU{1Ra6^on{9gUUB0mwzP3S%B#h0fjo>JvV~#+X0P~JV=IG=yHG$O+p5O3NUgG zEQ}z6BTp^Fie)Sg<){Z&I8NwPR(=mO4joTLHkJ>|Tnk23E(Bo`FSbPc05lF2-+)X? z6vV3*m~IBHTy*^E!<0nA(tCOJW2G4DsH7)BxLV8kICn5lu6@U*R`w)o9;Ro$i8=Q^V%uH8n3q=+Yf;SFRZu z!+F&PKcH#8cG?aSK_Tl@K9P#8o+jry@gdexz&d(Q=47<7nw@e@FFfIRNL9^)1i@;A z28+$Z#rjv-wj#heI|<&J_DiJ*s}xd-f!{J8jfqOHE`TiHHZVIA8CjkNQ_u;Ery^^t zl1I75&u^`1_q)crO+JT4rx|z2ToSC>)Or@-D zy3S>jW*sNIZR-EBsfyaJ+Jq4BQE4?SePtD2+jY8*%FsSLZ9MY>+wk?}}}AFAw)vr{ml)8LUG-y9>^t!{~|sgpxYc0Gnkg`&~R z-pilJZjr@y5$>B=VMdZ73svct%##v%wdX~9fz6i3Q-zOKJ9wso+h?VME7}SjL=!NUG{J?M&i!>ma`eoEa@IX`5G>B1(7;%}M*%-# zfhJ(W{y;>MRz!Ic8=S}VaBKqh;~7KdnGEHxcL$kA-6E~=!hrN*zw9N+_=odt<$_H_8dbo;0=42wcAETPCVGUr~v(`Uai zb{=D!Qc!dOEU6v)2eHSZq%5iqK?B(JlCq%T6av$Cb4Rko6onlG&?CqaX7Y_C_cOC3 zYZ;_oI(}=>_07}Oep&Ws7x7-R)cc8zfe!SYxJYP``pi$FDS)4Fvw5HH=FiU6xfVqIM!hJ;Rx8c0cB7~aPtNH(Nmm5Vh{ibAoU#J6 zImRCr?(iyu_4W_6AWo3*vxTPUw@vPwy@E0`(>1Qi=%>5eSIrp^`` zK*Y?fK_6F1W>-7UsB)RPC4>>Ps9)f+^MqM}8AUm@tZ->j%&h1M8s*s!LX5&WxQcAh z8mciQej@RPm?660%>{_D+7er>%zX_{s|$Z+;G7_sfNfBgY(zLB4Ey}J9F>zX#K0f6 z?dVNIeEh?EIShmP6>M+d|0wMM85Sa4diw1hrg|ITJ}JDg@o8y>(rF9mXk5M z2@D|NA)-7>wD&wF;S_$KS=eE84`BGw3g0?6wGxu8ys4rwI?9U=*^VF22t3%mbGeOh z`!O-OpF7#Vceu~F`${bW0nYVU9ecmk31V{tF%iv&5hWofC>I~cqAt@u6|R+|HLMMX zVxuSlMFOK_EQ86#E8&KwxIr8S9tj_goWtLv4f@!&h8;Ov41{J~496vp9vX=(LK#j! zAwi*21RAV-LD>9Cw3bV_9X(X3)Kr0-UaB*7Y>t82EQ%!)(&(XuAYtTsYy-dz+w=$ir)VJpe!_$ z6SGpX^i(af3{o=VlFPC);|J8#(=_8#vdxDe|Cok+ANhYwbE*FO`Su2m1~w+&9<_9~ z-|tTU_ACGN`~CNW5WYYBn^B#SwZ(t4%3aPp z;o)|L6Rk569KGxFLUPx@!6OOa+5OjQLK5w&nAmwxkC5rZ|m&HT8G%GVZxB_@ME z>>{rnXUqyiJrT(8GMj_ap#yN_!9-lO5e8mR3cJiK3NE{_UM&=*vIU`YkiL$1%kf+1 z4=jk@7EEj`u(jy$HnzE33ZVW_J4bj}K;vT?T91YlO(|Y0FU4r+VdbmQ97%(J5 zkK*Bed8+C}FcZ@HIgdCMioV%A<*4pw_n}l*{Cr4}a(lq|injK#O?$tyvyE`S%(1`H z_wwRvk#13ElkZvij2MFGOj`fhy?nC^8`Zyo%yVcUAfEr8x&J#A{|moUBAV_^f$hpaUuyQeY3da^ zS9iRgf87YBwfe}>BO+T&Fl%rfpZh#+AM?Dq-k$Bq`vG6G_b4z%Kbd&v>qFjow*mBl z-OylnqOpLg}or7_VNwRg2za3VBK6FUfFX{|TD z`Wt0Vm2H$vdlRWYQJqDmM?JUbVqL*ZQY|5&sY*?!&%P8qhA~5+Af<{MaGo(dl&C5t zE%t!J0 zh6jqANt4ABdPxSTrVV}fLsRQal*)l&_*rFq(Ez}ClEH6LHv{J#v?+H-BZ2)Wy{K@9 z+ovXHq~DiDvm>O~r$LJo!cOuwL+Oa--6;UFE2q@g3N8Qkw5E>ytz^(&($!O47+i~$ zKM+tkAd-RbmP{s_rh+ugTD;lriL~`Xwkad#;_aM?nQ7L_muEFI}U_4$phjvYgleK~`Fo`;GiC07&Hq1F<%p;9Q;tv5b?*QnR%8DYJH3P>Svmv47Y>*LPZJy8_{9H`g6kQpyZU{oJ`m%&p~D=K#KpfoJ@ zn-3cqmHsdtN!f?~w+(t+I`*7GQA#EQC^lUA9(i6=i1PqSAc|ha91I%X&nXzjYaM{8$s&wEx@aVkQ6M{E2 zfzId#&r(XwUNtPcq4Ngze^+XaJA1EK-%&C9j>^9(secqe{}z>hR5CFNveMsVA)m#S zk)_%SidkY-XmMWlVnQ(mNJ>)ooszQ#vaK;!rPmGKXV7am^_F!Lz>;~{VrIO$;!#30XRhE1QqO_~#+Ux;B_D{Nk=grn z8Y0oR^4RqtcYM)7a%@B(XdbZCOqnX#fD{BQTeLvRHd(irHKq=4*jq34`6@VAQR8WG z^%)@5CXnD_T#f%@-l${>y$tfb>2LPmc{~5A82|16mH)R?&r#KKLs7xpN-D`=&Cm^R zvMA6#Ahr<3X>Q7|-qfTY)}32HkAz$_mibYV!I)u>bmjK`qwBe(>za^0Kt*HnFbSdO z1>+ryKCNxmm^)*$XfiDOF2|{-v3KKB?&!(S_Y=Ht@|ir^hLd978xuI&N{k>?(*f8H z=ClxVJK_%_z1TH0eUwm2J+2To7FK4o+n_na)&#VLn1m;!+CX+~WC+qg1?PA~KdOlC zW)C@pw75_xoe=w7i|r9KGIvQ$+3K?L{7TGHwrQM{dCp=Z*D}3kX7E-@sZnup!BImw z*T#a=+WcTwL78exTgBn|iNE3#EsOorO z*kt)gDzHiPt07fmisA2LWN?AymkdqTgr?=loT7z@d`wnlr6oN}@o|&JX!yPzC*Y8d zu6kWlTzE1)ckyBn+0Y^HMN+GA$wUO_LN6W>mxCo!0?oiQvT`z$jbSEu&{UHRU0E8# z%B^wOc@S!yhMT49Y)ww(Xta^8pmPCe@eI5C*ed96)AX9<>))nKx0(sci8gwob_1}4 z0DIL&vsJ1_s%<@y%U*-eX z5rN&(zef-5G~?@r79oZGW1d!WaTqQn0F6RIOa9tJ=0(kdd{d1{<*tHT#cCvl*i>YY zH+L7jq8xZNcTUBqj(S)ztTU!TM!RQ}In*n&Gn<>(60G7}4%WQL!o>hbJqNDSGwl#H z`4k+twp0cj%PsS+NKaxslAEu9!#U3xT1|_KB6`h=PI0SW`P9GTa7caD1}vKEglV8# zjKZR`pluCW19c2fM&ZG)c3T3Um;ir3y(tSCJ7Agl6|b524dy5El{^EQBG?E61H0XY z`bqg!;zhGhyMFl&(o=JWEJ8n~z)xI}A@C0d2hQGvw7nGv)?POU@(kS1m=%`|+^ika zXl8zjS?xqW$WlO?Ewa;vF~XbybHBor$f<%I&*t$F5fynwZlTGj|IjZtVfGa7l&tK} zW>I<69w(cZLu)QIVG|M2xzW@S+70NinQzk&Y0+3WT*cC)rx~04O-^<{JohU_&HL5XdUKW!uFy|i$FB|EMu0eUyW;gsf`XfIc!Z0V zeK&*hPL}f_cX=@iv>K%S5kL;cl_$v?n(Q9f_cChk8Lq$glT|=e+T*8O4H2n<=NGmn z+2*h+v;kBvF>}&0RDS>)B{1!_*XuE8A$Y=G8w^qGMtfudDBsD5>T5SB;Qo}fSkkiV ze^K^M(UthkwrD!&*tTsu>Dacdj_q`~V%r_twr$(Ct&_dKeeXE?fA&4&yASJWJ*}~- zel=@W)tusynfC_YqH4ll>4Eg`Xjs5F7Tj>tTLz<0N3)X<1px_d2yUY>X~y>>93*$) z5PuNMQLf9Bu?AAGO~a_|J2akO1M*@VYN^VxvP0F$2>;Zb9;d5Yfd8P%oFCCoZE$ z4#N$^J8rxYjUE_6{T%Y>MmWfHgScpuGv59#4u6fpTF%~KB^Ae`t1TD_^Ud#DhL+Dm zbY^VAM#MrAmFj{3-BpVSWph2b_Y6gCnCAombVa|1S@DU)2r9W<> zT5L8BB^er3zxKt1v(y&OYk!^aoQisqU zH(g@_o)D~BufUXcPt!Ydom)e|aW{XiMnes2z&rE?og>7|G+tp7&^;q?Qz5S5^yd$i z8lWr4g5nctBHtigX%0%XzIAB8U|T6&JsC4&^hZBw^*aIcuNO47de?|pGXJ4t}BB`L^d8tD`H`i zqrP8?#J@8T#;{^B!KO6J=@OWKhAerih(phML`(Rg7N1XWf1TN>=Z3Do{l_!d~DND&)O)D>ta20}@Lt77qSnVsA7>)uZAaT9bsB>u&aUQl+7GiY2|dAEg@%Al3i316y;&IhQL^8fw_nwS>f60M_-m+!5)S_6EPM7Y)(Nq^8gL7(3 zOiot`6Wy6%vw~a_H?1hLVzIT^i1;HedHgW9-P#)}Y6vF%C=P70X0Tk^z9Te@kPILI z_(gk!k+0%CG)%!WnBjjw*kAKs_lf#=5HXC00s-}oM-Q1aXYLj)(1d!_a7 z*Gg4Fe6F$*ujVjI|79Z5+Pr`us%zW@ln++2l+0hsngv<{mJ%?OfSo_3HJXOCys{Ug z00*YR-(fv<=&%Q!j%b-_ppA$JsTm^_L4x`$k{VpfLI(FMCap%LFAyq;#ns5bR7V+x zO!o;c5y~DyBPqdVQX)8G^G&jWkBy2|oWTw>)?5u}SAsI$RjT#)lTV&Rf8;>u*qXnb z8F%Xb=7#$m)83z%`E;49)t3fHInhtc#kx4wSLLms!*~Z$V?bTyUGiS&m>1P(952(H zuHdv=;o*{;5#X-uAyon`hP}d#U{uDlV?W?_5UjJvf%11hKwe&(&9_~{W)*y1nR5f_ z!N(R74nNK`y8>B!0Bt_Vr!;nc3W>~RiKtGSBkNlsR#-t^&;$W#)f9tTlZz>n*+Fjz z3zXZ;jf(sTM(oDzJt4FJS*8c&;PLTW(IQDFs_5QPy+7yhi1syPCarvqrHFcf&yTy)^O<1EBx;Ir`5W{TIM>{8w&PB>ro4;YD<5LF^TjTb0!zAP|QijA+1Vg>{Afv^% zmrkc4o6rvBI;Q8rj4*=AZacy*n8B{&G3VJc)so4$XUoie0)vr;qzPZVbb<#Fc=j+8CGBWe$n|3K& z_@%?{l|TzKSlUEO{U{{%Fz_pVDxs7i9H#bnbCw7@4DR=}r_qV!Zo~CvD4ZI*+j3kO zW6_=|S`)(*gM0Z;;}nj`73OigF4p6_NPZQ-Od~e$c_);;4-7sR>+2u$6m$Gf%T{aq zle>e3(*Rt(TPD}03n5)!Ca8Pu!V}m6v0o1;5<1h$*|7z|^(3$Y&;KHKTT}hV056wuF0Xo@mK-52~r=6^SI1NC%c~CC?n>yX6wPTgiWYVz!Sx^atLby9YNn1Rk{g?|pJaxD4|9cUf|V1_I*w zzxK)hRh9%zOl=*$?XUjly5z8?jPMy%vEN)f%T*|WO|bp5NWv@B(K3D6LMl!-6dQg0 zXNE&O>Oyf%K@`ngCvbGPR>HRg5!1IV$_}m@3dWB7x3t&KFyOJn9pxRXCAzFr&%37wXG;z^xaO$ekR=LJG ztIHpY8F5xBP{mtQidqNRoz= z@){+N3(VO5bD+VrmS^YjG@+JO{EOIW)9=F4v_$Ed8rZtHvjpiEp{r^c4F6Ic#ChlC zJX^DtSK+v(YdCW)^EFcs=XP7S>Y!4=xgmv>{S$~@h=xW-G4FF9?I@zYN$e5oF9g$# zb!eVU#J+NjLyX;yb)%SY)xJdvGhsnE*JEkuOVo^k5PyS=o#vq!KD46UTW_%R=Y&0G zFj6bV{`Y6)YoKgqnir2&+sl+i6foAn-**Zd1{_;Zb7Ki=u394C5J{l^H@XN`_6XTKY%X1AgQM6KycJ+= zYO=&t#5oSKB^pYhNdzPgH~aEGW2=ec1O#s-KG z71}LOg@4UEFtp3GY1PBemXpNs6UK-ax*)#$J^pC_me;Z$Je(OqLoh|ZrW*mAMBFn< zHttjwC&fkVfMnQeen8`Rvy^$pNRFVaiEN4Pih*Y3@jo!T0nsClN)pdrr9AYLcZxZ| zJ5Wlj+4q~($hbtuY zVQ7hl>4-+@6g1i`1a)rvtp-;b0>^`Dloy(#{z~ytgv=j4q^Kl}wD>K_Y!l~ zp(_&7sh`vfO(1*MO!B%<6E_bx1)&s+Ae`O)a|X=J9y~XDa@UB`m)`tSG4AUhoM=5& znWoHlA-(z@3n0=l{E)R-p8sB9XkV zZ#D8wietfHL?J5X0%&fGg@MH~(rNS2`GHS4xTo7L$>TPme+Is~!|79=^}QbPF>m%J zFMkGzSndiPO|E~hrhCeo@&Ea{M(ieIgRWMf)E}qeTxT8Q#g-!Lu*x$v8W^M^>?-g= zwMJ$dThI|~M06rG$Sv@C@tWR>_YgaG&!BAbkGggVQa#KdtDB)lMLNVLN|51C@F^y8 zCRvMB^{GO@j=cHfmy}_pCGbP%xb{pNN>? z?7tBz$1^zVaP|uaatYaIN+#xEN4jBzwZ|YI_)p(4CUAz1ZEbDk>J~Y|63SZaak~#0 zoYKruYsWHoOlC1(MhTnsdUOwQfz5p6-D0}4;DO$B;7#M{3lSE^jnTT;ns`>!G%i*F?@pR1JO{QTuD0U+~SlZxcc8~>IB{)@8p`P&+nDxNj`*gh|u?yrv$phpQcW)Us)bi`kT%qLj(fi{dWRZ%Es2!=3mI~UxiW0$-v3vUl?#g{p6eF zMEUAqo5-L0Ar(s{VlR9g=j7+lt!gP!UN2ICMokAZ5(Agd>})#gkA2w|5+<%-CuEP# zqgcM}u@3(QIC^Gx<2dbLj?cFSws_f3e%f4jeR?4M^M3cx1f+Qr6ydQ>n)kz1s##2w zk}UyQc+Z5G-d-1}{WzjkLXgS-2P7auWSJ%pSnD|Uivj5u!xk0 z_^-N9r9o;(rFDt~q1PvE#iJZ_f>J3gcP$)SOqhE~pD2|$=GvpL^d!r z6u=sp-CrMoF7;)}Zd7XO4XihC4ji?>V&(t^?@3Q&t9Mx=qex6C9d%{FE6dvU6%d94 zIE;hJ1J)cCqjv?F``7I*6bc#X)JW2b4f$L^>j{*$R`%5VHFi*+Q$2;nyieduE}qdS{L8y8F08yLs?w}{>8>$3236T-VMh@B zq-nujsb_1aUv_7g#)*rf9h%sFj*^mIcImRV*k~Vmw;%;YH(&ylYpy!&UjUVqqtfG` zox3esju?`unJJA_zKXRJP)rA3nXc$m^{S&-p|v|-0x9LHJm;XIww7C#R$?00l&Yyj z=e}gKUOpsImwW?N)+E(awoF@HyP^EhL+GlNB#k?R<2>95hz!h9sF@U20DHSB3~WMa zk90+858r@-+vWwkawJ)8ougd(i#1m3GLN{iSTylYz$brAsP%=&m$mQQrH$g%3-^VR zE%B`Vi&m8f3T~&myTEK28BDWCVzfWir1I?03;pX))|kY5ClO^+bae z*7E?g=3g7EiisYOrE+lA)2?Ln6q2*HLNpZEWMB|O-JI_oaHZB%CvYB(%=tU= zE*OY%QY58fW#RG5=gm0NR#iMB=EuNF@)%oZJ}nmm=tsJ?eGjia{e{yuU0l3{d^D@)kVDt=1PE)&tf_hHC%0MB znL|CRCPC}SeuVTdf>-QV70`0(EHizc21s^sU>y%hW0t!0&y<7}Wi-wGy>m%(-jsDj zP?mF|>p_K>liZ6ZP(w5(|9Ga%>tLgb$|doDDfkdW>Z z`)>V2XC?NJT26mL^@ zf+IKr27TfM!UbZ@?zRddC7#6ss1sw%CXJ4FWC+t3lHZupzM77m^=9 z&(a?-LxIq}*nvv)y?27lZ{j zifdl9hyJudyP2LpU$-kXctshbJDKS{WfulP5Dk~xU4Le4c#h^(YjJit4#R8_khheS z|8(>2ibaHES4+J|DBM7I#QF5u-*EdN{n=Kt@4Zt?@Tv{JZA{`4 zU#kYOv{#A&gGPwT+$Ud}AXlK3K7hYzo$(fBSFjrP{QQ zeaKg--L&jh$9N}`pu{Bs>?eDFPaWY4|9|foN%}i;3%;@4{dc+iw>m}{3rELqH21G! z`8@;w-zsJ1H(N3%|1B@#ioLOjib)j`EiJqPQVSbPSPVHCj6t5J&(NcWzBrzCiDt{4 zdlPAUKldz%6x5II1H_+jv)(xVL+a;P+-1hv_pM>gMRr%04@k;DTokASSKKhU1Qms| zrWh3a!b(J3n0>-tipg{a?UaKsP7?+|@A+1WPDiQIW1Sf@qDU~M_P65_s}7(gjTn0X zucyEm)o;f8UyshMy&>^SC3I|C6jR*R_GFwGranWZe*I>K+0k}pBuET&M~ z;Odo*ZcT?ZpduHyrf8E%IBFtv;JQ!N_m>!sV6ly$_1D{(&nO~w)G~Y`7sD3#hQk%^ zp}ucDF_$!6DAz*PM8yE(&~;%|=+h(Rn-=1Wykas_-@d&z#=S}rDf`4w(rVlcF&lF! z=1)M3YVz7orwk^BXhslJ8jR);sh^knJW(Qmm(QdSgIAIdlN4Te5KJisifjr?eB{FjAX1a0AB>d?qY4Wx>BZ8&}5K0fA+d{l8 z?^s&l8#j7pR&ijD?0b%;lL9l$P_mi2^*_OL+b}4kuLR$GAf85sOo02?Y#90}CCDiS zZ%rbCw>=H~CBO=C_JVV=xgDe%b4FaEFtuS7Q1##y686r%F6I)s-~2(}PWK|Z8M+Gu zl$y~5@#0Ka%$M<&Cv%L`a8X^@tY&T7<0|(6dNT=EsRe0%kp1Qyq!^43VAKYnr*A5~ zsI%lK1ewqO;0TpLrT9v}!@vJK{QoVa_+N4FYT#h?Y8rS1S&-G+m$FNMP?(8N`MZP zels(*?kK{{^g9DOzkuZXJ2;SrOQsp9T$hwRB1(phw1c7`!Q!by?Q#YsSM#I12RhU{$Q+{xj83axHcftEc$mNJ8_T7A-BQc*k(sZ+~NsO~xAA zxnbb%dam_fZlHvW7fKXrB~F&jS<4FD2FqY?VG?ix*r~MDXCE^WQ|W|WM;gsIA4lQP zJ2hAK@CF*3*VqPr2eeg6GzWFlICi8S>nO>5HvWzyZTE)hlkdC_>pBej*>o0EOHR|) z$?};&I4+_?wvL*g#PJ9)!bc#9BJu1(*RdNEn>#Oxta(VWeM40ola<0aOe2kSS~{^P zDJBd}0L-P#O-CzX*%+$#v;(x%<*SPgAje=F{Zh-@ucd2DA(yC|N_|ocs*|-!H%wEw z@Q!>siv2W;C^^j^59OAX03&}&D*W4EjCvfi(ygcL#~t8XGa#|NPO+*M@Y-)ctFA@I z-p7npT1#5zOLo>7q?aZpCZ=iecn3QYklP;gF0bq@>oyBq94f6C=;Csw3PkZ|5q=(c zfs`aw?II0e(h=|7o&T+hq&m$; zBrE09Twxd9BJ2P+QPN}*OdZ-JZV7%av@OM7v!!NL8R;%WFq*?{9T3{ct@2EKgc8h) zMxoM$SaF#p<`65BwIDfmXG6+OiK0e)`I=!A3E`+K@61f}0e z!2a*FOaDrOe>U`q%K!QN`&=&0C~)CaL3R4VY(NDt{Xz(Xpqru5=r#uQN1L$Je1*dkdqQ*=lofQaN%lO!<5z9ZlHgxt|`THd>2 zsWfU$9=p;yLyJyM^t zS2w9w?Bpto`@H^xJpZDKR1@~^30Il6oFGfk5%g6w*C+VM)+%R@gfIwNprOV5{F^M2 zO?n3DEzpT+EoSV-%OdvZvNF+pDd-ZVZ&d8 zKeIyrrfPN=EcFRCPEDCVflX#3-)Ik_HCkL(ejmY8vzcf-MTA{oHk!R2*36`O68$7J zf}zJC+bbQk--9Xm!u#lgLvx8TXx2J258E5^*IZ(FXMpq$2LUUvhWQPs((z1+2{Op% z?J}9k5^N=z;7ja~zi8a_-exIqWUBJwohe#4QJ`|FF*$C{lM18z^#hX6!5B8KAkLUX ziP=oti-gpV(BsLD{0(3*dw}4JxK23Y7M{BeFPucw!sHpY&l%Ws4pSm`+~V7;bZ%Dx zeI)MK=4vC&5#;2MT7fS?^ch9?2;%<8Jlu-IB&N~gg8t;6S-#C@!NU{`p7M8@2iGc& zg|JPg%@gCoCQ&s6JvDU&`X2S<57f(k8nJ1wvBu{8r?;q3_kpZZ${?|( z+^)UvR33sjSd)aT!UPkA;ylO6{aE3MQa{g%Mcf$1KONcjO@&g5zPHWtzM1rYC{_K> zgQNcs<{&X{OA=cEWw5JGqpr0O>x*Tfak2PE9?FuWtz^DDNI}rwAaT0(bdo-<+SJ6A z&}S%boGMWIS0L}=S>|-#kRX;e^sUsotry(MjE|3_9duvfc|nwF#NHuM-w7ZU!5ei8 z6Mkf>2)WunY2eU@C-Uj-A zG(z0Tz2YoBk>zCz_9-)4a>T46$(~kF+Y{#sA9MWH%5z#zNoz)sdXq7ZR_+`RZ%0(q zC7&GyS_|BGHNFl8Xa%@>iWh%Gr?=J5<(!OEjauj5jyrA-QXBjn0OAhJJ9+v=!LK`` z@g(`^*84Q4jcDL`OA&ZV60djgwG`|bcD*i50O}Q{9_noRg|~?dj%VtKOnyRs$Uzqg z191aWoR^rDX#@iSq0n z?9Sg$WSRPqSeI<}&n1T3!6%Wj@5iw5`*`Btni~G=&;J+4`7g#OQTa>u`{4ZZ(c@s$ zK0y;ySOGD-UTjREKbru{QaS>HjN<2)R%Nn-TZiQ(Twe4p@-saNa3~p{?^V9Nixz@a zykPv~<@lu6-Ng9i$Lrk(xi2Tri3q=RW`BJYOPC;S0Yly%77c727Yj-d1vF!Fuk{Xh z)lMbA69y7*5ufET>P*gXQrxsW+ zz)*MbHZv*eJPEXYE<6g6_M7N%#%mR{#awV3i^PafNv(zyI)&bH?F}2s8_rR(6%!V4SOWlup`TKAb@ee>!9JKPM=&8g#BeYRH9FpFybxBXQI2|g}FGJfJ+ zY-*2hB?o{TVL;Wt_ek;AP5PBqfDR4@Z->_182W z{P@Mc27j6jE*9xG{R$>6_;i=y{qf(c`5w9fa*`rEzX6t!KJ(p1H|>J1pC-2zqWENF zmm=Z5B4u{cY2XYl(PfrInB*~WGWik3@1oRhiMOS|D;acnf-Bs(QCm#wR;@Vf!hOPJ zgjhDCfDj$HcyVLJ=AaTbQ{@vIv14LWWF$=i-BDoC11}V;2V8A`S>_x)vIq44-VB-v z*w-d}$G+Ql?En8j!~ZkCpQ$|cA0|+rrY>tiCeWxkRGPoarxlGU2?7%k#F693RHT24 z-?JsiXlT2PTqZqNb&sSc>$d;O4V@|b6VKSWQb~bUaWn1Cf0+K%`Q&Wc<>mQ>*iEGB zbZ;aYOotBZ{vH3y<0A*L0QVM|#rf*LIsGx(O*-7)r@yyBIzJnBFSKBUSl1e|8lxU* zzFL+YDVVkIuzFWeJ8AbgN&w(4-7zbiaMn{5!JQXu)SELk*CNL+Fro|2v|YO)1l15t zs(0^&EB6DPMyaqvY>=KL>)tEpsn;N5Q#yJj<9}ImL((SqErWN3Q=;tBO~ExTCs9hB z2E$7eN#5wX4<3m^5pdjm#5o>s#eS_Q^P)tm$@SawTqF*1dj_i#)3};JslbLKHXl_N z)Fxzf>FN)EK&Rz&*|6&%Hs-^f{V|+_vL1S;-1K-l$5xiC@}%uDuwHYhmsV?YcOUlk zOYkG5v2+`+UWqpn0aaaqrD3lYdh0*!L`3FAsNKu=Q!vJu?Yc8n|CoYyDo_`r0mPoo z8>XCo$W4>l(==h?2~PoRR*kEe)&IH{1sM41mO#-36`02m#nTX{r*r`Q5rZ2-sE|nA zhnn5T#s#v`52T5|?GNS`%HgS2;R(*|^egNPDzzH_z^W)-Q98~$#YAe)cEZ%vge965AS_am#DK#pjPRr-!^za8>`kksCAUj(Xr*1NW5~e zpypt_eJpD&4_bl_y?G%>^L}=>xAaV>KR6;^aBytqpiHe%!j;&MzI_>Sx7O%F%D*8s zSN}cS^<{iiK)=Ji`FpO#^zY!_|D)qeRNAtgmH)m;qC|mq^j(|hL`7uBz+ULUj37gj zksdbnU+LSVo35riSX_4z{UX=%n&}7s0{WuZYoSfwAP`8aKN9P@%e=~1`~1ASL-z%# zw>DO&ixr}c9%4InGc*_y42bdEk)ZdG7-mTu0bD@_vGAr*NcFoMW;@r?@LUhRI zCUJgHb`O?M3!w)|CPu~ej%fddw20lod?Ufp8Dmt0PbnA0J%KE^2~AIcnKP()025V> zG>noSM3$5Btmc$GZoyP^v1@Poz0FD(6YSTH@aD0}BXva?LphAiSz9f&Y(aDAzBnUh z?d2m``~{z;{}kZJ>a^wYI?ry(V9hIoh;|EFc0*-#*`$T0DRQ1;WsqInG;YPS+I4{g zJGpKk%%Sdc5xBa$Q^_I~(F97eqDO7AN3EN0u)PNBAb+n+ zWBTxQx^;O9o0`=g+Zrt_{lP!sgWZHW?8bLYS$;1a@&7w9rD9|Ge;Gb?sEjFoF9-6v z#!2)t{DMHZ2@0W*fCx;62d#;jouz`R5Y(t{BT=$N4yr^^o$ON8d{PQ=!O zX17^CrdM~7D-;ZrC!||<+FEOxI_WI3CA<35va%4v>gc zEX-@h8esj=a4szW7x{0g$hwoWRQG$yK{@3mqd-jYiVofJE!Wok1* znV7Gm&Ssq#hFuvj1sRyHg(6PFA5U*Q8Rx>-blOs=lb`qa{zFy&n4xY;sd$fE+<3EI z##W$P9M{B3c3Si9gw^jlPU-JqD~Cye;wr=XkV7BSv#6}DrsXWFJ3eUNrc%7{=^sP> zrp)BWKA9<}^R9g!0q7yWlh;gr_TEOD|#BmGq<@IV;ueg+D2}cjpp+dPf&Q(36sFU&K8}hA85U61faW&{ zlB`9HUl-WWCG|<1XANN3JVAkRYvr5U4q6;!G*MTdSUt*Mi=z_y3B1A9j-@aK{lNvx zK%p23>M&=KTCgR!Ee8c?DAO2_R?B zkaqr6^BSP!8dHXxj%N1l+V$_%vzHjqvu7p@%Nl6;>y*S}M!B=pz=aqUV#`;h%M0rU zHfcog>kv3UZAEB*g7Er@t6CF8kHDmKTjO@rejA^ULqn!`LwrEwOVmHx^;g|5PHm#B zZ+jjWgjJ!043F+&#_;D*mz%Q60=L9Ove|$gU&~As5^uz@2-BfQ!bW)Khn}G+Wyjw- z19qI#oB(RSNydn0t~;tAmK!P-d{b-@@E5|cdgOS#!>%#Rj6ynkMvaW@37E>@hJP^8 z2zk8VXx|>#R^JCcWdBCy{0nPmYFOxN55#^-rlqobe0#L6)bi?E?SPymF*a5oDDeSd zO0gx?#KMoOd&G(2O@*W)HgX6y_aa6iMCl^~`{@UR`nMQE`>n_{_aY5nA}vqU8mt8H z`oa=g0SyiLd~BxAj2~l$zRSDHxvDs;I4>+M$W`HbJ|g&P+$!U7-PHX4RAcR0szJ*( ze-417=bO2q{492SWrqDK+L3#ChUHtz*@MP)e^%@>_&#Yk^1|tv@j4%3T)diEX zATx4K*hcO`sY$jk#jN5WD<=C3nvuVsRh||qDHnc~;Kf59zr0;c7VkVSUPD%NnnJC_ zl3F^#f_rDu8l}l8qcAz0FFa)EAt32IUy_JLIhU_J^l~FRH&6-ivSpG2PRqzDdMWft>Zc(c)#tb%wgmWN%>IOPm zZi-noqS!^Ftb81pRcQi`X#UhWK70hy4tGW1mz|+vI8c*h@ zfFGJtW3r>qV>1Z0r|L>7I3un^gcep$AAWfZHRvB|E*kktY$qQP_$YG60C@X~tTQjB3%@`uz!qxtxF+LE!+=nrS^07hn` zEgAp!h|r03h7B!$#OZW#ACD+M;-5J!W+{h|6I;5cNnE(Y863%1(oH}_FTW})8zYb$7czP zg~Szk1+_NTm6SJ0MS_|oSz%e(S~P-&SFp;!k?uFayytV$8HPwuyELSXOs^27XvK-D zOx-Dl!P|28DK6iX>p#Yb%3`A&CG0X2S43FjN%IB}q(!hC$fG}yl1y9W&W&I@KTg6@ zK^kpH8=yFuP+vI^+59|3%Zqnb5lTDAykf z9S#X`3N(X^SpdMyWQGOQRjhiwlj!0W-yD<3aEj^&X%=?`6lCy~?`&WSWt z?U~EKFcCG_RJ(Qp7j=$I%H8t)Z@6VjA#>1f@EYiS8MRHZphp zMA_5`znM=pzUpBPO)pXGYpQ6gkine{6u_o!P@Q+NKJ}k!_X7u|qfpAyIJb$_#3@wJ z<1SE2Edkfk9C!0t%}8Yio09^F`YGzpaJHGk*-ffsn85@)%4@`;Fv^8q(-Wk7r=Q8p zT&hD`5(f?M{gfzGbbwh8(}G#|#fDuk7v1W)5H9wkorE0ZZjL0Q1=NRGY>zwgfm81DdoaVwNH;or{{eSyybt)m<=zXoA^RALYG-2t zouH|L*BLvmm9cdMmn+KGopyR@4*=&0&4g|FLoreZOhRmh=)R0bg~ zT2(8V_q7~42-zvb)+y959OAv!V$u(O3)%Es0M@CRFmG{5sovIq4%8Ahjk#*5w{+)+ zMWQoJI_r$HxL5km1#6(e@{lK3Udc~n0@g`g$s?VrnQJ$!oPnb?IHh-1qA`Rz$)Ai< z6w$-MJW-gKNvOhL+XMbE7&mFt`x1KY>k4(!KbbpZ`>`K@1J<(#vVbjx@Z@(6Q}MF# zMnbr-f55(cTa^q4+#)=s+ThMaV~E`B8V=|W_fZWDwiso8tNMTNse)RNBGi=gVwgg% zbOg8>mbRN%7^Um-7oj4=6`$|(K7!+t^90a{$18Z>}<#!bm%ZEFQ{X(yBZMc>lCz0f1I2w9Sq zuGh<9<=AO&g6BZte6hn>Qmvv;Rt)*cJfTr2=~EnGD8P$v3R|&1RCl&7)b+`=QGapi zPbLg_pxm`+HZurtFZ;wZ=`Vk*do~$wB zxoW&=j0OTbQ=Q%S8XJ%~qoa3Ea|au5o}_(P;=!y-AjFrERh%8la!z6Fn@lR?^E~H12D?8#ht=1F;7@o4$Q8GDj;sSC%Jfn01xgL&%F2 zwG1|5ikb^qHv&9hT8w83+yv&BQXOQyMVJSBL(Ky~p)gU3#%|blG?IR9rP^zUbs7rOA0X52Ao=GRt@C&zlyjNLv-} z9?*x{y(`509qhCV*B47f2hLrGl^<@SuRGR!KwHei?!CM10Tq*YDIoBNyRuO*>3FU? zHjipIE#B~y3FSfOsMfj~F9PNr*H?0oHyYB^G(YyNh{SxcE(Y-`x5jFMKb~HO*m+R% zrq|ic4fzJ#USpTm;X7K+E%xsT_3VHKe?*uc4-FsILUH;kL>_okY(w`VU*8+l>o>Jm ziU#?2^`>arnsl#)*R&nf_%>A+qwl%o{l(u)M?DK1^mf260_oteV3#E_>6Y4!_hhVD zM8AI6MM2V*^_M^sQ0dmHu11fy^kOqXqzpr?K$`}BKWG`=Es(9&S@K@)ZjA{lj3ea7_MBP zk(|hBFRjHVMN!sNUkrB;(cTP)T97M$0Dtc&UXSec<+q?y>5=)}S~{Z@ua;1xt@=T5 zI7{`Z=z_X*no8s>mY;>BvEXK%b`a6(DTS6t&b!vf_z#HM{Uoy_5fiB(zpkF{})ruka$iX*~pq1ZxD?q68dIo zIZSVls9kFGsTwvr4{T_LidcWtt$u{kJlW7moRaH6+A5hW&;;2O#$oKyEN8kx`LmG)Wfq4ykh+q{I3|RfVpkR&QH_x;t41Uw z`P+tft^E2B$domKT@|nNW`EHwyj>&}K;eDpe z1bNOh=fvIfk`&B61+S8ND<(KC%>y&?>opCnY*r5M+!UrWKxv0_QvTlJc>X#AaI^xo zaRXL}t5Ej_Z$y*|w*$6D+A?Lw-CO-$itm^{2Ct82-<0IW)0KMNvJHgBrdsIR0v~=H z?n6^}l{D``Me90`^o|q!olsF?UX3YSq^6Vu>Ijm>>PaZI8G@<^NGw{Cx&%|PwYrfw zR!gX_%AR=L3BFsf8LxI|K^J}deh0ZdV?$3r--FEX`#INxsOG6_=!v)DI>0q|BxT)z z-G6kzA01M?rba+G_mwNMQD1mbVbNTWmBi*{s_v_Ft9m2Avg!^78(QFu&n6mbRJ2bA zv!b;%yo{g*9l2)>tsZJOOp}U~8VUH`}$ z8p_}t*XIOehezolNa-a2x0BS})Y9}&*TPgua{Ewn-=wVrmJUeU39EKx+%w%=ixQWK zDLpwaNJs65#6o7Ln7~~X+p_o2BR1g~VCfxLzxA{HlWAI6^H;`juI=&r1jQrUv_q0Z z1Ja-tjdktrrP>GOC*#p?*xfQU5MqjMsBe!9lh(u8)w$e@Z|>aUHI5o;MGw*|Myiz3 z-f0;pHg~Q#%*Kx8MxH%AluVXjG2C$)WL-K63@Q`#y9_k_+}eR(x4~dp7oV-ek0H>I zgy8p#i4GN{>#v=pFYUQT(g&b$OeTy-X_#FDgNF8XyfGY6R!>inYn8IR2RDa&O!(6< znXs{W!bkP|s_YI*Yx%4stI`=ZO45IK6rBs`g7sP40ic}GZ58s?Mc$&i`kq_tfci>N zIHrC0H+Qpam1bNa=(`SRKjixBTtm&e`j9porEci!zdlg1RI0Jw#b(_Tb@RQK1Zxr_ z%7SUeH6=TrXt3J@js`4iDD0=IoHhK~I7^W8^Rcp~Yaf>2wVe|Hh1bUpX9ATD#moByY57-f2Ef1TP^lBi&p5_s7WGG9|0T}dlfxOx zXvScJO1Cnq`c`~{Dp;{;l<-KkCDE+pmexJkd}zCgE{eF=)K``-qC~IT6GcRog_)!X z?fK^F8UDz$(zFUrwuR$qro5>qqn>+Z%<5>;_*3pZ8QM|yv9CAtrAx;($>4l^_$_-L z*&?(77!-=zvnCVW&kUcZMb6;2!83si518Y%R*A3JZ8Is|kUCMu`!vxDgaWjs7^0j( ziTaS4HhQ)ldR=r)_7vYFUr%THE}cPF{0H45FJ5MQW^+W>P+eEX2kLp3zzFe*-pFVA zdDZRybv?H|>`9f$AKVjFWJ=wegO7hOOIYCtd?Vj{EYLT*^gl35|HQ`R=ti+ADm{jyQE7K@kdjuqJhWVSks>b^ zxha88-h3s;%3_5b1TqFCPTxVjvuB5U>v=HyZ$?JSk+&I%)M7KE*wOg<)1-Iy)8-K! z^XpIt|0ibmk9RtMmlUd7#Ap3Q!q9N4atQy)TmrhrFhfx1DAN`^vq@Q_SRl|V z#lU<~n67$mT)NvHh`%als+G-)x1`Y%4Bp*6Un5Ri9h=_Db zA-AdP!f>f0m@~>7X#uBM?diI@)Egjuz@jXKvm zJo+==juc9_<;CqeRaU9_Mz@;3e=E4=6TK+c`|uu#pIqhSyNm`G(X)&)B`8q0RBv#> z`gGlw(Q=1Xmf55VHj%C#^1lpc>LY8kfA@|rlC1EA<1#`iuyNO z(=;irt{_&K=i4)^x%;U(Xv<)+o=dczC5H3W~+e|f~{*ucxj@{Yi-cw^MqYr3fN zF5D+~!wd$#al?UfMnz(@K#wn`_5na@rRr8XqN@&M&FGEC@`+OEv}sI1hw>Up0qAWf zL#e4~&oM;TVfjRE+10B_gFlLEP9?Q-dARr3xi6nQqnw>k-S;~b z;!0s2VS4}W8b&pGuK=7im+t(`nz@FnT#VD|!)eQNp-W6)@>aA+j~K*H{$G`y2|QHY z|Hmy+CR@#jWY4~)lr1qBJB_RfHJFfP<}pK5(#ZZGSqcpyS&}01LnTWk5fzmXMGHkJ zTP6L^B+uj;lmB_W<~4=${+v0>z31M!-_O@o-O9GyW)j_mjx}!0@br_LE-7SIuPP84 z;5=O(U*g_um0tyG|61N@d9lEuOeiRd+#NY^{nd5;-CVlw&Ap7J?qwM^?E29wvS}2d zbzar4Fz&RSR(-|s!Z6+za&Z zY#D<5q_JUktIzvL0)yq_kLWG6DO{ri=?c!y!f(Dk%G{8)k`Gym%j#!OgXVDD3;$&v@qy#ISJfp=Vm>pls@9-mapVQChAHHd-x+OGx)(*Yr zC1qDUTZ6mM(b_hi!TuFF2k#8uI2;kD70AQ&di$L*4P*Y-@p`jdm%_c3f)XhYD^6M8&#Y$ZpzQMcR|6nsH>b=*R_Von!$BTRj7yGCXokoAQ z&ANvx0-Epw`QIEPgI(^cS2f(Y85yV@ygI{ewyv5Frng)e}KCZF7JbR(&W618_dcEh(#+^zZFY;o<815<5sOHQdeax9_!PyM&;{P zkBa5xymca0#)c#tke@3KNEM8a_mT&1gm;p&&JlMGH(cL(b)BckgMQ^9&vRwj!~3@l zY?L5}=Jzr080OGKb|y`ee(+`flQg|!lo6>=H)X4`$Gz~hLmu2a%kYW_Uu8x09Pa0J zKZ`E$BKJ=2GPj_3l*TEcZ*uYRr<*J^#5pILTT;k_cgto1ZL-%slyc16J~OH-(RgDA z%;EjEnoUkZ&acS{Q8`{i6T5^nywgqQI5bDIymoa7CSZG|WWVk>GM9)zy*bNih|QIm z%0+(Nnc*a_xo;$=!HQYaapLms>J1ToyjtFByY`C2H1wT#178#4+|{H0BBqtCdd$L% z_3Hc60j@{t9~MjM@LBalR&6@>B;9?r<7J~F+WXyYu*y3?px*=8MAK@EA+jRX8{CG?GI-< z54?Dc9CAh>QTAvyOEm0^+x;r2BWX|{3$Y7)L5l*qVE*y0`7J>l2wCmW zL1?|a`pJ-l{fb_N;R(Z9UMiSj6pQjOvQ^%DvhIJF!+Th7jO2~1f1N+(-TyCFYQZYw z4)>7caf^Ki_KJ^Zx2JUb z&$3zJy!*+rCV4%jqwyuNY3j1ZEiltS0xTzd+=itTb;IPYpaf?8Y+RSdVdpacB(bVQ zC(JupLfFp8y43%PMj2}T|VS@%LVp>hv4Y!RPMF?pp8U_$xCJ)S zQx!69>bphNTIb9yn*_yfj{N%bY)t{L1cs8<8|!f$;UQ*}IN=2<6lA;x^(`8t?;+ST zh)z4qeYYgZkIy{$4x28O-pugO&gauRh3;lti9)9Pvw+^)0!h~%m&8Q!AKX%urEMnl z?yEz?g#ODn$UM`+Q#$Q!6|zsq_`dLO5YK-6bJM6ya>}H+vnW^h?o$z;V&wvuM$dR& zeEq;uUUh$XR`TWeC$$c&Jjau2it3#%J-y}Qm>nW*s?En?R&6w@sDXMEr#8~$=b(gk zwDC3)NtAP;M2BW_lL^5ShpK$D%@|BnD{=!Tq)o(5@z3i7Z){} zGr}Exom_qDO{kAVkZ*MbLNHE666Kina#D{&>Jy%~w7yX$oj;cYCd^p9zy z8*+wgSEcj$4{WxKmCF(5o7U4jqwEvO&dm1H#7z}%VXAbW&W24v-tS6N3}qrm1OnE)fUkoE8yMMn9S$?IswS88tQWm4#Oid#ckgr6 zRtHm!mfNl-`d>O*1~d7%;~n+{Rph6BBy^95zqI{K((E!iFQ+h*C3EsbxNo_aRm5gj zKYug($r*Q#W9`p%Bf{bi6;IY0v`pB^^qu)gbg9QHQ7 zWBj(a1YSu)~2RK8Pi#C>{DMlrqFb9e_RehEHyI{n?e3vL_}L>kYJC z_ly$$)zFi*SFyNrnOt(B*7E$??s67EO%DgoZL2XNk8iVx~X_)o++4oaK1M|ou73vA0K^503j@uuVmLcHH4ya-kOIDfM%5%(E z+Xpt~#7y2!KB&)PoyCA+$~DXqxPxxALy!g-O?<9+9KTk4Pgq4AIdUkl`1<1#j^cJg zgU3`0hkHj_jxV>`Y~%LAZl^3o0}`Sm@iw7kwff{M%VwtN)|~!p{AsfA6vB5UolF~d zHWS%*uBDt<9y!9v2Xe|au&1j&iR1HXCdyCjxSgG*L{wmTD4(NQ=mFjpa~xooc6kju z`~+d{j7$h-;HAB04H!Zscu^hZffL#9!p$)9>sRI|Yovm)g@F>ZnosF2EgkU3ln0bR zTA}|+E(tt)!SG)-bEJi_0m{l+(cAz^pi}`9=~n?y&;2eG;d9{M6nj>BHGn(KA2n|O zt}$=FPq!j`p&kQ8>cirSzkU0c08%8{^Qyqi-w2LoO8)^E7;;I1;HQ6B$u0nNaX2CY zSmfi)F`m94zL8>#zu;8|{aBui@RzRKBlP1&mfFxEC@%cjl?NBs`cr^nm){>;$g?rhKr$AO&6qV_Wbn^}5tfFBry^e1`%du2~o zs$~dN;S_#%iwwA_QvmMjh%Qo?0?rR~6liyN5Xmej8(*V9ym*T`xAhHih-v$7U}8=dfXi2i*aAB!xM(Xekg*ix@r|ymDw*{*s0?dlVys2e)z62u1 z+k3esbJE=-P5S$&KdFp+2H7_2e=}OKDrf( z9-207?6$@f4m4B+9E*e((Y89!q?zH|mz_vM>kp*HGXldO0Hg#!EtFhRuOm$u8e~a9 z5(roy7m$Kh+zjW6@zw{&20u?1f2uP&boD}$#Zy)4o&T;vyBoqFiF2t;*g=|1=)PxB z8eM3Mp=l_obbc?I^xyLz?4Y1YDWPa+nm;O<$Cn;@ane616`J9OO2r=rZr{I_Kizyc zP#^^WCdIEp*()rRT+*YZK>V@^Zs=ht32x>Kwe zab)@ZEffz;VM4{XA6e421^h~`ji5r%)B{wZu#hD}f3$y@L0JV9f3g{-RK!A?vBUA}${YF(vO4)@`6f1 z-A|}e#LN{)(eXloDnX4Vs7eH|<@{r#LodP@Nz--$Dg_Par%DCpu2>2jUnqy~|J?eZ zBG4FVsz_A+ibdwv>mLp>P!(t}E>$JGaK$R~;fb{O3($y1ssQQo|5M;^JqC?7qe|hg zu0ZOqeFcp?qVn&Qu7FQJ4hcFi&|nR!*j)MF#b}QO^lN%5)4p*D^H+B){n8%VPUzi! zDihoGcP71a6!ab`l^hK&*dYrVYzJ0)#}xVrp!e;lI!+x+bfCN0KXwUAPU9@#l7@0& QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e750102..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100644 index c53aefa..0000000 --- a/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index ac1b06f..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega From 9a283890870ebf0728093c2cab04258b65ee880c Mon Sep 17 00:00:00 2001 From: elucent <9532786+elucent@users.noreply.github.com> Date: Sat, 21 May 2022 07:21:50 -0700 Subject: [PATCH 3/3] Stash a bunch of incomplete changes. --- build.gradle | 6 +- .../java/elucent/eidolon/ClientConfig.java | 37 +- .../java/elucent/eidolon/ClientEvents.java | 81 +++ .../java/elucent/eidolon/ClientRegistry.java | 484 ++++++++++++++++++ src/main/java/elucent/eidolon/Config.java | 29 +- src/main/java/elucent/eidolon/Eidolon.java | 61 ++- src/main/java/elucent/eidolon/Events.java | 156 +++++- src/main/java/elucent/eidolon/Registry.java | 315 +++++++----- src/main/java/elucent/eidolon/WorldGen.java | 64 ++- .../java/elucent/eidolon/block/BlockBase.java | 3 - .../elucent/eidolon/block/BrazierBlock.java | 13 - .../elucent/eidolon/block/CandleBlock.java | 2 - .../eidolon/block/CandlestickBlock.java | 2 - .../elucent/eidolon/block/CisternBlock.java | 3 - .../elucent/eidolon/block/CrucibleBlock.java | 12 - .../elucent/eidolon/block/EffigyBlock.java | 14 - .../eidolon/block/EnchantedAshBlock.java | 2 - .../elucent/eidolon/block/GobletBlock.java | 24 + .../java/elucent/eidolon/block/HandBlock.java | 13 - .../eidolon/block/HorizontalBlockBase.java | 2 - .../block/HorizontalWaterloggableBlock.java | 4 - .../eidolon/block/NecroticFocusBlock.java | 2 - .../eidolon/block/PillarBlockBase.java | 2 - .../java/elucent/eidolon/block/PipeBlock.java | 3 - .../eidolon/block/ResearchTableBlock.java | 67 +++ .../eidolon/block/SoulEnchanterBlock.java | 2 - .../elucent/eidolon/block/TableBlockBase.java | 2 - .../block/TwoHighHorizontalBlockBase.java | 55 ++ .../eidolon/block/WoodenStandBlock.java | 2 - .../elucent/eidolon/block/WorktableBlock.java | 2 - .../eidolon/capability/IKnowledge.java | 17 + .../eidolon/capability/IPlayerData.java | 89 ++++ .../eidolon/capability/IReputation.java | 9 +- .../elucent/eidolon/capability/ISoul.java | 85 +++ .../eidolon/capability/KnowledgeCommand.java | 252 +++++++++ .../eidolon/capability/KnowledgeImpl.java | 102 ++++ .../eidolon/capability/PlayerDataImpl.java | 177 +++++++ .../eidolon/capability/ReputationImpl.java | 9 +- .../elucent/eidolon/capability/SoulImpl.java | 90 ++++ .../java/elucent/eidolon/codex/ChantPage.java | 4 +- .../elucent/eidolon/codex/CodexChapters.java | 54 +- .../java/elucent/eidolon/codex/CodexGui.java | 41 +- .../java/elucent/eidolon/codex/IndexPage.java | 2 +- .../elucent/eidolon/codex/RitualPage.java | 7 +- .../elucent/eidolon/codex/RuneDescPage.java | 35 ++ .../elucent/eidolon/codex/RuneIndexPage.java | 136 +++++ .../elucent/eidolon/codex/SignIndexPage.java | 18 +- .../java/elucent/eidolon/codex/SignPage.java | 5 +- .../java/elucent/eidolon/deity/DarkDeity.java | 6 +- .../java/elucent/eidolon/deity/Deity.java | 89 ++++ .../elucent/eidolon/deity/LightDeity.java | 2 +- .../eidolon/deity/RegisterDeitiesEvent.java | 3 +- .../eidolon/entity/AngelArrowRenderer.java | 1 - .../eidolon/entity/ChantCasterEntity.java | 156 ++++-- .../eidolon/entity/ChantCasterRenderer.java | 189 +++++++ .../eidolon/entity/NecromancerEntity.java | 2 +- .../eidolon/entity/NecromancerRenderer.java | 9 +- .../elucent/eidolon/entity/RavenEntity.java | 15 +- .../elucent/eidolon/entity/RavenRenderer.java | 4 +- .../eidolon/entity/RavenVariantLayer.java | 9 +- .../eidolon/entity/SlimySlugEntity.java | 79 ++- .../eidolon/entity/SlimySlugModel.java | 3 - .../eidolon/entity/SlimySlugRenderer.java | 15 +- .../elucent/eidolon/entity/WraithModel.java | 2 - .../eidolon/entity/WraithRenderer.java | 4 +- .../eidolon/entity/ZombieBruteRenderer.java | 4 +- .../eidolon/entity/ai/GenericBarterGoal.java | 2 - .../eidolon/event/SpeedFactorEvent.java | 25 - .../eidolon/event/StuckInBlockEvent.java | 29 ++ .../eidolon/gui/ResearchTableContainer.java | 281 ++++++++++ .../eidolon/gui/ResearchTableScreen.java | 189 +++++++ .../java/elucent/eidolon/item/AthameItem.java | 1 - .../eidolon/item/BonechillWandItem.java | 2 - .../eidolon/item/BonelordArmorItem.java | 133 +++++ .../elucent/eidolon/item/CleavingAxeItem.java | 2 - .../java/elucent/eidolon/item/CodexItem.java | 6 +- .../eidolon/item/CompletedResearchItem.java | 78 +++ .../eidolon/item/DeathbringerScytheItem.java | 72 +++ .../eidolon/item/IManaRelatedItem.java | 5 + .../eidolon/item/IRechargeableWand.java | 7 + .../java/elucent/eidolon/item/IWingsItem.java | 15 + .../java/elucent/eidolon/item/ItemBase.java | 18 +- .../eidolon/item/NotetakingToolsItem.java | 66 +++ .../eidolon/item/ReaperScytheItem.java | 2 - .../eidolon/item/ResearchNotesItem.java | 75 +++ .../eidolon/item/ReversalPickItem.java | 2 - .../eidolon/item/SappingSwordItem.java | 10 +- .../elucent/eidolon/item/SilverArmorItem.java | 11 +- .../eidolon/item/SoulfireWandItem.java | 12 +- .../eidolon/item/SummoningStaffItem.java | 222 ++++++++ src/main/java/elucent/eidolon/item/Tiers.java | 34 ++ .../java/elucent/eidolon/item/TongsItem.java | 2 - .../java/elucent/eidolon/item/TopHatItem.java | 11 +- .../eidolon/item/UnholySymbolItem.java | 21 - .../java/elucent/eidolon/item/WandItem.java | 10 +- .../eidolon/item/WarlockRobesItem.java | 10 +- .../eidolon/item/curio/AngelSightItem.java | 2 - .../eidolon/item/curio/BasicAmuletItem.java | 2 - .../eidolon/item/curio/BasicBeltItem.java | 2 - .../eidolon/item/curio/BasicRingItem.java | 2 - .../item/curio/EnervatingRingItem.java | 2 - .../eidolon/item/curio/GlassHandItem.java | 2 - .../eidolon/item/curio/GravityBeltItem.java | 2 - .../item/curio/MindShieldingPlateItem.java | 2 - .../item/curio/PrestigiousPalmItem.java | 2 - .../eidolon/item/curio/RavenCloakItem.java | 89 ++++ .../item/curio/RavenCloakRenderer.java | 40 ++ .../eidolon/item/curio/ResoluteBeltItem.java | 2 - .../item/curio/SanguineAmuletItem.java | 9 - .../item/curio/SoulboneAmuletItem.java | 55 ++ .../item/curio/TerminusMirrorItem.java | 2 - .../eidolon/item/curio/VoidAmuletItem.java | 2 - .../eidolon/item/curio/WardedMailItem.java | 2 - .../eidolon/item/model/ArmorModel.java | 17 +- .../item/model/BonelordArmorModel.java | 93 ++++ .../eidolon/item/model/RavenCloakModel.java | 196 +++++++ .../eidolon/item/model/SilverArmorModel.java | 1 - .../eidolon/item/model/TopHatModel.java | 3 - .../eidolon/item/model/UnholySymbolModel.java | 228 --------- .../eidolon/item/model/WarlockArmorModel.java | 6 - .../mixin/AbstractContainerMenuMixin.java | 33 ++ .../eidolon/mixin/LevelRendererMixin.java | 12 +- .../eidolon/mixin/LivingEntityMixin.java | 39 +- .../eidolon/mixin/LocalPlayerMixin.java | 30 ++ .../eidolon/mixin/PlayerRendererMixin.java | 2 +- .../eidolon/mixin/StructureSettingsMixin.java | 4 - .../eidolon/network/AttemptCastPacket.java | 34 +- .../eidolon/network/ChilledEffectPacket.java | 2 - .../DeathbringerSlashEffectPacket.java | 153 ++++++ .../network/ExtinguishEffectPacket.java | 2 - .../eidolon/network/FlameEffectPacket.java | 2 - .../eidolon/network/IgniteEffectPacket.java | 2 - .../network/KnowledgeUpdatePacket.java | 2 - .../network/LifestealEffectPacket.java | 2 - .../network/MagicBurstEffectPacket.java | 2 - .../elucent/eidolon/network/Networking.java | 48 ++ .../eidolon/network/ResearchActionPacket.java | 68 +++ .../eidolon/network/SoulUpdatePacket.java | 82 +++ .../eidolon/network/SpellCastPacket.java | 22 +- .../eidolon/network/WingsDashPacket.java | 61 +++ .../network/WingsDataUpdatePacket.java | 71 +++ .../eidolon/network/WingsFlapPacket.java | 61 +++ .../eidolon/particle/GenericParticleData.java | 2 - .../particle/GlowParticleRenderType.java | 3 +- .../particle/GlowingSlashParticle.java | 158 ++++++ .../particle/GlowingSlashParticleType.java | 35 ++ .../eidolon/particle/RuneParticle.java | 150 ++++++ .../eidolon/particle/RuneParticleData.java | 102 ++++ .../particle/RuneParticleRenderType.java | 45 ++ .../eidolon/particle/RuneParticleType.java | 48 ++ .../eidolon/particle/SignParticleData.java | 2 - .../particle/SignParticleRenderType.java | 2 + .../eidolon/particle/SlashParticle.java | 165 ++++++ .../eidolon/particle/SlashParticleData.java | 265 ++++++++++ .../eidolon/particle/SlashParticleType.java | 35 ++ .../particle/SpriteParticleRenderType.java | 3 +- .../eidolon/potion/AnchoredEffect.java | 3 - .../elucent/eidolon/potion/ChilledEffect.java | 74 --- .../eidolon/potion/ReinforcedEffect.java | 5 - .../elucent/eidolon/potion/UndeathEffect.java | 33 ++ .../eidolon/potion/VulnerableEffect.java | 5 - .../elucent/eidolon/research/Research.java | 58 +++ .../eidolon/research/ResearchReward.java | 5 + .../eidolon/research/ResearchTask.java | 312 +++++++++++ .../elucent/eidolon/research/Researches.java | 78 +++ .../eidolon/ritual/AbsorptionRitual.java | 74 +++ .../elucent/eidolon/ritual/CrystalRitual.java | 2 +- .../ritual/FocusItemPresentRequirement.java | 41 ++ .../eidolon/ritual/FocusItemRequirement.java | 12 +- .../eidolon/ritual/IRitualItemFocus.java | 6 +- .../eidolon/ritual/RechargingRitual.java | 42 ++ .../eidolon/ritual/RitualRegistry.java | 25 +- .../elucent/eidolon/spell/KnowledgeUtil.java | 49 -- .../elucent/eidolon/spell/PrayerSpell.java | 1 - src/main/java/elucent/eidolon/spell/Rune.java | 42 ++ .../java/elucent/eidolon/spell/Runes.java | 44 ++ .../elucent/eidolon/spell/SignSequence.java | 175 +++++++ .../java/elucent/eidolon/spell/Signs.java | 35 +- .../java/elucent/eidolon/spell/Spell.java | 6 +- .../java/elucent/eidolon/spell/Spells.java | 2 +- .../elucent/eidolon/spell/StaticSpell.java | 14 +- .../eidolon/tile/BrazierTileEntity.java | 5 +- .../eidolon/tile/BrazierTileRenderer.java | 1 - .../elucent/eidolon/tile/CabinetModel.java | 54 ++ .../eidolon/tile/CrucibleTileEntity.java | 9 +- .../eidolon/tile/CrucibleTileRenderer.java | 33 +- .../eidolon/tile/EffigyTileEntity.java | 4 +- .../eidolon/tile/GobletTileEntity.java | 4 +- .../eidolon/tile/GobletTileRenderer.java | 1 - .../elucent/eidolon/tile/HandTileEntity.java | 4 +- .../eidolon/tile/HandTileRenderer.java | 1 - .../eidolon/tile/NecroticFocusTileEntity.java | 10 +- .../tile/NecroticFocusTileRenderer.java | 1 - .../eidolon/tile/ResearchTableTileEntity.java | 271 ++++++++++ .../tile/SoulEnchanterTileRenderer.java | 1 - .../elucent/eidolon/tile/TileEntityBase.java | 16 +- .../eidolon/tile/WoodenStandTileEntity.java | 5 +- .../tile/reagent/CisternTileRenderer.java | 1 - .../tile/reagent/PipeTileRenderer.java | 1 - .../tile/reagent/ReagentTankTileEntity.java | 6 +- .../elucent/eidolon/util/KnowledgeUtil.java | 157 ++++++ .../java/elucent/eidolon/util/RecipeUtil.java | 3 - .../java/elucent/eidolon/util/RenderUtil.java | 31 +- .../elucent/eidolon/world/BasicPiece.java | 6 - .../elucent/eidolon/world/CatacombPieces.java | 1 - .../eidolon/world/CatacombStructure.java | 11 - .../elucent/eidolon/world/LabStructure.java | 21 - .../eidolon/world/RandomlyRotatedPiece.java | 1 - .../eidolon/world/StrayTowerStructure.java | 35 +- .../resources/META-INF/accesstransformer.cfg | 8 +- .../assets/eidolon/blockstates/bone_pile.json | 7 + .../eidolon/blockstates/bone_pile_slab.json | 13 + .../eidolon/blockstates/bone_pile_stairs.json | 209 ++++++++ .../eidolon/blockstates/elder_bricks.json | 7 + .../eidolon/blockstates/elder_bricks_eye.json | 7 + .../blockstates/elder_bricks_slab.json | 13 + .../blockstates/elder_bricks_stairs.json | 209 ++++++++ .../blockstates/elder_bricks_wall.json | 90 ++++ .../eidolon/blockstates/elder_masonry.json | 7 + .../blockstates/elder_masonry_slab.json | 13 + .../blockstates/elder_masonry_stairs.json | 209 ++++++++ .../eidolon/blockstates/elder_pillar.json | 16 + .../eidolon/blockstates/illwood_bark.json | 16 + .../eidolon/blockstates/illwood_leaves.json | 7 + .../eidolon/blockstates/illwood_log.json | 16 + .../eidolon/blockstates/illwood_planks.json | 7 + .../blockstates/illwood_planks_fence.json | 48 ++ .../illwood_planks_fence_gate.json | 80 +++ .../blockstates/illwood_planks_slab.json | 13 + .../blockstates/illwood_planks_stairs.json | 209 ++++++++ .../eidolon/blockstates/illwood_sapling.json | 7 + .../eidolon/blockstates/magic_candle.json | 7 + .../blockstates/magic_candlestick.json | 23 + .../mossy_smooth_stone_bricks.json | 7 + .../eidolon/blockstates/research_table.json | 19 + .../blockstates/smooth_stone_arch.json | 16 + .../blockstates/smooth_stone_masonry.json | 7 + .../smooth_stone_masonry_slab.json | 13 + .../smooth_stone_masonry_stairs.json | 209 ++++++++ .../blockstates/stripped_illwood_bark.json | 16 + .../blockstates/stripped_illwood_log.json | 16 + .../resources/assets/eidolon/lang/en_us.json | 99 +++- .../models/block/bone_pile_slab_top.json | 8 + .../models/block/bone_pile_stairs_inner.json | 8 + .../models/block/bone_pile_stairs_outer.json | 8 + .../eidolon/models/block/cabinet_bottom.json | 100 ++++ .../eidolon/models/block/cabinet_top.json | 58 +++ .../models/block/elder_bricks_slab_top.json | 8 + .../block/elder_bricks_stairs_inner.json | 8 + .../block/elder_bricks_stairs_outer.json | 8 + .../models/block/elder_bricks_wall_post.json | 6 + .../models/block/elder_bricks_wall_side.json | 6 + .../block/elder_bricks_wall_side_tall.json | 6 + .../models/block/elder_masonry_slab_top.json | 8 + .../block/elder_masonry_stairs_inner.json | 8 + .../block/elder_masonry_stairs_outer.json | 8 + .../models/block/elder_pillar_bottom.json | 7 + .../models/block/elder_pillar_mid.json | 7 + .../models/block/elder_pillar_top.json | 7 + .../models/block/illwood_bark_horizontal.json | 7 + .../models/block/illwood_log_horizontal.json | 7 + .../block/illwood_planks_fence_gate_open.json | 6 + .../block/illwood_planks_fence_gate_wall.json | 6 + .../illwood_planks_fence_gate_wall_open.json | 6 + .../block/illwood_planks_fence_post.json | 6 + .../block/illwood_planks_fence_side.json | 6 + .../models/block/illwood_planks_slab_top.json | 8 + .../block/illwood_planks_stairs_inner.json | 8 + .../block/illwood_planks_stairs_outer.json | 8 + .../eidolon/models/block/illwood_sapling.json | 6 + .../eidolon/models/block/magic_candle.json | 36 ++ .../models/block/magic_candlestick.json | 73 +++ .../models/block/magic_candlestick_wall.json | 85 +++ .../block/smooth_stone_arch_bottom.json | 7 + .../models/block/smooth_stone_arch_mid.json | 7 + .../models/block/smooth_stone_arch_top.json | 7 + .../block/smooth_stone_masonry_slab_top.json | 8 + .../smooth_stone_masonry_stairs_inner.json | 8 + .../smooth_stone_masonry_stairs_outer.json | 8 + .../stripped_illwood_bark_horizontal.json | 7 + .../stripped_illwood_log_horizontal.json | 7 + .../eidolon/models/item/arcane_seal.json | 6 + .../assets/eidolon/models/item/archive.json | 219 ++++++++ .../assets/eidolon/models/item/bone_pile.json | 6 + .../eidolon/models/item/bone_pile_slab.json | 8 + .../eidolon/models/item/bone_pile_stairs.json | 8 + .../models/item/bonelord_chestplate.json | 6 + .../eidolon/models/item/bonelord_greaves.json | 6 + .../eidolon/models/item/bonelord_helm.json | 6 + .../assets/eidolon/models/item/cabinet.json | 148 ++++++ .../models/item/completed_research.json | 6 + .../models/item/deathbringer_scythe.json | 6 + .../eidolon/models/item/elder_brick.json | 6 + .../eidolon/models/item/elder_bricks.json | 6 + .../eidolon/models/item/elder_bricks_eye.json | 7 + .../models/item/elder_bricks_slab.json | 8 + .../models/item/elder_bricks_stairs.json | 8 + .../models/item/elder_bricks_wall.json | 6 + .../eidolon/models/item/elder_masonry.json | 6 + .../models/item/elder_masonry_slab.json | 8 + .../models/item/elder_masonry_stairs.json | 8 + .../eidolon/models/item/elder_pillar.json | 7 + .../eidolon/models/item/grape_candy.json | 6 + .../eidolon/models/item/illwood_bark.json | 7 + .../eidolon/models/item/illwood_leaves.json | 6 + .../eidolon/models/item/illwood_log.json | 7 + .../eidolon/models/item/illwood_planks.json | 6 + .../models/item/illwood_planks_fence.json | 6 + .../item/illwood_planks_fence_gate.json | 6 + .../models/item/illwood_planks_slab.json | 8 + .../models/item/illwood_planks_stairs.json | 8 + .../eidolon/models/item/illwood_sapling.json | 6 + .../eidolon/models/item/imbued_bones.json | 6 + .../eidolon/models/item/magic_candle.json | 6 + .../models/item/magic_candlestick.json | 6 + .../assets/eidolon/models/item/magic_ink.json | 6 + .../eidolon/models/item/magicians_wax.json | 6 + .../item/mossy_smooth_stone_bricks.json | 6 + .../eidolon/models/item/notetaking_tools.json | 6 + .../assets/eidolon/models/item/parchment.json | 6 + .../eidolon/models/item/raven_cloak.json | 6 + .../assets/eidolon/models/item/red_candy.json | 6 + .../eidolon/models/item/research_notes.json | 6 + .../research_table.json} | 12 +- .../eidolon/models/item/scriptorium.json | 217 ++++++++ .../models/item/smooth_stone_arch.json | 7 + .../models/item/smooth_stone_masonry.json | 6 + .../item/smooth_stone_masonry_slab.json | 8 + .../item/smooth_stone_masonry_stairs.json | 8 + .../eidolon/models/item/soulbone_amulet.json | 6 + .../models/item/stripped_illwood_bark.json | 7 + .../models/item/stripped_illwood_log.json | 7 + .../eidolon/models/item/summoning_staff.json | 6 + .../eidolon/models/item/unholy_symbol.json | 45 +- .../eidolon/models/item/withered_heart.json | 6 + .../particles/glowing_slash_particle.json | 5 + .../eidolon/particles/rune_particle.json | 5 + .../eidolon/particles/slash_particle.json | 5 + .../eidolon/shaders/core/sprite_particle.fsh | 24 + .../eidolon/shaders/core/sprite_particle.json | 27 + .../eidolon/shaders/core/sprite_particle.vsh | 23 + src/main/resources/assets/eidolon/sounds.json | 4 +- .../{select_sign.ogg => select_rune.ogg} | Bin .../textures/block/Sprite-0001.aseprite | Bin 0 -> 783 bytes .../eidolon/textures/block/archive_bottom.png | Bin 0 -> 226 bytes .../eidolon/textures/block/archive_detail.png | Bin 0 -> 605 bytes .../eidolon/textures/block/archive_side.png | Bin 0 -> 511 bytes .../eidolon/textures/block/archive_top.png | Bin 0 -> 346 bytes .../eidolon/textures/block/bone_pile.png | Bin 0 -> 684 bytes .../eidolon/textures/block/cabinet_bottom.png | Bin 0 -> 292 bytes .../textures/block/cabinet_bottom_front.png | Bin 0 -> 377 bytes .../textures/block/cabinet_bottom_side.png | Bin 0 -> 379 bytes .../eidolon/textures/block/cabinet_top.png | Bin 0 -> 337 bytes .../textures/block/cabinet_top_front.png | Bin 0 -> 315 bytes .../textures/block/cabinet_top_side.png | Bin 0 -> 361 bytes .../eidolon/textures/block/elder_bricks.png | Bin 0 -> 521 bytes .../textures/block/elder_bricks_eye.png | Bin 0 -> 584 bytes .../eidolon/textures/block/elder_masonry.png | Bin 0 -> 494 bytes .../textures/block/elder_pillar_both_side.png | Bin 0 -> 496 bytes .../block/elder_pillar_bottom_side.png | Bin 0 -> 377 bytes .../textures/block/elder_pillar_end.png | Bin 0 -> 345 bytes .../textures/block/elder_pillar_side.png | Bin 0 -> 274 bytes .../textures/block/elder_pillar_top_side.png | Bin 0 -> 421 bytes .../eidolon/textures/block/illwood_leaves.png | Bin 0 -> 662 bytes .../eidolon/textures/block/illwood_log.png | Bin 0 -> 411 bytes .../textures/block/illwood_log_top.png | Bin 0 -> 565 bytes .../eidolon/textures/block/illwood_planks.png | Bin 0 -> 385 bytes .../textures/block/illwood_sapling.png | Bin 0 -> 469 bytes .../eidolon/textures/block/magic_candle.png | Bin 0 -> 503 bytes .../block/mossy_smooth_stone_bricks.png | Bin 0 -> 758 bytes ...e_bottom.png => research_table_bottom.png} | Bin ...e_detail.png => research_table_detail.png} | Bin ...n_table_mid.png => research_table_mid.png} | Bin ...table_side.png => research_table_side.png} | Bin ...n_table_top.png => research_table_top.png} | Bin .../textures/block/scriptorium_detail.png | Bin 0 -> 504 bytes .../textures/block/scriptorium_legs.png | Bin 0 -> 362 bytes .../textures/block/scriptorium_top.png | Bin 0 -> 328 bytes .../textures/block/smooth_stone_arch.png | Bin 0 -> 577 bytes .../block/smooth_stone_arch_bottom.png | Bin 0 -> 510 bytes .../textures/block/smooth_stone_arch_mid.png | Bin 0 -> 458 bytes .../textures/block/smooth_stone_arch_top.png | Bin 0 -> 548 bytes .../textures/block/smooth_stone_masonry.png | Bin 0 -> 484 bytes .../textures/block/stripped_illwood_log.png | Bin 0 -> 434 bytes .../block/stripped_illwood_log_top.png | Bin 0 -> 468 bytes .../textures/entity/bonelord_armor.png | Bin 0 -> 3849 bytes .../textures/entity/giant_skeleton.png | Bin 0 -> 2662 bytes .../eidolon/textures/entity/raven_cloak.png | Bin 0 -> 3001 bytes .../textures/entity/tall_archive_doors.png | Bin 0 -> 592 bytes .../assets/eidolon/textures/entity/wight.png | Bin 0 -> 4287 bytes .../assets/eidolon/textures/gui/codex_bg.png | Bin 12020 -> 12557 bytes .../textures/gui/codex_rune_index_page.png | Bin 0 -> 2434 bytes .../eidolon/textures/gui/codex_rune_page.png | Bin 0 -> 3766 bytes .../assets/eidolon/textures/gui/icons.png | Bin 448 -> 750 bytes .../textures/gui/inscription_table.png | Bin 0 -> 1221 bytes .../assets/eidolon/textures/gui/mana_bar.png | Bin 0 -> 4077 bytes .../eidolon/textures/gui/research_table.png | Bin 0 -> 8313 bytes .../eidolon/textures/gui/soul_enchanter.png | Bin 4213 -> 4209 bytes .../textures/item/ancient_armor_plate.png | Bin 0 -> 432 bytes .../textures/item/ancient_metal_scrap.png | Bin 0 -> 338 bytes .../eidolon/textures/item/arcane_seal.png | Bin 0 -> 551 bytes .../eidolon/textures/item/bone_stake.png | Bin 0 -> 427 bytes .../textures/item/bonelord_chestplate.png | Bin 0 -> 643 bytes .../textures/item/bonelord_greaves.png | Bin 0 -> 408 bytes .../eidolon/textures/item/bonelord_helm.png | Bin 0 -> 522 bytes .../textures/item/completed_research.png | Bin 0 -> 608 bytes .../textures/item/deathbringer_scythe.png | Bin 0 -> 486 bytes .../eidolon/textures/item/elder_brick.png | Bin 0 -> 332 bytes .../eidolon/textures/item/giant_bone.png | Bin 0 -> 435 bytes .../assets/eidolon/textures/item/goblet.png | Bin 379 -> 454 bytes .../eidolon/textures/item/grape_candy.png | Bin 0 -> 410 bytes .../eidolon/textures/item/imbued_bones.png | Bin 0 -> 503 bytes .../eidolon/textures/item/lead_ingot.png | Bin 378 -> 448 bytes .../eidolon/textures/item/magic_candle.png | Bin 0 -> 358 bytes .../textures/item/magic_candlestick.png | Bin 0 -> 463 bytes .../eidolon/textures/item/magic_ink.png | Bin 0 -> 417 bytes .../eidolon/textures/item/magicians_wax.png | Bin 0 -> 469 bytes .../textures/item/notetaking_tools.png | Bin 0 -> 709 bytes .../eidolon/textures/item/parchment.png | Bin 0 -> 523 bytes .../eidolon/textures/item/pewter_ingot.png | Bin 373 -> 438 bytes .../eidolon/textures/item/raven_cloak.png | Bin 0 -> 560 bytes .../eidolon/textures/item/raven_feather.png | Bin 352 -> 455 bytes .../eidolon/textures/item/raven_wings.png | Bin 0 -> 607 bytes .../eidolon/textures/item/red_candy.png | Bin 0 -> 465 bytes .../eidolon/textures/item/research_notes.png | Bin 0 -> 648 bytes .../eidolon/textures/item/silver_axe.png | Bin 334 -> 479 bytes .../eidolon/textures/item/soulbone_amulet.png | Bin 0 -> 700 bytes .../eidolon/textures/item/summoning_staff.png | Bin 0 -> 470 bytes .../eidolon/textures/item/withered_heart.png | Bin 0 -> 525 bytes .../eidolon/textures/item/wooden_stake.png | Bin 0 -> 409 bytes .../textures/mob_effect/reinforced.png | Bin 568 -> 532 bytes .../eidolon/textures/mob_effect/undeath.png | Bin 0 -> 521 bytes .../textures/particle/absorption_ritual.png | Bin 0 -> 491 bytes .../assets/eidolon/textures/particle/aura.png | Bin 0 -> 878 bytes .../eidolon/textures/particle/basic_ring.png | Bin 393 -> 0 bytes .../assets/eidolon/textures/particle/beam.png | Bin 0 -> 178 bytes .../eidolon/textures/particle/death_sign.png | Bin 0 -> 491 bytes .../assets/eidolon/textures/particle/eye.png | Bin 0 -> 405 bytes .../eidolon/textures/particle/feather.png | Bin 0 -> 446 bytes .../eidolon/textures/particle/flame_sign.png | Bin 466 -> 439 bytes .../textures/particle/harmony_sign.png | Bin 0 -> 515 bytes .../eidolon/textures/particle/magic_sign.png | Bin 0 -> 494 bytes .../eidolon/textures/particle/mind_sign.png | Bin 497 -> 505 bytes .../textures/particle/recharge_ritual.png | Bin 0 -> 494 bytes .../assets/eidolon/textures/particle/ring.png | Bin 0 -> 2882 bytes .../textures/particle/warding_sign.png | Bin 474 -> 477 bytes .../eidolon/textures/particle/winter_sign.png | Bin 0 -> 518 bytes .../eidolon/textures/rune/crimson_rose.png | Bin 0 -> 246 bytes .../assets/eidolon/textures/rune/sin.png | Bin 0 -> 240 bytes .../data/curios/tags/items/body.json | 3 +- .../data/curios/tags/items/necklace.json | 3 +- .../loot_tables/blocks/magic_candle.json | 19 + .../loot_tables/blocks/magic_candlestick.json | 19 + .../loot_tables/blocks/research_table.json | 19 + .../data/eidolon/recipes/arcane_seal.json | 18 + .../recipes/death_essence_withered.json | 27 + .../eidolon/recipes/deathbringer_scythe.json | 33 ++ .../recipes/enchanted_ash_from_block.json | 12 + .../data/eidolon/recipes/glowstone_dust.json | 23 + .../data/eidolon/recipes/magic_candle.json | 20 + .../eidolon/recipes/magic_candlestick.json | 21 + .../data/eidolon/recipes/magic_ink.json | 34 ++ .../data/eidolon/recipes/magicians_wax.json | 31 ++ .../eidolon/recipes/notetaking_tools.json | 21 + .../data/eidolon/recipes/parchment.json | 28 + .../data/eidolon/recipes/research_table.json | 23 + .../data/eidolon/recipes/soulbone_amulet.json | 32 ++ .../data/eidolon/tags/items/zombie_food.json | 7 + .../forge/tags/items/raw_materials/lead.json | 6 + .../tags/items/raw_materials/silver.json | 6 + .../tags/items/storage_blocks/raw_lead.json | 6 + .../tags/items/storage_blocks/raw_silver.json | 6 + .../minecraft/tags/blocks/fence_gates.json | 3 +- .../minecraft/tags/blocks/illwood_logs.json | 7 + .../minecraft/tags/blocks/logs_that_burn.json | 6 + .../minecraft/tags/blocks/mineable/axe.json | 12 +- .../tags/blocks/mineable/pickaxe.json | 14 + .../data/minecraft/tags/blocks/planks.json | 3 +- .../data/minecraft/tags/blocks/walls.json | 3 +- .../minecraft/tags/blocks/wooden_fences.json | 3 +- .../minecraft/tags/blocks/wooden_slabs.json | 3 +- .../minecraft/tags/blocks/wooden_stairs.json | 3 +- src/main/resources/eidolon.mixins.json | 6 +- src/main/resources/pack.mcmeta | 2 +- 484 files changed, 11426 insertions(+), 1240 deletions(-) create mode 100644 src/main/java/elucent/eidolon/ClientRegistry.java create mode 100644 src/main/java/elucent/eidolon/block/GobletBlock.java create mode 100644 src/main/java/elucent/eidolon/block/ResearchTableBlock.java create mode 100644 src/main/java/elucent/eidolon/block/TwoHighHorizontalBlockBase.java create mode 100644 src/main/java/elucent/eidolon/capability/IPlayerData.java create mode 100644 src/main/java/elucent/eidolon/capability/ISoul.java create mode 100644 src/main/java/elucent/eidolon/capability/KnowledgeCommand.java create mode 100644 src/main/java/elucent/eidolon/capability/PlayerDataImpl.java create mode 100644 src/main/java/elucent/eidolon/capability/SoulImpl.java create mode 100644 src/main/java/elucent/eidolon/codex/RuneDescPage.java create mode 100644 src/main/java/elucent/eidolon/codex/RuneIndexPage.java create mode 100644 src/main/java/elucent/eidolon/entity/ChantCasterRenderer.java delete mode 100644 src/main/java/elucent/eidolon/event/SpeedFactorEvent.java create mode 100644 src/main/java/elucent/eidolon/event/StuckInBlockEvent.java create mode 100644 src/main/java/elucent/eidolon/gui/ResearchTableContainer.java create mode 100644 src/main/java/elucent/eidolon/gui/ResearchTableScreen.java create mode 100644 src/main/java/elucent/eidolon/item/BonelordArmorItem.java create mode 100644 src/main/java/elucent/eidolon/item/CompletedResearchItem.java create mode 100644 src/main/java/elucent/eidolon/item/DeathbringerScytheItem.java create mode 100644 src/main/java/elucent/eidolon/item/IManaRelatedItem.java create mode 100644 src/main/java/elucent/eidolon/item/IRechargeableWand.java create mode 100644 src/main/java/elucent/eidolon/item/IWingsItem.java create mode 100644 src/main/java/elucent/eidolon/item/NotetakingToolsItem.java create mode 100644 src/main/java/elucent/eidolon/item/ResearchNotesItem.java create mode 100644 src/main/java/elucent/eidolon/item/SummoningStaffItem.java create mode 100644 src/main/java/elucent/eidolon/item/curio/RavenCloakItem.java create mode 100644 src/main/java/elucent/eidolon/item/curio/RavenCloakRenderer.java create mode 100644 src/main/java/elucent/eidolon/item/curio/SoulboneAmuletItem.java create mode 100644 src/main/java/elucent/eidolon/item/model/BonelordArmorModel.java create mode 100644 src/main/java/elucent/eidolon/item/model/RavenCloakModel.java delete mode 100644 src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java create mode 100644 src/main/java/elucent/eidolon/mixin/AbstractContainerMenuMixin.java create mode 100644 src/main/java/elucent/eidolon/mixin/LocalPlayerMixin.java create mode 100644 src/main/java/elucent/eidolon/network/DeathbringerSlashEffectPacket.java create mode 100644 src/main/java/elucent/eidolon/network/ResearchActionPacket.java create mode 100644 src/main/java/elucent/eidolon/network/SoulUpdatePacket.java create mode 100644 src/main/java/elucent/eidolon/network/WingsDashPacket.java create mode 100644 src/main/java/elucent/eidolon/network/WingsDataUpdatePacket.java create mode 100644 src/main/java/elucent/eidolon/network/WingsFlapPacket.java create mode 100644 src/main/java/elucent/eidolon/particle/GlowingSlashParticle.java create mode 100644 src/main/java/elucent/eidolon/particle/GlowingSlashParticleType.java create mode 100644 src/main/java/elucent/eidolon/particle/RuneParticle.java create mode 100644 src/main/java/elucent/eidolon/particle/RuneParticleData.java create mode 100644 src/main/java/elucent/eidolon/particle/RuneParticleRenderType.java create mode 100644 src/main/java/elucent/eidolon/particle/RuneParticleType.java create mode 100644 src/main/java/elucent/eidolon/particle/SlashParticle.java create mode 100644 src/main/java/elucent/eidolon/particle/SlashParticleData.java create mode 100644 src/main/java/elucent/eidolon/particle/SlashParticleType.java create mode 100644 src/main/java/elucent/eidolon/potion/UndeathEffect.java create mode 100644 src/main/java/elucent/eidolon/research/Research.java create mode 100644 src/main/java/elucent/eidolon/research/ResearchReward.java create mode 100644 src/main/java/elucent/eidolon/research/ResearchTask.java create mode 100644 src/main/java/elucent/eidolon/research/Researches.java create mode 100644 src/main/java/elucent/eidolon/ritual/AbsorptionRitual.java create mode 100644 src/main/java/elucent/eidolon/ritual/FocusItemPresentRequirement.java create mode 100644 src/main/java/elucent/eidolon/ritual/RechargingRitual.java delete mode 100644 src/main/java/elucent/eidolon/spell/KnowledgeUtil.java create mode 100644 src/main/java/elucent/eidolon/spell/Rune.java create mode 100644 src/main/java/elucent/eidolon/spell/Runes.java create mode 100644 src/main/java/elucent/eidolon/spell/SignSequence.java create mode 100644 src/main/java/elucent/eidolon/tile/CabinetModel.java create mode 100644 src/main/java/elucent/eidolon/tile/ResearchTableTileEntity.java create mode 100644 src/main/java/elucent/eidolon/util/KnowledgeUtil.java create mode 100644 src/main/resources/assets/eidolon/blockstates/bone_pile.json create mode 100644 src/main/resources/assets/eidolon/blockstates/bone_pile_slab.json create mode 100644 src/main/resources/assets/eidolon/blockstates/bone_pile_stairs.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_bricks.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_bricks_eye.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_bricks_slab.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_bricks_stairs.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_bricks_wall.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_masonry.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_masonry_slab.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_masonry_stairs.json create mode 100644 src/main/resources/assets/eidolon/blockstates/elder_pillar.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_bark.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_leaves.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_log.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_planks.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_planks_fence.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_planks_fence_gate.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_planks_slab.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_planks_stairs.json create mode 100644 src/main/resources/assets/eidolon/blockstates/illwood_sapling.json create mode 100644 src/main/resources/assets/eidolon/blockstates/magic_candle.json create mode 100644 src/main/resources/assets/eidolon/blockstates/magic_candlestick.json create mode 100644 src/main/resources/assets/eidolon/blockstates/mossy_smooth_stone_bricks.json create mode 100644 src/main/resources/assets/eidolon/blockstates/research_table.json create mode 100644 src/main/resources/assets/eidolon/blockstates/smooth_stone_arch.json create mode 100644 src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry.json create mode 100644 src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_slab.json create mode 100644 src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_stairs.json create mode 100644 src/main/resources/assets/eidolon/blockstates/stripped_illwood_bark.json create mode 100644 src/main/resources/assets/eidolon/blockstates/stripped_illwood_log.json create mode 100644 src/main/resources/assets/eidolon/models/block/bone_pile_slab_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/bone_pile_stairs_inner.json create mode 100644 src/main/resources/assets/eidolon/models/block/bone_pile_stairs_outer.json create mode 100644 src/main/resources/assets/eidolon/models/block/cabinet_bottom.json create mode 100644 src/main/resources/assets/eidolon/models/block/cabinet_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_slab_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_inner.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_outer.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_wall_post.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side_tall.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_masonry_slab_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_inner.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_outer.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_pillar_bottom.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_pillar_mid.json create mode 100644 src/main/resources/assets/eidolon/models/block/elder_pillar_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_bark_horizontal.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_log_horizontal.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_open.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall_open.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_fence_post.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_fence_side.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_slab_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_inner.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_outer.json create mode 100644 src/main/resources/assets/eidolon/models/block/illwood_sapling.json create mode 100644 src/main/resources/assets/eidolon/models/block/magic_candle.json create mode 100644 src/main/resources/assets/eidolon/models/block/magic_candlestick.json create mode 100644 src/main/resources/assets/eidolon/models/block/magic_candlestick_wall.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_arch_bottom.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_arch_mid.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_arch_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_slab_top.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_inner.json create mode 100644 src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_outer.json create mode 100644 src/main/resources/assets/eidolon/models/block/stripped_illwood_bark_horizontal.json create mode 100644 src/main/resources/assets/eidolon/models/block/stripped_illwood_log_horizontal.json create mode 100644 src/main/resources/assets/eidolon/models/item/arcane_seal.json create mode 100644 src/main/resources/assets/eidolon/models/item/archive.json create mode 100644 src/main/resources/assets/eidolon/models/item/bone_pile.json create mode 100644 src/main/resources/assets/eidolon/models/item/bone_pile_slab.json create mode 100644 src/main/resources/assets/eidolon/models/item/bone_pile_stairs.json create mode 100644 src/main/resources/assets/eidolon/models/item/bonelord_chestplate.json create mode 100644 src/main/resources/assets/eidolon/models/item/bonelord_greaves.json create mode 100644 src/main/resources/assets/eidolon/models/item/bonelord_helm.json create mode 100644 src/main/resources/assets/eidolon/models/item/cabinet.json create mode 100644 src/main/resources/assets/eidolon/models/item/completed_research.json create mode 100644 src/main/resources/assets/eidolon/models/item/deathbringer_scythe.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_brick.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_bricks.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_bricks_eye.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_bricks_slab.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_bricks_stairs.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_bricks_wall.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_masonry.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_masonry_slab.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_masonry_stairs.json create mode 100644 src/main/resources/assets/eidolon/models/item/elder_pillar.json create mode 100644 src/main/resources/assets/eidolon/models/item/grape_candy.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_bark.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_leaves.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_log.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_planks.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_planks_fence.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_planks_fence_gate.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_planks_slab.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_planks_stairs.json create mode 100644 src/main/resources/assets/eidolon/models/item/illwood_sapling.json create mode 100644 src/main/resources/assets/eidolon/models/item/imbued_bones.json create mode 100644 src/main/resources/assets/eidolon/models/item/magic_candle.json create mode 100644 src/main/resources/assets/eidolon/models/item/magic_candlestick.json create mode 100644 src/main/resources/assets/eidolon/models/item/magic_ink.json create mode 100644 src/main/resources/assets/eidolon/models/item/magicians_wax.json create mode 100644 src/main/resources/assets/eidolon/models/item/mossy_smooth_stone_bricks.json create mode 100644 src/main/resources/assets/eidolon/models/item/notetaking_tools.json create mode 100644 src/main/resources/assets/eidolon/models/item/parchment.json create mode 100644 src/main/resources/assets/eidolon/models/item/raven_cloak.json create mode 100644 src/main/resources/assets/eidolon/models/item/red_candy.json create mode 100644 src/main/resources/assets/eidolon/models/item/research_notes.json rename src/main/resources/assets/eidolon/models/{block/inscription_table.json => item/research_table.json} (97%) create mode 100644 src/main/resources/assets/eidolon/models/item/scriptorium.json create mode 100644 src/main/resources/assets/eidolon/models/item/smooth_stone_arch.json create mode 100644 src/main/resources/assets/eidolon/models/item/smooth_stone_masonry.json create mode 100644 src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_slab.json create mode 100644 src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_stairs.json create mode 100644 src/main/resources/assets/eidolon/models/item/soulbone_amulet.json create mode 100644 src/main/resources/assets/eidolon/models/item/stripped_illwood_bark.json create mode 100644 src/main/resources/assets/eidolon/models/item/stripped_illwood_log.json create mode 100644 src/main/resources/assets/eidolon/models/item/summoning_staff.json create mode 100644 src/main/resources/assets/eidolon/models/item/withered_heart.json create mode 100644 src/main/resources/assets/eidolon/particles/glowing_slash_particle.json create mode 100644 src/main/resources/assets/eidolon/particles/rune_particle.json create mode 100644 src/main/resources/assets/eidolon/particles/slash_particle.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/sprite_particle.fsh create mode 100644 src/main/resources/assets/eidolon/shaders/core/sprite_particle.json create mode 100644 src/main/resources/assets/eidolon/shaders/core/sprite_particle.vsh rename src/main/resources/assets/eidolon/sounds/{select_sign.ogg => select_rune.ogg} (100%) create mode 100644 src/main/resources/assets/eidolon/textures/block/Sprite-0001.aseprite create mode 100644 src/main/resources/assets/eidolon/textures/block/archive_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/archive_detail.png create mode 100644 src/main/resources/assets/eidolon/textures/block/archive_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/archive_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/bone_pile.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_bottom_front.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_bottom_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_top_front.png create mode 100644 src/main/resources/assets/eidolon/textures/block/cabinet_top_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_bricks.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_bricks_eye.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_masonry.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_pillar_both_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_pillar_bottom_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_pillar_end.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_pillar_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/elder_pillar_top_side.png create mode 100644 src/main/resources/assets/eidolon/textures/block/illwood_leaves.png create mode 100644 src/main/resources/assets/eidolon/textures/block/illwood_log.png create mode 100644 src/main/resources/assets/eidolon/textures/block/illwood_log_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/illwood_planks.png create mode 100644 src/main/resources/assets/eidolon/textures/block/illwood_sapling.png create mode 100644 src/main/resources/assets/eidolon/textures/block/magic_candle.png create mode 100644 src/main/resources/assets/eidolon/textures/block/mossy_smooth_stone_bricks.png rename src/main/resources/assets/eidolon/textures/block/{inscription_table_bottom.png => research_table_bottom.png} (100%) rename src/main/resources/assets/eidolon/textures/block/{inscription_table_detail.png => research_table_detail.png} (100%) rename src/main/resources/assets/eidolon/textures/block/{inscription_table_mid.png => research_table_mid.png} (100%) rename src/main/resources/assets/eidolon/textures/block/{inscription_table_side.png => research_table_side.png} (100%) rename src/main/resources/assets/eidolon/textures/block/{inscription_table_top.png => research_table_top.png} (100%) create mode 100644 src/main/resources/assets/eidolon/textures/block/scriptorium_detail.png create mode 100644 src/main/resources/assets/eidolon/textures/block/scriptorium_legs.png create mode 100644 src/main/resources/assets/eidolon/textures/block/scriptorium_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/smooth_stone_arch.png create mode 100644 src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_bottom.png create mode 100644 src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_mid.png create mode 100644 src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_top.png create mode 100644 src/main/resources/assets/eidolon/textures/block/smooth_stone_masonry.png create mode 100644 src/main/resources/assets/eidolon/textures/block/stripped_illwood_log.png create mode 100644 src/main/resources/assets/eidolon/textures/block/stripped_illwood_log_top.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/bonelord_armor.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/giant_skeleton.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/raven_cloak.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/tall_archive_doors.png create mode 100644 src/main/resources/assets/eidolon/textures/entity/wight.png create mode 100644 src/main/resources/assets/eidolon/textures/gui/codex_rune_index_page.png create mode 100644 src/main/resources/assets/eidolon/textures/gui/codex_rune_page.png create mode 100644 src/main/resources/assets/eidolon/textures/gui/inscription_table.png create mode 100644 src/main/resources/assets/eidolon/textures/gui/mana_bar.png create mode 100644 src/main/resources/assets/eidolon/textures/gui/research_table.png create mode 100644 src/main/resources/assets/eidolon/textures/item/ancient_armor_plate.png create mode 100644 src/main/resources/assets/eidolon/textures/item/ancient_metal_scrap.png create mode 100644 src/main/resources/assets/eidolon/textures/item/arcane_seal.png create mode 100644 src/main/resources/assets/eidolon/textures/item/bone_stake.png create mode 100644 src/main/resources/assets/eidolon/textures/item/bonelord_chestplate.png create mode 100644 src/main/resources/assets/eidolon/textures/item/bonelord_greaves.png create mode 100644 src/main/resources/assets/eidolon/textures/item/bonelord_helm.png create mode 100644 src/main/resources/assets/eidolon/textures/item/completed_research.png create mode 100644 src/main/resources/assets/eidolon/textures/item/deathbringer_scythe.png create mode 100644 src/main/resources/assets/eidolon/textures/item/elder_brick.png create mode 100644 src/main/resources/assets/eidolon/textures/item/giant_bone.png create mode 100644 src/main/resources/assets/eidolon/textures/item/grape_candy.png create mode 100644 src/main/resources/assets/eidolon/textures/item/imbued_bones.png create mode 100644 src/main/resources/assets/eidolon/textures/item/magic_candle.png create mode 100644 src/main/resources/assets/eidolon/textures/item/magic_candlestick.png create mode 100644 src/main/resources/assets/eidolon/textures/item/magic_ink.png create mode 100644 src/main/resources/assets/eidolon/textures/item/magicians_wax.png create mode 100644 src/main/resources/assets/eidolon/textures/item/notetaking_tools.png create mode 100644 src/main/resources/assets/eidolon/textures/item/parchment.png create mode 100644 src/main/resources/assets/eidolon/textures/item/raven_cloak.png create mode 100644 src/main/resources/assets/eidolon/textures/item/raven_wings.png create mode 100644 src/main/resources/assets/eidolon/textures/item/red_candy.png create mode 100644 src/main/resources/assets/eidolon/textures/item/research_notes.png create mode 100644 src/main/resources/assets/eidolon/textures/item/soulbone_amulet.png create mode 100644 src/main/resources/assets/eidolon/textures/item/summoning_staff.png create mode 100644 src/main/resources/assets/eidolon/textures/item/withered_heart.png create mode 100644 src/main/resources/assets/eidolon/textures/item/wooden_stake.png create mode 100644 src/main/resources/assets/eidolon/textures/mob_effect/undeath.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/absorption_ritual.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/aura.png delete mode 100644 src/main/resources/assets/eidolon/textures/particle/basic_ring.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/beam.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/death_sign.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/eye.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/feather.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/harmony_sign.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/magic_sign.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/recharge_ritual.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/ring.png create mode 100644 src/main/resources/assets/eidolon/textures/particle/winter_sign.png create mode 100644 src/main/resources/assets/eidolon/textures/rune/crimson_rose.png create mode 100644 src/main/resources/assets/eidolon/textures/rune/sin.png create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/magic_candle.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/magic_candlestick.json create mode 100644 src/main/resources/data/eidolon/loot_tables/blocks/research_table.json create mode 100644 src/main/resources/data/eidolon/recipes/arcane_seal.json create mode 100644 src/main/resources/data/eidolon/recipes/death_essence_withered.json create mode 100644 src/main/resources/data/eidolon/recipes/deathbringer_scythe.json create mode 100644 src/main/resources/data/eidolon/recipes/enchanted_ash_from_block.json create mode 100644 src/main/resources/data/eidolon/recipes/glowstone_dust.json create mode 100644 src/main/resources/data/eidolon/recipes/magic_candle.json create mode 100644 src/main/resources/data/eidolon/recipes/magic_candlestick.json create mode 100644 src/main/resources/data/eidolon/recipes/magic_ink.json create mode 100644 src/main/resources/data/eidolon/recipes/magicians_wax.json create mode 100644 src/main/resources/data/eidolon/recipes/notetaking_tools.json create mode 100644 src/main/resources/data/eidolon/recipes/parchment.json create mode 100644 src/main/resources/data/eidolon/recipes/research_table.json create mode 100644 src/main/resources/data/eidolon/recipes/soulbone_amulet.json create mode 100644 src/main/resources/data/eidolon/tags/items/zombie_food.json create mode 100644 src/main/resources/data/forge/tags/items/raw_materials/lead.json create mode 100644 src/main/resources/data/forge/tags/items/raw_materials/silver.json create mode 100644 src/main/resources/data/forge/tags/items/storage_blocks/raw_lead.json create mode 100644 src/main/resources/data/forge/tags/items/storage_blocks/raw_silver.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/illwood_logs.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json diff --git a/build.gradle b/build.gradle index 63d2b75..a4659f0 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ apply plugin: 'eclipse' apply plugin: 'maven-publish' // apply from: 'https://raw.githubusercontent.com/SizableShrimp/Forge-Class-Remapper/main/classremapper.gradle' -version = '0.3' +version = '0.3b' group = 'elucent.eidolon' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'eidolon' @@ -105,7 +105,9 @@ repositories { } dependencies { - minecraft 'net.minecraftforge:forge:1.18.1-39.0.5' + minecraft 'net.minecraftforge:forge:1.18.1-39.0.55' + + annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.18-5.0.2.4:api") runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:1.18-5.0.2.4") diff --git a/src/main/java/elucent/eidolon/ClientConfig.java b/src/main/java/elucent/eidolon/ClientConfig.java index 2b44c86..9be53a1 100644 --- a/src/main/java/elucent/eidolon/ClientConfig.java +++ b/src/main/java/elucent/eidolon/ClientConfig.java @@ -1,20 +1,51 @@ package elucent.eidolon; +import java.util.List; + import org.apache.commons.lang3.tuple.Pair; +import com.google.common.collect.ImmutableList; + import net.minecraftforge.common.ForgeConfigSpec; public class ClientConfig { // graphics public static ForgeConfigSpec.ConfigValue BETTER_LAYERING; + // ui + public static ForgeConfigSpec.ConfigValue MANA_BAR_POSITION, MANA_BAR_ORIENTATION; + + public static class Positions { + public static final String BOTTOM_LEFT = "bottomLeft", + LEFT = "left", + TOP_LEFT = "topLeft", + TOP = "top", + TOP_RIGHT = "topRight", + RIGHT = "right", + BOTTOM_RIGHT = "bottomRight"; + public static List VALUES = ImmutableList.of(BOTTOM_LEFT, LEFT, TOP_LEFT, TOP, TOP_RIGHT, RIGHT, BOTTOM_RIGHT); + } + + public static class Orientations { + public static final String HORIZONTAL = "horizontal", + VERTICAL = "vertical", + DEFAULT = "default"; + + public static final List VALUES = ImmutableList.of(HORIZONTAL, VERTICAL, DEFAULT); + } public ClientConfig(ForgeConfigSpec.Builder builder) { builder.comment("Graphics settings").push("graphics"); - BETTER_LAYERING = builder.comment("Enable better particle/effect layering.") - .comment("Fixes particles and effects rendering behind clouds and weather.") - .comment("NOTE: Does NOT work with fabulous graphics mode.") + BETTER_LAYERING = builder.comment("Enable better particle/effect layering.", + "Fixes particles and effects rendering behind clouds and weather.", + "NOTE: Does NOT work with fabulous graphics mode.") .define("betterLayering", true); builder.pop(); + builder.comment("UI settings").push("ui"); + MANA_BAR_POSITION = builder.comment("Onscreen positioning of the magic power meter.") + .defineInList("manaBarPosition", "top", Positions.VALUES); + MANA_BAR_ORIENTATION = builder.comment("Orientation of the magic power meter.") + .defineInList("manaBarOrientation", "default", Orientations.VALUES); + builder.pop(); } public static final ClientConfig INSTANCE; diff --git a/src/main/java/elucent/eidolon/ClientEvents.java b/src/main/java/elucent/eidolon/ClientEvents.java index 3b7bc07..b6bc933 100644 --- a/src/main/java/elucent/eidolon/ClientEvents.java +++ b/src/main/java/elucent/eidolon/ClientEvents.java @@ -2,19 +2,55 @@ import java.util.HashMap; import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; + +import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.systems.RenderSystem; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.item.IWingsItem; +import elucent.eidolon.item.WarlockRobesItem; import elucent.eidolon.util.RenderUtil; import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; +import net.minecraft.client.Camera; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; import net.minecraftforge.client.event.RenderLevelLastEvent; +import net.minecraftforge.client.gui.ForgeIngameGui; +import net.minecraftforge.event.TickEvent.PlayerTickEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; public class ClientEvents { @OnlyIn(Dist.CLIENT) @@ -48,11 +84,15 @@ public static MultiBufferSource.BufferSource getDelayedRender() { @SubscribeEvent public void onRenderLast(RenderLevelLastEvent event) { if (ClientConfig.BETTER_LAYERING.get()) { + PoseStack mStack = RenderSystem.getModelViewStack(); + RenderSystem.getModelViewStack().pushPose(); // this feels...cheaty RenderSystem.getModelViewStack().setIdentity(); if (particleMVMatrix != null) RenderSystem.getModelViewStack().mulPoseMatrix(particleMVMatrix); RenderSystem.applyModelViewMatrix(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); getDelayedRender().endBatch(RenderUtil.DELAYED_PARTICLE); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); getDelayedRender().endBatch(RenderUtil.GLOWING_PARTICLE); getDelayedRender().endBatch(RenderUtil.GLOWING_BLOCK_PARTICLE); RenderSystem.getModelViewStack().popPose(); @@ -68,4 +108,45 @@ public void onRenderLast(RenderLevelLastEvent event) { public static float getClientTicks() { return clientTicks; } + + public static boolean isInGui = false; + + @SubscribeEvent + public void onRenderGuiStart(RenderGameOverlayEvent.Pre event) { + if (event.getType() == ElementType.ALL) isInGui = true; + } + + @SubscribeEvent + public void onRenderGuiStart(RenderGameOverlayEvent.Post event) { + if (event.getType() == ElementType.ALL) isInGui = false; + } + + public static int jumpTicks = 0; + public static boolean wasJumping = false; + + @SubscribeEvent + public void onPlayerTick(PlayerTickEvent event) { + if (event.side != LogicalSide.CLIENT) return; + Player p = event.player; + if (p instanceof LocalPlayer lp) { + p.getCapability(IPlayerData.INSTANCE).ifPresent((d) -> { + ItemStack wings = d.getWingsItem(p); + if (!d.canFlap(p)) return; + if (!(wings.getItem() instanceof IWingsItem)) return; + if (lp.input.jumping && (!wasJumping || jumpTicks > 0)) { + jumpTicks ++; + if (jumpTicks > 20) jumpTicks = 20; + } + else if (wasJumping && jumpTicks > 0) { + if (jumpTicks >= 20 && !d.isDashing(p)) { + d.tryDash(p); + } + else d.tryFlapWings(p); + jumpTicks = 0; + } + }); + if (p.isOnGround()) jumpTicks = 0; + wasJumping = p.isOnGround() || lp.input.jumping; + } + } } diff --git a/src/main/java/elucent/eidolon/ClientRegistry.java b/src/main/java/elucent/eidolon/ClientRegistry.java new file mode 100644 index 0000000..8d94b9e --- /dev/null +++ b/src/main/java/elucent/eidolon/ClientRegistry.java @@ -0,0 +1,484 @@ +package elucent.eidolon; + +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.Random; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.entity.AngelArrowRenderer; +import elucent.eidolon.entity.ChantCasterRenderer; +import elucent.eidolon.entity.NecromancerModel; +import elucent.eidolon.entity.NecromancerRenderer; +import elucent.eidolon.entity.RavenModel; +import elucent.eidolon.entity.RavenRenderer; +import elucent.eidolon.entity.SlimySlugModel; +import elucent.eidolon.entity.SlimySlugRenderer; +import elucent.eidolon.entity.WraithModel; +import elucent.eidolon.entity.WraithRenderer; +import elucent.eidolon.entity.ZombieBruteModel; +import elucent.eidolon.entity.ZombieBruteRenderer; +import elucent.eidolon.item.IManaRelatedItem; +import elucent.eidolon.item.curio.RavenCloakRenderer; +import elucent.eidolon.item.model.BonelordArmorModel; +import elucent.eidolon.item.model.RavenCloakModel; +import elucent.eidolon.item.model.SilverArmorModel; +import elucent.eidolon.item.model.TopHatModel; +import elucent.eidolon.item.model.WarlockArmorModel; +import elucent.eidolon.reagent.Reagent; +import elucent.eidolon.reagent.ReagentRegistry; +import elucent.eidolon.ritual.AbsorptionRitual; +import elucent.eidolon.ritual.AllureRitual; +import elucent.eidolon.ritual.CrystalRitual; +import elucent.eidolon.ritual.DaylightRitual; +import elucent.eidolon.ritual.DeceitRitual; +import elucent.eidolon.ritual.MoonlightRitual; +import elucent.eidolon.ritual.PurifyRitual; +import elucent.eidolon.ritual.RechargingRitual; +import elucent.eidolon.ritual.RepellingRitual; +import elucent.eidolon.ritual.SanguineRitual; +import elucent.eidolon.ritual.SummonRitual; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import elucent.eidolon.tile.CrucibleTileRenderer; +import elucent.eidolon.tile.SoulEnchanterTileRenderer; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.client.renderer.entity.EntityRenderers; +import net.minecraft.client.renderer.entity.NoopRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.client.event.RegisterShadersEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; +import net.minecraftforge.client.gui.ForgeIngameGui; +import net.minecraftforge.client.gui.IIngameOverlay; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import top.theillusivec4.curios.api.client.CuriosRendererRegistry; + +public class ClientRegistry { + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public void onTextureStitch(TextureStitchEvent.Pre event) { + event.addSprite(AbsorptionRitual.SYMBOL); + event.addSprite(CrystalRitual.SYMBOL); + event.addSprite(SummonRitual.SYMBOL); + event.addSprite(DeceitRitual.SYMBOL); + event.addSprite(AllureRitual.SYMBOL); + event.addSprite(DaylightRitual.SYMBOL); + event.addSprite(MoonlightRitual.SYMBOL); + event.addSprite(PurifyRitual.SYMBOL); + event.addSprite(RepellingRitual.SYMBOL); + event.addSprite(SanguineRitual.SYMBOL); + event.addSprite(RechargingRitual.SYMBOL); + event.addSprite(SoulEnchanterTileRenderer.BOOK_TEXTURE); + + event.addSprite(new ResourceLocation(Eidolon.MODID, "particle/aura")); + event.addSprite(new ResourceLocation(Eidolon.MODID, "particle/beam")); + event.addSprite(new ResourceLocation(Eidolon.MODID, "particle/ring")); + for (Reagent r : ReagentRegistry.getReagents()) event.addSprite(r.getTexture()); + for (Sign s : Signs.getSigns()) event.addSprite(s.getSprite()); + for (Rune r : Runes.getRunes()) event.addSprite(r.getSprite()); + } + + public static ModelLayerLocation + SILVER_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "silver_armor"), "main"), + WARLOCK_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "warlock_armor"), "main"), + BONELORD_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "bonelord_armor"), "main"), + TOP_HAT_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "top_hat"), "main"), + RAVEN_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "raven"), "main"), + NECROMANCER_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "necromancer"), "main"), + WRAITH_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "wraith"), "main"), + ZOMBIE_BRUTE_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "zombie_brute"), "main"), + SLUG_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "slimy_slug"), "main"), + CRUCIBLE_STIRRER_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "crucible_stirrer"), "main"), + RAVEN_CLOAK_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "raven_cloak"), "main"); + + public static WarlockArmorModel WARLOCK_ARMOR_MODEL = null; + public static BonelordArmorModel BONELORD_ARMOR_MODEL = null; + public static TopHatModel TOP_HAT_MODEL = null; + public static SilverArmorModel SILVER_ARMOR_MODEL = null; + public static ZombieBruteModel ZOMBIE_BRUTE_MODEL = null; + public static WraithModel WRAITH_MODEL = null; + public static RavenModel RAVEN_MODEL = null; + public static NecromancerModel NECROMANCER_MODEL = null; + public static SlimySlugModel SLUG_MODEL = null; + + @SubscribeEvent + public void onRegisterLayers(EntityRenderersEvent.RegisterLayerDefinitions event) { + event.registerLayerDefinition(WARLOCK_ARMOR_LAYER, WarlockArmorModel::createBodyLayer); + event.registerLayerDefinition(BONELORD_ARMOR_LAYER, BonelordArmorModel::createBodyLayer); + event.registerLayerDefinition(TOP_HAT_LAYER, TopHatModel::createBodyLayer); + event.registerLayerDefinition(SILVER_ARMOR_LAYER, SilverArmorModel::createBodyLayer); + event.registerLayerDefinition(RAVEN_CLOAK_LAYER, RavenCloakModel::createBodyLayer); + + event.registerLayerDefinition(RAVEN_LAYER, RavenModel::createBodyLayer); + event.registerLayerDefinition(ZOMBIE_BRUTE_LAYER, ZombieBruteModel::createBodyLayer); + event.registerLayerDefinition(WRAITH_LAYER, WraithModel::createBodyLayer); + event.registerLayerDefinition(NECROMANCER_LAYER, NecromancerModel::createBodyLayer); + event.registerLayerDefinition(SLUG_LAYER, SlimySlugModel::createBodyLayer); + + event.registerLayerDefinition(CRUCIBLE_STIRRER_LAYER, CrucibleTileRenderer::createModelLayer); + } + + @SubscribeEvent + public void onRegisterLayers(EntityRenderersEvent.AddLayers event) { + WARLOCK_ARMOR_MODEL = new WarlockArmorModel(event.getEntityModels().bakeLayer(WARLOCK_ARMOR_LAYER)); + BONELORD_ARMOR_MODEL = new BonelordArmorModel(event.getEntityModels().bakeLayer(BONELORD_ARMOR_LAYER)); + TOP_HAT_MODEL = new TopHatModel(event.getEntityModels().bakeLayer(TOP_HAT_LAYER)); + SILVER_ARMOR_MODEL = new SilverArmorModel(event.getEntityModels().bakeLayer(SILVER_ARMOR_LAYER)); + + RAVEN_MODEL = new RavenModel(event.getEntityModels().bakeLayer(RAVEN_LAYER)); + ZOMBIE_BRUTE_MODEL = new ZombieBruteModel(event.getEntityModels().bakeLayer(ZOMBIE_BRUTE_LAYER)); + WRAITH_MODEL = new WraithModel(event.getEntityModels().bakeLayer(WRAITH_LAYER)); + NECROMANCER_MODEL = new NecromancerModel(event.getEntityModels().bakeLayer(NECROMANCER_LAYER)); + SLUG_MODEL = new SlimySlugModel(event.getEntityModels().bakeLayer(SLUG_LAYER)); + } + + @SubscribeEvent + public void onRegisterEntityRenders(EntityRenderersEvent.RegisterRenderers event) { + EntityRenderers.register(Registry.ZOMBIE_BRUTE.get(), ZombieBruteRenderer::new); + EntityRenderers.register(Registry.WRAITH.get(), WraithRenderer::new); + EntityRenderers.register(Registry.NECROMANCER.get(), NecromancerRenderer::new); + EntityRenderers.register(Registry.SOULFIRE_PROJECTILE.get(), NoopRenderer::new); + EntityRenderers.register(Registry.BONECHILL_PROJECTILE.get(), NoopRenderer::new); + EntityRenderers.register(Registry.NECROMANCER_SPELL.get(), NoopRenderer::new); + EntityRenderers.register(Registry.CHANT_CASTER.get(), ChantCasterRenderer::new); + EntityRenderers.register(Registry.RAVEN.get(), RavenRenderer::new); + EntityRenderers.register(Registry.ANGEL_ARROW.get(), AngelArrowRenderer::new); + EntityRenderers.register(Registry.SLIMY_SLUG.get(), SlimySlugRenderer::new); + } + + public static ShaderInstance GLOWING_SHADER, GLOWING_SPRITE_SHADER, GLOWING_PARTICLE_SHADER, VAPOR_SHADER, GLOWING_ENTITY_SHADER, SPRITE_PARTICLE_SHADER; + + public static ShaderInstance getGlowingShader() { return GLOWING_SHADER; } + public static ShaderInstance getGlowingSpriteShader() { return GLOWING_SPRITE_SHADER; } + public static ShaderInstance getGlowingParticleShader() { return GLOWING_PARTICLE_SHADER; } + public static ShaderInstance getGlowingEntityShader() { return GLOWING_ENTITY_SHADER; } + public static ShaderInstance getVaporShader() { return VAPOR_SHADER; } + public static ShaderInstance getSpriteParticleShader() { return SPRITE_PARTICLE_SHADER; } + + @SubscribeEvent + public void shaderRegistry(RegisterShadersEvent event) throws IOException { + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing"), DefaultVertexFormat.POSITION_COLOR), + shader -> { GLOWING_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_sprite"), DefaultVertexFormat.POSITION_TEX_COLOR), + shader -> { GLOWING_SPRITE_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_particle"), DefaultVertexFormat.PARTICLE), + shader -> { GLOWING_PARTICLE_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_entity"), DefaultVertexFormat.NEW_ENTITY), + shader -> { GLOWING_ENTITY_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:vapor"), DefaultVertexFormat.BLOCK), + shader -> { VAPOR_SHADER = shader; }); + event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:sprite_particle"), DefaultVertexFormat.PARTICLE), + shader -> { SPRITE_PARTICLE_SHADER = shader; }); + } + + public static void initCurios() { + CuriosRendererRegistry.register(Registry.RAVEN_CLOAK.get(), RavenCloakRenderer::new); + } + + protected static final ResourceLocation ICONS_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/gui/icons.png"); + protected static final ResourceLocation MANA_BAR_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/gui/mana_bar.png"); + + public static class EidolonManaBar implements IIngameOverlay { + int xPos() { + String origin = ClientConfig.MANA_BAR_POSITION.get(); + if (origin.equals(ClientConfig.Positions.BOTTOM_LEFT) + || origin.equals(ClientConfig.Positions.LEFT) + || origin.equals(ClientConfig.Positions.TOP_LEFT)) + return -1; + if (origin.equals(ClientConfig.Positions.BOTTOM_RIGHT) + || origin.equals(ClientConfig.Positions.RIGHT) + || origin.equals(ClientConfig.Positions.TOP_RIGHT)) + return 1; + return 0; + } + + int yPos() { + String origin = ClientConfig.MANA_BAR_POSITION.get(); + if (origin.equals(ClientConfig.Positions.TOP_LEFT) + || origin.equals(ClientConfig.Positions.TOP) + || origin.equals(ClientConfig.Positions.TOP_LEFT)) + return -1; + if (origin.equals(ClientConfig.Positions.BOTTOM_LEFT) + || origin.equals(ClientConfig.Positions.BOTTOM_RIGHT)) + return 1; + return 0; + } + + boolean horiz() { + String orient = ClientConfig.MANA_BAR_ORIENTATION.get(); + String origin = ClientConfig.MANA_BAR_POSITION.get(); + if (orient.equals(ClientConfig.Orientations.HORIZONTAL)) return true; + else if (orient.equals(ClientConfig.Orientations.VERTICAL)) return false; + else if (origin.equals(ClientConfig.Positions.LEFT) + || origin.equals(ClientConfig.Positions.RIGHT)) return false; + else return true; + } + + @Override + public void render(ForgeIngameGui gui, PoseStack mStack, float partialTicks, int width, int height) { + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + + int xp = xPos(), yp = yPos(); + boolean isHoriz = horiz(); + + int w = isHoriz ? 120 : 28, h = isHoriz ? 28 : 120; + + int ox = width / 2 - w / 2; + int oy = height / 2 - h / 2; + if (isHoriz) { + if (yp == -1) oy = 4; + else if (yp == 1) oy = height + 4 - h; + if (xp == -1) ox = 8; + else if (xp == 1) ox = width - 4 - w; + } + else { + if (yp == -1) oy = -8; + else if (yp == 1) oy = height - 20 - h; + if (xp == -1) ox = 4; + else if (xp == 1) ox = width + 4 - w; + } + + final int barlength = 114; + float magic = 0, maxMagic = 0; + try { + ISoul soul = player.getCapability(ISoul.INSTANCE).resolve().get(); + magic = soul.getMagic(); + maxMagic = soul.getMaxMagic(); + } catch (NoSuchElementException e) { + // + } + if (maxMagic == 0) return; + if (!(player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof IManaRelatedItem) + && !(player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof IManaRelatedItem)) + return; + + int length = Mth.ceil(barlength * magic / maxMagic); + + int iconU = 48, iconV = 48; + + mStack.pushPose(); + mStack.translate(0, 0, 0.01); + RenderSystem.setShaderTexture(0, MANA_BAR_TEXTURE); + if (isHoriz) { + ox -= 4; + gui.blit(mStack, ox, oy, 2, length == 0 ? 6 : 38, 6, 20); + if (xp > 0) { + gui.blit(mStack, ox - 23, oy - 2, 0, 64, 24, 24); + gui.blit(mStack, ox - 18, oy + 4, iconU, iconV, 12, 12); + } + ox += 6; + + int firstSegment = Math.min(8, length); + length -= firstSegment; + gui.blit(mStack, ox, oy, 8, 38, firstSegment, 20); + ox += firstSegment; + if (firstSegment < 8) { + gui.blit(mStack, ox, oy, 8 + firstSegment, 6, 8 - firstSegment, 20); + ox += 8 - firstSegment; + } + + for (int i = 0; i < 6; i ++) { + int segment = Math.min(16, length); + length -= segment; + gui.blit(mStack, ox, oy, 16, 38, segment, 20); + ox += segment; + if (segment < 16) { + gui.blit(mStack, ox, oy, 16 + segment, 6, 16 - segment, 20); + ox += 16 - segment; + } + } + + int lastSegment = Math.min(8, length); + length -= lastSegment; + gui.blit(mStack, ox, oy, 32, 38, lastSegment, 20); + ox += lastSegment; + if (lastSegment < 8) { + gui.blit(mStack, ox, oy, 32 + lastSegment, 6, 8 - lastSegment, 20); + ox += 8 - lastSegment; + } + + gui.blit(mStack, ox, oy, 40, Mth.ceil(barlength * magic / maxMagic) == barlength ? 6 : 38, 7, 20); + if (xp <= 0) { + gui.blit(mStack, ox + 5, oy - 2, 32, 64, 24, 24); + gui.blit(mStack, ox + 12, oy + 4, iconU, iconV, 12, 12); + } + } + else { + oy += 16; + oy += barlength; + gui.blit(mStack, ox, oy, length == 0 ? 54 : 86, 40, 20, 6); + if (yp < 0) { + gui.blit(mStack, ox - 2, oy + 5, 32, 96, 24, 24); + gui.blit(mStack, ox + 4, oy + 12, iconU, iconV, 12, 12); + } + + int firstSegment = Math.min(8, length); + length -= firstSegment; + oy -= firstSegment; + gui.blit(mStack, ox, oy, 86, 32, 20, firstSegment); + if (firstSegment < 8) { + oy -= 8 - firstSegment; + gui.blit(mStack, ox, oy, 54, 32 + firstSegment, 20, 8 - firstSegment); + } + + for (int i = 0; i < 6; i ++) { + int segment = Math.min(16, length); + length -= segment; + oy -= segment; + gui.blit(mStack, ox, oy, 86, 16, 20, segment); + if (segment < 16) { + oy -= 16 - segment; + gui.blit(mStack, ox, oy, 54, 16 + segment, 20, 16 - segment); + } + } + + int lastSegment = Math.min(8, length); + length -= lastSegment; + oy -= lastSegment; + gui.blit(mStack, ox, oy, 86, 8, 20, lastSegment); + if (lastSegment < 8) { + oy -= 8 - lastSegment; + gui.blit(mStack, ox, oy, 54, 8 + lastSegment, 20, 8 - lastSegment); + } + + oy -= 6; + gui.blit(mStack, ox, oy, Mth.ceil(barlength * magic / maxMagic) == barlength ? 54 : 86, 2, 20, 6); + if (yp >= 0) { + gui.blit(mStack, ox - 2, oy - 23, 0, 96, 24, 24); + gui.blit(mStack, ox + 4, oy - 18, iconU, iconV, 12, 12); + } + } + + mStack.popPose(); + } + } + + public static class EidolonHearts implements IIngameOverlay { + float lastEtherealHealth = 0; + long healthBlinkTime = 0; + long lastHealthTime = 0; + + @Override + public void render(ForgeIngameGui gui, PoseStack mStack, float partialTicks, int width, int height) { + if (!gui.shouldDrawSurvivalElements()) return; + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + mStack.pushPose(); + mStack.translate(0, 0, 0.01); + + int health = Mth.ceil(player.getHealth()); + float absorb = Mth.ceil(player.getAbsorptionAmount()); + AttributeInstance attrMaxHealth = player.getAttribute(Attributes.MAX_HEALTH); + float healthMax = (float)attrMaxHealth.getValue(); + + float etherealHealth = 0, etherealMax = 0; + try { + ISoul cap = player.getCapability(ISoul.INSTANCE).resolve().get(); + etherealHealth = cap.getEtherealHealth(); + etherealMax = cap.getMaxEtherealHealth(); + } catch (NoSuchElementException e) { + // ignore empty optional + } + + int ticks = gui.getGuiTicks(); + boolean highlight = healthBlinkTime > (long)ticks && (healthBlinkTime - (long)ticks) / 3L % 2L == 1L; + + if (etherealHealth < this.lastEtherealHealth && player.invulnerableTime > 0) { + this.lastHealthTime = Util.getMillis(); + this.healthBlinkTime = (long)(ticks + 20); + } + else if (etherealHealth > this.lastEtherealHealth) { + this.lastHealthTime = Util.getMillis(); + this.healthBlinkTime = (long)(ticks + 10); + } + if (Util.getMillis() - this.lastHealthTime > 1000L) { + lastEtherealHealth = health; + lastHealthTime = Util.getMillis(); + } + + lastEtherealHealth = etherealHealth; + + float f = Math.max((float)player.getAttributeValue(Attributes.MAX_HEALTH), (float)Math.max(health, health)); + int regen = -1; + if (player.hasEffect(MobEffects.REGENERATION)) regen = ticks % Mth.ceil(f + 5.0F); + + Random rand = new Random(); + rand.setSeed((long)(ticks * 312871)); + + int absorptionHearts = Mth.ceil(absorb / 2.0f) - 1; + int hearts = Mth.ceil(healthMax / 2.0f) - 1; + int ethHearts = (int)Mth.ceil(etherealMax / 2.0f); + int healthRows = Mth.ceil((healthMax + absorb) / 2.0F / 10.0F); + int totalHealthRows = Mth.ceil((healthMax + absorb + etherealMax) / 2.0F / 10.0F); + int rowHeight = Math.max(10 - (healthRows - 2), 3); + int extraHealthRows = totalHealthRows - healthRows; + int extraRowHeight = Mth.clamp(10 - (healthRows - 2), 3, 10); + + int left = width / 2 - 91; + int top = height - ((ForgeIngameGui)Minecraft.getInstance().gui).left_height + healthRows * rowHeight; + if (rowHeight != 10) top += 10 - rowHeight; + + gui.left_height += extraHealthRows * extraRowHeight; + + RenderSystem.setShaderTexture(0, ICONS_TEXTURE); + for (int i = absorptionHearts + hearts + ethHearts; i > absorptionHearts + hearts; -- i) { + int row = (i + 1) / 10; + int heart = (i + 1) % 10; + int x = left + heart * 8; + int y = top - extraRowHeight * Math.max(0, row - healthRows + 1) - rowHeight * Math.min(row, healthRows - 1); + mc.gui.blit(mStack, x, y, highlight ? 9 : 0, 18, 9, 9); + } + for (int i = absorptionHearts + hearts + ethHearts; i > absorptionHearts + hearts; -- i) { + int row = (i + 1) / 10; + int heart = (i + 1) % 10; + int x = left + heart * 8; + int y = top - extraRowHeight * Math.max(0, row - healthRows + 1) - rowHeight * Math.min(row, healthRows - 1); + int i2 = i - (Mth.ceil((healthMax + absorb) / 2.0f) - 1); + if (i2 * 2 + 1 < etherealHealth) + mc.gui.blit(mStack, x, y, 0, 9, 9, 9); + else if (i2 * 2 + 1 == etherealHealth) + mc.gui.blit(mStack, x, y, 9, 9, 9, 9); + } + for (int i = Mth.ceil((healthMax + absorb) / 2.0F) - 1; i >= 0; -- i) { + int row = i / 10; + int heart = i % 10; + int x = left + heart * 8; + int y = top - row * rowHeight; + + if (health <= 4) y += rand.nextInt(2); + if (i == regen) y -= 2; + + RenderSystem.enableBlend(); + if (player.hasEffect(Registry.CHILLED_EFFECT.get()) && i <= Mth.ceil(healthMax / 2.0f) - 1) { + if (i * 2 + 1 < health) + mc.gui.blit(mStack, x, y, 0, 0, 9, 9); + else if (i * 2 + 1 == health) + mc.gui.blit(mStack, x, y, 9, 0, 9, 9); + } + RenderSystem.disableBlend(); + } + mStack.popPose(); + } + } +} diff --git a/src/main/java/elucent/eidolon/Config.java b/src/main/java/elucent/eidolon/Config.java index 198a448..20abb7e 100644 --- a/src/main/java/elucent/eidolon/Config.java +++ b/src/main/java/elucent/eidolon/Config.java @@ -6,8 +6,12 @@ import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; public class Config { + // generic + public static ConfigValue CRUCIBLE_STEP_DURATION, MAX_ETHEREAL_HEALTH; + // mobs - public static ConfigValue WRAITH_SPAWN_WEIGHT, ZOMBIE_BRUTE_SPAWN_WEIGHT, RAVEN_SPAWN_WEIGHT; + public static ConfigValue WRAITH_SPAWN_WEIGHT, ZOMBIE_BRUTE_SPAWN_WEIGHT, RAVEN_SPAWN_WEIGHT, + ABOVEGROUND_SLUG_WEIGHT, UNDERGROUND_SLUG_WEIGHT; // world public static ConfigValue LEAD_MIN_Y, LEAD_MAX_Y, LEAD_VEIN_SIZE, LEAD_VEIN_COUNT; @@ -17,22 +21,33 @@ public class Config { LAB_ENABLED, STRAY_TOWER_ENABLED, CATACOMB_ENABLED; public Config(ForgeConfigSpec.Builder builder) { + builder.comment("Generic settings").push("generic"); + CRUCIBLE_STEP_DURATION = builder.comment("Duration in ticks of each step of a crucible recipe.") + .defineInRange("crucibleStepDuration", 100, 20, 1200); + MAX_ETHEREAL_HEALTH = builder.comment("Maximum amount of ethereal health (soul half-hearts) an entity can have at once.") + .defineInRange("maxEtherealHealth", 80, 0, 1000); + builder.pop(); + builder.comment("Mob settings").push("mobs"); WRAITH_SPAWN_WEIGHT = builder.comment("Spawn weight for wraith entity. Set to zero to disable spawning.") - .defineInRange("wraithSpawnWeight", 40, 0, 1000); + .defineInRange("wraithSpawnWeight", 60, 0, 1000); ZOMBIE_BRUTE_SPAWN_WEIGHT = builder.comment("Spawn weight for zombie brute entity. Set to zero to disable spawning.") - .defineInRange("zombieBruteSpawnWeight", 40, 0, 1000); + .defineInRange("zombieBruteSpawnWeight", 60, 0, 1000); RAVEN_SPAWN_WEIGHT = builder.comment("Spawn weight for raven entity. Set to zero to disable spawning.") .defineInRange("ravenSpawnWeight", 6, 0, 1000); + ABOVEGROUND_SLUG_WEIGHT = builder.comment("Spawn weight for slug entity in aboveground biomes. Set to zero to disable spawning.") + .defineInRange("slugWeightAboveground", 8, 0, 1000); + UNDERGROUND_SLUG_WEIGHT = builder.comment("Spawn weight for slug entity in underground biomes. Set to zero to disable spawning.") + .defineInRange("slugWeightUnderground", 6, 0, 1000); builder.pop(); builder.comment("World generation settings").push("world"); LEAD_ENABLED = builder.comment("Whether lead ore is enabled. Set to false to disable spawning.") .define("leadEnabled", true); LEAD_MIN_Y = builder.comment("Minimum Y value for lead ore veins") - .defineInRange("leadOreMinY", -27, 0, 254); + .defineInRange("leadOreMinY", -27, -63, 318); LEAD_MAX_Y = builder.comment("Maximum Y value for lead ore veins") - .defineInRange("leadOreMaxY", 41, 1, 255); + .defineInRange("leadOreMaxY", 41, -62, 319); LEAD_VEIN_SIZE = builder.comment("Maximum number of blocks per lead ore vein") .defineInRange("leadOreVeinSize", 6, 1, 255); LEAD_VEIN_COUNT = builder.comment("Number of lead ore veins per chunk") @@ -40,9 +55,9 @@ public Config(ForgeConfigSpec.Builder builder) { SILVER_ENABLED = builder.comment("Whether silver ore is enabled. Set to false to disable spawning.") .define("silverEnabled", true); SILVER_MIN_Y = builder.comment("Minimum Y value for silver ore veins") - .defineInRange("silverOreMinY", -60, 0, 254); + .defineInRange("silverOreMinY", -60, -63, 318); SILVER_MAX_Y = builder.comment("Maximum Y value for silver ore veins") - .defineInRange("silverOreMaxY", 33, 1, 255); + .defineInRange("silverOreMaxY", 33, -62, 319); SILVER_VEIN_SIZE = builder.comment("Maximum number of blocks per silver ore vein") .defineInRange("silverOreVeinSize", 6, 1, 255); SILVER_VEIN_COUNT = builder.comment("Number of silver ore veins per chunk") diff --git a/src/main/java/elucent/eidolon/Eidolon.java b/src/main/java/elucent/eidolon/Eidolon.java index fbdddab..c9871bd 100644 --- a/src/main/java/elucent/eidolon/Eidolon.java +++ b/src/main/java/elucent/eidolon/Eidolon.java @@ -1,24 +1,8 @@ package elucent.eidolon; -import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.capability.IReputation; -import elucent.eidolon.capability.KnowledgeImpl; -import elucent.eidolon.capability.ReputationImpl; import elucent.eidolon.codex.CodexChapters; import elucent.eidolon.deity.RegisterDeitiesEvent; -import elucent.eidolon.entity.AngelArrowRenderer; -import elucent.eidolon.entity.NecromancerEntity; -import elucent.eidolon.entity.NecromancerModel; -import elucent.eidolon.entity.NecromancerRenderer; -import elucent.eidolon.entity.RavenEntity; -import elucent.eidolon.entity.RavenModel; -import elucent.eidolon.entity.RavenRenderer; -import elucent.eidolon.entity.WraithEntity; -import elucent.eidolon.entity.WraithModel; -import elucent.eidolon.entity.WraithRenderer; -import elucent.eidolon.entity.ZombieBruteEntity; -import elucent.eidolon.entity.ZombieBruteModel; -import elucent.eidolon.entity.ZombieBruteRenderer; +import elucent.eidolon.gui.ResearchTableScreen; import elucent.eidolon.gui.SoulEnchanterScreen; import elucent.eidolon.gui.WoodenBrewingStandScreen; import elucent.eidolon.gui.WorktableScreen; @@ -29,8 +13,11 @@ import elucent.eidolon.proxy.ServerProxy; import elucent.eidolon.reagent.RegisterReagentsEvent; import elucent.eidolon.recipe.CrucibleRegistry; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; import elucent.eidolon.ritual.RitualRegistry; import elucent.eidolon.spell.AltarEntries; +import elucent.eidolon.spell.Runes; import elucent.eidolon.tile.BrazierTileRenderer; import elucent.eidolon.tile.CrucibleTileRenderer; import elucent.eidolon.tile.GobletTileRenderer; @@ -42,10 +29,12 @@ import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; -import net.minecraft.client.renderer.entity.EntityRenderers; +import net.minecraft.resources.ResourceLocation; import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobType; import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.entity.ai.attributes.DefaultAttributes; import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.animal.Animal; import net.minecraft.world.item.CreativeModeTab; @@ -54,11 +43,10 @@ import net.minecraft.world.level.levelgen.Heightmap.Types; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.gui.ForgeIngameGui; +import net.minecraftforge.client.gui.OverlayRegistry; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; -import net.minecraftforge.event.entity.EntityAttributeCreationEvent; -import net.minecraftforge.event.entity.EntityAttributeModificationEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.InterModComms; import net.minecraftforge.fml.ModLoadingContext; @@ -73,7 +61,7 @@ @Mod(Eidolon.MODID) public class Eidolon { - public static ISidedProxy proxy = DistExecutor.safeRunForDist(() -> ClientProxy::new, () -> ServerProxy::new); + public static ISidedProxy proxy = DistExecutor.unsafeRunForDist(() -> ClientProxy::new, () -> ServerProxy::new); public static final String MODID = "eidolon"; @@ -83,6 +71,15 @@ public ItemStack makeIcon() { return new ItemStack(Registry.SHADOW_GEM.get(), 1); } }; + + public static boolean trueMobType = false; + + public static MobType getTrueMobType(LivingEntity e) { + trueMobType = true; + MobType type = e.getMobType(); + trueMobType = false; + return type; + } public Eidolon() { FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); @@ -98,6 +95,7 @@ public Eidolon() { MinecraftForge.EVENT_BUS.register(new Events()); DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> { MinecraftForge.EVENT_BUS.register(new ClientEvents()); + FMLJavaModLoadingContext.get().getModEventBus().register(new ClientRegistry()); return new Object(); }); } @@ -108,12 +106,12 @@ public void setup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { CrucibleRegistry.init(); RitualRegistry.init(); - CodexChapters.init(); Registry.addBrewingRecipes(); AltarEntries.init(); - MinecraftForge.EVENT_BUS.post(new RegisterDeitiesEvent()); - MinecraftForge.EVENT_BUS.post(new RegisterReagentsEvent()); + Researches.init(); + Runes.init(); AthameItem.initHarvestables(); + CodexChapters.init(); }); SpawnPlacements.register(Registry.ZOMBIE_BRUTE.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, @@ -123,7 +121,7 @@ public void setup(final FMLCommonSetupEvent event) { SpawnPlacements.register(Registry.RAVEN.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Animal::checkAnimalSpawnRules); SpawnPlacements.register(Registry.SLIMY_SLUG.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, - (e, w, t, pos, rand) -> pos.getY() < w.getHeight(Types.WORLD_SURFACE, pos.getX(), pos.getZ())); + (e, w, t, pos, rand) -> true); } @OnlyIn(Dist.CLIENT) @@ -148,11 +146,18 @@ public static void clientSetup(final FMLClientSetupEvent event){ ItemBlockRenderTypes.setRenderLayer(Registry.SILDRIAN_SEED.get(), RenderType.cutoutMipped()); ItemBlockRenderTypes.setRenderLayer(Registry.OANNA_BLOOM.get(), RenderType.cutoutMipped()); ItemBlockRenderTypes.setRenderLayer(Registry.AVENNIAN_SPRIG.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.ILLWOOD_LEAVES.get(), RenderType.cutoutMipped()); + ItemBlockRenderTypes.setRenderLayer(Registry.ILLWOOD_SAPLING.get(), RenderType.cutoutMipped()); event.enqueueWork(() -> { MenuScreens.register(Registry.WORKTABLE_CONTAINER.get(), WorktableScreen::new); MenuScreens.register(Registry.SOUL_ENCHANTER_CONTAINER.get(), SoulEnchanterScreen::new); MenuScreens.register(Registry.WOODEN_STAND_CONTAINER.get(), WoodenBrewingStandScreen::new); + MenuScreens.register(Registry.RESEARCH_TABLE_CONTAINER.get(), ResearchTableScreen::new); + + OverlayRegistry.registerOverlayAbove(ForgeIngameGui.PLAYER_HEALTH_ELEMENT, Eidolon.MODID + ":hearts", new ClientRegistry.EidolonHearts()); + OverlayRegistry.registerOverlayBelow(ForgeIngameGui.CHAT_PANEL_ELEMENT, Eidolon.MODID + ":mana_bar", new ClientRegistry.EidolonManaBar()); + ClientRegistry.initCurios(); }); } diff --git a/src/main/java/elucent/eidolon/Events.java b/src/main/java/elucent/eidolon/Events.java index 47b90f7..b1f1195 100644 --- a/src/main/java/elucent/eidolon/Events.java +++ b/src/main/java/elucent/eidolon/Events.java @@ -2,14 +2,20 @@ import java.util.Comparator; import java.util.List; +import java.util.UUID; import com.mojang.authlib.GameProfile; import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IPlayerData; import elucent.eidolon.capability.IReputation; +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.capability.KnowledgeCommand; +import elucent.eidolon.entity.ZombieBruteEntity; import elucent.eidolon.entity.ai.PriestBarterGoal; import elucent.eidolon.entity.ai.WitchBarterGoal; -import elucent.eidolon.event.SpeedFactorEvent; +import elucent.eidolon.event.StuckInBlockEvent; +import elucent.eidolon.item.BonelordArmorItem; import elucent.eidolon.item.CleavingAxeItem; import elucent.eidolon.item.CodexItem; import elucent.eidolon.item.ReaperScytheItem; @@ -17,12 +23,19 @@ import elucent.eidolon.network.CrystallizeEffectPacket; import elucent.eidolon.network.KnowledgeUpdatePacket; import elucent.eidolon.network.Networking; +import elucent.eidolon.network.SoulUpdatePacket; +import elucent.eidolon.network.WingsDataUpdatePacket; +import elucent.eidolon.research.Research; import elucent.eidolon.ritual.Ritual; import elucent.eidolon.spell.Signs; import elucent.eidolon.tile.GobletTileEntity; import elucent.eidolon.util.EntityUtil; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; @@ -35,34 +48,49 @@ import net.minecraft.world.entity.monster.WitherSkeleton; import net.minecraft.world.entity.monster.Zombie; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.biome.MobSpawnSettings; +import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.TickEvent.PlayerTickEvent; +import net.minecraftforge.event.entity.EntityAttributeModificationEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; +import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent; +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.event.entity.living.PotionEvent.PotionAddedEvent; +import net.minecraftforge.event.entity.living.PotionEvent.PotionApplicableEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.world.BiomeLoadingEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.registries.ForgeRegistries; public class Events { @@ -73,21 +101,45 @@ public void attachWorldCaps(AttachCapabilitiesEvent event) { @SubscribeEvent public void attachEntityCaps(AttachCapabilitiesEvent event) { - if (event.getObject() instanceof Player) event.addCapability(new ResourceLocation(Eidolon.MODID, "knowledge"), new IKnowledge.Provider()); + if (event.getObject() instanceof Player) { + event.addCapability(new ResourceLocation(Eidolon.MODID, "knowledge"), new IKnowledge.Provider()); + event.addCapability(new ResourceLocation(Eidolon.MODID, "player_data"), new IPlayerData.Provider()); + } + if (event.getObject() instanceof LivingEntity) event.addCapability(new ResourceLocation(Eidolon.MODID, "soul"), new ISoul.Provider()); } @SubscribeEvent public void onClone(PlayerEvent.Clone event) { Capability KNOWLEDGE = IKnowledge.INSTANCE; + Capability SOUL = ISoul.INSTANCE; + Capability PDATA = IPlayerData.INSTANCE; + event.getOriginal().reviveCaps(); event.getPlayer().getCapability(KNOWLEDGE).ifPresent((k) -> { event.getOriginal().getCapability(KNOWLEDGE).ifPresent((o) -> { ((INBTSerializable)k).deserializeNBT(((INBTSerializable)o).serializeNBT()); }); }); + event.getPlayer().getCapability(SOUL).ifPresent((k) -> { + event.getOriginal().getCapability(SOUL).ifPresent((o) -> { + ((INBTSerializable)k).deserializeNBT(((INBTSerializable)o).serializeNBT()); + }); + }); + event.getPlayer().getCapability(PDATA).ifPresent((k) -> { + event.getOriginal().getCapability(PDATA).ifPresent((o) -> { + ((INBTSerializable)k).deserializeNBT(((INBTSerializable)o).serializeNBT()); + }); + }); + event.getOriginal().invalidateCaps(); if (!event.getPlayer().level.isClientSide) { Networking.sendTo(event.getPlayer(), new KnowledgeUpdatePacket(event.getPlayer(), false)); + Networking.sendTo(event.getPlayer(), new SoulUpdatePacket(event.getPlayer())); } } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event) { + KnowledgeCommand.register(event.getDispatcher()); + } @SubscribeEvent public void onTarget(LivingSetAttackTargetEvent event) { @@ -95,6 +147,25 @@ public void onTarget(LivingSetAttackTargetEvent event) { ((Mob)event.getEntityLiving()).setTarget(null); } + @SubscribeEvent + public void onTarget(LivingUpdateEvent event) { + Level level = event.getEntity().getLevel(); + LivingEntity e = event.getEntityLiving(); + if (e.hasEffect(Registry.UNDEATH_EFFECT.get()) && level.isDay() && !level.isClientSide) { + float f = e.getBrightness(); + BlockPos blockpos = e.getVehicle() instanceof Boat ? (new BlockPos(e.getX(), (double) Math.round(e.getY()), e.getZ())).above() : new BlockPos(e.getX(), (double) Math.round(e.getY()), e.getZ()); + if (f > 0.5F && e.getRandom().nextFloat() * 30.0F < (f - 0.4F) * 2.0F && level.canSeeSky(blockpos)) { + e.setSecondsOnFire(8); + } + } + boolean hasBoneArmor = false; + for (ItemStack s : e.getArmorSlots()) { + if (s.getItem() instanceof BonelordArmorItem) hasBoneArmor = true; + } + if (hasBoneArmor && event.getEntityLiving().getHealth() >= event.getEntityLiving().getMaxHealth() * 0.999 && event.getEntity().tickCount % 80 == 0) + event.getEntityLiving().getCapability(ISoul.INSTANCE).ifPresent(s -> s.healEtherealHealth(1, ISoul.getPersistentHealth(event.getEntityLiving()))); + } + @SubscribeEvent public void onDeath(LivingDropsEvent event) { LivingEntity entity = event.getEntityLiving(); @@ -117,11 +188,19 @@ public void onDeath(LivingDropsEvent event) { event.getDrops().clear(); return; } + + if (entity instanceof ZombieBruteEntity z && entity.hasEffect(MobEffects.WITHER) && !entity.level.isClientSide) { + for (ItemEntity item : event.getDrops()) if (item.getItem().is(Registry.ZOMBIE_HEART.get())) { + item.setItem(new ItemStack(Registry.WITHERED_HEART.get(), item.getItem().getCount())); + } + } if (event.getSource().getEntity() != null && event.getSource().getEntity() instanceof LivingEntity) { LivingEntity source = (LivingEntity) event.getSource().getEntity(); ItemStack held = source.getMainHandItem(); - if (!entity.level.isClientSide && held.getItem() instanceof ReaperScytheItem && entity.isInvertedHealAndHarm()) { + if (!entity.level.isClientSide && (held.getItem() instanceof ReaperScytheItem || event.getSource() == Registry.RITUAL_DAMAGE) + && entity.isInvertedHealAndHarm()) { + if (!(entity instanceof Player)) event.getDrops().clear(); int looting = ForgeHooks.getLootingLevel(entity, source, event.getSource()); ItemEntity drop = new ItemEntity(source.level, entity.getX(), entity.getY(), entity.getZ(), new ItemStack(Registry.SOUL_SHARD.get(), source.level.random.nextInt(2 + looting))); @@ -151,6 +230,9 @@ else if (entity instanceof Player) { break; } } + for (ItemEntity e : event.getDrops()) { + if (e.getItem().is(head.getItem())) doDrop = false; // No duplicate heads. + } if (doDrop) { ItemEntity drop = new ItemEntity(source.level, entity.getX(), entity.getY(), entity.getZ(), head); drop.setDefaultPickUpDelay(); @@ -174,6 +256,12 @@ public void registerSpawns(BiomeLoadingEvent ev) { ev.getSpawns().addSpawn(MobCategory.CREATURE, new MobSpawnSettings.SpawnerData(Registry.RAVEN.get(), Config.RAVEN_SPAWN_WEIGHT.get(), 2, 5)); } + if (key.equals(Biomes.OLD_GROWTH_PINE_TAIGA) || key.equals(Biomes.OLD_GROWTH_SPRUCE_TAIGA) || key.equals(Biomes.FLOWER_FOREST)) + ev.getSpawns().addSpawn(MobCategory.AMBIENT, + new MobSpawnSettings.SpawnerData(Registry.SLIMY_SLUG.get(), Config.ABOVEGROUND_SLUG_WEIGHT.get(), 2, 5)); + if (key.equals(Biomes.LUSH_CAVES)) + ev.getSpawns().addSpawn(MobCategory.AMBIENT, + new MobSpawnSettings.SpawnerData(Registry.SLIMY_SLUG.get(), Config.UNDERGROUND_SLUG_WEIGHT.get(), 2, 5)); } @SubscribeEvent @@ -181,6 +269,7 @@ public void registerCustomAI(EntityJoinWorldEvent event) { if (event.getEntity() instanceof LivingEntity && !event.getWorld().isClientSide) { if (event.getEntity() instanceof Player) { Networking.sendTo((Player)event.getEntity(), new KnowledgeUpdatePacket((Player)event.getEntity(), false)); + Networking.sendTo((Player)event.getEntity(), new SoulUpdatePacket((Player)event.getEntity())); } if (event.getEntity() instanceof Witch) { ((Witch)event.getEntity()).goalSelector.addGoal(1, new WitchBarterGoal( @@ -198,6 +287,29 @@ public void registerCustomAI(EntityJoinWorldEvent event) { } } } + + @SubscribeEvent + public void onPlayerTick(PlayerTickEvent event) { + if (event.phase == TickEvent.Phase.END) event.player.getCapability(IPlayerData.INSTANCE).ifPresent((d) -> { + if (!d.getWingsItem(event.player).isEmpty()) { + if (event.player.isCrouching() && event.player.getDeltaMovement().y < -0.1) { + d.startFlying(event.player); + event.player.setDeltaMovement(event.player.getDeltaMovement().x, -0.1, event.player.getDeltaMovement().z); + } + if (d.isFlying(event.player)) event.player.resetFallDistance(); + + if (d.isDashing(event.player)) d.doDashTick(event.player); + + if (event.player.isOnGround()) { + d.rechargeWings(event.player); + d.stopFlying(event.player); + } + if (!event.player.level.isClientSide) { + Networking.sendToTracking(event.player.level, event.player.blockPosition(), new WingsDataUpdatePacket(event.player)); + } + } + }); + } @SubscribeEvent public void onApplyPotion(PotionEvent.PotionApplicableEvent event) { @@ -205,6 +317,28 @@ public void onApplyPotion(PotionEvent.PotionApplicableEvent event) { event.setResult(Event.Result.DENY); } } + + @SubscribeEvent + public void onLivingUse(LivingEntityUseItemEvent event) { + if (event.getEntityLiving().hasEffect(Registry.UNDEATH_EFFECT.get())) { + if (!Registry.ZOMBIE_FOOD_TAG.contains(event.getItem().getItem())) + event.setCanceled(true); + } + } + + @SubscribeEvent + public void onPotionApplicable(PotionAddedEvent event) { + if (event.getEntityLiving().hasEffect(MobEffects.HUNGER) && event.getPotionEffect().getEffect() == Registry.UNDEATH_EFFECT.get()) { + event.getEntityLiving().removeEffect(MobEffects.HUNGER); + } + } + + @SubscribeEvent + public void onPotionApplicable(PotionApplicableEvent event) { + if (event.getEntityLiving().hasEffect(Registry.UNDEATH_EFFECT.get()) && event.getPotionEffect().getEffect() == MobEffects.HUNGER) { + event.setResult(Result.DENY); + } + } @SubscribeEvent public void onLivingHurt(LivingHurtEvent event) { @@ -218,13 +352,21 @@ public void onLivingHurt(LivingHurtEvent event) { if (event.getEntityLiving().getItemBySlot(EquipmentSlot.CHEST).getItem() instanceof WarlockRobesItem) event.setAmount(event.getAmount() / 2); } + + event.getEntityLiving().getCapability(ISoul.INSTANCE).ifPresent(s -> { + if (s.hasEtherealHealth()) { + s.hurtEtherealHealth(event.getAmount(), ISoul.getPersistentHealth(event.getEntityLiving())); + event.setAmount(0); + Networking.sendToTracking(event.getEntity().level, event.getEntity().getOnPos(), new SoulUpdatePacket((Player)event.getEntityLiving())); + } + }); } @SubscribeEvent - public void onGetSpeedFactor(SpeedFactorEvent event) { - if (event.getSpeedFactor() < 1.0f && event.getEntity() instanceof LivingEntity && ((LivingEntity)event.getEntity()).getItemBySlot(EquipmentSlot.FEET).getItem() instanceof WarlockRobesItem) { - float diff = 1.0f - event.getSpeedFactor(); - event.setSpeedFactor(1.0f - diff / 2); + public void onGetSpeedFactor(StuckInBlockEvent event) { + if (event.getStuckMultiplier().length() < 1.0f && event.getEntity() instanceof LivingEntity && ((LivingEntity)event.getEntity()).getItemBySlot(EquipmentSlot.FEET).getItem() instanceof WarlockRobesItem) { + Vec3 diff = new Vec3(1, 1, 1).subtract(event.getStuckMultiplier()).scale(0.5); + event.setStuckMultiplier(new Vec3(1, 1, 1).subtract(diff)); } } } diff --git a/src/main/java/elucent/eidolon/Registry.java b/src/main/java/elucent/eidolon/Registry.java index fa115a7..3f74d2f 100644 --- a/src/main/java/elucent/eidolon/Registry.java +++ b/src/main/java/elucent/eidolon/Registry.java @@ -15,19 +15,23 @@ import elucent.eidolon.block.CrucibleBlock; import elucent.eidolon.block.EffigyBlock; import elucent.eidolon.block.EnchantedAshBlock; +import elucent.eidolon.block.GobletBlock; import elucent.eidolon.block.HandBlock; import elucent.eidolon.block.HerbBlockBase; -import elucent.eidolon.block.HorizontalWaterloggableBlock; import elucent.eidolon.block.NecroticFocusBlock; import elucent.eidolon.block.PillarBlockBase; import elucent.eidolon.block.PipeBlock; +import elucent.eidolon.block.ResearchTableBlock; import elucent.eidolon.block.SoulEnchanterBlock; import elucent.eidolon.block.TableBlockBase; import elucent.eidolon.block.TwoHighBlockBase; import elucent.eidolon.block.WoodenStandBlock; import elucent.eidolon.block.WorktableBlock; import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IPlayerData; import elucent.eidolon.capability.IReputation; +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.capability.KnowledgeCommand; import elucent.eidolon.entity.AngelArrowEntity; import elucent.eidolon.entity.AngelArrowRenderer; import elucent.eidolon.entity.BonechillProjectileEntity; @@ -49,19 +53,26 @@ import elucent.eidolon.entity.ZombieBruteEntity; import elucent.eidolon.entity.ZombieBruteModel; import elucent.eidolon.entity.ZombieBruteRenderer; +import elucent.eidolon.gui.ResearchTableContainer; import elucent.eidolon.gui.SoulEnchanterContainer; import elucent.eidolon.gui.WoodenBrewingStandContainer; import elucent.eidolon.gui.WorktableContainer; import elucent.eidolon.item.AthameItem; import elucent.eidolon.item.BonechillWandItem; +import elucent.eidolon.item.BonelordArmorItem; import elucent.eidolon.item.CleavingAxeItem; import elucent.eidolon.item.CodexItem; +import elucent.eidolon.item.CompletedResearchItem; +import elucent.eidolon.item.DeathbringerScytheItem; import elucent.eidolon.item.ItemBase; +import elucent.eidolon.item.NotetakingToolsItem; import elucent.eidolon.item.ReaperScytheItem; +import elucent.eidolon.item.ResearchNotesItem; import elucent.eidolon.item.ReversalPickItem; import elucent.eidolon.item.SappingSwordItem; import elucent.eidolon.item.SilverArmorItem; import elucent.eidolon.item.SoulfireWandItem; +import elucent.eidolon.item.SummoningStaffItem; import elucent.eidolon.item.Tiers; import elucent.eidolon.item.TongsItem; import elucent.eidolon.item.TopHatItem; @@ -76,8 +87,10 @@ import elucent.eidolon.item.curio.GravityBeltItem; import elucent.eidolon.item.curio.MindShieldingPlateItem; import elucent.eidolon.item.curio.PrestigiousPalmItem; +import elucent.eidolon.item.curio.RavenCloakItem; import elucent.eidolon.item.curio.ResoluteBeltItem; import elucent.eidolon.item.curio.SanguineAmuletItem; +import elucent.eidolon.item.curio.SoulboneAmuletItem; import elucent.eidolon.item.curio.TerminusMirrorItem; import elucent.eidolon.item.curio.VoidAmuletItem; import elucent.eidolon.item.curio.WardedMailItem; @@ -87,8 +100,11 @@ import elucent.eidolon.mixin.PotionBrewingMixin; import elucent.eidolon.particle.BubbleParticleType; import elucent.eidolon.particle.FlameParticleType; +import elucent.eidolon.particle.GlowingSlashParticleType; import elucent.eidolon.particle.LineWispParticleType; +import elucent.eidolon.particle.RuneParticleType; import elucent.eidolon.particle.SignParticleType; +import elucent.eidolon.particle.SlashParticleType; import elucent.eidolon.particle.SmokeParticleType; import elucent.eidolon.particle.SparkleParticleType; import elucent.eidolon.particle.SteamParticleType; @@ -96,11 +112,13 @@ import elucent.eidolon.potion.AnchoredEffect; import elucent.eidolon.potion.ChilledEffect; import elucent.eidolon.potion.ReinforcedEffect; +import elucent.eidolon.potion.UndeathEffect; import elucent.eidolon.potion.VulnerableEffect; import elucent.eidolon.reagent.Reagent; import elucent.eidolon.reagent.ReagentRegistry; import elucent.eidolon.recipe.CrucibleRecipe; import elucent.eidolon.recipe.WorktableRecipe; +import elucent.eidolon.research.Research; import elucent.eidolon.ritual.AllureRitual; import elucent.eidolon.ritual.CrystalRitual; import elucent.eidolon.ritual.DaylightRitual; @@ -114,10 +132,12 @@ import elucent.eidolon.spell.Signs; import elucent.eidolon.tile.BrazierTileEntity; import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.CrucibleTileRenderer; import elucent.eidolon.tile.EffigyTileEntity; import elucent.eidolon.tile.GobletTileEntity; import elucent.eidolon.tile.HandTileEntity; import elucent.eidolon.tile.NecroticFocusTileEntity; +import elucent.eidolon.tile.ResearchTableTileEntity; import elucent.eidolon.tile.SoulEnchanterTileEntity; import elucent.eidolon.tile.SoulEnchanterTileRenderer; import elucent.eidolon.tile.WoodenStandTileEntity; @@ -125,6 +145,7 @@ import elucent.eidolon.tile.reagent.PipeTileEntity; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BushBlock; import net.minecraft.world.level.block.FenceBlock; import net.minecraft.world.level.block.FenceGateBlock; import net.minecraft.world.level.block.RotatedPillarBlock; @@ -134,8 +155,8 @@ import net.minecraft.world.level.block.WallBlock; import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.model.Model; import net.minecraft.client.model.geom.ModelLayerLocation; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.renderer.entity.EntityRenderers; @@ -143,9 +164,12 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; @@ -166,9 +190,11 @@ import net.minecraft.core.particles.ParticleType; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.Potions; import net.minecraft.tags.ItemTags; +import net.minecraft.tags.Tag; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType.BlockEntitySupplier; @@ -182,11 +208,13 @@ import net.minecraftforge.client.event.ParticleFactoryRegisterEvent; import net.minecraftforge.client.event.RegisterShadersEvent; import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.Tags; -import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.event.entity.EntityAttributeModificationEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; @@ -213,6 +241,9 @@ public class Registry { static DeferredRegister SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Eidolon.MODID); static DeferredRegister> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Eidolon.MODID); static DeferredRegister> RECIPE_TYPES = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Eidolon.MODID); + static DeferredRegister ATTRIBUTES = DeferredRegister.create(ForgeRegistries.ATTRIBUTES, Eidolon.MODID); + + public static Tag ZOMBIE_FOOD_TAG = ItemTags.createOptional(new ResourceLocation(Eidolon.MODID, "zombie_food")); static Item.Properties itemProps() { return new Item.Properties().tab(Eidolon.TAB); @@ -239,6 +270,10 @@ static RegistryObject addItem(String name, Item item) { return ITEMS.register(name, () -> item); } + static RegistryObject addItem(String name, Supplier item) { + return ITEMS.register(name, item); + } + static RegistryObject addBlock(String name, Block.Properties props) { Block b = new Block(props); BLOCK_MAP.put(name, b); @@ -325,7 +360,7 @@ static BlockEntityType addTileEntity(IForgeRegistry BlockEntityType addTileEntity(IForgeRegistry new ReinforcedEffect() .addAttributeModifier(Attributes.ARMOR, "483b6415-421e-45d1-ab28-d85d11a19c70", 0.25, Operation.MULTIPLY_TOTAL)), VULNERABLE_EFFECT = POTIONS.register("vulnerable", () -> new VulnerableEffect() - .addAttributeModifier(Attributes.ARMOR, "e5bae4de-2019-4316-b8cc-b4d879d676f9", -0.25, Operation.MULTIPLY_TOTAL)); + .addAttributeModifier(Attributes.ARMOR, "e5bae4de-2019-4316-b8cc-b4d879d676f9", -0.25, Operation.MULTIPLY_TOTAL)), + UNDEATH_EFFECT = POTIONS.register("undeath", () -> new UndeathEffect()); public static RegistryObject CHILLED_POTION = POTION_TYPES.register("chilled", () -> new Potion(new MobEffectInstance(CHILLED_EFFECT.get(), 3600))), @@ -347,7 +383,12 @@ static BlockEntityType addTileEntity(IForgeRegistry new Potion(new MobEffectInstance(REINFORCED_EFFECT.get(), 1800, 1))), VULNERABLE_POTION = POTION_TYPES.register("vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 3600))), LONG_VULNERABLE_POTION = POTION_TYPES.register("long_vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 9600))), - STRONG_VULNERABLE_POTION = POTION_TYPES.register("strong_vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 1800, 1))); + STRONG_VULNERABLE_POTION = POTION_TYPES.register("strong_vulnerable", () -> new Potion(new MobEffectInstance(VULNERABLE_EFFECT.get(), 1800, 1))), + UNDEATH_POTION = POTION_TYPES.register("undeath", () -> new Potion(new MobEffectInstance(UNDEATH_EFFECT.get(), 3600))), + LONG_UNDEATH_POTION = POTION_TYPES.register("long_undeath", () -> new Potion(new MobEffectInstance(UNDEATH_EFFECT.get(), 9600))), + DECAY_POTION = POTION_TYPES.register("decay", () -> new Potion(new MobEffectInstance(MobEffects.WITHER, 900))), + LONG_DECAY_POTION = POTION_TYPES.register("long_decay", () -> new Potion(new MobEffectInstance(MobEffects.WITHER, 1800))), + STRONG_DECAY_POTION = POTION_TYPES.register("strong_decay", () -> new Potion(new MobEffectInstance(MobEffects.WITHER, 450, 1))); public static RegistryObject LEAD_INGOT = addItem("lead_ingot"), @@ -362,10 +403,15 @@ static BlockEntityType addTileEntity(IForgeRegistry new MobEffectInstance(MobEffects.HUNGER, 1800), 0.875f) + .effect(() -> new MobEffectInstance(MobEffects.POISON, 900, 1), 1.0f) + .build())).setLore("lore.eidolon.zombie_heart")), TATTERED_CLOTH = addItem("tattered_cloth"), WRAITH_HEART = addItem("wraith_heart", new ItemBase(itemProps() .rarity(Rarity.UNCOMMON)).setLore("lore.eidolon.wraith_heart")), @@ -434,35 +480,66 @@ static BlockEntityType addTileEntity(IForgeRegistry new MobEffectInstance(MobEffects.HUNGER, 1800), 0.875f) + .effect(() -> new MobEffectInstance(MobEffects.WITHER, 900, 1), 1.0f) + .build())).setLore("lore.eidolon.withered_heart")), + IMBUED_BONES = addItem("imbued_bones", itemProps().rarity(Rarity.UNCOMMON)), + SUMMONING_STAFF = addItem("summoning_staff", new SummoningStaffItem(itemProps().rarity(Rarity.RARE))), + DEATHBRINGER_SCYTHE = addItem("deathbringer_scythe", new DeathbringerScytheItem(itemProps().rarity(Rarity.RARE)) + .setLore("lore.eidolon.deathbringer_scythe")), + SOULBONE_AMULET = addItem("soulbone_amulet", new SoulboneAmuletItem(itemProps() + .rarity(Rarity.RARE).stacksTo(1)).setLore("lore.eidolon.soulbone_amulet")), + BONELORD_HELM = addItem("bonelord_helm", new BonelordArmorItem(EquipmentSlot.HEAD, itemProps().rarity(Rarity.RARE))), + BONELORD_CHESTPLATE = addItem("bonelord_chestplate", new BonelordArmorItem(EquipmentSlot.CHEST, itemProps().rarity(Rarity.RARE))), + BONELORD_GREAVES = addItem("bonelord_greaves", new BonelordArmorItem(EquipmentSlot.LEGS, itemProps().rarity(Rarity.RARE))), PAROUSIA_DISC = addItem("music_disc_parousia", new RecordItem(9, () -> PAROUSIA.get(), itemProps().stacksTo(1).tab(CreativeModeTab.TAB_MISC).rarity(Rarity.RARE))), RAVEN_FEATHER = addItem("raven_feather"), + RAVEN_CLOAK = addItem("raven_cloak", new RavenCloakItem(itemProps().rarity(Rarity.RARE))), ALCHEMISTS_TONGS = addItem("alchemists_tongs", new TongsItem(itemProps().stacksTo(1))), - MERAMMER_RESIN = addItem("merammer_resin"); + MERAMMER_RESIN = addItem("merammer_resin"), + MAGIC_INK = addItem("magic_ink"), + MAGICIANS_WAX = addItem("magicians_wax"), + ARCANE_SEAL = addItem("arcane_seal"), + PARCHMENT = addItem("parchment"), + NOTETAKING_TOOLS = addItem("notetaking_tools", new NotetakingToolsItem(itemProps().stacksTo(16))), + RESEARCH_NOTES = addItem("research_notes", new ResearchNotesItem(itemProps().rarity(Rarity.UNCOMMON).stacksTo(1))), + COMPLETED_RESEARCH = addItem("completed_research", new CompletedResearchItem(itemProps().rarity(Rarity.UNCOMMON).stacksTo(1))), + RED_CANDY = addItem("red_candy", new ItemBase(itemProps().rarity(Rarity.COMMON).food( + new FoodProperties.Builder() + .nutrition(2).saturationMod(2) + .build())).setLore(ChatFormatting.RED, "lore.eidolon.red_candy")), + GRAPE_CANDY = addItem("grape_candy", new ItemBase(itemProps().rarity(Rarity.COMMON).food( + new FoodProperties.Builder() + .nutrition(2).saturationMod(2) + .build())).setLore(ChatFormatting.LIGHT_PURPLE, "lore.eidolon.grape_candy")); public static RegistryObject LEAD_ORE = addBlock("lead_ore", blockProps(Material.STONE, MaterialColor.STONE) - .sound(SoundType.STONE).strength(2.8f, 3.0f)), + .sound(SoundType.STONE).strength(2.8f, 3.0f).requiresCorrectToolForDrops()), DEEP_LEAD_ORE = addBlock("deep_lead_ore", blockProps(Material.STONE, MaterialColor.DEEPSLATE) - .sound(SoundType.STONE).strength(3.2f, 3.0f)), + .sound(SoundType.DEEPSLATE).strength(3.2f, 3.0f).requiresCorrectToolForDrops()), LEAD_BLOCK = addBlock("lead_block", blockProps(Material.STONE, MaterialColor.TERRACOTTA_PURPLE) - .sound(SoundType.METAL).strength(3.0f, 3.0f)), + .sound(SoundType.METAL).strength(3.0f, 3.0f).requiresCorrectToolForDrops()), RAW_LEAD_BLOCK = addBlock("raw_lead_block", blockProps(Material.STONE, MaterialColor.TERRACOTTA_PURPLE) - .sound(SoundType.STONE).strength(2.4f, 3.0f)), + .sound(SoundType.DEEPSLATE).strength(2.4f, 3.0f).requiresCorrectToolForDrops()), SILVER_ORE = addBlock("silver_ore", blockProps(Material.STONE, MaterialColor.STONE) - .sound(SoundType.STONE).strength(3.2f, 3.0f)), + .sound(SoundType.STONE).strength(3.2f, 3.0f).requiresCorrectToolForDrops()), DEEP_SILVER_ORE = addBlock("deep_silver_ore", blockProps(Material.STONE, MaterialColor.DEEPSLATE) - .sound(SoundType.STONE).strength(3.6f, 3.0f)), + .sound(SoundType.DEEPSLATE).strength(3.6f, 3.0f).requiresCorrectToolForDrops()), SILVER_BLOCK = addBlock("silver_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_BLUE) - .sound(SoundType.METAL).strength(3.0f, 3.0f)), + .sound(SoundType.METAL).strength(3.0f, 3.0f).requiresCorrectToolForDrops()), RAW_SILVER_BLOCK = addBlock("raw_silver_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_BLUE) - .sound(SoundType.STONE).strength(2.4f, 3.0f)), + .sound(SoundType.STONE).strength(2.4f, 3.0f).requiresCorrectToolForDrops()), PEWTER_BLOCK = addBlock("pewter_block", blockProps(Material.STONE, MaterialColor.COLOR_LIGHT_GRAY) - .sound(SoundType.METAL).strength(4.0f, 4.0f)), + .sound(SoundType.METAL).strength(4.0f, 4.0f).requiresCorrectToolForDrops()), ARCANE_GOLD_BLOCK = addBlock("arcane_gold_block", blockProps(Material.STONE, MaterialColor.GOLD) - .sound(SoundType.METAL).strength(3.0f, 4.0f)), + .sound(SoundType.METAL).strength(3.0f, 4.0f).requiresCorrectToolForDrops()), SHADOW_GEM_BLOCK = addBlock("shadow_gem_block", blockProps(Material.STONE, MaterialColor.COLOR_PURPLE) - .sound(SoundType.METAL).strength(3.0f, 4.0f)), + .sound(SoundType.METAL).strength(3.0f, 4.0f).requiresCorrectToolForDrops()), WOODEN_ALTAR = addBlock("wooden_altar", new TableBlockBase(blockProps(Material.WOOD, MaterialColor.WOOD) .sound(SoundType.WOOD).strength(1.6f, 3.0f))), STONE_ALTAR = addBlock("stone_altar", new TableBlockBase(blockProps(Material.STONE, MaterialColor.STONE) @@ -476,12 +553,16 @@ static BlockEntityType addTileEntity(IForgeRegistry 15).strength(0.6f, 0.8f).noOcclusion())), CANDLESTICK = addBlock("candlestick", new CandlestickBlock(blockProps(Material.METAL, MaterialColor.GOLD) .sound(SoundType.STONE).lightLevel((state) -> 15).strength(1.2f, 2.0f).noOcclusion())), + MAGIC_CANDLE = addBlock("magic_candle", new CandleBlock(blockProps(Material.DECORATION, MaterialColor.TERRACOTTA_RED) + .sound(SoundType.STONE).lightLevel((state) -> 15).strength(0.6f, 0.8f).noOcclusion())), + MAGIC_CANDLESTICK = addBlock("magic_candlestick", new CandlestickBlock(blockProps(Material.DECORATION, MaterialColor.GOLD) + .sound(SoundType.STONE).lightLevel((state) -> 15).strength(1.2f, 2.0f).noOcclusion())), STRAW_EFFIGY = addBlock("straw_effigy", new EffigyBlock(blockProps(Material.PLANT, MaterialColor.COLOR_YELLOW) .sound(SoundType.WOOD).strength(1.4f, 2.0f) .noOcclusion()).setShape( Shapes.box(0.28125, 0, 0.28125, 0.71875, 1, 0.71875) )), - GOBLET = addBlock("goblet", new BlockBase(blockProps(Material.METAL, MaterialColor.GOLD) + GOBLET = addBlock("goblet", new GobletBlock(blockProps(Material.METAL, MaterialColor.GOLD) .sound(SoundType.METAL).strength(1.4f, 2.0f).requiresCorrectToolForDrops() .noOcclusion()).setShape(Shapes.box(0.3125, 0, 0.3125, 0.6875, 0.5, 0.6875))), UNHOLY_EFFIGY = addBlock("unholy_effigy", new EffigyBlock(blockProps(Material.STONE, MaterialColor.STONE) @@ -497,14 +578,21 @@ static BlockEntityType addTileEntity(IForgeRegistry BlockEntityType addTileEntity(IForgeRegistry BlockEntityType addTileEntity(IForgeRegistry POLISHED_WOOD_PILLAR = addBlock("polished_wood_pillar", new RotatedPillarBlock(blockProps(Material.WOOD, MaterialColor.WOOD) - .strength(1.6f, 3.0f))); + .strength(1.6f, 3.0f))), + SMOOTH_STONE_ARCH = addBlock("smooth_stone_arch", new PillarBlockBase(blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.0f, 3.0f).requiresCorrectToolForDrops())), + MOSSY_SMOOTH_STONE_BRICKS = addBlock("mossy_smooth_stone_bricks", blockProps(Material.STONE, MaterialColor.STONE) + .sound(SoundType.STONE).strength(2.0f, 3.0f).requiresCorrectToolForDrops()), + ELDER_BRICKS_EYE = addBlock("elder_bricks_eye", blockProps(Material.STONE, MaterialColor.TERRACOTTA_ORANGE) + .sound(SoundType.STONE).strength(3.0f, 3.0f).requiresCorrectToolForDrops()), + ELDER_PILLAR = addBlock("elder_pillar", new PillarBlockBase(blockProps(Material.STONE, MaterialColor.TERRACOTTA_ORANGE) + .sound(SoundType.STONE).strength(3.0f, 3.0f) + .requiresCorrectToolForDrops())); public static RegistryObject> ZOMBIE_BRUTE = addEntity("zombie_brute", 7969893, 44975, 1.2f, 2.5f, ZombieBruteEntity::new, MobCategory.MONSTER); @@ -603,13 +724,31 @@ static BlockEntityType addTileEntity(IForgeRegistry> WOODEN_STAND_CONTAINER = addContainer("wooden_brewing_stand", WoodenBrewingStandContainer::new); + public static RegistryObject> + RESEARCH_TABLE_CONTAINER = addContainer("research_table", ResearchTableContainer::new); public static RegistryObject> WORKTABLE_RECIPE = RECIPE_TYPES.register("worktable", () -> new WorktableRecipe.Serializer()); public static RegistryObject> CRUCIBLE_RECIPE = RECIPE_TYPES.register("crucible", () -> new CrucibleRecipe.Serializer()); + + public static RegistryObject + MAX_SOUL_HEARTS = ATTRIBUTES.register("max_soul_hearts", () -> new RangedAttribute(Eidolon.MODID + ".max_soul_hearts", Config.MAX_ETHEREAL_HEALTH.get(), 0, 2000).setSyncable(true)), + PERSISTENT_SOUL_HEARTS = ATTRIBUTES.register("persistent_soul_hearts", () -> new RangedAttribute(Eidolon.MODID + ".persistent_soul_hearts", 0, 0, 2000).setSyncable(true)); + + @SubscribeEvent + public void addCustomAttributes(EntityAttributeModificationEvent event) { + for (EntityType t : event.getTypes()) { + if (event.has(t, Attributes.MAX_HEALTH)) { + event.add(t, Registry.PERSISTENT_SOUL_HEARTS.get()); + event.add(t, Registry.MAX_SOUL_HEARTS.get()); + } + } + } + public static void init() { + ATTRIBUTES.register(FMLJavaModLoadingContext.get().getModEventBus()); BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus()); ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus()); @@ -628,12 +767,17 @@ public static void addBrewingRecipes() { PotionBrewingMixin.callAddMix(Registry.CHILLED_POTION.get(), Items.REDSTONE, Registry.LONG_CHILLED_POTION.get()); PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.WARPED_SPROUTS.get(), Registry.ANCHORED_POTION.get()); PotionBrewingMixin.callAddMix(Registry.ANCHORED_POTION.get(), Items.REDSTONE, Registry.LONG_ANCHORED_POTION.get()); - PotionBrewingMixin.callAddMix(Potions.AWKWARD, Items.LEATHER, Registry.REINFORCED_POTION.get()); + PotionBrewingMixin.callAddMix(Potions.AWKWARD, Items.NAUTILUS_SHELL, Registry.REINFORCED_POTION.get()); PotionBrewingMixin.callAddMix(Registry.REINFORCED_POTION.get(), Items.REDSTONE, Registry.LONG_REINFORCED_POTION.get()); PotionBrewingMixin.callAddMix(Registry.REINFORCED_POTION.get(), Items.GLOWSTONE, Registry.STRONG_REINFORCED_POTION.get()); PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.TATTERED_CLOTH.get(), Registry.VULNERABLE_POTION.get()); PotionBrewingMixin.callAddMix(Registry.VULNERABLE_POTION.get(), Items.REDSTONE, Registry.LONG_VULNERABLE_POTION.get()); PotionBrewingMixin.callAddMix(Registry.VULNERABLE_POTION.get(), Items.GLOWSTONE, Registry.STRONG_VULNERABLE_POTION.get()); + PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.DEATH_ESSENCE.get(), Registry.UNDEATH_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.UNDEATH_POTION.get(), Items.REDSTONE, Registry.LONG_UNDEATH_POTION.get()); + PotionBrewingMixin.callAddMix(Potions.AWKWARD, Registry.WITHERED_HEART.get(), Registry.DECAY_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.DECAY_POTION.get(), Items.REDSTONE, Registry.LONG_DECAY_POTION.get()); + PotionBrewingMixin.callAddMix(Registry.DECAY_POTION.get(), Items.GLOWSTONE, Registry.STRONG_DECAY_POTION.get()); } @OnlyIn(Dist.CLIENT) @@ -650,6 +794,7 @@ public static void clientInit() { public static BlockEntityType GOBLET_TILE_ENTITY; public static BlockEntityType CISTERN_TILE_ENTITY; public static BlockEntityType PIPE_TILE_ENTITY; + public static BlockEntityType RESEARCH_TABLE_TILE_ENTITY; @SubscribeEvent public void registerTiles(RegistryEvent.Register> evt) { @@ -663,6 +808,7 @@ public void registerTiles(RegistryEvent.Register> evt) { GOBLET_TILE_ENTITY = addTileEntity(evt.getRegistry(), "goblet", GobletTileEntity::new, GOBLET.get()); CISTERN_TILE_ENTITY = addTileEntity(evt.getRegistry(), "cistern", CisternTileEntity::new, CISTERN.get()); PIPE_TILE_ENTITY = addTileEntity(evt.getRegistry(), "pipe", PipeTileEntity::new, GLASS_TUBE.get()); + RESEARCH_TABLE_TILE_ENTITY = addTileEntity(evt.getRegistry(), "research_table", ResearchTableTileEntity::new, RESEARCH_TABLE.get()); } public static DamageSource RITUAL_DAMAGE = new DamageSource("ritual").bypassArmor().bypassMagic(); @@ -671,6 +817,8 @@ public void registerTiles(RegistryEvent.Register> evt) { public void registerCaps(RegisterCapabilitiesEvent event) { event.register(IReputation.class); event.register(IKnowledge.class); + event.register(ISoul.class); + event.register(IPlayerData.class); } @SubscribeEvent @@ -700,6 +848,12 @@ public void defineAttributes(EntityAttributeCreationEvent event) { STEAM_PARTICLE = PARTICLES.register("steam_particle", SteamParticleType::new); public static RegistryObject SIGN_PARTICLE = PARTICLES.register("sign_particle", SignParticleType::new); + public static RegistryObject + SLASH_PARTICLE = PARTICLES.register("slash_particle", SlashParticleType::new); + public static RegistryObject + GLOWING_SLASH_PARTICLE = PARTICLES.register("glowing_slash_particle", GlowingSlashParticleType::new); + public static RegistryObject + RUNE_PARTICLE = PARTICLES.register("rune_particle", RuneParticleType::new); @OnlyIn(Dist.CLIENT) @SubscribeEvent @@ -712,109 +866,8 @@ public void registerFactories(ParticleFactoryRegisterEvent evt) { Minecraft.getInstance().particleEngine.register(STEAM_PARTICLE.get(), SteamParticleType.Factory::new); Minecraft.getInstance().particleEngine.register(LINE_WISP_PARTICLE.get(), LineWispParticleType.Factory::new); Minecraft.getInstance().particleEngine.register(SIGN_PARTICLE.get(), (sprite) -> new SignParticleType.Factory()); - } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public void onTextureStitch(TextureStitchEvent.Pre event) { - event.addSprite(CrystalRitual.SYMBOL); - event.addSprite(SummonRitual.SYMBOL); - event.addSprite(DeceitRitual.SYMBOL); - event.addSprite(AllureRitual.SYMBOL); - event.addSprite(DaylightRitual.SYMBOL); - event.addSprite(MoonlightRitual.SYMBOL); - event.addSprite(PurifyRitual.SYMBOL); - event.addSprite(RepellingRitual.SYMBOL); - event.addSprite(SanguineRitual.SYMBOL); - event.addSprite(SoulEnchanterTileRenderer.BOOK_TEXTURE); - - for (Reagent r : ReagentRegistry.getReagents()) event.addSprite(r.getTexture()); - for (Sign s : Signs.getSigns()) event.addSprite(s.getSprite()); - } - - public static ModelLayerLocation - SILVER_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "silver_armor"), "main"), - WARLOCK_ARMOR_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "warlock_armor"), "main"), - TOP_HAT_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "top_hat"), "main"), - RAVEN_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "raven"), "main"), - NECROMANCER_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "necromancer"), "main"), - WRAITH_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "wraith"), "main"), - ZOMBIE_BRUTE_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "zombie_brute"), "main"), - SLUG_LAYER = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "slimy_slug"), "main"); - - public static WarlockArmorModel WARLOCK_ARMOR_MODEL = null; - public static TopHatModel TOP_HAT_MODEL = null; - public static SilverArmorModel SILVER_ARMOR_MODEL = null; - public static ZombieBruteModel ZOMBIE_BRUTE_MODEL = null; - public static WraithModel WRAITH_MODEL = null; - public static RavenModel RAVEN_MODEL = null; - public static NecromancerModel NECROMANCER_MODEL = null; - public static SlimySlugModel SLUG_MODEL = null; - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public void onRegisterLayers(EntityRenderersEvent.RegisterLayerDefinitions event) { - event.registerLayerDefinition(WARLOCK_ARMOR_LAYER, WarlockArmorModel::createBodyLayer); - event.registerLayerDefinition(TOP_HAT_LAYER, TopHatModel::createBodyLayer); - event.registerLayerDefinition(SILVER_ARMOR_LAYER, SilverArmorModel::createBodyLayer); - - event.registerLayerDefinition(RAVEN_LAYER, RavenModel::createBodyLayer); - event.registerLayerDefinition(ZOMBIE_BRUTE_LAYER, ZombieBruteModel::createBodyLayer); - event.registerLayerDefinition(WRAITH_LAYER, WraithModel::createBodyLayer); - event.registerLayerDefinition(NECROMANCER_LAYER, NecromancerModel::createBodyLayer); - event.registerLayerDefinition(SLUG_LAYER, SlimySlugModel::createBodyLayer); - } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public void onRegisterLayers(EntityRenderersEvent.AddLayers event) { - WARLOCK_ARMOR_MODEL = new WarlockArmorModel(event.getEntityModels().bakeLayer(WARLOCK_ARMOR_LAYER)); - TOP_HAT_MODEL = new TopHatModel(event.getEntityModels().bakeLayer(TOP_HAT_LAYER)); - SILVER_ARMOR_MODEL = new SilverArmorModel(event.getEntityModels().bakeLayer(SILVER_ARMOR_LAYER)); - - RAVEN_MODEL = new RavenModel(event.getEntityModels().bakeLayer(RAVEN_LAYER)); - ZOMBIE_BRUTE_MODEL = new ZombieBruteModel(event.getEntityModels().bakeLayer(ZOMBIE_BRUTE_LAYER)); - WRAITH_MODEL = new WraithModel(event.getEntityModels().bakeLayer(WRAITH_LAYER)); - NECROMANCER_MODEL = new NecromancerModel(event.getEntityModels().bakeLayer(NECROMANCER_LAYER)); - SLUG_MODEL = new SlimySlugModel(event.getEntityModels().bakeLayer(SLUG_LAYER)); - } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public void onRegisterEntityRenders(EntityRenderersEvent.RegisterRenderers event) { - EntityRenderers.register(Registry.ZOMBIE_BRUTE.get(), ZombieBruteRenderer::new); - EntityRenderers.register(Registry.WRAITH.get(), WraithRenderer::new); - EntityRenderers.register(Registry.NECROMANCER.get(), NecromancerRenderer::new); - EntityRenderers.register(Registry.SOULFIRE_PROJECTILE.get(), NoopRenderer::new); - EntityRenderers.register(Registry.BONECHILL_PROJECTILE.get(), NoopRenderer::new); - EntityRenderers.register(Registry.NECROMANCER_SPELL.get(), NoopRenderer::new); - EntityRenderers.register(Registry.CHANT_CASTER.get(), NoopRenderer::new); - EntityRenderers.register(Registry.RAVEN.get(), RavenRenderer::new); - EntityRenderers.register(Registry.ANGEL_ARROW.get(), AngelArrowRenderer::new); - EntityRenderers.register(Registry.SLIMY_SLUG.get(), SlimySlugRenderer::new); - } - - @OnlyIn(Dist.CLIENT) - public static ShaderInstance GLOWING_SHADER, GLOWING_SPRITE_SHADER, GLOWING_PARTICLE_SHADER, VAPOR_SHADER, GLOWING_ENTITY_SHADER; - - public static ShaderInstance getGlowingShader() { return GLOWING_SHADER; } - public static ShaderInstance getGlowingSpriteShader() { return GLOWING_SPRITE_SHADER; } - public static ShaderInstance getGlowingParticleShader() { return GLOWING_PARTICLE_SHADER; } - public static ShaderInstance getGlowingEntityShader() { return GLOWING_ENTITY_SHADER; } - public static ShaderInstance getVaporShader() { return VAPOR_SHADER; } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent - public void shaderRegistry(RegisterShadersEvent event) throws IOException { - event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing"), DefaultVertexFormat.POSITION_COLOR), - shader -> { GLOWING_SHADER = shader; }); - event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_sprite"), DefaultVertexFormat.POSITION_TEX_COLOR), - shader -> { GLOWING_SPRITE_SHADER = shader; }); - event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_particle"), DefaultVertexFormat.PARTICLE), - shader -> { GLOWING_PARTICLE_SHADER = shader; }); - event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:glowing_entity"), DefaultVertexFormat.NEW_ENTITY), - shader -> { GLOWING_ENTITY_SHADER = shader; }); - event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("eidolon:vapor"), DefaultVertexFormat.BLOCK), - shader -> { VAPOR_SHADER = shader; }); + Minecraft.getInstance().particleEngine.register(SLASH_PARTICLE.get(), SlashParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(GLOWING_SLASH_PARTICLE.get(), GlowingSlashParticleType.Factory::new); + Minecraft.getInstance().particleEngine.register(RUNE_PARTICLE.get(), (sprite) -> new RuneParticleType.Factory()); } } diff --git a/src/main/java/elucent/eidolon/WorldGen.java b/src/main/java/elucent/eidolon/WorldGen.java index 361fe41..07f4ace 100644 --- a/src/main/java/elucent/eidolon/WorldGen.java +++ b/src/main/java/elucent/eidolon/WorldGen.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; +import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; @@ -18,11 +19,15 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.worldgen.features.OreFeatures; import net.minecraft.data.worldgen.placement.PlacementUtils; +import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biome.BiomeCategory; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.Feature; @@ -117,13 +122,13 @@ public static void init() { Registry.LEAD_ORE.get().defaultBlockState(), Config.LEAD_VEIN_SIZE.get())), "lead_ore"); LEAD_ORE_GEN = PlacementUtils.register("lead_ore", LEAD_ORE.placed( InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.LEAD_VEIN_COUNT.get()), - HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.LEAD_MIN_Y.get()), VerticalAnchor.absolute(Config.LEAD_MAX_Y.get())) + HeightRangePlacement.uniform(VerticalAnchor.absolute(Math.max(0, Config.LEAD_MIN_Y.get())), VerticalAnchor.absolute(Config.LEAD_MAX_Y.get())) )); ConfiguredFeature DEEP_LEAD_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_DEEPSLATE, Registry.DEEP_LEAD_ORE.get().defaultBlockState(), Config.LEAD_VEIN_SIZE.get())), "deep_lead_ore"); DEEP_LEAD_ORE_GEN = PlacementUtils.register("deep_lead_ore", DEEP_LEAD_ORE.placed( InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.LEAD_VEIN_COUNT.get()), - HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.LEAD_MIN_Y.get()), VerticalAnchor.absolute(Config.LEAD_MAX_Y.get())) + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.LEAD_MIN_Y.get()), VerticalAnchor.absolute(Math.min(0, Config.LEAD_MAX_Y.get()))) )); if (Config.LEAD_ENABLED.get()) { ORES.add(LEAD_ORE_GEN); @@ -134,13 +139,13 @@ public static void init() { Registry.SILVER_ORE.get().defaultBlockState(), Config.SILVER_VEIN_SIZE.get())), "silver_ore"); SILVER_ORE_GEN = PlacementUtils.register("silver_ore", SILVER_ORE.placed( InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.SILVER_VEIN_COUNT.get()), - HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.SILVER_MIN_Y.get()), VerticalAnchor.absolute(Config.SILVER_MAX_Y.get())) + HeightRangePlacement.uniform(VerticalAnchor.absolute(Math.max(0, Config.SILVER_MIN_Y.get())), VerticalAnchor.absolute(Config.SILVER_MAX_Y.get())) )); ConfiguredFeature DEEP_SILVER_ORE = register(Feature.ORE.configured(new OreConfiguration(IN_DEEPSLATE, Registry.DEEP_SILVER_ORE.get().defaultBlockState(), Config.SILVER_VEIN_SIZE.get())), "deep_silver_ore"); DEEP_SILVER_ORE_GEN = PlacementUtils.register("deep_silver_ore", DEEP_SILVER_ORE.placed( InSquarePlacement.spread(), BiomeFilter.biome(), CountPlacement.of(Config.SILVER_VEIN_COUNT.get()), - HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.SILVER_MIN_Y.get()), VerticalAnchor.absolute(Config.SILVER_MAX_Y.get())) + HeightRangePlacement.uniform(VerticalAnchor.absolute(Config.SILVER_MIN_Y.get()), VerticalAnchor.absolute(Math.min(0, Config.SILVER_MAX_Y.get()))) )); if (Config.SILVER_ENABLED.get()) { ORES.add(SILVER_ORE_GEN); @@ -181,18 +186,43 @@ public static void init() { @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { -// if (event.getWorld() instanceof ServerLevel level) { -// StructureSettings settings = level.getChunkSource().getGenerator().getSettings(); -// -// ImmutableMap, ImmutableMultimap, ResourceKey>> -// if (Config.LAB_ENABLED.get()) -// Structure -// settings.structureConfig.computeIfAbsent(LAB_STRUCTURE.get(), ).addFeature(LAB_FEATURE); -// if (Config.CATACOMB_ENABLED.get()) -// event.getGeneration().addStructureStart(CATACOMB_FEATURE); -// if (event.getCategory() == Biome.BiomeCategory.ICY && Config.STRAY_TOWER_ENABLED.get()) -// event.getGeneration().addStructureStart(STRAY_TOWER_FEATURE); -// } + if (event.getWorld() instanceof ServerLevel sl) { + ChunkGenerator chunkGenerator = sl.getChunkSource().getGenerator(); + + if (chunkGenerator instanceof FlatLevelSource && sl.dimensionType().equals(DimensionType.OVERWORLD_LOCATION)) { + return; + } + + StructureSettings worldStructureConfig = chunkGenerator.getSettings(); + HashMap, HashMultimap, ResourceKey>> structureMap = new HashMap<>(); + + for(Map.Entry, Biome> biomeEntry : sl.registryAccess().ownedRegistryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY).entrySet()) { + Biome.BiomeCategory biomeCategory = biomeEntry.getValue().getBiomeCategory(); + if (Config.LAB_ENABLED.get()) + associateBiomeToConfiguredStructure(structureMap, LAB_FEATURE, biomeEntry.getKey()); + if ((biomeCategory == BiomeCategory.ICY || biomeCategory == BiomeCategory.TAIGA) && Config.STRAY_TOWER_ENABLED.get()) + associateBiomeToConfiguredStructure(structureMap, STRAY_TOWER_FEATURE, biomeEntry.getKey()); + if (Config.CATACOMB_ENABLED.get()) + associateBiomeToConfiguredStructure(structureMap, CATACOMB_FEATURE, biomeEntry.getKey()); + } + + ImmutableMap.Builder, ImmutableMultimap, ResourceKey>> tempStructureToMultiMap = ImmutableMap.builder(); + worldStructureConfig.configuredStructures.entrySet().stream().filter(entry -> !structureMap.containsKey(entry.getKey())).forEach(tempStructureToMultiMap::put); + structureMap.forEach((key, value) -> tempStructureToMultiMap.put(key, ImmutableMultimap.copyOf(value))); + worldStructureConfig.configuredStructures = tempStructureToMultiMap.build(); + + Map, StructureFeatureConfiguration> tempMap = new HashMap<>(worldStructureConfig.structureConfig()); + tempMap.putIfAbsent(STRAY_TOWER_STRUCTURE.get(), STRUCTURE_SETTINGS.get(STRAY_TOWER_STRUCTURE.getId())); + tempMap.putIfAbsent(LAB_STRUCTURE.get(), STRUCTURE_SETTINGS.get(LAB_STRUCTURE.getId())); + tempMap.putIfAbsent(CATACOMB_STRUCTURE.get(), STRUCTURE_SETTINGS.get(CATACOMB_STRUCTURE.getId())); + worldStructureConfig.structureConfig = tempMap; + } + } + + private static void associateBiomeToConfiguredStructure(Map, HashMultimap, ResourceKey>> STStructureToMultiMap, ConfiguredStructureFeature configuredStructureFeature, ResourceKey biomeRegistryKey) { + STStructureToMultiMap.putIfAbsent(configuredStructureFeature.feature, HashMultimap.create()); + HashMultimap, ResourceKey> configuredStructureToBiomeMultiMap = STStructureToMultiMap.get(configuredStructureFeature.feature); + configuredStructureToBiomeMultiMap.put(configuredStructureFeature, biomeRegistryKey); } @SubscribeEvent diff --git a/src/main/java/elucent/eidolon/block/BlockBase.java b/src/main/java/elucent/eidolon/block/BlockBase.java index b5a946a..9f892b1 100644 --- a/src/main/java/elucent/eidolon/block/BlockBase.java +++ b/src/main/java/elucent/eidolon/block/BlockBase.java @@ -6,7 +6,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionHand; import net.minecraft.core.BlockPos; @@ -18,8 +17,6 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class BlockBase extends Block { VoxelShape shape = null; diff --git a/src/main/java/elucent/eidolon/block/BrazierBlock.java b/src/main/java/elucent/eidolon/block/BrazierBlock.java index 71ae9bf..419e96e 100644 --- a/src/main/java/elucent/eidolon/block/BrazierBlock.java +++ b/src/main/java/elucent/eidolon/block/BrazierBlock.java @@ -2,27 +2,14 @@ import javax.annotation.Nullable; -import elucent.eidolon.gui.SoulEnchanterContainer; import elucent.eidolon.tile.BrazierTileEntity; -import elucent.eidolon.tile.CrucibleTileEntity; -import elucent.eidolon.tile.HandTileEntity; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.network.chat.TextComponent; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class BrazierBlock extends BlockBase implements EntityBlock { public BrazierBlock(Properties properties) { diff --git a/src/main/java/elucent/eidolon/block/CandleBlock.java b/src/main/java/elucent/eidolon/block/CandleBlock.java index 452a6ee..b02fd6a 100644 --- a/src/main/java/elucent/eidolon/block/CandleBlock.java +++ b/src/main/java/elucent/eidolon/block/CandleBlock.java @@ -18,8 +18,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class CandleBlock extends BlockBase { protected static final VoxelShape SHAPE = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 9.0, 10.0D); diff --git a/src/main/java/elucent/eidolon/block/CandlestickBlock.java b/src/main/java/elucent/eidolon/block/CandlestickBlock.java index 92b3120..aae53c9 100644 --- a/src/main/java/elucent/eidolon/block/CandlestickBlock.java +++ b/src/main/java/elucent/eidolon/block/CandlestickBlock.java @@ -23,8 +23,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class CandlestickBlock extends BlockBase { public static final DirectionProperty FACING = DirectionProperty.create("facing", (d) -> d != Direction.DOWN); protected static final VoxelShape UP_SHAPE = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 14.0D, 10.0D); diff --git a/src/main/java/elucent/eidolon/block/CisternBlock.java b/src/main/java/elucent/eidolon/block/CisternBlock.java index 4bf5735..800692e 100644 --- a/src/main/java/elucent/eidolon/block/CisternBlock.java +++ b/src/main/java/elucent/eidolon/block/CisternBlock.java @@ -8,14 +8,11 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.core.Direction; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import elucent.eidolon.tile.reagent.CisternTileEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class CisternBlock extends BlockBase implements EntityBlock { public static final BooleanProperty TOP = BooleanProperty.create("top"); public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); diff --git a/src/main/java/elucent/eidolon/block/CrucibleBlock.java b/src/main/java/elucent/eidolon/block/CrucibleBlock.java index 548b1d9..710964d 100644 --- a/src/main/java/elucent/eidolon/block/CrucibleBlock.java +++ b/src/main/java/elucent/eidolon/block/CrucibleBlock.java @@ -2,26 +2,14 @@ import javax.annotation.Nullable; -import elucent.eidolon.gui.SoulEnchanterContainer; -import elucent.eidolon.tile.BrazierTileEntity; import elucent.eidolon.tile.CrucibleTileEntity; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.network.chat.TextComponent; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class CrucibleBlock extends BlockBase implements EntityBlock { public CrucibleBlock(Properties properties) { diff --git a/src/main/java/elucent/eidolon/block/EffigyBlock.java b/src/main/java/elucent/eidolon/block/EffigyBlock.java index f4a30b9..7459551 100644 --- a/src/main/java/elucent/eidolon/block/EffigyBlock.java +++ b/src/main/java/elucent/eidolon/block/EffigyBlock.java @@ -1,24 +1,10 @@ package elucent.eidolon.block; -import elucent.eidolon.gui.SoulEnchanterContainer; -import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.EffigyTileEntity; -import elucent.eidolon.tile.HandTileEntity; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.network.chat.TextComponent; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class EffigyBlock extends HorizontalWaterloggableBlock implements EntityBlock { public EffigyBlock(Properties properties) { diff --git a/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java b/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java index 68f8987..9eb208a 100644 --- a/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java +++ b/src/main/java/elucent/eidolon/block/EnchantedAshBlock.java @@ -35,8 +35,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class EnchantedAshBlock extends BlockBase { public static final EnumProperty NORTH = BlockStateProperties.NORTH_REDSTONE; public static final EnumProperty EAST = BlockStateProperties.EAST_REDSTONE; diff --git a/src/main/java/elucent/eidolon/block/GobletBlock.java b/src/main/java/elucent/eidolon/block/GobletBlock.java new file mode 100644 index 0000000..59ef3ea --- /dev/null +++ b/src/main/java/elucent/eidolon/block/GobletBlock.java @@ -0,0 +1,24 @@ +package elucent.eidolon.block; + +import javax.annotation.Nullable; + +import elucent.eidolon.tile.CrucibleTileEntity; +import elucent.eidolon.tile.GobletTileEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class GobletBlock extends BlockBase implements EntityBlock { + public GobletBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new GobletTileEntity(pos, state); + } +} diff --git a/src/main/java/elucent/eidolon/block/HandBlock.java b/src/main/java/elucent/eidolon/block/HandBlock.java index 70efb1e..8eb2efa 100644 --- a/src/main/java/elucent/eidolon/block/HandBlock.java +++ b/src/main/java/elucent/eidolon/block/HandBlock.java @@ -1,23 +1,10 @@ package elucent.eidolon.block; -import elucent.eidolon.gui.SoulEnchanterContainer; -import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.HandTileEntity; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.network.chat.TextComponent; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class HandBlock extends HorizontalWaterloggableBlock implements EntityBlock { public HandBlock(Properties properties) { diff --git a/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java b/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java index 7449e6f..2d27611 100644 --- a/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java +++ b/src/main/java/elucent/eidolon/block/HorizontalBlockBase.java @@ -7,8 +7,6 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class HorizontalBlockBase extends BlockBase { public static final DirectionProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; diff --git a/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java b/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java index 7a8ae81..ea6c298 100644 --- a/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java +++ b/src/main/java/elucent/eidolon/block/HorizontalWaterloggableBlock.java @@ -3,10 +3,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.ticks.ScheduledTick; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.StateDefinition; @@ -16,8 +14,6 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class HorizontalWaterloggableBlock extends HorizontalBlockBase implements SimpleWaterloggedBlock { public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; diff --git a/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java b/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java index 6d37099..f35e5fd 100644 --- a/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java +++ b/src/main/java/elucent/eidolon/block/NecroticFocusBlock.java @@ -2,7 +2,6 @@ import net.minecraft.world.level.block.state.BlockState; import elucent.eidolon.tile.NecroticFocusTileEntity; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; @@ -10,7 +9,6 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class NecroticFocusBlock extends HorizontalWaterloggableBlock implements EntityBlock { VoxelShape SOUTH = Shapes.box(0, 0, 0, 1, 1, 0.5), diff --git a/src/main/java/elucent/eidolon/block/PillarBlockBase.java b/src/main/java/elucent/eidolon/block/PillarBlockBase.java index a8970f7..8c0e581 100644 --- a/src/main/java/elucent/eidolon/block/PillarBlockBase.java +++ b/src/main/java/elucent/eidolon/block/PillarBlockBase.java @@ -16,8 +16,6 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class PillarBlockBase extends BlockBase implements SimpleWaterloggedBlock { public static final BooleanProperty TOP = BooleanProperty.create("top"); public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); diff --git a/src/main/java/elucent/eidolon/block/PipeBlock.java b/src/main/java/elucent/eidolon/block/PipeBlock.java index 69c01bd..7b5383f 100644 --- a/src/main/java/elucent/eidolon/block/PipeBlock.java +++ b/src/main/java/elucent/eidolon/block/PipeBlock.java @@ -2,7 +2,6 @@ import com.google.common.base.Predicates; -import elucent.eidolon.tile.SoulEnchanterTileEntity; import elucent.eidolon.tile.reagent.PipeTileEntity; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; @@ -20,8 +19,6 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class PipeBlock extends BlockBase implements EntityBlock { static final VoxelShape UP = Shapes.box(0.375, 0.625, 0.375, 0.625, 1, 0.625), diff --git a/src/main/java/elucent/eidolon/block/ResearchTableBlock.java b/src/main/java/elucent/eidolon/block/ResearchTableBlock.java new file mode 100644 index 0000000..33dcfab --- /dev/null +++ b/src/main/java/elucent/eidolon/block/ResearchTableBlock.java @@ -0,0 +1,67 @@ +package elucent.eidolon.block; + +import javax.annotation.Nullable; + +import elucent.eidolon.gui.ResearchTableContainer; +import elucent.eidolon.gui.WoodenBrewingStandContainer; +import elucent.eidolon.gui.WorktableContainer; +import elucent.eidolon.tile.ResearchTableTileEntity; +import elucent.eidolon.tile.WoodenStandTileEntity; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.item.ItemStack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.network.NetworkHooks; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; + +public class ResearchTableBlock extends HorizontalBlockBase implements EntityBlock { + public ResearchTableBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { + if (worldIn.isClientSide) { + return InteractionResult.SUCCESS; + } else { + BlockEntity tileentity = worldIn.getBlockEntity(pos); + if (tileentity instanceof ResearchTableTileEntity) { + NetworkHooks.openGui((ServerPlayer)player, new SimpleMenuProvider((id, inventory, p) -> { + return new ResearchTableContainer(id, inventory, ((ResearchTableTileEntity)tileentity), ((ResearchTableTileEntity)tileentity).dataAccess); + }, ((ResearchTableTileEntity)tileentity).getDisplayName()), pos); + } + + return InteractionResult.CONSUME; + } + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new ResearchTableTileEntity(pos, state); + } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return new BlockEntityTicker() { + @Override + public void tick(Level level, BlockPos pos, BlockState state, T tile) { + ((ResearchTableTileEntity)tile).tick(); + } + }; + } +} diff --git a/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java b/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java index d43b75b..62f4e3a 100644 --- a/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java +++ b/src/main/java/elucent/eidolon/block/SoulEnchanterBlock.java @@ -3,7 +3,6 @@ import javax.annotation.Nullable; import elucent.eidolon.gui.SoulEnchanterContainer; -import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.SoulEnchanterTileEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.entity.player.Player; @@ -20,7 +19,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class SoulEnchanterBlock extends HorizontalBlockBase implements EntityBlock { public SoulEnchanterBlock(Properties properties) { diff --git a/src/main/java/elucent/eidolon/block/TableBlockBase.java b/src/main/java/elucent/eidolon/block/TableBlockBase.java index a94f271..8bc9abe 100644 --- a/src/main/java/elucent/eidolon/block/TableBlockBase.java +++ b/src/main/java/elucent/eidolon/block/TableBlockBase.java @@ -17,8 +17,6 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class TableBlockBase extends BlockBase implements SimpleWaterloggedBlock { VoxelShape NORMAL = Shapes.box(0, 0.75, 0, 1, 1, 1), CORNER = Shapes.joinUnoptimized( diff --git a/src/main/java/elucent/eidolon/block/TwoHighHorizontalBlockBase.java b/src/main/java/elucent/eidolon/block/TwoHighHorizontalBlockBase.java new file mode 100644 index 0000000..2d0b2a1 --- /dev/null +++ b/src/main/java/elucent/eidolon/block/TwoHighHorizontalBlockBase.java @@ -0,0 +1,55 @@ +package elucent.eidolon.block; + +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.Level; + +public class TwoHighHorizontalBlockBase extends BlockBase { + public static final EnumProperty HALF = BlockStateProperties.HALF; + public static final DirectionProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; + + public TwoHighHorizontalBlockBase(BlockBehaviour.Properties properties) { + super(properties); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return super.canSurvive(state, world, pos) && world.isEmptyBlock(pos.above()); + } + + @Override + public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity entity, ItemStack stack) { + world.setBlockAndUpdate(pos.above(), defaultBlockState().setValue(HALF, Half.TOP) + .setValue(HORIZONTAL_FACING, state.getValue(HORIZONTAL_FACING))); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState().setValue(HALF, Half.BOTTOM) + .setValue(HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override + public void breakBlock(BlockState state, Level world, BlockPos pos) { + if (state.getValue(HALF) == Half.BOTTOM && world.getBlockState(pos.above()).getBlock() == this) + world.destroyBlock(pos.above(), false); + else if (state.getValue(HALF) == Half.TOP && world.getBlockState(pos.below()).getBlock() == this) + world.destroyBlock(pos.below(), false); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(HALF).add(HORIZONTAL_FACING); + } +} diff --git a/src/main/java/elucent/eidolon/block/WoodenStandBlock.java b/src/main/java/elucent/eidolon/block/WoodenStandBlock.java index fa0a912..85b4fb4 100644 --- a/src/main/java/elucent/eidolon/block/WoodenStandBlock.java +++ b/src/main/java/elucent/eidolon/block/WoodenStandBlock.java @@ -5,7 +5,6 @@ import javax.annotation.Nullable; import elucent.eidolon.gui.WoodenBrewingStandContainer; -import elucent.eidolon.tile.CrucibleTileEntity; import elucent.eidolon.tile.WoodenStandTileEntity; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -32,7 +31,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.network.NetworkHooks; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; public class WoodenStandBlock extends BrewingStandBlock { protected static final VoxelShape SHAPE = Shapes.or(Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 14.0D, 9.0D)); diff --git a/src/main/java/elucent/eidolon/block/WorktableBlock.java b/src/main/java/elucent/eidolon/block/WorktableBlock.java index 617d2c0..434597a 100644 --- a/src/main/java/elucent/eidolon/block/WorktableBlock.java +++ b/src/main/java/elucent/eidolon/block/WorktableBlock.java @@ -13,8 +13,6 @@ import net.minecraft.network.chat.TextComponent; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - public class WorktableBlock extends BlockBase { public WorktableBlock(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/capability/IKnowledge.java b/src/main/java/elucent/eidolon/capability/IKnowledge.java index 8975852..6788eff 100644 --- a/src/main/java/elucent/eidolon/capability/IKnowledge.java +++ b/src/main/java/elucent/eidolon/capability/IKnowledge.java @@ -2,6 +2,7 @@ import java.util.Set; +import elucent.eidolon.spell.Rune; import elucent.eidolon.spell.Sign; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -38,9 +39,25 @@ public void deserializeNBT(CompoundTag nbt) { boolean knowsSign(Sign sign); void addSign(Sign sign); + void removeSign(Sign sign); + void resetSigns(); Set getKnownSigns(); boolean knowsFact(ResourceLocation fact); void addFact(ResourceLocation fact); + void removeFact(ResourceLocation fact); + void resetFacts(); Set getKnownFacts(); + + boolean knowsResearch(ResourceLocation research); + void addResearch(ResourceLocation research); + void removeResearch(ResourceLocation research); + void resetResearch(); + Set getKnownResearches(); + + boolean knowsRune(Rune rune); + void addRune(Rune rune); + void removeRune(Rune rune); + void resetRunes(); + Set getKnownRunes(); } diff --git a/src/main/java/elucent/eidolon/capability/IPlayerData.java b/src/main/java/elucent/eidolon/capability/IPlayerData.java new file mode 100644 index 0000000..87e8533 --- /dev/null +++ b/src/main/java/elucent/eidolon/capability/IPlayerData.java @@ -0,0 +1,89 @@ +package elucent.eidolon.capability; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import elucent.eidolon.Registry; +import elucent.eidolon.deity.Deities; +import elucent.eidolon.deity.Deity; +import elucent.eidolon.item.IWingsItem; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; +import top.theillusivec4.curios.api.CuriosApi; + +public interface IPlayerData { + public static final Capability INSTANCE = CapabilityManager.get(new CapabilityToken<>(){}); + + public static class Provider implements ICapabilityProvider, INBTSerializable { + PlayerDataImpl impl = new PlayerDataImpl(); + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == INSTANCE) return (LazyOptional) LazyOptional.of(() -> impl); + else return LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT() { + return impl.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + impl.deserializeNBT(nbt); + } + } + + default ItemStack getWingsItem(Player player) { + ItemStack result[] = new ItemStack[] { ItemStack.EMPTY }; + CuriosApi.getCuriosHelper().getEquippedCurios(player).ifPresent((h) -> { + for (int i = 0; i < h.getSlots(); i ++) { + ItemStack s = h.getStackInSlot(i); + if (s.getItem() instanceof IWingsItem) { + result[0] = s; + break; + } + } + }); + return result[0]; + } + + default int getMaxWingCharges(Player player) { + ItemStack wings = getWingsItem(player); + if (wings.getItem() instanceof IWingsItem i) return i.getMaxCharges(wings); + return 0; + } + + default boolean isDashing(Player player) { + return getDashTicks(player) > 0; + } + + default boolean canFlap(Player player) { + return !player.isOnGround() && !player.isInPowderSnow && !player.isSwimming() && !player.isPassenger() && !player.getAbilities().flying; + } + + int getDashTicks(Player player); + void doDashTick(Player player); + boolean tryDash(Player player); + int getWingCharges(Player player); + void rechargeWings(Player player); + boolean tryFlapWings(Player player); + long getFlightStartTime(Player player); + long getLastFlapTime(Player player); + boolean isFlying(Player player); + void startFlying(Player player); + void stopFlying(Player player); + void setDashTicks(int ticks); + void setLastFlapTime(long lastFlapTime); +} diff --git a/src/main/java/elucent/eidolon/capability/IReputation.java b/src/main/java/elucent/eidolon/capability/IReputation.java index a932aef..f1f410b 100644 --- a/src/main/java/elucent/eidolon/capability/IReputation.java +++ b/src/main/java/elucent/eidolon/capability/IReputation.java @@ -13,7 +13,6 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; @@ -46,6 +45,7 @@ public void deserializeNBT(CompoundTag nbt) { void subtractReputation(UUID player, ResourceLocation deity, double amount); void setReputation(UUID player, ResourceLocation deity, double amount); boolean isLocked(UUID player, ResourceLocation deity); + boolean hasLock(UUID player, ResourceLocation deity, ResourceLocation lock); void lock(UUID player, ResourceLocation deity, ResourceLocation key); boolean unlock(UUID player, ResourceLocation deity, ResourceLocation key); void pray(UUID player, ResourceLocation spell, long time); @@ -92,6 +92,10 @@ default boolean unlock(Player player, ResourceLocation deity, ResourceLocation k return false; } + default boolean hasLock(Player player, ResourceLocation deity, ResourceLocation key) { + return hasLock(player.getUUID(), deity, key); + } + default void pray(Player player, ResourceLocation spell, long time) { pray(player.getUUID(), spell, time); } @@ -102,6 +106,9 @@ default boolean canPray(Player player, ResourceLocation spell, long time) { Map> getPrayerTimes(); Map> getReputationMap(); + default Map getPrayerTimeMap(UUID player) { + return getPrayerTimes().computeIfAbsent(player, (k) -> new HashMap<>()); + } default Map getReputationMap(UUID player) { return getReputationMap().computeIfAbsent(player, (k) -> new HashMap<>()); } diff --git a/src/main/java/elucent/eidolon/capability/ISoul.java b/src/main/java/elucent/eidolon/capability/ISoul.java new file mode 100644 index 0000000..85e3d00 --- /dev/null +++ b/src/main/java/elucent/eidolon/capability/ISoul.java @@ -0,0 +1,85 @@ +package elucent.eidolon.capability; + +import java.util.Set; + +import javax.xml.stream.events.Attribute; + +import elucent.eidolon.Registry; +import elucent.eidolon.spell.Sign; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; + +public interface ISoul { + public static final Capability INSTANCE = CapabilityManager.get(new CapabilityToken<>(){}); + + public static class Provider implements ICapabilityProvider, INBTSerializable { + SoulImpl impl = new SoulImpl(); + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == INSTANCE) return (LazyOptional) LazyOptional.of(() -> impl); + else return LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT() { + return impl.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + impl.deserializeNBT(nbt); + } + } + + boolean hasEtherealHealth(); + float getMaxEtherealHealth(); + float getEtherealHealth(); + void setEtherealHealth(float health); + void setMaxEtherealHealth(float max); + + default void hurtEtherealHealth(float amount, float persistentHealth) { + amount = Math.max(0, amount); + float oldHealth = getEtherealHealth(); + setMaxEtherealHealth(Math.max(getMaxEtherealHealth() - amount, Math.min(persistentHealth, getMaxEtherealHealth()))); + setEtherealHealth(oldHealth - amount); + } + + default void healEtherealHealth(float amount, float persistentHealth) { + amount = Math.max(0, amount); + setEtherealHealth(Math.min(Math.max(getEtherealHealth(), persistentHealth), getEtherealHealth() + amount)); + } + + boolean hasMagic(); + float getMaxMagic(); + float getMagic(); + void setMagic(float magic); + void setMaxMagic(float max); + + default void takeMagic(float amount) { + amount = Math.max(0, amount); + setMagic(getMagic() - amount); + } + + default void giveMagic(float amount) { + amount = Math.max(0, amount); + setMagic(getMagic() + amount); + } + + public static float getPersistentHealth(LivingEntity entity) { + AttributeInstance attr = entity.getAttribute(Registry.PERSISTENT_SOUL_HEARTS.get()); + if (attr != null) return (float)attr.getValue(); + else return 0; + } +} diff --git a/src/main/java/elucent/eidolon/capability/KnowledgeCommand.java b/src/main/java/elucent/eidolon/capability/KnowledgeCommand.java new file mode 100644 index 0000000..3fbb139 --- /dev/null +++ b/src/main/java/elucent/eidolon/capability/KnowledgeCommand.java @@ -0,0 +1,252 @@ +package elucent.eidolon.capability; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableList; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; + +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.commands.ExperienceCommand; +import net.minecraft.server.commands.KillCommand; +import net.minecraft.server.commands.MsgCommand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; + +public class KnowledgeCommand { + public static class SignArgument implements ArgumentType { + private static final DynamicCommandExceptionType UNKNOWN = new DynamicCommandExceptionType((obj) -> new TranslatableComponent("argument.eidolon.sign.unknown", obj)); + + public static Sign getSign(final CommandContext context, final String name) { + return context.getArgument(name, Sign.class); + } + + @Override + public CompletableFuture listSuggestions(final CommandContext context, final SuggestionsBuilder builder) { + for (Sign s : Signs.getSigns()) + if (s.getRegistryName().toString().startsWith(builder.getRemainingLowerCase())) + builder.suggest(s.getRegistryName().toString()); + return builder.buildFuture(); + } + + @Override + public Sign parse(StringReader reader) throws CommandSyntaxException { + ResourceLocation rl = ResourceLocation.read(reader); + Sign s = Signs.find(rl); + if (s == null) throw UNKNOWN.create(rl.toString()); + return s; + } + } + + public static class ResearchArgument implements ArgumentType { + private static final DynamicCommandExceptionType UNKNOWN = new DynamicCommandExceptionType((obj) -> new TranslatableComponent("argument.eidolon.research.unknown", obj)); + + public static Research getResearch(final CommandContext context, final String name) { + return context.getArgument(name, Research.class); + } + + @Override + public CompletableFuture listSuggestions(final CommandContext context, final SuggestionsBuilder builder) { + for (Research r : Researches.getResearches()) + if (r.getRegistryName().toString().startsWith(builder.getRemainingLowerCase())) + builder.suggest(r.getRegistryName().toString()); + return builder.buildFuture(); + } + + @Override + public Research parse(StringReader reader) throws CommandSyntaxException { + ResourceLocation rl = ResourceLocation.read(reader); + Research r = Researches.find(rl); + if (r == null) throw UNKNOWN.create(rl.toString()); + return r; + } + } + + public static class RuneArgument implements ArgumentType { + private static final DynamicCommandExceptionType UNKNOWN = new DynamicCommandExceptionType((obj) -> new TranslatableComponent("argument.eidolon.rune.unknown", obj)); + + public static Rune getRune(final CommandContext context, final String name) { + return context.getArgument(name, Rune.class); + } + + @Override + public CompletableFuture listSuggestions(final CommandContext context, final SuggestionsBuilder builder) { + for (Rune r : Runes.getRunes()) + if (r.getRegistryName().toString().startsWith(builder.getRemainingLowerCase())) + builder.suggest(r.getRegistryName().toString()); + return builder.buildFuture(); + } + + @Override + public Rune parse(StringReader reader) throws CommandSyntaxException { + ResourceLocation rl = ResourceLocation.read(reader); + Rune r = Runes.find(rl); + if (r == null) throw UNKNOWN.create(rl.toString()); + return r; + } + } + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(Commands.literal("knowledge").requires((player) -> { + return player.hasPermission(2); + }).then(Commands.argument("targets", EntityArgument.players()) + .then(Commands.literal("reset").then(Commands.literal("signs").executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.resetSigns(player); + }); + }); + })) + .then(Commands.literal("facts").executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.resetFacts(player); + }); + }); + })) + .then(Commands.literal("research").executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.resetResearch(player); + }); + }); + })) + .then(Commands.literal("runes").executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.resetRunes(player); + }); + }); + })) + ) + .then(Commands.literal("grant") + .then(Commands.literal("sign").then(Commands.argument("sign", new SignArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.grantSign(player, SignArgument.getSign(ctx, "sign")); + }); + }); + }))) + .then(Commands.literal("fact").then(Commands.argument("fact", ResourceLocationArgument.id()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.grantFact(player, ResourceLocationArgument.getId(ctx, "sign")); + }); + }); + }))) + .then(Commands.literal("research").then(Commands.argument("research", new ResearchArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.grantResearch(player, ResearchArgument.getResearch(ctx, "research").getRegistryName()); + }); + }); + }))) + .then(Commands.literal("rune").then(Commands.argument("rune", new RuneArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.grantRune(player, RuneArgument.getRune(ctx, "rune")); + }); + }); + }))) + ) +// .then(Commands.literal("grant") +// .then(Commands.literal("sign").then(Commands.argument("sign", new SignArgument()).executes((ctx) -> { +// return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { +// player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { +// KnowledgeUtil.grantSign(player, SignArgument.getSign(ctx, "sign")); +// }); +// }); +// }))) +// .then(Commands.literal("fact").then(Commands.argument("fact", ResourceLocationArgument.id()).executes((ctx) -> { +// return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { +// player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { +// KnowledgeUtil.grantFact(player, ResourceLocationArgument.getId(ctx, "sign")); +// }); +// }); +// }))) +// .then(Commands.literal("research").then(Commands.argument("research", new ResearchArgument()).executes((ctx) -> { +// return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { +// player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { +// KnowledgeUtil.grantResearch(player, ResearchArgument.getResearch(ctx, "research").getRegistryName()); +// }); +// }); +// }))) +// .then(Commands.literal("rune").then(Commands.argument("rune", new RuneArgument()).executes((ctx) -> { +// return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { +// player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { +// KnowledgeUtil.grantRune(player, RuneArgument.getRune(ctx, "rune")); +// }); +// }); +// }))) +// ) + .then(Commands.literal("remove") + .then(Commands.literal("sign").then(Commands.argument("sign", new SignArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.removeSign(player, SignArgument.getSign(ctx, "sign")); + }); + }); + }))) + .then(Commands.literal("fact").then(Commands.argument("fact", ResourceLocationArgument.id()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.removeFact(player, ResourceLocationArgument.getId(ctx, "sign")); + }); + }); + }))) + .then(Commands.literal("research").then(Commands.argument("research", new ResearchArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.removeResearch(player, ResearchArgument.getResearch(ctx, "research").getRegistryName()); + }); + }); + }))) + .then(Commands.literal("rune").then(Commands.argument("rune", new RuneArgument()).executes((ctx) -> { + return apply(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), (player, sources) -> { + player.getCapability(IKnowledge.INSTANCE).ifPresent((k) -> { + KnowledgeUtil.removeRune(player, RuneArgument.getRune(ctx, "rune")); + }); + }); + }))) + ) + )); + } + + private static int apply(CommandSourceStack sources, Collection players, BiConsumer action) { + for (Player player : players) { + action.accept(player, sources); + } + + if (players.size() == 1) { + sources.sendSuccess(new TranslatableComponent("commands.eidolon.knowledge.success.single", players.iterator().next().getDisplayName()), true); + } else { + sources.sendSuccess(new TranslatableComponent("commands.eidolon.knowledge.success.multiple", players.size()), true); + } + + return players.size(); + } +} diff --git a/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java b/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java index 2c57987..90f575d 100644 --- a/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java +++ b/src/main/java/elucent/eidolon/capability/KnowledgeImpl.java @@ -3,6 +3,8 @@ import java.util.HashSet; import java.util.Set; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; import net.minecraft.nbt.CompoundTag; @@ -15,6 +17,8 @@ public class KnowledgeImpl implements IKnowledge, INBTSerializable { Set signs = new HashSet<>(); Set facts = new HashSet<>(); + Set researches = new HashSet<>(); + Set runes = new HashSet<>(); @Override public boolean knowsSign(Sign sign) { @@ -26,6 +30,16 @@ public void addSign(Sign sign) { signs.add(sign); } + @Override + public void removeSign(Sign sign) { + signs.remove(sign); + } + + @Override + public void resetSigns() { + signs.clear(); + } + @Override public Set getKnownSigns() { return signs; @@ -41,11 +55,71 @@ public void addFact(ResourceLocation fact) { facts.add(fact); } + @Override + public void removeFact(ResourceLocation fact) { + facts.remove(fact); + } + + @Override + public void resetFacts() { + facts.clear(); + } + @Override public Set getKnownFacts() { return facts; } + @Override + public boolean knowsResearch(ResourceLocation research) { + return researches.contains(research); + } + + @Override + public void addResearch(ResourceLocation research) { + researches.add(research); + } + + @Override + public void removeResearch(ResourceLocation research) { + researches.remove(research); + } + + @Override + public void resetResearch() { + researches.clear(); + } + + @Override + public Set getKnownResearches() { + return researches; + } + + @Override + public boolean knowsRune(Rune rune) { + return runes.contains(rune); + } + + @Override + public void addRune(Rune rune) { + runes.add(rune); + } + + @Override + public void removeRune(Rune rune) { + runes.remove(rune); + } + + @Override + public void resetRunes() { + runes.clear(); + } + + @Override + public Set getKnownRunes() { + return runes; + } + @Override public CompoundTag serializeNBT() { ListTag signs = new ListTag(); @@ -56,9 +130,19 @@ public CompoundTag serializeNBT() { for (ResourceLocation s : getKnownFacts()) { facts.add(StringTag.valueOf(s.toString())); } + ListTag researches = new ListTag(); + for (ResourceLocation s : getKnownResearches()) { + researches.add(StringTag.valueOf(s.toString())); + } + ListTag runes = new ListTag(); + for (Rune r : getKnownRunes()) { + runes.add(StringTag.valueOf(r.getRegistryName().toString())); + } CompoundTag wrapper = new CompoundTag(); wrapper.put("signs", signs); wrapper.put("facts", facts); + wrapper.put("researches", researches); + wrapper.put("runes", runes); return wrapper; } @@ -66,6 +150,8 @@ public CompoundTag serializeNBT() { public void deserializeNBT(CompoundTag nbt) { getKnownSigns().clear(); getKnownFacts().clear(); + getKnownResearches().clear(); + getKnownRunes().clear(); if (((CompoundTag)nbt).contains("signs")) { ListTag signs = ((CompoundTag) nbt).getList("signs", Tag.TAG_STRING); @@ -82,5 +168,21 @@ public void deserializeNBT(CompoundTag nbt) { addFact(new ResourceLocation(facts.getString(i))); } } + + if (((CompoundTag)nbt).contains("researches")) { + ListTag researches = ((CompoundTag) nbt).getList("researches", Tag.TAG_STRING); + for (int i = 0; i < researches.size(); i++) { + addResearch(new ResourceLocation(researches.getString(i))); + } + } + + if (((CompoundTag)nbt).contains("runes")) { + ListTag runes = ((CompoundTag) nbt).getList("runes", Tag.TAG_STRING); + for (int i = 0; i < runes.size(); i++) { + ResourceLocation loc = new ResourceLocation(runes.getString(i)); + Rune r = Runes.find(loc); + if (r != null) addRune(r); + } + } } } diff --git a/src/main/java/elucent/eidolon/capability/PlayerDataImpl.java b/src/main/java/elucent/eidolon/capability/PlayerDataImpl.java new file mode 100644 index 0000000..fff023f --- /dev/null +++ b/src/main/java/elucent/eidolon/capability/PlayerDataImpl.java @@ -0,0 +1,177 @@ +package elucent.eidolon.capability; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import elucent.eidolon.item.IWingsItem; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.WingsDashPacket; +import elucent.eidolon.network.WingsFlapPacket; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.common.util.INBTSerializable; + +public class PlayerDataImpl implements IPlayerData, INBTSerializable { + int wingCharges = 0, dashTicks = 0; + long lastFlapTime = 0, flightStartTime = 0; + boolean isFlying = false; + + @Override + public int getWingCharges(Player player) { + return wingCharges; + } + + @Override + public void rechargeWings(Player player) { + wingCharges = getMaxWingCharges(player); + } + + @Override + public boolean tryFlapWings(Player player) { + if (wingCharges <= 0 || getWingsItem(player).isEmpty()) { + wingCharges = 0; + return false; + } + else if (canFlap(player)) { + wingCharges --; + ItemStack wings = getWingsItem(player); + if (wings.getItem() instanceof IWingsItem i) { + if (isDashing(player)) { + i.onDashFlap(player, player.level, wings, getDashTicks(player)); + } + else { + i.onFlap(player, player.level, wings, getDashTicks(player)); + } + lastFlapTime = player.level.getGameTime(); + startFlying(player); + if (player.level.isClientSide) Networking.sendToServer(new WingsFlapPacket(player)); + } + return true; + } + return false; + } + + public int getDashTicks(Player player) { + return dashTicks; + } + + public void doDashTick(Player player) { + if (dashTicks > 0) { + ItemStack wings = getWingsItem(player); + if (wings.getItem() instanceof IWingsItem i) { + i.onDashTick(player, player.level, wings, dashTicks); + } + dashTicks --; + if (dashTicks == 0) { + if (wings.getItem() instanceof IWingsItem i) { + i.onDashEnd(player, player.level, wings); + } + } + } + } + + public boolean tryDash(Player player) { + if (wingCharges > 0 && canFlap(player)) { + wingCharges --; + ItemStack wings = getWingsItem(player); + if (wings.getItem() instanceof IWingsItem i) { + i.onDashStart(player, player.level, wings); + lastFlapTime = player.level.getGameTime(); + if (!isFlying) flightStartTime = lastFlapTime; + isFlying = true; + this.dashTicks = i.getDashTicks(wings); + if (player.level.isClientSide) Networking.sendToServer(new WingsDashPacket(player)); + } + return true; + } + else return false; + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putInt("wingCharges", wingCharges); + tag.putInt("dashTicks", dashTicks); + tag.putLong("lastFlapTime", lastFlapTime); + tag.putLong("flightStartTime", flightStartTime); + tag.putBoolean("isFlying", isFlying); + return tag; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + wingCharges = nbt.getInt("wingCharges"); + dashTicks = nbt.getInt("dashTicks"); + lastFlapTime = nbt.getLong("lastFlapTime"); + flightStartTime = nbt.getLong("flightStartTime"); + isFlying = nbt.getBoolean("isFlying"); + } + + @Override + public long getLastFlapTime(Player player) { + return lastFlapTime; + } + + @Override + public boolean isFlying(Player player) { + return isFlying; + } + + static final AttributeModifier WINGS_SLOWFALL = new AttributeModifier(new UUID(4035878977813972397L, 2208061895106560443L), "Wings slow falling", -0.6, AttributeModifier.Operation.MULTIPLY_TOTAL); + + @Override + public void startFlying(Player player) { + if (!isFlying) { + this.flightStartTime = player.level.getGameTime(); + isFlying = true; + AttributeInstance attr = player.getAttribute(ForgeMod.ENTITY_GRAVITY.get()); + if (attr != null && !attr.hasModifier(WINGS_SLOWFALL)) attr.addTransientModifier(WINGS_SLOWFALL); + } + } + + @Override + public void stopFlying(Player player) { + if (isFlying) { + isFlying = false; + if (isDashing(player)) { + setDashTicks(0); + ItemStack wings = getWingsItem(player); + if (wings.getItem() instanceof IWingsItem i) { + i.onDashEnd(player, player.level, wings); + } + } + this.flightStartTime = player.level.getGameTime(); + AttributeInstance attr = player.getAttribute(ForgeMod.ENTITY_GRAVITY.get()); + if (attr != null && attr.hasModifier(WINGS_SLOWFALL)) attr.removeModifier(WINGS_SLOWFALL); + } + } + + @Override + public void setDashTicks(int ticks) { + dashTicks = ticks; + } + + @Override + public void setLastFlapTime(long lastFlapTime) { + this.lastFlapTime = lastFlapTime; + } + + @Override + public long getFlightStartTime(Player player) { + return this.flightStartTime; + } +} diff --git a/src/main/java/elucent/eidolon/capability/ReputationImpl.java b/src/main/java/elucent/eidolon/capability/ReputationImpl.java index 00d5e17..dc4e305 100644 --- a/src/main/java/elucent/eidolon/capability/ReputationImpl.java +++ b/src/main/java/elucent/eidolon/capability/ReputationImpl.java @@ -44,6 +44,13 @@ public boolean isLocked(UUID player, ResourceLocation deity) { return getReputationMap(player).computeIfAbsent(deity, (k) -> new ReputationEntry()).lock != null; } + @Override + public boolean hasLock(UUID player, ResourceLocation deity, ResourceLocation lock) { + ResourceLocation l = getReputationMap(player).computeIfAbsent(deity, (k) -> new ReputationEntry()).lock; + if (l != null && l.equals(lock)) return true; + return false; + } + @Override public void lock(UUID player, ResourceLocation deity, ResourceLocation key) { getReputationMap(player).computeIfAbsent(deity, (k) -> new ReputationEntry()).lock = key; @@ -67,7 +74,7 @@ public void pray(UUID player, ResourceLocation spell, long time) { @Override public boolean canPray(UUID player, ResourceLocation spell, long time) { Map times = getPrayerTimes().computeIfAbsent(player, (p) -> new HashMap<>()); - return !times.containsKey(player) || times.get(spell) < time - 21000; + return !times.containsKey(spell) || times.get(spell) < time - 21000; } @Override diff --git a/src/main/java/elucent/eidolon/capability/SoulImpl.java b/src/main/java/elucent/eidolon/capability/SoulImpl.java new file mode 100644 index 0000000..dbb1d23 --- /dev/null +++ b/src/main/java/elucent/eidolon/capability/SoulImpl.java @@ -0,0 +1,90 @@ +package elucent.eidolon.capability; + +import java.util.HashSet; +import java.util.Set; + +import elucent.eidolon.Config; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraftforge.common.util.INBTSerializable; + +public class SoulImpl implements ISoul, INBTSerializable { + float maxMagic, magic; + float maxEtherealHealth, etherealHealth; + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putFloat("maxEtherealHealth", maxEtherealHealth); + tag.putFloat("etherealHealth", etherealHealth); + tag.putFloat("maxMagic", maxMagic); + tag.putFloat("magic", magic); + return tag; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + maxEtherealHealth = nbt.contains("maxEtherealHealth") ? nbt.getFloat("maxEtherealHealth") : 0; + etherealHealth = nbt.contains("etherealHealth") ? nbt.getFloat("etherealHealth") : 0; + maxMagic = nbt.contains("maxMagic") ? nbt.getFloat("maxMagic") : 0; + magic = nbt.contains("magic") ? nbt.getFloat("magic") : 0; + } + + @Override + public boolean hasEtherealHealth() { + return maxEtherealHealth > 0; + } + + @Override + public float getMaxEtherealHealth() { + return maxEtherealHealth; + } + + @Override + public float getEtherealHealth() { + return etherealHealth; + } + + @Override + public boolean hasMagic() { + return maxMagic > 0; + } + + @Override + public float getMaxMagic() { + return maxMagic; + } + + @Override + public float getMagic() { + return magic; + } + + @Override + public void setEtherealHealth(float health) { + this.etherealHealth = Mth.clamp(health, 0, maxEtherealHealth); + } + + @Override + public void setMagic(float magic) { + this.magic = Mth.clamp(magic, 0, maxMagic); + } + + @Override + public void setMaxEtherealHealth(float max) { + this.maxEtherealHealth = Mth.clamp(max, 0, Config.MAX_ETHEREAL_HEALTH.get()); + this.etherealHealth = Math.min(maxEtherealHealth, etherealHealth); + } + + @Override + public void setMaxMagic(float max) { + this.maxMagic = Math.max(0, max); + this.magic = Math.min(maxMagic, magic); + } +} diff --git a/src/main/java/elucent/eidolon/codex/ChantPage.java b/src/main/java/elucent/eidolon/codex/ChantPage.java index e48a3a8..4dde8ae 100644 --- a/src/main/java/elucent/eidolon/codex/ChantPage.java +++ b/src/main/java/elucent/eidolon/codex/ChantPage.java @@ -1,12 +1,11 @@ package elucent.eidolon.codex; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.capability.IKnowledge; import elucent.eidolon.spell.Sign; @@ -86,6 +85,7 @@ public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); Sign sign = chant[i]; float flicker = 0.875f + 0.125f * (float)Math.sin(Math.toRadians(12 * ClientEvents.getClientTicks())); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), baseX + i * 24 + 4, y + 32, 16, 16, sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); diff --git a/src/main/java/elucent/eidolon/codex/CodexChapters.java b/src/main/java/elucent/eidolon/codex/CodexChapters.java index 362ca5e..05903ee 100644 --- a/src/main/java/elucent/eidolon/codex/CodexChapters.java +++ b/src/main/java/elucent/eidolon/codex/CodexChapters.java @@ -23,13 +23,14 @@ public class CodexChapters { static List categories = new ArrayList<>(); - static Category NATURE, RITUALS, ARTIFICE, THEURGY, SIGNS; + static Category NATURE, RITUALS, ARTIFICE, THEURGY, SIGNS, RUNES; static Chapter NATURE_INDEX, MONSTERS, ORES, PEWTER, ENCHANTED_ASH, RITUALS_INDEX, BRAZIER, ITEM_PROVIDERS, CRYSTAL_RITUAL, SUMMON_RITUAL, ALLURE_RITUAL, REPELLING_RITUAL, DECEIT_RITUAL, TIME_RITUALS, PURIFY_RITUAL, SANGUINE_RITUAL, ARTIFICE_INDEX, WOODEN_STAND, TALLOW, CRUCIBLE, ARCANE_GOLD, REAGENTS, SOUL_GEMS, SHADOW_GEM, WARPED_SPROUTS, BASIC_ALCHEMY, INLAYS, BASIC_BAUBLES, MAGIC_WORKBENCH, VOID_AMULET, WARDED_MAIL, SOULFIRE_WAND, BONECHILL_WAND, REAPER_SCYTHE, CLEAVING_AXE, SOUL_ENCHANTER, REVERSAL_PICK, WARLOCK_ARMOR, GRAVITY_BELT, PRESTIGIOUS_PALM, MIND_SHIELDING_PLATE, RESOLUTE_BELT, GLASS_HAND, THEURGY_INDEX, INTRO_SIGNS, EFFIGY, ALTARS, ALTAR_LIGHTS, ALTAR_SKULLS, ALTAR_HERBS, GOBLET, DARK_PRAYER, ANIMAL_SACRIFICE, DARK_TOUCH, STONE_ALTAR, UNHOLY_EFFIGY, VILLAGER_SACRIFICE, - SIGNS_INDEX, WICKED_SIGN, SACRED_SIGN, BLOOD_SIGN, SOUL_SIGN, MIND_SIGN, FLAME_SIGN; + SIGNS_INDEX, WICKED_SIGN, SACRED_SIGN, BLOOD_SIGN, SOUL_SIGN, MIND_SIGN, FLAME_SIGN, WINTER_SIGN, HARMONY_SIGN, DEATH_SIGN, WARDING_SIGN, MAGIC_SIGN, + RUNES_INDEX; public static void init() { MONSTERS = new Chapter( @@ -810,6 +811,36 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY, new SignPage(Signs.FLAME_SIGN) ); + WINTER_SIGN = new Chapter( + "eidolon.codex.chapter.winter_sign", + new TitlePage("eidolon.codex.page.winter_sign"), + new SignPage(Signs.WINTER_SIGN) + ); + + HARMONY_SIGN = new Chapter( + "eidolon.codex.chapter.harmony_sign", + new TitlePage("eidolon.codex.page.harmony_sign"), + new SignPage(Signs.HARMONY_SIGN) + ); + + DEATH_SIGN = new Chapter( + "eidolon.codex.chapter.death_sign", + new TitlePage("eidolon.codex.page.death_sign"), + new SignPage(Signs.DEATH_SIGN) + ); + + WARDING_SIGN = new Chapter( + "eidolon.codex.chapter.warding_sign", + new TitlePage("eidolon.codex.page.warding_sign"), + new SignPage(Signs.WARDING_SIGN) + ); + + MAGIC_SIGN = new Chapter( + "eidolon.codex.chapter.magic_sign", + new TitlePage("eidolon.codex.page.magic_sign"), + new SignPage(Signs.MAGIC_SIGN) + ); + SIGNS_INDEX = new Chapter( "eidolon.codex.chapter.signs_index", new SignIndexPage( @@ -819,6 +850,13 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY, new SignEntry(SOUL_SIGN, Signs.SOUL_SIGN), new SignEntry(MIND_SIGN, Signs.MIND_SIGN), new SignEntry(FLAME_SIGN, Signs.FLAME_SIGN) + ), + new SignIndexPage( + new SignEntry(WINTER_SIGN, Signs.WINTER_SIGN), + new SignEntry(HARMONY_SIGN, Signs.HARMONY_SIGN), + new SignEntry(DEATH_SIGN, Signs.DEATH_SIGN), + new SignEntry(WARDING_SIGN, Signs.WARDING_SIGN), + new SignEntry(MAGIC_SIGN, Signs.MAGIC_SIGN) ) ); @@ -828,5 +866,17 @@ ItemStack.EMPTY, new ItemStack(Blocks.STONE), ItemStack.EMPTY, ColorUtil.packColor(255, 163, 74, 207), SIGNS_INDEX )); + + RUNES_INDEX = new Chapter( + "eidolon.codex.chapter.runes_index", + new RuneDescPage(), new RuneIndexPage() + ); + + categories.add(RUNES = new Category( + "runes", + new ItemStack(Registry.PARCHMENT.get()), + ColorUtil.packColor(255, 70, 70, 194), + RUNES_INDEX + )); } } diff --git a/src/main/java/elucent/eidolon/codex/CodexGui.java b/src/main/java/elucent/eidolon/codex/CodexGui.java index 9152866..a18dc7a 100644 --- a/src/main/java/elucent/eidolon/codex/CodexGui.java +++ b/src/main/java/elucent/eidolon/codex/CodexGui.java @@ -1,20 +1,19 @@ package elucent.eidolon.codex; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.lwjgl.glfw.GLFW; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.network.AttemptCastPacket; import elucent.eidolon.network.Networking; +import elucent.eidolon.spell.Rune; import elucent.eidolon.spell.Sign; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; @@ -37,7 +36,8 @@ public class CodexGui extends Screen { public static final CodexGui DUMMY = new CodexGui(); public static final ResourceLocation CODEX_BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_bg.png"); static int xSize = 312, ySize = 208; - List chant = new ArrayList<>(); + List chant = new ArrayList<>(); + Rune hoveredRune = null; Chapter currentChapter; int currentPage = 0; @@ -65,12 +65,12 @@ protected void changeChapter(Chapter next) { currentPage = 0; } - public void addToChant(Sign sign) { - if (this.chant.size() < 9) this.chant.add(sign); + public void addToChant(Rune rune) { + if (this.chant.size() < 18) this.chant.add(rune); } protected void renderChant(PoseStack mStack, int x, int y, int mouseX, int mouseY, float pticks) { - int chantWidth = 32 + 24 * chant.size(); + int chantWidth = 32 + 12 * chant.size(); int baseX = x + this.xSize / 2 - chantWidth / 2, baseY = y + 180; RenderSystem.enableBlend(); @@ -79,9 +79,9 @@ protected void renderChant(PoseStack mStack, int x, int y, int mouseX, int mouse blit(mStack, bgx, baseY, 256, 208, 16, 32, 512, 512); bgx += 16; for (int i = 0; i < chant.size(); i ++) { - blit(mStack, bgx, baseY, 272, 208, 24, 32, 512, 512); - blit(mStack, bgx, baseY, 312, 208, 24, 24, 512, 512); - bgx += 24; + blit(mStack, bgx, baseY, 272, 208, 12, 32, 512, 512); + blit(mStack, bgx, baseY + 6, 320, 240, 12, 12, 512, 512); + bgx += 12; } blit(mStack, bgx, baseY, 296, 208, 16, 32, 512, 512); bgx += 24; @@ -94,25 +94,26 @@ protected void renderChant(PoseStack mStack, int x, int y, int mouseX, int mouse if (cancelHover) renderTooltip(mStack, new TranslatableComponent("eidolon.codex.cancel_hover"), mouseX, mouseY); RenderSystem.enableBlend(); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); bgx = baseX + 16; Tesselator tess = Tesselator.getInstance(); for (int i = 0; i < chant.size(); i ++) { - Sign sign = chant.get(i); - RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 4, baseY + 4, 16, 16, - sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + Rune rune = chant.get(i); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 2, baseY + 8, 8, 8, + 1, 1, 1, 0.5f, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(rune.getSprite())); tess.end(); - bgx += 24; + bgx += 12; } bgx = baseX + 16; RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - float flicker = 0.875f + 0.125f * (float)Math.sin(Math.toRadians(12 * ClientEvents.getClientTicks())); for (int i = 0; i < chant.size(); i ++) { - Sign sign = chant.get(i); - RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 4, baseY + 4, 16, 16, - sign.getRed() * flicker, sign.getGreen() * flicker, sign.getBlue() * flicker, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); + float flicker = 0.75f + 0.25f * (float)Math.sin(Math.toRadians(12 * ClientEvents.getClientTicks() - 360.0f * i / chant.size())); + Rune rune = chant.get(i); + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), bgx + 2, baseY + 8, 8, 8, + flicker, flicker, flicker, 0.5f * flicker, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(rune.getSprite())); tess.end(); - bgx += 24; + bgx += 12; } RenderSystem.defaultBlendFunc(); RenderSystem.disableBlend(); @@ -188,7 +189,7 @@ public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialT } protected boolean interactChant(int x, int y, int mouseX, int mouseY) { - int chantWidth = 32 + 24 * chant.size(); + int chantWidth = 32 + 12 * chant.size(); int baseX = x + this.xSize / 2 - chantWidth / 2, baseY = y + 180; int bgx = baseX + chantWidth + 8; boolean chantHover = mouseX >= bgx && mouseY >= baseY - 4 && mouseX <= bgx + 32 && mouseY <= baseY + 28; diff --git a/src/main/java/elucent/eidolon/codex/IndexPage.java b/src/main/java/elucent/eidolon/codex/IndexPage.java index 3fd8108..56c9a9f 100644 --- a/src/main/java/elucent/eidolon/codex/IndexPage.java +++ b/src/main/java/elucent/eidolon/codex/IndexPage.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import elucent.eidolon.Eidolon; -import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Sign; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.language.I18n; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/elucent/eidolon/codex/RitualPage.java b/src/main/java/elucent/eidolon/codex/RitualPage.java index eae77e9..0cc10d5 100644 --- a/src/main/java/elucent/eidolon/codex/RitualPage.java +++ b/src/main/java/elucent/eidolon/codex/RitualPage.java @@ -1,11 +1,10 @@ package elucent.eidolon.codex; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.ritual.Ritual; @@ -61,11 +60,11 @@ public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int Tesselator tess = Tesselator.getInstance(); RenderSystem.disableTexture(); RenderSystem.depthMask(false); - RenderSystem.setShader(Registry::getGlowingShader); + RenderSystem.setShader(ClientRegistry::getGlowingShader); RenderUtil.dragon(mStack, MultiBufferSource.immediate(tess.getBuilder()), x + 64, y + 48, 20, 20, ritual.getRed(), ritual.getGreen(), ritual.getBlue()); tess.end(); RenderSystem.enableTexture(); - RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); for (int j = 0; j < 2; j++) { RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), x + 52, y + 36, 24, 24, diff --git a/src/main/java/elucent/eidolon/codex/RuneDescPage.java b/src/main/java/elucent/eidolon/codex/RuneDescPage.java new file mode 100644 index 0000000..1edd8ad --- /dev/null +++ b/src/main/java/elucent/eidolon/codex/RuneDescPage.java @@ -0,0 +1,35 @@ +package elucent.eidolon.codex; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.Eidolon; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class RuneDescPage extends Page { + public static final ResourceLocation BLANK = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_blank_page.png"); + public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_title_page.png"); + + public RuneDescPage() { + super(BACKGROUND); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + if (gui.hoveredRune == null) { + } + else { + ResourceLocation rl = gui.hoveredRune.getRegistryName(); + String title = I18n.get(rl.getNamespace() + ".rune." + rl.getPath()); + String text = I18n.get(rl.getNamespace() + ".codex.rune." + rl.getPath()); + int titleWidth = Minecraft.getInstance().font.width(title); + drawText(gui, mStack, title, x + 64 - titleWidth / 2, y + 15 - Minecraft.getInstance().font.lineHeight); + drawWrappingText(gui, mStack, text, x + 4, y + 24, 120); + } + } +} diff --git a/src/main/java/elucent/eidolon/codex/RuneIndexPage.java b/src/main/java/elucent/eidolon/codex/RuneIndexPage.java new file mode 100644 index 0000000..4b48e0f --- /dev/null +++ b/src/main/java/elucent/eidolon/codex/RuneIndexPage.java @@ -0,0 +1,136 @@ +package elucent.eidolon.codex; + +import com.mojang.blaze3d.vertex.PoseStack; + +import java.util.Optional; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.util.ColorUtil; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.Minecraft; +import com.mojang.blaze3d.vertex.BufferBuilder; + +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import com.mojang.blaze3d.vertex.BufferUploader; +import net.minecraft.client.renderer.texture.TextureAtlas; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.world.entity.player.Player; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class RuneIndexPage extends Page { + public static final ResourceLocation BACKGROUND = new ResourceLocation(Eidolon.MODID, "textures/gui/codex_rune_index_page.png"); + Rune[] runes; + int scroll = 0; + + public static class SignEntry { + Chapter chapter; + Sign sign; + + public SignEntry(Chapter chapter, Sign sign) { + this.chapter = chapter; + this.sign = sign; + } + } + + public RuneIndexPage() { + super(BACKGROUND); + this.runes = Runes.getRunes().toArray((i) -> new Rune[i]); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { + Player entity = Minecraft.getInstance().player; + if (entity.getCapability(IKnowledge.INSTANCE, null).resolve().isEmpty()) return false; + IKnowledge knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve().get(); + for (int i = 0; i < runes.length; i ++) { + int xx = x + 2 + (i % 6) * 20, yy = y + 2 + (i / 6) * 20; + if (knowledge.knowsRune(runes[i]) && mouseX >= xx && mouseX <= xx + 16 && mouseY >= yy && mouseY <= yy + 16) { + gui.addToChant(runes[i]); + entity.playNotifySound(Registry.SELECT_RUNE.get(), SoundSource.NEUTRAL, 0.5f, entity.level.random.nextFloat() * 0.25f + 0.75f); + return true; + } + } + return false; + } + + @OnlyIn(Dist.CLIENT) + static void colorBlit(PoseStack mStack, int x, int y, int uOffset, int vOffset, int width, int height, int textureWidth, int textureHeight, int color) { + Matrix4f matrix = mStack.last().pose(); + int maxX = x + width, maxY = y + height; + float minU = (float)uOffset / textureWidth, minV = (float)vOffset / textureHeight; + float maxU = minU + (float)width / textureWidth, maxV = minV + (float)height / textureHeight; + int r = ColorUtil.getRed(color), + g = ColorUtil.getGreen(color), + b = ColorUtil.getBlue(color); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + bufferbuilder.vertex(matrix, (float)x, (float)maxY, 0).uv(minU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)maxY, 0).uv(maxU, maxV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)maxX, (float)y, 0).uv(maxU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.vertex(matrix, (float)x, (float)y, 0).uv(minU, minV).color(r, g, b, 255).endVertex(); + bufferbuilder.end(); + BufferUploader.end(bufferbuilder); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int mouseY) { + gui.hoveredRune = null; + Player entity = Minecraft.getInstance().player; + Optional knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve(); + for (int i = 0; i < runes.length; i ++) { + RenderSystem.setShaderTexture(0, BACKGROUND); + int xx = x + 2 + (i % 6) * 20, yy = y + 2 + (i / 6) * 20; + boolean hover = knowledge.isPresent() && knowledge.get().knowsRune(runes[i]) && mouseX >= xx && mouseX <= xx + 16 && mouseY >= yy && mouseY <= yy + 16; + if (hover) gui.hoveredRune = runes[i]; + gui.blit(mStack, xx, yy, knowledge.isPresent() && knowledge.get().knowsRune(runes[i]) ? 128 : 148, 0, 20, 20); + + if (knowledge.isPresent() && knowledge.get().knowsRune(runes[i])) { + Tesselator tess = Tesselator.getInstance(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); + if (hover) { + mStack.pushPose(); + mStack.translate(xx + 10, yy + 10, 0); + mStack.mulPose(Vector3f.ZP.rotationDegrees(ClientEvents.getClientTicks() * 1.5f)); + mStack.scale(0.5f, 0.5f, 1); + colorBlit(mStack, -12, -12, 128, 20, 24, 24, 256, 256, ColorUtil.packColor(255, 255, 255, 255)); + mStack.popPose(); + } + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + for (int j = 0; j < (hover ? 2 : 1); j++) { + RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), xx + 6, yy + 6, 8, 8, + 1, 1, 1, 0.75f, Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(runes[i].getSprite())); + tess.end(); + } + RenderSystem.disableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, BACKGROUND); + } + } + } +} diff --git a/src/main/java/elucent/eidolon/codex/SignIndexPage.java b/src/main/java/elucent/eidolon/codex/SignIndexPage.java index ce40acd..c1489b6 100644 --- a/src/main/java/elucent/eidolon/codex/SignIndexPage.java +++ b/src/main/java/elucent/eidolon/codex/SignIndexPage.java @@ -1,12 +1,11 @@ package elucent.eidolon.codex; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.capability.IKnowledge; @@ -59,16 +58,16 @@ public boolean click(CodexGui gui, int x, int y, int mouseX, int mouseY) { IKnowledge knowledge = entity.getCapability(IKnowledge.INSTANCE, null).resolve().get(); for (int i = 0; i < entries.length; i ++) { int xx = x + 8 + (i % 2) * 56, yy = y + 4 + (i / 2) * 52; - if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx + 38 && mouseY >= yy + 38 && mouseX <= xx + 50 && mouseY <= yy + 50) { + if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx && mouseX <= xx + 48 && mouseY >= yy && mouseY <= yy + 48) { gui.changeChapter(entries[i].chapter); Minecraft.getInstance().player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.NEUTRAL, 1.0f, 1.0f); return true; } - else if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx && mouseX <= xx + 48 && mouseY >= yy && mouseY <= yy + 48) { - gui.addToChant(entries[i].sign); - entity.playNotifySound(Registry.SELECT_SIGN.get(), SoundSource.NEUTRAL, 0.5f, entity.level.random.nextFloat() * 0.25f + 0.75f); - return true; - } +// else if (knowledge.knowsSign(entries[i].sign) && mouseX >= xx && mouseX <= xx + 48 && mouseY >= yy && mouseY <= yy + 48) { +// gui.addToChant(entries[i].sign); +// entity.playNotifySound(Registry.SELECT_SIGN.get(), SoundSource.NEUTRAL, 0.5f, entity.level.random.nextFloat() * 0.25f + 0.75f); +// return true; +// } } return false; } @@ -109,7 +108,7 @@ public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int Tesselator tess = Tesselator.getInstance(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); if (hover && !infoHover) { mStack.pushPose(); mStack.translate(xx + 24, yy + 24, 0); @@ -119,6 +118,7 @@ public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int } RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); for (int j = 0; j < (hover && !infoHover ? 2 : 1); j++) { + float r = sign.getRed(), g = sign.getGreen(), b = sign.getBlue(); RenderUtil.litQuad(mStack, MultiBufferSource.immediate(tess.getBuilder()), xx + 12, yy + 12, 24, 24, sign.getRed(), sign.getGreen(), sign.getBlue(), Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(sign.getSprite())); tess.end(); diff --git a/src/main/java/elucent/eidolon/codex/SignPage.java b/src/main/java/elucent/eidolon/codex/SignPage.java index 6525f7f..b286225 100644 --- a/src/main/java/elucent/eidolon/codex/SignPage.java +++ b/src/main/java/elucent/eidolon/codex/SignPage.java @@ -1,12 +1,11 @@ package elucent.eidolon.codex; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.spell.Sign; @@ -61,7 +60,7 @@ public void render(CodexGui gui, PoseStack mStack, int x, int y, int mouseX, int Tesselator tess = Tesselator.getInstance(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); mStack.pushPose(); mStack.translate(x + 64, y + 80, 0); // mStack.scale(0.9f, 0.9f, 0.9f); diff --git a/src/main/java/elucent/eidolon/deity/DarkDeity.java b/src/main/java/elucent/eidolon/deity/DarkDeity.java index 4988ced..535d03a 100644 --- a/src/main/java/elucent/eidolon/deity/DarkDeity.java +++ b/src/main/java/elucent/eidolon/deity/DarkDeity.java @@ -2,8 +2,8 @@ import elucent.eidolon.capability.Facts; import elucent.eidolon.capability.IReputation; -import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.world.entity.player.Player; import net.minecraft.resources.ResourceLocation; @@ -24,12 +24,12 @@ else if (lock.equals(DeityLocks.SACRIFICE_VILLAGER)) { @Override public void onReputationChange(Player player, IReputation rep, double prev, double current) { - if (!KnowledgeUtil.knowsSign(player, Signs.BLOOD_SIGN) && current >= 3) { + if (!KnowledgeUtil.knowsSign(player, Signs.BLOOD_SIGN) && (current >= 3 || rep.hasLock(player, id, DeityLocks.SACRIFICE_MOB))) { rep.setReputation(player, id, 3); rep.lock(player, id, DeityLocks.SACRIFICE_MOB); KnowledgeUtil.grantSign(player, Signs.BLOOD_SIGN); } - else if (!KnowledgeUtil.knowsFact(player, Facts.VILLAGER_SACRIFICE) && current >= 15) { + else if (!KnowledgeUtil.knowsFact(player, Facts.VILLAGER_SACRIFICE) && (current >= 15 || rep.hasLock(player, id, DeityLocks.SACRIFICE_VILLAGER))) { rep.setReputation(player, id, 15); rep.lock(player, id, DeityLocks.SACRIFICE_VILLAGER); KnowledgeUtil.grantFact(player, Facts.VILLAGER_SACRIFICE); diff --git a/src/main/java/elucent/eidolon/deity/Deity.java b/src/main/java/elucent/eidolon/deity/Deity.java index 1fac850..109f94b 100644 --- a/src/main/java/elucent/eidolon/deity/Deity.java +++ b/src/main/java/elucent/eidolon/deity/Deity.java @@ -1,6 +1,13 @@ package elucent.eidolon.deity; +import java.util.List; +import java.util.TreeMap; +import java.util.UUID; + import elucent.eidolon.capability.IReputation; +import elucent.eidolon.research.Research; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.world.entity.player.Player; import net.minecraft.resources.ResourceLocation; @@ -30,6 +37,88 @@ public float getBlue() { public ResourceLocation getId() { return id; } + + public interface StageRequirement { + boolean isMet(Player player); + } + + public class ResearchRequirement implements StageRequirement { + Research r; + public ResearchRequirement(Research r) { + this.r = r; + } + + @Override + public boolean isMet(Player player) { + return KnowledgeUtil.knowsResearch(player, r.getRegistryName()); + } + } + + public class SignRequirement implements StageRequirement { + Sign sign; + public SignRequirement(Sign sign) { + this.sign = sign; + } + + @Override + public boolean isMet(Player player) { + return KnowledgeUtil.knowsSign(player, sign); + } + } + + public class Stage { + ResourceLocation id; + int rep; // Required reputation to meet this stage. + List reqs; // Requirements to meet this stage. + boolean major; // Whether or not this is considered a major stage. + + public Stage(ResourceLocation id, int rep, boolean major) { + this.id = id; + this.rep = rep; + this.major = major; + } + + boolean satisfiedBy(Player player) { + for (StageRequirement req : reqs) { + + } + return true; + } + } + + public class Progression { + TreeMap steps; + int max; + + public Progression(Stage... stages) { + this.steps = new TreeMap(); + for (Stage s : stages) this.steps.put(s.rep, s); + max = this.steps.lastKey(); + } + + public Stage next(double rep) { + return steps.ceilingEntry((int)(rep + 0.5f)).getValue(); + } + + public Stage last(double rep) { + return steps.floorEntry((int)rep).getValue(); + } + + public boolean progress(IReputation rep, Player player) { + double level = rep.getReputation(player, Deity.this.getId()); + if (level >= max) return false; // Can't progress past max. + Stage s = next(level); + if (s.satisfiedBy(player)) return true; + else if (level > s.rep) { + rep.setReputation(player, Deity.this.getId(), s.rep); + } + return false; + } + + public void regress(IReputation rep, Player player) { + + } + } public abstract void onReputationUnlock(Player player, IReputation rep, ResourceLocation lock); public abstract void onReputationChange(Player player, IReputation rep, double prev, double current); diff --git a/src/main/java/elucent/eidolon/deity/LightDeity.java b/src/main/java/elucent/eidolon/deity/LightDeity.java index 4d8a340..8b1bbad 100644 --- a/src/main/java/elucent/eidolon/deity/LightDeity.java +++ b/src/main/java/elucent/eidolon/deity/LightDeity.java @@ -1,8 +1,8 @@ package elucent.eidolon.deity; import elucent.eidolon.capability.IReputation; -import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.world.entity.player.Player; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java b/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java index bc5c0a4..3deba46 100644 --- a/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java +++ b/src/main/java/elucent/eidolon/deity/RegisterDeitiesEvent.java @@ -1,7 +1,8 @@ package elucent.eidolon.deity; import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; -public class RegisterDeitiesEvent extends Event { +public class RegisterDeitiesEvent extends Event implements IModBusEvent { } diff --git a/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java b/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java index f00971f..dd93005 100644 --- a/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java +++ b/src/main/java/elucent/eidolon/entity/AngelArrowRenderer.java @@ -5,7 +5,6 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.resources.ResourceLocation; public class AngelArrowRenderer extends EntityRenderer { diff --git a/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java b/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java index 2ff82b9..618b74f 100644 --- a/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java +++ b/src/main/java/elucent/eidolon/entity/ChantCasterEntity.java @@ -5,11 +5,18 @@ import java.util.Optional; import java.util.UUID; +import com.mojang.math.Vector3f; + import elucent.eidolon.Registry; import elucent.eidolon.network.Networking; import elucent.eidolon.network.SpellCastPacket; +import elucent.eidolon.particle.RuneParticleData; import elucent.eidolon.particle.SignParticleData; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Rune.RuneResult; +import elucent.eidolon.spell.Runes; import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.SignSequence; import elucent.eidolon.spell.Signs; import elucent.eidolon.spell.Spell; import elucent.eidolon.spell.Spells; @@ -20,7 +27,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; -import net.minecraft.nbt.TagTypes; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; @@ -29,100 +36,177 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.level.Level; -import net.minecraftforge.common.Tags; -import net.minecraftforge.event.TagsUpdatedEvent; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.entity.IEntityAdditionalSpawnData; import net.minecraftforge.network.NetworkHooks; -public class ChantCasterEntity extends Entity { +public class ChantCasterEntity extends Entity implements IEntityAdditionalSpawnData { + public static final EntityDataAccessor RUNES = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.COMPOUND_TAG); public static final EntityDataAccessor SIGNS = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.COMPOUND_TAG); public static final EntityDataAccessor INDEX = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.INT); public static final EntityDataAccessor> CASTER_ID = SynchedEntityData.>defineId(ChantCasterEntity.class, EntityDataSerializers.OPTIONAL_UUID); - int timer = 0; + public static final EntityDataAccessor SUCCEEDED = SynchedEntityData.defineId(ChantCasterEntity.class, EntityDataSerializers.BOOLEAN); + int timer = 0, deathTimer = 0; + Vec3 look; - public ChantCasterEntity(Level world, Player caster, List signs) { + public ChantCasterEntity(Level world, Player caster, List runes, Vec3 look) { super(Registry.CHANT_CASTER.get(), world); - ListTag list = new ListTag(); - for (Sign sign : signs) list.add(StringTag.valueOf(sign.getRegistryName().toString())); - CompoundTag nbt = new CompoundTag(); - nbt.put("signs", list); - getEntityData().set(SIGNS, nbt); + this.look = look; + setRunesTag(runes); getEntityData().set(CASTER_ID, Optional.of(caster.getUUID())); } public ChantCasterEntity(EntityType entityTypeIn, Level worldIn) { super(entityTypeIn, worldIn); } + + protected CompoundTag getNoRunesTag() { + CompoundTag emptyRunes = new CompoundTag(); + emptyRunes.put("runes", new ListTag()); + return emptyRunes; + } + + protected List loadRunesTag() { + List runes = new ArrayList<>(); + ListTag runesTag = getEntityData().get(RUNES).getList("runes", Tag.TAG_STRING); + for (int i = 0; i < runesTag.size(); i ++) { + Rune r = Runes.find(new ResourceLocation(runesTag.getString(i))); + if (r != null) runes.add(r); + } + return runes; + } + + protected void setRunesTag(List runes) { + ListTag runesList = new ListTag(); + CompoundTag runesTag = new CompoundTag(); + for (Rune r : runes) runesList.add(StringTag.valueOf(r.getRegistryName().toString())); + runesTag.put("runes", runesList); + getEntityData().set(RUNES, runesTag); + } @Override protected void defineSynchedData() { - getEntityData().define(SIGNS, new CompoundTag()); + getEntityData().define(RUNES, getNoRunesTag()); + getEntityData().define(SIGNS, new SignSequence().serializeNbt()); getEntityData().define(INDEX, 0); getEntityData().define(CASTER_ID, Optional.empty()); + getEntityData().define(SUCCEEDED, false); } @Override public void tick() { super.tick(); - + if (deathTimer > 0) { + deathTimer --; + if (deathTimer <= 0) remove(RemovalReason.KILLED); + return; + } if (timer > 0) { timer --; - if (timer == 0) { - ListTag signData = getEntityData().get(SIGNS).getList("signs", Tag.TAG_STRING); + if (timer <= 0) { + CompoundTag signData = getEntityData().get(SIGNS); Optional optuuid = getEntityData().get(CASTER_ID); if (!level.isClientSide && optuuid.isPresent()) { - List signs = new ArrayList<>(); - for (int i = 0; i < signData.size(); i++) - signs.add(Signs.find(new ResourceLocation(signData.getString(i)))); - Spell spell = Spells.find(signs); + SignSequence seq = SignSequence.deserializeNbt(signData); + Spell spell = Spells.find(seq); Player player = level.getPlayerByUUID(optuuid.get()); - if (spell != null && player != null && spell.canCast(level, blockPosition(), player, signs)) { - spell.cast(level, blockPosition(), player, signs); - Networking.sendToTracking(level, blockPosition(), new SpellCastPacket(player, blockPosition(), spell, signs)); + if (spell != null && player != null && spell.canCast(level, blockPosition(), player, seq)) { + spell.cast(level, blockPosition(), player, seq); + Networking.sendToTracking(level, blockPosition(), new SpellCastPacket(player, blockPosition(), spell, seq)); + getEntityData().set(SUCCEEDED, true); + } + else { + level.playSound(null, blockPosition(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 1.0f, 1.0f); + getEntityData().set(SUCCEEDED, false); } - else level.playSound(null, blockPosition(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 1.0f, 1.0f); } - if (!level.isClientSide) removeAfterChangingDimensions(); + deathTimer = 20; return; } } if (tickCount % 5 == 0) { - ListTag signs = getEntityData().get(SIGNS).getList("signs", Tag.TAG_STRING); + List runes = loadRunesTag(); + SignSequence seq = SignSequence.deserializeNbt(getEntityData().get(SIGNS)); + Vector3f initColor = seq.getAverageColor(); + int index = getEntityData().get(INDEX); - if (index >= signs.size()) return; - Sign sign = Signs.find(new ResourceLocation(signs.getString(index))); - double x = getX() + 0.2 * random.nextGaussian(), - y = getY() + 0.2 * random.nextGaussian(), - z = getZ() + 0.2 * random.nextGaussian(); - for (int i = 0; i < 2; i ++) { - level.addParticle(new SignParticleData(sign), x, y, z, 0, 0, 0); + if (index >= runes.size()) return; + Rune rune = runes.get(index); + RuneResult result = rune.doEffect(seq); + if (result == RuneResult.FAIL) { + if (!level.isClientSide) { + level.playSound(null, blockPosition(), SoundEvents.FIRE_EXTINGUISH, SoundSource.NEUTRAL, 1.0f, 1.0f); + getEntityData().set(INDEX, runes.size()); + getEntityData().set(SUCCEEDED, false); + } + deathTimer = 20; + return; } - level.playSound(null, blockPosition(), Registry.CHANT_WORD.get(), SoundSource.NEUTRAL, 0.7f, random.nextFloat() * 0.375f + 0.625f); - if (index + 1 >= signs.size()) { - timer = 40; + else { + Vector3f afterColor = seq.getAverageColor(); + double x = getX() + 0.1 * random.nextGaussian(), + y = getY() + 0.1 * random.nextGaussian(), + z = getZ() + 0.1 * random.nextGaussian(); + for (int i = 0; i < 2; i ++) { + level.addParticle(new RuneParticleData( + rune, + initColor.x(), initColor.y(), initColor.z(), + afterColor.x(), afterColor.y(), afterColor.z() + ), x, y, z, look.x * 0.03, look.y * 0.03, look.z * 0.03); + } + level.playSound(null, blockPosition(), Registry.CHANT_WORD.get(), SoundSource.NEUTRAL, 0.7f, random.nextFloat() * 0.375f + 0.625f); + if (index + 1 >= runes.size()) { + timer = 20; + } + if (!level.isClientSide) { + getEntityData().set(INDEX, index + 1); + getEntityData().set(SIGNS, seq.serializeNbt()); + } } - if (!level.isClientSide) getEntityData().set(INDEX, index + 1); } } @Override protected void readAdditionalSaveData(CompoundTag compound) { + getEntityData().set(RUNES, compound.getCompound("runes_tag")); getEntityData().set(SIGNS, compound.getCompound("signs_tag")); getEntityData().set(INDEX, compound.getInt("index")); getEntityData().set(CASTER_ID, Optional.of(compound.getUUID("caster_id"))); + look = new Vec3(compound.getDouble("lookX"), compound.getDouble("lookY"), compound.getDouble("lookZ")); timer = compound.getInt("timer"); + deathTimer = compound.getInt("deathTimer"); + getEntityData().set(SUCCEEDED, compound.getBoolean("succeeded")); } @Override protected void addAdditionalSaveData(CompoundTag compound) { + compound.put("runes_tag", getEntityData().get(RUNES)); compound.put("signs_tag", getEntityData().get(SIGNS)); compound.putInt("index", getEntityData().get(INDEX)); compound.putInt("timer", timer); compound.putUUID("caster_id", getEntityData().get(CASTER_ID).get()); + compound.putDouble("lookX", look.x); + compound.putDouble("lookY", look.y); + compound.putDouble("lookZ", look.z); + compound.putInt("deathTimer", deathTimer); + compound.putBoolean("succeeded", getEntityData().get(SUCCEEDED)); } @Override public Packet getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } + + @Override + public void writeSpawnData(FriendlyByteBuf buffer) { + buffer.writeDouble(look.x); + buffer.writeDouble(look.y); + buffer.writeDouble(look.z); + } + + @Override + public void readSpawnData(FriendlyByteBuf buf) { + look = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); + } } diff --git a/src/main/java/elucent/eidolon/entity/ChantCasterRenderer.java b/src/main/java/elucent/eidolon/entity/ChantCasterRenderer.java new file mode 100644 index 0000000..4c520ac --- /dev/null +++ b/src/main/java/elucent/eidolon/entity/ChantCasterRenderer.java @@ -0,0 +1,189 @@ +package elucent.eidolon.entity; + +import java.util.Iterator; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; + +import elucent.eidolon.ClientConfig; +import elucent.eidolon.ClientEvents; +import elucent.eidolon.Eidolon; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.SignSequence; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; + +public class ChantCasterRenderer extends EntityRenderer { + public ChantCasterRenderer(Context erm) { + super(erm); + } + + @Override + public void render(ChantCasterEntity entity, float yaw, float pticks, PoseStack mStack, MultiBufferSource mb, int lmap) { + mStack.pushPose(); + VertexConsumer b = ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_SPRITE); + VertexConsumer sb = ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_BLOCK_PARTICLE); + + Minecraft mc = Minecraft.getInstance(); + double ex = Mth.lerp(pticks, entity.xOld, entity.getX()); + double ey = Mth.lerp(pticks, entity.yOld, entity.getY()); + double ez = Mth.lerp(pticks, entity.zOld, entity.getZ()); + double px = Mth.lerp(pticks, mc.player.xOld, mc.player.getX()); + double py = Mth.lerp(pticks, mc.player.yOld, mc.player.getY()); + double pz = Mth.lerp(pticks, mc.player.zOld, mc.player.getZ()); +// mStack.mulPose(this.entityRenderDispatcher.cameraOrientation()); +// mStack.translate(-px, -py, -pz); + TextureAtlasSprite beam = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation(Eidolon.MODID, "particle/beam")); + TextureAtlasSprite ring = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation(Eidolon.MODID, "particle/ring")); + + Vec3 look = entity.look; + yaw = (float) Mth.atan2(look.x, look.z); + Vec3 left = new Vec3(Math.cos(yaw), 0, -Math.sin(yaw)); + Vec3 up = left.cross(look); + + SignSequence spell = SignSequence.deserializeNbt(entity.getEntityData().get(entity.SIGNS)); + int i = 0; + int sz = Math.max(0, spell.seq.size() - 1); + float r = Mth.sqrt(sz) / 4f; + if (sz > 0) r = Math.max(0.3f, r); + Vec3 center = look.add(0, 0.5f, 0); + int nreps = entity.deathTimer > 0 && entity.getEntityData().get(entity.SUCCEEDED) ? 3 : 1; + float alphaMod = 1; + if (entity.deathTimer > 0) { + alphaMod = entity.deathTimer / 20.0f; + alphaMod *= alphaMod; + if (!entity.getEntityData().get(entity.SUCCEEDED)) { + alphaMod *= alphaMod; + center = center.add(look.scale(1 - alphaMod)); + r += 0.25f - 0.25f * alphaMod; + } + } + for (int k = 0; k < nreps; k ++) { + for (Sign s : spell.seq) { + float a = -Mth.PI / 2 - i * 2 * Mth.PI / spell.seq.size(); + float sa = Mth.sin(a), ca = Mth.cos(a); + + Vec3 od = center.add(left.scale(r * ca)).add(up.scale(r * sa)); + Vec3 dxd = left.scale(0.175), dyd = up.scale(0.175); + Vector3f o = new Vector3f((float)od.x, (float)od.y, (float)od.z); + Vector3f dx = new Vector3f((float)dxd.x, (float)dxd.y, (float)dxd.z); + Vector3f dy = new Vector3f((float)dyd.x, (float)dyd.y, (float)dyd.z); + + TextureAtlasSprite spr = mc.getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(s.getSprite()); + + float brightMod = Mth.clamp(Mth.sin(a + Mth.TWO_PI * entity.tickCount / 20), 0, 1); + brightMod *= brightMod; + brightMod = 0.6f + 0.4f * brightMod; + + for (int j = 0; j < 2; j ++) { + sb.vertex(mStack.last().pose(), o.x() - dx.x() + dy.x(), o.y() - dx.y() + dy.y(), o.z() - dx.z() + dy.z()).uv(spr.getU1(), spr.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() - dy.x(), o.y() - dx.y() - dy.y(), o.z() - dx.z() - dy.z()).uv(spr.getU1(), spr.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() - dy.x(), o.y() + dx.y() - dy.y(), o.z() + dx.z() - dy.z()).uv(spr.getU0(), spr.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() + dy.x(), o.y() + dx.y() + dy.y(), o.z() + dx.z() + dy.z()).uv(spr.getU0(), spr.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + + sb.vertex(mStack.last().pose(), o.x() + dx.x() + dy.x(), o.y() + dx.y() + dy.y(), o.z() + dx.z() + dy.z()).uv(spr.getU1(), spr.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() - dy.x(), o.y() + dx.y() - dy.y(), o.z() + dx.z() - dy.z()).uv(spr.getU1(), spr.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() - dy.x(), o.y() - dx.y() - dy.y(), o.z() - dx.z() - dy.z()).uv(spr.getU0(), spr.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() + dy.x(), o.y() - dx.y() + dy.y(), o.z() - dx.z() + dy.z()).uv(spr.getU0(), spr.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), brightMod * alphaMod).uv2(0).endVertex(); + } + + dx.mul(1.75f); + dy.mul(1.75f); + sb.vertex(mStack.last().pose(), o.x() - dx.x() + dy.x(), o.y() - dx.y() + dy.y(), o.z() - dx.z() + dy.z()).uv(ring.getU1(), ring.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() - dy.x(), o.y() - dx.y() - dy.y(), o.z() - dx.z() - dy.z()).uv(ring.getU1(), ring.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() - dy.x(), o.y() + dx.y() - dy.y(), o.z() + dx.z() - dy.z()).uv(ring.getU0(), ring.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() + dy.x(), o.y() + dx.y() + dy.y(), o.z() + dx.z() + dy.z()).uv(ring.getU0(), ring.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + + sb.vertex(mStack.last().pose(), o.x() + dx.x() + dy.x(), o.y() + dx.y() + dy.y(), o.z() + dx.z() + dy.z()).uv(ring.getU1(), ring.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() + dx.x() - dy.x(), o.y() + dx.y() - dy.y(), o.z() + dx.z() - dy.z()).uv(ring.getU1(), ring.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() - dy.x(), o.y() - dx.y() - dy.y(), o.z() - dx.z() - dy.z()).uv(ring.getU0(), ring.getV0()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o.x() - dx.x() + dy.x(), o.y() - dx.y() + dy.y(), o.z() - dx.z() + dy.z()).uv(ring.getU0(), ring.getV1()).color(s.getRed(), s.getGreen(), s.getBlue(), alphaMod * 0.5f).uv2(0).endVertex(); + + i ++; + } + i = 0; + if (!spell.seq.isEmpty()) { + Iterator iter = spell.seq.iterator(); + Sign cur = null, next = spell.seq.getLast(); + float rr = r + 0.1375f; + float rr2 = rr + 0.2f; + float rs = r - 0.3f; + float rs2 = rs + 0.2f; + int steps = Math.max(24, spell.seq.size() * 4); + if (steps % spell.seq.size() != 0) steps += spell.seq.size() - steps % spell.seq.size(); + int periodicity = Math.max(4, steps / spell.seq.size()); + for (i = 0; i < steps; i ++) { + if (i % periodicity == 0) { + cur = next; + next = iter.next(); + if (!iter.hasNext()) iter = spell.seq.iterator(); + } + float a1 = -Mth.PI / 2 - (i - periodicity) * Mth.TWO_PI / steps, a2 = -Mth.PI / 2 - (i - periodicity + 1) * Mth.TWO_PI / steps; + float sa1 = Mth.sin(a1), ca1 = Mth.cos(a1); + float sa2 = Mth.sin(a2), ca2 = Mth.cos(a2); + + float r1 = Mth.lerp((i % periodicity) / (float)periodicity, cur.getRed(), next.getRed()); + float r2 = Mth.lerp((i % periodicity + 1) / (float)periodicity, cur.getRed(), next.getRed()); + float g1 = Mth.lerp((i % periodicity) / (float)periodicity, cur.getGreen(), next.getGreen()); + float g2 = Mth.lerp((i % periodicity + 1) / (float)periodicity, cur.getGreen(), next.getGreen()); + float b1 = Mth.lerp((i % periodicity) / (float)periodicity, cur.getBlue(), next.getBlue()); + float b2 = Mth.lerp((i % periodicity + 1) / (float)periodicity, cur.getBlue(), next.getBlue()); + + Vec3 id1 = center.add(left.scale(rr * ca1)).add(up.scale(rr * sa1)); + Vec3 id2 = center.add(left.scale(rr * ca2)).add(up.scale(rr * sa2)); + Vec3 od1 = center.add(left.scale(rr2 * ca1)).add(up.scale(rr2 * sa1)); + Vec3 od2 = center.add(left.scale(rr2 * ca2)).add(up.scale(rr2 * sa2)); + Vector3f i1 = new Vector3f((float)id1.x, (float)id1.y, (float)id1.z); + Vector3f i2 = new Vector3f((float)id2.x, (float)id2.y, (float)id2.z); + Vector3f o1 = new Vector3f((float)od1.x, (float)od1.y, (float)od1.z); + Vector3f o2 = new Vector3f((float)od2.x, (float)od2.y, (float)od2.z); + + sb.vertex(mStack.last().pose(), o1.x(), o1.y(), o1.z()).uv(beam.getU1(), beam.getV1()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o2.x(), o2.y(), o2.z()).uv(beam.getU0(), beam.getV1()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i2.x(), i2.y(), i2.z()).uv(beam.getU0(), beam.getV0()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i1.x(), i1.y(), i1.z()).uv(beam.getU1(), beam.getV0()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + + sb.vertex(mStack.last().pose(), o2.x(), o2.y(), o2.z()).uv(beam.getU1(), beam.getV1()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o1.x(), o1.y(), o1.z()).uv(beam.getU0(), beam.getV1()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i1.x(), i1.y(), i1.z()).uv(beam.getU0(), beam.getV0()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i2.x(), i2.y(), i2.z()).uv(beam.getU1(), beam.getV0()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + + id1 = center.add(left.scale(rs * ca1)).add(up.scale(rs * sa1)); + id2 = center.add(left.scale(rs * ca2)).add(up.scale(rs * sa2)); + od1 = center.add(left.scale(rs2 * ca1)).add(up.scale(rs2 * sa1)); + od2 = center.add(left.scale(rs2 * ca2)).add(up.scale(rs2 * sa2)); + i1 = new Vector3f((float)id1.x, (float)id1.y, (float)id1.z); + i2 = new Vector3f((float)id2.x, (float)id2.y, (float)id2.z); + o1 = new Vector3f((float)od1.x, (float)od1.y, (float)od1.z); + o2 = new Vector3f((float)od2.x, (float)od2.y, (float)od2.z); + + sb.vertex(mStack.last().pose(), o1.x(), o1.y(), o1.z()).uv(beam.getU1(), beam.getV1()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o2.x(), o2.y(), o2.z()).uv(beam.getU0(), beam.getV1()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i2.x(), i2.y(), i2.z()).uv(beam.getU0(), beam.getV0()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i1.x(), i1.y(), i1.z()).uv(beam.getU1(), beam.getV0()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + + sb.vertex(mStack.last().pose(), o2.x(), o2.y(), o2.z()).uv(beam.getU1(), beam.getV1()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), o1.x(), o1.y(), o1.z()).uv(beam.getU0(), beam.getV1()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i1.x(), i1.y(), i1.z()).uv(beam.getU0(), beam.getV0()).color(r1, g1, b1, alphaMod * 0.5f).uv2(0).endVertex(); + sb.vertex(mStack.last().pose(), i2.x(), i2.y(), i2.z()).uv(beam.getU1(), beam.getV0()).color(r2, g2, b2, alphaMod * 0.5f).uv2(0).endVertex(); + } + } + } + mStack.popPose(); + } + + @Override + public ResourceLocation getTextureLocation(ChantCasterEntity entity) { + return new ResourceLocation(Eidolon.MODID, "textures/particle/beam.png"); + } +} diff --git a/src/main/java/elucent/eidolon/entity/NecromancerEntity.java b/src/main/java/elucent/eidolon/entity/NecromancerEntity.java index 1d56d99..9a48979 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerEntity.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerEntity.java @@ -211,7 +211,7 @@ protected void registerGoals() { this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); - this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, 10, false, false, (e) -> e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).isPresent() && e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).resolve().get().getReputation((Player)e, Deities.DARK_DEITY.getId()) >= 50)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (e) -> e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).isPresent() && e.getCommandSenderWorld().getCapability(IReputation.INSTANCE).resolve().get().getReputation((Player)e, Deities.DARK_DEITY.getId()) >= 50)).setUnseenMemoryTicks(300)); } protected SoundEvent getCastingSoundEvent() { diff --git a/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java b/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java index b5d78f4..53f3708 100644 --- a/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java +++ b/src/main/java/elucent/eidolon/entity/NecromancerRenderer.java @@ -1,20 +1,17 @@ package elucent.eidolon.entity; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.util.RenderUtil; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.MobRenderer; @@ -25,7 +22,7 @@ public class NecromancerRenderer extends MobRenderer { public NecromancerRenderer(Context erm) { - super(erm, new NecromancerModel(erm.bakeLayer(Registry.NECROMANCER_LAYER)), 0.6f); + super(erm, new NecromancerModel(erm.bakeLayer(ClientRegistry.NECROMANCER_LAYER)), 0.6f); this.addLayer(new NecromancerEyesLayer(this)); } @@ -37,7 +34,7 @@ public static class NecromancerEyesLayer extends RenderLayer type, Level worldIn) { super(type, worldIn); @@ -82,16 +85,24 @@ public static AttributeSupplier createAttributes() { .build(); } + @Override public void aiStep() { super.aiStep(); Vec3 motion = this.getDeltaMovement(); if (!this.onGround && motion.y < 0.0D) { this.setDeltaMovement(motion.multiply(1.0D, 0.6D, 1.0D)); } + + if (!this.level.isClientSide && this.isAlive() && !this.isBaby() && --this.featherTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + this.spawnAtLocation(Registry.RAVEN_FEATHER.get()); + this.featherTime = this.random.nextInt(12000) + 12000; + } } - public boolean causeFallDamage(float distance, float damageMultiplier) { - return false; + @Override + public int calculateFallDamage(float distance, float damageMultiplier) { + return 0; } @Override diff --git a/src/main/java/elucent/eidolon/entity/RavenRenderer.java b/src/main/java/elucent/eidolon/entity/RavenRenderer.java index 42ddc3a..762d297 100644 --- a/src/main/java/elucent/eidolon/entity/RavenRenderer.java +++ b/src/main/java/elucent/eidolon/entity/RavenRenderer.java @@ -2,9 +2,9 @@ import com.mojang.blaze3d.vertex.PoseStack; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.resources.ResourceLocation; @@ -12,7 +12,7 @@ public class RavenRenderer extends MobRenderer { protected static final ResourceLocation TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/raven.png"); public RavenRenderer(Context erm) { - super(erm, new RavenModel(erm.bakeLayer(Registry.RAVEN_LAYER)), 0.25f); + super(erm, new RavenModel(erm.bakeLayer(ClientRegistry.RAVEN_LAYER)), 0.25f); } @Override diff --git a/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java b/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java index 60e8573..af8ae62 100644 --- a/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java +++ b/src/main/java/elucent/eidolon/entity/RavenVariantLayer.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Registry; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.RenderLayerParent; @@ -15,11 +16,10 @@ import net.minecraft.nbt.CompoundTag; public class RavenVariantLayer extends RenderLayer> { - private final RavenModel model; + private RavenModel model = null; public RavenVariantLayer(RenderLayerParent> rendererIn) { super(rendererIn); - this.model = new RavenModel(Minecraft.getInstance().getEntityModels().bakeLayer(Registry.RAVEN_LAYER)); } public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, T entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { @@ -28,7 +28,10 @@ public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int pack } private void renderRaven(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, T entitylivingbaseIn, float limbSwing, float limbSwingAmount, float netHeadYaw, float headPitch, boolean leftShoulderIn) { - CompoundTag compoundnbt = leftShoulderIn ? entitylivingbaseIn.getShoulderEntityLeft() : entitylivingbaseIn.getShoulderEntityRight(); + if (model == null) { + model = new RavenModel(Minecraft.getInstance().getEntityModels().bakeLayer(ClientRegistry.RAVEN_LAYER)); + } + CompoundTag compoundnbt = leftShoulderIn ? entitylivingbaseIn.getShoulderEntityLeft() : entitylivingbaseIn.getShoulderEntityRight(); EntityType.byString(compoundnbt.getString("id")).filter((p_215344_0_) -> p_215344_0_ == Registry.RAVEN.get()).ifPresent((p_229137_11_) -> { matrixStackIn.pushPose(); matrixStackIn.translate(leftShoulderIn ? (double)0.4F : (double)-0.4F, entitylivingbaseIn.isCrouching() ? (double)-1.3F : -1.5D, 0.0D); diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java b/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java index 8d35735..9ea1667 100644 --- a/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java +++ b/src/main/java/elucent/eidolon/entity/SlimySlugEntity.java @@ -1,57 +1,76 @@ package elucent.eidolon.entity; -import elucent.eidolon.Registry; -import net.minecraft.world.entity.AgeableMob; -import net.minecraft.world.entity.Entity; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.ai.control.FlyingMoveControl; -import net.minecraft.world.entity.ai.goal.BreedGoal; -import net.minecraft.world.entity.ai.goal.FollowOwnerGoal; -import net.minecraft.world.entity.ai.goal.FollowParentGoal; -import net.minecraft.world.entity.ai.goal.LandOnOwnersShoulderGoal; import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; import net.minecraft.world.entity.ai.goal.PanicGoal; -import net.minecraft.world.entity.ai.goal.SitWhenOrderedToGoal; import net.minecraft.world.entity.ai.goal.FloatGoal; import net.minecraft.world.entity.ai.goal.TemptGoal; -import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; import net.minecraft.world.entity.monster.Monster; -import net.minecraft.world.entity.animal.FlyingAnimal; -import net.minecraft.world.entity.animal.ShoulderRidingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.server.level.ServerPlayer; + +import java.util.Optional; +import java.util.UUID; + +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.deity.Deities; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; -import net.minecraft.world.entity.ai.navigation.PathNavigation; -import net.minecraft.world.level.pathfinder.BlockPathTypes; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.phys.Vec3; import net.minecraft.world.level.Level; -import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraftforge.common.extensions.IForgeEntity; +import net.minecraftforge.registries.ForgeRegistries; -public class SlimySlugEntity extends PathfinderMob { +public class SlimySlugEntity extends PathfinderMob implements IForgeEntity { private static final Ingredient TEMPTATION_ITEMS = Ingredient.of(Items.PUMPKIN_SEEDS); float yRotTrail = 0.0f; float squishAmount = 1.0f; - + public static final EntityDataAccessor TYPE = SynchedEntityData.defineId(SlimySlugEntity.class, EntityDataSerializers.INT); + public SlimySlugEntity(EntityType type, Level worldIn) { super(type, worldIn); registerGoals(); yRotTrail = this.getYRot(); + getEntityData().set(TYPE, 0); + } + + @Override + public void onAddedToWorld() { + Biome b = level.getBiome(getOnPos()); + if (Biomes.LUSH_CAVES.getRegistryName().equals(b.getRegistryName())) { + getEntityData().set(TYPE, 0); + } + else if (Biomes.OLD_GROWTH_PINE_TAIGA.location().equals(b.getRegistryName()) + || Biomes.OLD_GROWTH_SPRUCE_TAIGA.location().equals(b.getRegistryName())) { + getEntityData().set(TYPE, 1); + } + else if (Biomes.FLOWER_FOREST.location().equals(b.getRegistryName())) { + getEntityData().set(TYPE, 2); + } + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + getEntityData().define(TYPE, 0); } protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, + (e) -> ((Player)e).getGameProfile().getId().equals(UUID.fromString("0ca54301-6170-4c44-b3e0-b8afa6b81ed2")))); this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, TEMPTATION_ITEMS, false)); this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); @@ -64,6 +83,7 @@ public static AttributeSupplier createAttributes() { .add(Attributes.MAX_HEALTH, 8.0D) .add(Attributes.MOVEMENT_SPEED, (double)0.1F) .add(Attributes.ARMOR, 0.0D) + .add(Attributes.ATTACK_DAMAGE, 999.0D) .build(); } @@ -71,4 +91,15 @@ public void tick() { super.tick(); yRotTrail = Mth.rotLerp(yRotTrail, getYRot(), 0.2f); } + + @Override + public boolean hurt(DamageSource source, float amt) { + if (source != null && source.getEntity() instanceof Player p + && p.getGameProfile().getId().equals(UUID.fromString("0ca54301-6170-4c44-b3e0-b8afa6b81ed2"))) { + // SammySemicolon is not allowed to hurt slugs >:/ + p.hurt(source, amt); + return false; + } + return super.hurt(source, amt); + } } diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugModel.java b/src/main/java/elucent/eidolon/entity/SlimySlugModel.java index 501c308..2e699f7 100644 --- a/src/main/java/elucent/eidolon/entity/SlimySlugModel.java +++ b/src/main/java/elucent/eidolon/entity/SlimySlugModel.java @@ -7,7 +7,6 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.model.EntityModel; -import net.minecraft.client.model.geom.ModelLayerLocation; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; import net.minecraft.client.model.geom.builders.CubeDeformation; @@ -15,9 +14,7 @@ import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; public class SlimySlugModel extends EntityModel { private final ModelPart body; diff --git a/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java b/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java index 6cb4cef..607f014 100644 --- a/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java +++ b/src/main/java/elucent/eidolon/entity/SlimySlugRenderer.java @@ -2,22 +2,29 @@ import com.mojang.blaze3d.vertex.PoseStack; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.resources.ResourceLocation; public class SlimySlugRenderer extends MobRenderer { - protected static final ResourceLocation TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/slimy_slug.png"); + protected static final ResourceLocation SLIMY_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/slimy_slug.png"); + protected static final ResourceLocation BANANA_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/banana_slug.png"); + protected static final ResourceLocation BROWN_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/brown_slug.png"); public SlimySlugRenderer(Context erm) { - super(erm, new SlimySlugModel(erm.bakeLayer(Registry.SLUG_LAYER)), 0.4f); + super(erm, new SlimySlugModel(erm.bakeLayer(ClientRegistry.SLUG_LAYER)), 0.4f); } @Override public ResourceLocation getTextureLocation(SlimySlugEntity entity) { - return TEXTURE; + return switch (entity.getEntityData().get(SlimySlugEntity.TYPE)) { + case 0 -> SLIMY_TEXTURE; + case 1 -> BANANA_TEXTURE; + case 2 -> BROWN_TEXTURE; + default -> SLIMY_TEXTURE; + }; } @Override diff --git a/src/main/java/elucent/eidolon/entity/WraithModel.java b/src/main/java/elucent/eidolon/entity/WraithModel.java index d932165..0ec4830 100644 --- a/src/main/java/elucent/eidolon/entity/WraithModel.java +++ b/src/main/java/elucent/eidolon/entity/WraithModel.java @@ -2,8 +2,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Matrix3f; - import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; diff --git a/src/main/java/elucent/eidolon/entity/WraithRenderer.java b/src/main/java/elucent/eidolon/entity/WraithRenderer.java index e01ce43..7ef3450 100644 --- a/src/main/java/elucent/eidolon/entity/WraithRenderer.java +++ b/src/main/java/elucent/eidolon/entity/WraithRenderer.java @@ -1,15 +1,15 @@ package elucent.eidolon.entity; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.resources.ResourceLocation; public class WraithRenderer extends MobRenderer { public WraithRenderer(Context erm) { - super(erm, new WraithModel(erm.bakeLayer(Registry.WRAITH_LAYER)), 0.45f); + super(erm, new WraithModel(erm.bakeLayer(ClientRegistry.WRAITH_LAYER)), 0.45f); } @Override diff --git a/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java b/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java index 48a55a3..7851d7e 100644 --- a/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java +++ b/src/main/java/elucent/eidolon/entity/ZombieBruteRenderer.java @@ -1,15 +1,15 @@ package elucent.eidolon.entity; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.resources.ResourceLocation; public class ZombieBruteRenderer extends MobRenderer { public ZombieBruteRenderer(Context erm) { - super(erm, new ZombieBruteModel(erm.bakeLayer(Registry.ZOMBIE_BRUTE_LAYER)), 0.6f); + super(erm, new ZombieBruteModel(erm.bakeLayer(ClientRegistry.ZOMBIE_BRUTE_LAYER)), 0.6f); } @Override diff --git a/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java b/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java index fc7f70f..674fe09 100644 --- a/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java +++ b/src/main/java/elucent/eidolon/entity/ai/GenericBarterGoal.java @@ -17,8 +17,6 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.phys.AABB; -import net.minecraft.world.entity.ai.goal.Goal.Flag; - public class GenericBarterGoal extends Goal { static Random rand = new Random(); Predicate valid; diff --git a/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java b/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java deleted file mode 100644 index 8d34a98..0000000 --- a/src/main/java/elucent/eidolon/event/SpeedFactorEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -package elucent.eidolon.event; - -import net.minecraft.world.entity.Entity; - -public class SpeedFactorEvent extends net.minecraftforge.eventbus.api.Event { - Entity entity; - float speedFactor; - - public SpeedFactorEvent(Entity entity, float speedFactor) { - this.entity = entity; - this.speedFactor = speedFactor; - } - - public Entity getEntity() { - return entity; - } - - public float getSpeedFactor() { - return speedFactor; - } - - public void setSpeedFactor(float factor) { - speedFactor = factor; - } -} diff --git a/src/main/java/elucent/eidolon/event/StuckInBlockEvent.java b/src/main/java/elucent/eidolon/event/StuckInBlockEvent.java new file mode 100644 index 0000000..df9f1f3 --- /dev/null +++ b/src/main/java/elucent/eidolon/event/StuckInBlockEvent.java @@ -0,0 +1,29 @@ +package elucent.eidolon.event; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fml.event.IModBusEvent; + +public class StuckInBlockEvent extends net.minecraftforge.eventbus.api.Event { + Entity entity; + BlockState state; + Vec3 mul; + + public StuckInBlockEvent(Entity entity, BlockState state, Vec3 factor) { + this.entity = entity; + this.mul = factor; + } + + public Entity getEntity() { + return entity; + } + + public Vec3 getStuckMultiplier() { + return mul; + } + + public void setStuckMultiplier(Vec3 factor) { + mul = factor; + } +} diff --git a/src/main/java/elucent/eidolon/gui/ResearchTableContainer.java b/src/main/java/elucent/eidolon/gui/ResearchTableContainer.java new file mode 100644 index 0000000..8700e33 --- /dev/null +++ b/src/main/java/elucent/eidolon/gui/ResearchTableContainer.java @@ -0,0 +1,281 @@ +package elucent.eidolon.gui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import elucent.eidolon.Registry; +import elucent.eidolon.mixin.AbstractContainerMenuMixin; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.research.ResearchTask; +import elucent.eidolon.tile.ResearchTableTileEntity; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.core.NonNullList; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.Tags; +import net.minecraftforge.common.brewing.BrewingRecipeRegistry; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.fml.DistExecutor; + +public class ResearchTableContainer extends AbstractContainerMenu implements ContainerListener { + private final Container tile; + private final ContainerData intArray; + protected final List tasks; + + public ResearchTableContainer(int id, Inventory playerInventory) { + this(id, playerInventory, new SimpleContainer(2), new SimpleContainerData(2)); + } + + public ResearchTableContainer(int id, Inventory playerInventory, Container inventory, ContainerData data) { + super(Registry.RESEARCH_TABLE_CONTAINER.get(), id); + this.tile = inventory; + this.intArray = data; + this.addSlot(new NotesSlot(inventory, 0, 58, 68)); + this.addSlot(new SealSlot(inventory, 1, 58, 32)); + this.addDataSlots(data); + this.tasks = new ArrayList<>(); + + for(int k = 0; k < 3; ++k) { + for(int i1 = 0; i1 < 9; ++i1) { + this.addSlot(new Slot(playerInventory, i1 + k * 9 + 9, 16 + i1 * 18, 142 + k * 18)); + } + } + + for(int l = 0; l < 9; ++l) { + this.addSlot(new Slot(playerInventory, l, 16 + l * 18, 200)); + } + + if (inventory instanceof ResearchTableTileEntity t) { + t.addListener(this); + } + + if (tile instanceof ResearchTableTileEntity) updateSlots(); + } + + protected void popSlot() { + slots.remove(slots.size() - 1); + List lastSlots = ((AbstractContainerMenuMixin)(Object)this).getLastSlots(); + List remoteSlots = ((AbstractContainerMenuMixin)(Object)this).getRemoteSlots(); + lastSlots.remove(lastSlots.size() - 1); + remoteSlots.remove(remoteSlots.size() - 1); + } + + @Override + public void clicked(int p_150400_, int p_150401_, ClickType p_150402_, Player p_150403_) { + if (p_150400_ >= slots.size()) return; + super.clicked(p_150400_, p_150401_, p_150402_, p_150403_); + } + + public void updateSlots() { + if (tile instanceof ResearchTableTileEntity t) { + for (int i = 38; i < slots.size(); i ++) if (!slots.get(i).getItem().isEmpty()) { + double d0 = t.getBlockPos().getY() + 1.3F; + ItemEntity itementity = new ItemEntity(t.getLevel(), t.getBlockPos().getX() + 0.5, d0, t.getBlockPos().getZ() + 0.5, slots.get(i).getItem()); + itementity.setPickUpDelay(40); + t.getLevel().addFreshEntity(itementity); + } + } + while (slots.size() > 38) popSlot(); // Pare down to just the base 2 slots + player inventory. + while (slots.get(0).getItem().is(Registry.RESEARCH_NOTES.get())) { + if (getProgress() > 0) break; // Slots don't appear when research is in progress. + ItemStack stack = slots.get(0).getItem(); + if (!stack.hasTag() || !stack.getTag().contains("research")) break; + Research r = Researches.find(new ResourceLocation(stack.getTag().getString("research"))); + if (r == null) break; + if (stack.getTag().getInt("stepsDone") >= r.getStars()) break; + List tasks = r.getTasks(getSeed(), stack.getTag().getInt("stepsDone")); + for (int i = 0; i < tasks.size(); i ++) { + int x = 189, y = 17 + 36 * i; + tasks.get(i).modifyContainer(this, x, y); + } + break; + } + if (tile instanceof ResearchTableTileEntity) this.broadcastFullState(); + } + + @Override + public void removed(Player player) { + super.removed(player); + if (player instanceof ServerPlayer) { + for (int i = 38; i < slots.size(); i ++) if (!slots.get(i).getItem().isEmpty()) { + player.drop(slots.get(i).getItem(), false); + } + } + if (this.tile instanceof ResearchTableTileEntity t) { + t.removeListener(this); + } + } + + public boolean stillValid(Player playerIn) { + return this.tile.stillValid(playerIn); + } + + public ItemStack quickMoveStack(Player playerIn, int index) { + ItemStack itemstack = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack stack = slot.getItem().copy(); + if ((index < 0 || (index > 2 && index < 38))) { + if (this.slots.get(0).mayPlace(stack)) { + if (!this.moveItemStackTo(stack, 0, 1, false)) { + return ItemStack.EMPTY; + } + } else if (this.slots.get(1).mayPlace(stack)) { + if (!this.moveItemStackTo(stack, 1, 2, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 2 && index < 29) { + if (!this.moveItemStackTo(stack, 29, 38, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 29 && index < 38) { + if (!this.moveItemStackTo(stack, 2, 29, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(stack, 2, 38, false)) { + return ItemStack.EMPTY; + } + } else { + if (!this.moveItemStackTo(stack, 2, 38, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(stack, itemstack); + } + + if (stack.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + if (stack.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + + slot.onTake(playerIn, stack); + } + + return itemstack; + } + + public int getProgress() { + return this.intArray.get(0); + } + + public int getSeed() { + return this.intArray.get(1); + } + + @Override + public void initializeContents(int id, List items, ItemStack carried) { + this.slots.get(0).set(items.get(0).copy()); + updateSlots(); + + try { + super.initializeContents(id, items, carried); + } catch (IndexOutOfBoundsException e) {} + } + + class NotesSlot extends Slot { + public NotesSlot(Container iInventoryIn, int index, int xPosition, int yPosition) { + super(iInventoryIn, index, xPosition, yPosition); + } + + @Override + public boolean mayPlace(ItemStack stack) { + return stack.is(Registry.RESEARCH_NOTES.get()); + } + + @Override + public void setChanged() { + super.setChanged(); + if (tile instanceof ResearchTableTileEntity) updateSlots(); + } + + @Override + public int getMaxStackSize() { + return 1; + } + } + + class SealSlot extends Slot { + public SealSlot(Container iInventoryIn, int index, int xPosition, int yPosition) { + super(iInventoryIn, index, xPosition, yPosition); + } + + public boolean mayPlace(ItemStack stack) { + return stack.is(Registry.ARCANE_SEAL.get()); + } + + public int getMaxStackSize() { + return 64; + } + } + + public void trySubmitGoal(Player player, int index) { + if (slots.get(0).getItem().is(Registry.RESEARCH_NOTES.get())) { + ItemStack stack = slots.get(0).getItem(); + if (!stack.hasTag() || !stack.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(stack.getTag().getString("research"))); + if (r == null) return; + List tasks = r.getTasks(getSeed(), stack.getTag().getInt("stepsDone")); + if (tasks.size() < index) return; + ResearchTask toComplete = tasks.get(index); + int startingSlot = 38; + for (int i = 0; i < index; i ++) startingSlot += tasks.get(i).getSlotCount(); + if (!toComplete.isComplete(this, player, startingSlot).complete()) return; + toComplete.onComplete(this, player, startingSlot); + this.setData(0, 200); // start progress countdown. + this.broadcastChanges(); + this.updateSlots(); + } + } + + public void tryStamp(Player player) { + if (slots.get(0).getItem().is(Registry.RESEARCH_NOTES.get()) && slots.get(1).getItem().is(Registry.ARCANE_SEAL.get())) { + ItemStack notes = slots.get(0).getItem(); + if (!notes.hasTag() || !notes.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(notes.getTag().getString("research"))); + if (r == null) return; + if (notes.getTag().getInt("stepsDone") < r.getStars()) return; + + slots.get(1).remove(1); + ItemStack completed = new ItemStack(Registry.COMPLETED_RESEARCH.get()); + completed.getOrCreateTag().putString("research", r.getRegistryName().toString()); + slots.get(0).set(completed); + this.updateSlots(); + } + } + + @Override + public void slotChanged(AbstractContainerMenu menu, int slot, ItemStack stack) { + if (slot == 0) updateSlots(); + } + + @Override + public void dataChanged(AbstractContainerMenu menu, int slot, int value) { + if (slot == 0 && (value == 0 || value == 200)) updateSlots(); + } +} diff --git a/src/main/java/elucent/eidolon/gui/ResearchTableScreen.java b/src/main/java/elucent/eidolon/gui/ResearchTableScreen.java new file mode 100644 index 0000000..3577dfe --- /dev/null +++ b/src/main/java/elucent/eidolon/gui/ResearchTableScreen.java @@ -0,0 +1,189 @@ +package elucent.eidolon.gui; + +import com.mojang.blaze3d.vertex.PoseStack; + +import java.util.List; + +import javax.swing.plaf.basic.BasicBorders.MenuBarBorder; + +import com.mojang.blaze3d.systems.RenderSystem; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.ResearchActionPacket; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.research.ResearchTask; +import elucent.eidolon.research.ResearchTask.CompletenessResult; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.chat.Component; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class ResearchTableScreen extends AbstractContainerScreen { + private static final ResourceLocation RESEARCH_TABLE_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/gui/research_table.png"); + + public ResearchTableScreen(ResearchTableContainer table, Inventory inv, Component p_i51097_3_) { + super(table, inv, p_i51097_3_); + this.imageHeight = 224; + this.imageWidth = 192; + } + + public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { + this.renderBackground(matrixStack); + super.render(matrixStack, mouseX, mouseY, partialTicks); + this.renderTooltip(matrixStack, mouseX, mouseY); + } + + @Override + protected void renderLabels(PoseStack matrixStack, int x, int y) { + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + int i = this.leftPos; + int j = (this.height - this.imageHeight) / 2; + + double mouseX = Minecraft.getInstance().mouseHandler.xpos(); + double mouseY = Minecraft.getInstance().mouseHandler.ypos(); + mouseX = mouseX * (double)Minecraft.getInstance().getWindow().getGuiScaledWidth() / (double)Minecraft.getInstance().getWindow().getScreenWidth(); + mouseY = mouseY * (double)Minecraft.getInstance().getWindow().getGuiScaledHeight() / (double)Minecraft.getInstance().getWindow().getScreenHeight(); + + if (menu.slots.get(0).getItem().getItem() == Registry.RESEARCH_NOTES.get() && menu.getProgress() == 0) { + ItemStack notes = menu.slots.get(0).getItem(); + if (!notes.hasTag() || !notes.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(notes.getTag().getString("research"))); + if (r == null) return; + + int nstars = r.getStars(); + int done = notes.getTag().getInt("stepsDone"); + + if (done < nstars) { + List tasks = r.getTasks(menu.getSeed(), notes.getTag().getInt("stepsDone")); + int slotStart = 38; + for (int k = 0; k < tasks.size(); k ++) { + ResearchTask task = tasks.get(k); + int xx = 164, yy = 16 + 36 * k; + if (isHovering(xx + 10, yy + 6, 20, 20, mouseX, mouseY)) { + task.drawTooltip(matrixStack, this, mouseX - i, mouseY - j); + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + } + } + } + } + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (menu.slots.get(0).getItem().getItem() == Registry.RESEARCH_NOTES.get() && menu.getProgress() == 0) { + ItemStack notes = menu.slots.get(0).getItem(); + if (!notes.hasTag() || !notes.getTag().contains("research")) return false; + Research r = Researches.find(new ResourceLocation(notes.getTag().getString("research"))); + if (r == null) return false; + + List tasks = r.getTasks(menu.getSeed(), notes.getTag().getInt("stepsDone")); + int slotStart = 38; + for (int k = 0; k < tasks.size(); k ++) { + ResearchTask task = tasks.get(k); + int xx = 164, yy = 16 + 36 * k; + + CompletenessResult isComplete = task.isComplete(menu, Minecraft.getInstance().player, slotStart); + if (isComplete.complete() && isHovering(xx + task.getWidth() - 30, yy + 9, 20, 13, mouseX, mouseY)) { + Networking.sendToServer(new ResearchActionPacket(ResearchActionPacket.Action.SUBMIT_GOAL, k)); + return true; + } + slotStart = isComplete.nextSlot(); + } + + int nstars = r.getStars(); + int done = notes.getTag().getInt("stepsDone"); + + if (done >= nstars && isHovering(75, 51, 17, 14, mouseX, mouseY) && !menu.getSlot(1).getItem().isEmpty()) { + Networking.sendToServer(new ResearchActionPacket(ResearchActionPacket.Action.STAMP)); + return true; + } + } + return super.mouseClicked(mouseX, mouseY, button); + } + + protected void slotClicked(Slot p_97778_, int p_97779_, int p_97780_, ClickType p_97781_) { + if (p_97779_ >= menu.slots.size()) return; + super.slotClicked(p_97778_, p_97779_, p_97780_, p_97781_); + } + + @Override + protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) { + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + int i = this.leftPos; + int j = (this.height - this.imageHeight) / 2; + this.blit(matrixStack, i, j, 0, 0, this.imageWidth, this.imageHeight); + + double mouseX = Minecraft.getInstance().mouseHandler.xpos(); + double mouseY = Minecraft.getInstance().mouseHandler.ypos(); + mouseX = mouseX * (double)Minecraft.getInstance().getWindow().getGuiScaledWidth() / (double)Minecraft.getInstance().getWindow().getScreenWidth(); + mouseY = mouseY * (double)Minecraft.getInstance().getWindow().getGuiScaledHeight() / (double)Minecraft.getInstance().getWindow().getScreenHeight(); + + if (menu.slots.get(0).getItem().getItem() == Registry.RESEARCH_NOTES.get()) { + ItemStack notes = menu.slots.get(0).getItem(); + if (!notes.hasTag() || !notes.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(notes.getTag().getString("research"))); + if (r == null) return; + + int progress = menu.getProgress(); + int amt = progress * 104 / 200; + if (progress > 0) blit(matrixStack, i + 137, j + 17 + amt, 192, 92 + amt, 9, 104 - amt); + + int nstars = r.getStars(); + int done = notes.getTag().getInt("stepsDone"); + + if (done < nstars && progress == 0) { + List tasks = r.getTasks(menu.getSeed(), notes.getTag().getInt("stepsDone")); + int slotStart = 38; + for (int k = 0; k < tasks.size(); k ++) { + ResearchTask task = tasks.get(k); + int xx = 164, yy = 16 + 36 * k; + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + blit(matrixStack, i + xx, j + yy, 80, 224, 8, 32); + blit(matrixStack, i + xx + 8, j + yy, 112, 224, 24, 32); + task.drawIcon(matrixStack, i + xx + 12, j + yy + 8); + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + task.drawCustom(matrixStack, i + xx + 32, j + yy); + RenderSystem.setShaderTexture(0, RESEARCH_TABLE_TEXTURE); + + CompletenessResult isComplete = task.isComplete(menu, Minecraft.getInstance().player, slotStart); + if (isComplete.complete()) { + if (isHovering(xx + task.getWidth() - 30, yy + 9, 20, 13, mouseX, mouseY)) { + blit(matrixStack, i + xx + task.getWidth() - 32, j + yy, 184, 224, 24, 32); + } + else blit(matrixStack, i + xx + task.getWidth() - 32, j + yy, 160, 224, 24, 32); + } + else { + blit(matrixStack, i + xx + task.getWidth() - 32, j + yy, 136, 224, 24, 32); + } + blit(matrixStack, i + xx + task.getWidth() - 8, j + yy, 96, 224, 8, 32); + + slotStart = isComplete.nextSlot(); + } + } + + int starsY = 61 + 5 * nstars; + for (int k = 0; k < nstars; k ++) { + if (k < done) blit(matrixStack, i + 152, j + starsY - k * 10, 201, 82, 9, 10); + else blit(matrixStack, i + 152, j + starsY - k * 10, 192, 82, 9, 10); + } + + if (done >= nstars && !menu.getSlot(1).getItem().isEmpty()) { + if (isHovering(75, 51, 17, 14, mouseX, mouseY)) { + blit(matrixStack, i + 73, j + 49, 234, 64, 21, 18); + } + else blit(matrixStack, i + 73, j + 49, 213, 64, 21, 18); + } + } + } +} + diff --git a/src/main/java/elucent/eidolon/item/AthameItem.java b/src/main/java/elucent/eidolon/item/AthameItem.java index 022ebd3..7193431 100644 --- a/src/main/java/elucent/eidolon/item/AthameItem.java +++ b/src/main/java/elucent/eidolon/item/AthameItem.java @@ -40,7 +40,6 @@ import net.minecraftforge.event.entity.living.LootingLevelEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraft.world.item.Item.Properties; import java.util.Random; public class AthameItem extends SwordItem { diff --git a/src/main/java/elucent/eidolon/item/BonechillWandItem.java b/src/main/java/elucent/eidolon/item/BonechillWandItem.java index 47b2e77..fcbf8aa 100644 --- a/src/main/java/elucent/eidolon/item/BonechillWandItem.java +++ b/src/main/java/elucent/eidolon/item/BonechillWandItem.java @@ -20,8 +20,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.item.Item.Properties; - public class BonechillWandItem extends WandItem { private Random random = new Random(); diff --git a/src/main/java/elucent/eidolon/item/BonelordArmorItem.java b/src/main/java/elucent/eidolon/item/BonelordArmorItem.java new file mode 100644 index 0000000..ab24755 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/BonelordArmorItem.java @@ -0,0 +1,133 @@ +package elucent.eidolon.item; + +import java.util.UUID; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +import elucent.eidolon.ClientRegistry; +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.item.model.BonelordArmorModel; +import elucent.eidolon.item.model.WarlockArmorModel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterials; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.IItemRenderProperties; +import net.minecraftforge.common.extensions.IForgeItem; + +public class BonelordArmorItem extends ArmorItem implements IForgeItem { + private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; + + public static class Material implements ArmorMaterial { + @Override + public int getDurabilityForSlot(EquipmentSlot slot) { + return MAX_DAMAGE_ARRAY[slot.getIndex()] * 38; + } + + @Override + public int getDefenseForSlot(EquipmentSlot slot) { + switch (slot) { + case CHEST: + return 9; + case HEAD: + return 4; + case LEGS: + return 7; + default: + return 0; + } + } + + @Override + public int getEnchantmentValue() { + return 25; + } + + @Override + public SoundEvent getEquipSound() { + return ArmorMaterials.TURTLE.getEquipSound(); + } + + @Override + public Ingredient getRepairIngredient() { + return Ingredient.of(new ItemStack(Registry.IMBUED_BONES.get())); + } + + @Override + public String getName() { + return Eidolon.MODID + ":bonelord"; + } + + @Override + public float getToughness() { + return 2; + } + + @Override + public float getKnockbackResistance() { + return 0; + } + + public static final Material INSTANCE = new Material(); + } + + Multimap modifiers = null; + + private static final UUID[] ARMOR_MODIFIER_UUID_PER_SLOT = 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")}; + + public BonelordArmorItem(EquipmentSlot slot, Properties builderIn) { + super(Material.INSTANCE, slot, builderIn); + } + + @Override + public Multimap getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { + if (modifiers == null) { + UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[this.slot.getIndex()]; + modifiers = ImmutableMultimap.builder() + .putAll(getDefaultAttributeModifiers(this.slot)) + .put(Registry.PERSISTENT_SOUL_HEARTS.get(), new AttributeModifier(uuid, "Persistent hearts", this.slot == EquipmentSlot.CHEST ? 20.0 : 10.0, Operation.ADDITION)) + .build(); + } + return slot == this.slot ? modifiers : super.getAttributeModifiers(slot, stack); + } + + @OnlyIn(Dist.CLIENT) + @Override + public void initializeClient(java.util.function.Consumer consumer) { + consumer.accept(new IItemRenderProperties() { + @Override + public BonelordArmorModel getArmorModel(LivingEntity entity, ItemStack itemStack, EquipmentSlot armorSlot, HumanoidModel _default) { + float pticks = Minecraft.getInstance().getFrameTime(); + float f = Mth.rotLerp(pticks, entity.yBodyRotO, entity.yBodyRot); + float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); + float netHeadYaw = f1 - f; + float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); + ClientRegistry.BONELORD_ARMOR_MODEL.slot = slot; + ClientRegistry.BONELORD_ARMOR_MODEL.copyFromDefault(_default); + ClientRegistry.BONELORD_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return ClientRegistry.BONELORD_ARMOR_MODEL; + } + }); + } + + @OnlyIn(Dist.CLIENT) + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { + return Eidolon.MODID + ":textures/entity/bonelord_armor.png"; + } +} diff --git a/src/main/java/elucent/eidolon/item/CleavingAxeItem.java b/src/main/java/elucent/eidolon/item/CleavingAxeItem.java index 1c58234..86d8718 100644 --- a/src/main/java/elucent/eidolon/item/CleavingAxeItem.java +++ b/src/main/java/elucent/eidolon/item/CleavingAxeItem.java @@ -14,8 +14,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.item.Item.Properties; - public class CleavingAxeItem extends AxeItem { public CleavingAxeItem(Properties builderIn) { super(Tiers.PewterTier.INSTANCE, 7, -3.2f, builderIn); diff --git a/src/main/java/elucent/eidolon/item/CodexItem.java b/src/main/java/elucent/eidolon/item/CodexItem.java index f6f983e..f5f12c9 100644 --- a/src/main/java/elucent/eidolon/item/CodexItem.java +++ b/src/main/java/elucent/eidolon/item/CodexItem.java @@ -1,9 +1,9 @@ package elucent.eidolon.item; import elucent.eidolon.Eidolon; -import elucent.eidolon.spell.KnowledgeUtil; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -14,9 +14,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.level.Level; -import net.minecraft.world.item.Item.Properties; - -public class CodexItem extends ItemBase { +public class CodexItem extends ItemBase implements IManaRelatedItem { public CodexItem(Properties properties) { super(properties); } diff --git a/src/main/java/elucent/eidolon/item/CompletedResearchItem.java b/src/main/java/elucent/eidolon/item/CompletedResearchItem.java new file mode 100644 index 0000000..12034a8 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/CompletedResearchItem.java @@ -0,0 +1,78 @@ +package elucent.eidolon.item; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import elucent.eidolon.Registry; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DoublePlantBlock; +import net.minecraft.world.level.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Endermite; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.item.SwordItem; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.Vec3; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.living.LootingLevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import java.util.Random; + +public class CompletedResearchItem extends ItemBase { + public CompletedResearchItem(Properties builderIn) { + super(builderIn); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + if (!stack.hasTag() || !stack.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(stack.getTag().getString("research"))); + if (r == null) return; + tooltip.add(new TextComponent("" + ChatFormatting.ITALIC + ChatFormatting.GOLD + r.getName())); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + if (stack.hasTag() && stack.getTag().contains("research")) { + Research r = Researches.find(new ResourceLocation(stack.getTag().getString("research"))); + if (r != null && !KnowledgeUtil.knowsResearch(player, r.getRegistryName())) { + KnowledgeUtil.grantResearch(player, r.getRegistryName()); + return InteractionResultHolder.consume(ItemStack.EMPTY); + } + } + return super.use(level, player, hand); + } +} diff --git a/src/main/java/elucent/eidolon/item/DeathbringerScytheItem.java b/src/main/java/elucent/eidolon/item/DeathbringerScytheItem.java new file mode 100644 index 0000000..413360e --- /dev/null +++ b/src/main/java/elucent/eidolon/item/DeathbringerScytheItem.java @@ -0,0 +1,72 @@ +package elucent.eidolon.item; + +import java.util.List; + +import elucent.eidolon.Registry; +import elucent.eidolon.network.DeathbringerSlashEffectPacket; +import elucent.eidolon.network.LifestealEffectPacket; +import elucent.eidolon.network.Networking; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.damagesource.EntityDamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SwordItem; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.ToolAction; +import net.minecraftforge.common.ToolActions; + +public class DeathbringerScytheItem extends SwordItem { + public DeathbringerScytheItem(Properties builderIn) { + super(Tiers.NecroticTier.INSTANCE, 7, -2.9f, builderIn); + } + + String loreTag = null; + + public Item setLore(String tag) { + this.loreTag = tag; + return this; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + if (this.loreTag != null) { + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); + } + } + + @Override + public boolean canPerformAction(ItemStack stack, ToolAction action) { + if (action == ToolActions.SWORD_SWEEP) return false; + return super.canPerformAction(stack, action); + } + + @Override + public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { + if (target.getMobType() != MobType.UNDEAD) { + target.addEffect(new MobEffectInstance(Registry.UNDEATH_EFFECT.get(), 900)); + } + if (!attacker.level.isClientSide) + Networking.sendToTracking(attacker.level, attacker.blockPosition(), new DeathbringerSlashEffectPacket( + attacker.getX(), attacker.getY() + target.getBbHeight() / 2, attacker.getZ(), + target.getX(), target.getY() + target.getBbHeight() / 2, target.getZ(), + ColorUtil.packColor(255, 33, 26, 23), + ColorUtil.packColor(255, 10, 10, 11), + ColorUtil.packColor(255, 161, 255, 123), + ColorUtil.packColor(255, 194, 171, 70) + )); + return super.hurtEnemy(stack, target, attacker); + } +} diff --git a/src/main/java/elucent/eidolon/item/IManaRelatedItem.java b/src/main/java/elucent/eidolon/item/IManaRelatedItem.java new file mode 100644 index 0000000..c9492a3 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/IManaRelatedItem.java @@ -0,0 +1,5 @@ +package elucent.eidolon.item; + +public interface IManaRelatedItem { + +} diff --git a/src/main/java/elucent/eidolon/item/IRechargeableWand.java b/src/main/java/elucent/eidolon/item/IRechargeableWand.java new file mode 100644 index 0000000..eaa1cac --- /dev/null +++ b/src/main/java/elucent/eidolon/item/IRechargeableWand.java @@ -0,0 +1,7 @@ +package elucent.eidolon.item; + +import net.minecraft.world.item.ItemStack; + +public interface IRechargeableWand { + public ItemStack recharge(ItemStack stack); +} diff --git a/src/main/java/elucent/eidolon/item/IWingsItem.java b/src/main/java/elucent/eidolon/item/IWingsItem.java new file mode 100644 index 0000000..1917295 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/IWingsItem.java @@ -0,0 +1,15 @@ +package elucent.eidolon.item; + +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public interface IWingsItem { + int getMaxCharges(ItemStack stack); + void onFlap(Player player, Level level, ItemStack stack, int nCharges); + int getDashTicks(ItemStack stack); + void onDashStart(Player player, Level level, ItemStack stack); + void onDashTick(Player player, Level level, ItemStack stack, int remainingTicks); + void onDashEnd(Player player, Level level, ItemStack stack); + void onDashFlap(Player player, Level level, ItemStack stack, int dashTicks); +} diff --git a/src/main/java/elucent/eidolon/item/ItemBase.java b/src/main/java/elucent/eidolon/item/ItemBase.java index ac28ac6..130d079 100644 --- a/src/main/java/elucent/eidolon/item/ItemBase.java +++ b/src/main/java/elucent/eidolon/item/ItemBase.java @@ -13,9 +13,8 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.item.Item.Properties; - public class ItemBase extends Item { + String loreFormat = "" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC; String loreTag = null; public ItemBase(Properties properties) { @@ -27,12 +26,23 @@ public ItemBase setLore(String tag) { return this; } + public ItemBase setLore(ChatFormatting format, String tag) { + this.loreFormat = "" + format; + this.loreTag = tag; + return this; + } + + public ItemBase setLore(String format, String tag) { + this.loreFormat = format; + this.loreTag = tag; + return this; + } + @Override @OnlyIn(Dist.CLIENT) public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (this.loreTag != null) { - tooltip.add(new TextComponent("")); - tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); + tooltip.add(new TextComponent(loreFormat + I18n.get(this.loreTag))); } } } diff --git a/src/main/java/elucent/eidolon/item/NotetakingToolsItem.java b/src/main/java/elucent/eidolon/item/NotetakingToolsItem.java new file mode 100644 index 0000000..8240561 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/NotetakingToolsItem.java @@ -0,0 +1,66 @@ +package elucent.eidolon.item; + +import java.util.Collection; +import java.util.stream.Collectors; + +import elucent.eidolon.Registry; +import elucent.eidolon.block.PipeBlock; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; + +public class NotetakingToolsItem extends ItemBase { + public NotetakingToolsItem(Properties properties) { + super(properties); + } + + @Override + public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity entity, InteractionHand hand) { + Collection researches = Researches.getEntityResearches(entity); + if (researches != null && !researches.isEmpty()) { + Research r = researches.iterator().next(); + if (!player.level.isClientSide && r != null) { + ItemStack notes = new ItemStack(Registry.RESEARCH_NOTES.get(), 1); + notes.getOrCreateTag().putString("research", r.getRegistryName().toString()); + notes.getTag().putInt("stepsDone", 0); + stack.shrink(1); + if (stack.getCount() == 0) player.setItemInHand(hand, notes); + else if (!player.getInventory().add(notes)) { + player.drop(notes, false); + } + } + return InteractionResult.PASS; + } + return super.interactLivingEntity(stack, player, entity, hand); + } + + @Override + public InteractionResult useOn(UseOnContext ctx) { + BlockState state = ctx.getLevel().getBlockState(ctx.getClickedPos()); + Collection researches = Researches.getBlockResearches(state.getBlock()); + if (researches != null) { + researches.removeIf((r) -> KnowledgeUtil.knowsResearch(ctx.getPlayer(), r.getRegistryName())); + if (!researches.isEmpty()) { + Research r = researches.iterator().next(); + ItemStack notes = new ItemStack(Registry.RESEARCH_NOTES.get(), 1); + notes.getOrCreateTag().putString("research", r.getRegistryName().toString()); + notes.getTag().putInt("stepsDone", 0); + ctx.getItemInHand().shrink(1); + if (ctx.getItemInHand().getCount() == 0) + ctx.getPlayer().setItemInHand(ctx.getHand(), ItemStack.EMPTY); + if (!ctx.getPlayer().getInventory().add(notes.copy())) { + ctx.getPlayer().drop(notes, false); + } + return InteractionResult.SUCCESS; + } + } + return super.useOn(ctx); + } +} diff --git a/src/main/java/elucent/eidolon/item/ReaperScytheItem.java b/src/main/java/elucent/eidolon/item/ReaperScytheItem.java index 9f4d7c6..3f4a6d1 100644 --- a/src/main/java/elucent/eidolon/item/ReaperScytheItem.java +++ b/src/main/java/elucent/eidolon/item/ReaperScytheItem.java @@ -14,8 +14,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.item.Item.Properties; - public class ReaperScytheItem extends SwordItem { public ReaperScytheItem(Properties builderIn) { super(Tiers.PewterTier.INSTANCE, 5, -2.9f, builderIn); diff --git a/src/main/java/elucent/eidolon/item/ResearchNotesItem.java b/src/main/java/elucent/eidolon/item/ResearchNotesItem.java new file mode 100644 index 0000000..3722b16 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/ResearchNotesItem.java @@ -0,0 +1,75 @@ +package elucent.eidolon.item; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import elucent.eidolon.Registry; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DoublePlantBlock; +import net.minecraft.world.level.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Endermite; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.item.SwordItem; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.InteractionResult; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.phys.Vec3; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.ChatFormatting; +import net.minecraft.world.level.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingHurtEvent; +import net.minecraftforge.event.entity.living.LootingLevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import java.util.Random; + +public class ResearchNotesItem extends ItemBase { + private Random random = new Random(); + + public ResearchNotesItem(Properties builderIn) { + super(builderIn); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + if (!stack.hasTag() || !stack.getTag().contains("research")) return; + Research r = Researches.find(new ResourceLocation(stack.getTag().getString("research"))); + if (r == null) return; + int done = stack.getTag().getInt("stepsDone"); + StringBuilder stars = new StringBuilder(); + stars.append(ChatFormatting.GOLD); + for (int i = 0; i < r.getStars(); i ++) { + if (i == done) stars.append(ChatFormatting.GRAY); + if (i < done) stars.append("\u2605"); + else stars.append("\u2606"); + } + tooltip.add(new TextComponent(stars.toString())); + boolean known = done >= r.getStars() || KnowledgeUtil.knowsResearch(Minecraft.getInstance().player, r.getRegistryName()); + String name = known ? r.getName() : "???"; + tooltip.add(new TextComponent("" + (known ? ChatFormatting.GRAY : ChatFormatting.DARK_GRAY) + ChatFormatting.ITALIC + name)); + } +} diff --git a/src/main/java/elucent/eidolon/item/ReversalPickItem.java b/src/main/java/elucent/eidolon/item/ReversalPickItem.java index b66a041..eee8ab1 100644 --- a/src/main/java/elucent/eidolon/item/ReversalPickItem.java +++ b/src/main/java/elucent/eidolon/item/ReversalPickItem.java @@ -18,8 +18,6 @@ import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraft.world.item.Item.Properties; - public class ReversalPickItem extends PickaxeItem { public ReversalPickItem(Properties builderIn) { super(Tiers.MagicToolTier.INSTANCE, 1, -2.8F, builderIn); diff --git a/src/main/java/elucent/eidolon/item/SappingSwordItem.java b/src/main/java/elucent/eidolon/item/SappingSwordItem.java index fc7f46f..31c4cb5 100644 --- a/src/main/java/elucent/eidolon/item/SappingSwordItem.java +++ b/src/main/java/elucent/eidolon/item/SappingSwordItem.java @@ -17,8 +17,8 @@ import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; - -import net.minecraft.world.item.Item.Properties; +import net.minecraftforge.common.ToolAction; +import net.minecraftforge.common.ToolActions; public class SappingSwordItem extends SwordItem { public SappingSwordItem(Properties builderIn) { @@ -40,6 +40,12 @@ public void appendHoverText(ItemStack stack, Level worldIn, List tool tooltip.add(new TextComponent("" + ChatFormatting.DARK_PURPLE + ChatFormatting.ITALIC + I18n.get(this.loreTag))); } } + +// @Override +// public boolean canPerformAction(ItemStack stack, ToolAction toolAction) { +// if (toolAction == ToolActions.SWORD_SWEEP) return false; +// return super.canPerformAction(stack, toolAction); +// } @Override public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { diff --git a/src/main/java/elucent/eidolon/item/SilverArmorItem.java b/src/main/java/elucent/eidolon/item/SilverArmorItem.java index c459e8f..038d979 100644 --- a/src/main/java/elucent/eidolon/item/SilverArmorItem.java +++ b/src/main/java/elucent/eidolon/item/SilverArmorItem.java @@ -1,9 +1,9 @@ package elucent.eidolon.item; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.model.SilverArmorModel; -import elucent.eidolon.item.model.WarlockArmorModel; import net.minecraft.client.Minecraft; import net.minecraft.client.model.HumanoidModel; import net.minecraft.world.entity.Entity; @@ -19,7 +19,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.IItemRenderProperties; -import net.minecraft.world.item.Item.Properties; public class SilverArmorItem extends ArmorItem { private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; @@ -94,10 +93,10 @@ public SilverArmorModel getArmorModel(LivingEntity entity, ItemStack itemStack, float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); float netHeadYaw = f1 - f; float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); - Registry.SILVER_ARMOR_MODEL.slot = slot; - Registry.SILVER_ARMOR_MODEL.copyFromDefault(_default); - Registry.SILVER_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); - return Registry.SILVER_ARMOR_MODEL; + ClientRegistry.SILVER_ARMOR_MODEL.slot = slot; + ClientRegistry.SILVER_ARMOR_MODEL.copyFromDefault(_default); + ClientRegistry.SILVER_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return ClientRegistry.SILVER_ARMOR_MODEL; } }); } diff --git a/src/main/java/elucent/eidolon/item/SoulfireWandItem.java b/src/main/java/elucent/eidolon/item/SoulfireWandItem.java index c609922..2ae454b 100644 --- a/src/main/java/elucent/eidolon/item/SoulfireWandItem.java +++ b/src/main/java/elucent/eidolon/item/SoulfireWandItem.java @@ -3,22 +3,18 @@ import java.util.Random; import elucent.eidolon.Registry; +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.capability.ISoul; import elucent.eidolon.entity.SoulfireProjectileEntity; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.SoulUpdatePacket; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.InteractionHand; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Rotation; import net.minecraft.sounds.SoundSource; -import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; import net.minecraft.world.level.Level; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.server.level.ServerLevel; - -import net.minecraft.world.item.Item.Properties; public class SoulfireWandItem extends WandItem { static Random random = new Random(); diff --git a/src/main/java/elucent/eidolon/item/SummoningStaffItem.java b/src/main/java/elucent/eidolon/item/SummoningStaffItem.java new file mode 100644 index 0000000..bff3f2c --- /dev/null +++ b/src/main/java/elucent/eidolon/item/SummoningStaffItem.java @@ -0,0 +1,222 @@ +package elucent.eidolon.item; + +import java.util.List; +import java.util.Optional; +import java.util.Random; + +import elucent.eidolon.Registry; +import elucent.eidolon.capability.IReputation; +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.entity.SoulfireProjectileEntity; +import elucent.eidolon.network.MagicBurstEffectPacket; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.SoulUpdatePacket; +import elucent.eidolon.particle.Particles; +import elucent.eidolon.util.ColorUtil; +import elucent.eidolon.util.EntityUtil; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ArrowItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.UseAnim; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionHand; +import net.minecraft.ChatFormatting; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.stats.Stats; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraft.world.level.Level; + +public class SummoningStaffItem extends ItemBase { + public SummoningStaffItem(Properties builderIn) { + super(builderIn); + } + + @Override + public UseAnim getUseAnimation(ItemStack stack) { + return UseAnim.BOW; + } + + @Override + public int getUseDuration(ItemStack stack) { + return 72000; + } + + Random random = new Random(); + + @Override + public void onUsingTick(ItemStack stack, LivingEntity entity, int time) { + if (entity.level.isClientSide) { + HitResult hit = entity.pick(16, 0, false); + if (hit.getType() != Type.MISS) { + Vec3 pos = hit.getLocation(); + time = 72000 - time; + float alpha = Mth.clamp(time / 40.0f, 0, 1); + float a = Mth.DEG_TO_RAD * (entity.level.getGameTime() % 360 + 12 * time); + float r = 0.3f + 0.3f * alpha; + float sa = r * Mth.sin(a), ca = r * Mth.cos(a); + if (time == 40) { + entity.playSound(SoundEvents.CROSSBOW_QUICK_CHARGE_3, 1, 1); + } + Particles.create(Registry.SMOKE_PARTICLE) + .randomVelocity(0.025f * alpha, 0.0125f * alpha) + .setColor(33.0f/255, 26.0f/255, 23.0f/255, 0.125f, 10.0f/255, 10.0f/255, 12.0f/255, 0) + .setAlpha(0.25f * alpha, 0) + .randomOffset(0.05f + 0.05f * alpha) + .setScale(0.25f + 0.25f * alpha, alpha * 0.125f) + .repeat(entity.level, pos.x + sa, pos.y, pos.z + ca, 2) + .repeat(entity.level, pos.x - sa, pos.y, pos.z - ca, 2); + } + } + } + + @Override + public void releaseUsing(ItemStack stack, Level level, LivingEntity entity, int time) { + if ((72000 - time) >= 20 && hasCharges(stack)) { + ListTag charges = getCharges(stack); + int selected = getSelected(stack); + CompoundTag tag = charges.getCompound(selected); + HitResult hit = entity.pick(16, 0, false); + if (hit.getType() != Type.MISS) { + Vec3 pos = hit.getLocation(); + Optional> etype = EntityType.by(tag); + if (etype.isPresent() && !level.isClientSide) { + tag.remove("UUID"); + Optional e = etype.get().create(tag, level); + if (e.isPresent()) { + e.get().setPos(pos); + EntityUtil.enthrall(entity, (LivingEntity)e.get()); + level.addFreshEntity(e.get()); + Networking.sendToTracking(entity.level, e.get().blockPosition(), new MagicBurstEffectPacket(e.get().getX(), e.get().getY() + e.get().getBbHeight() / 2, e.get().getZ(), + ColorUtil.packColor(255, 61, 70, 35), ColorUtil.packColor(255, 36, 24, 41))); + level.playSound(null, e.get().blockPosition(), SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.PLAYERS, 0.75f, 0.1f); + } + } + + entity.setItemInHand(entity.getUsedItemHand(), entity instanceof Player && ((Player)entity).getAbilities().instabuild ? stack : consumeCharge(stack, selected)); + entity.swing(entity.getUsedItemHand()); + entity.stopUsingItem(); + } + } + } + + public int getSelected(ItemStack stack) { + CompoundTag tag = stack.getOrCreateTag(); + if (!tag.contains("selected")) tag.putInt("selected", 0); + else if (tag.getInt("selected") >= getCharges(stack).size()) tag.putInt("selected", 0); + return tag.getInt("selected"); + } + + public int changeSelection(ItemStack stack, int diff) { + if (!hasCharges(stack)) return 0; + CompoundTag tag = stack.getOrCreateTag(); + int selected = getSelected(stack) + diff % getCharges(stack).size(); + tag.putInt("selected", selected); + return selected; + } + + public ItemStack addCharges(ItemStack stack, ListTag charges) { + CompoundTag tag = stack.getOrCreateTag(); + if (!tag.contains("charges")) { + while (charges.size() > 100) charges.remove(charges.size() - 1); + tag.put("charges", charges); + } + else { + ListTag existing = tag.getList("charges", Tag.TAG_COMPOUND); + while (existing.size() + charges.size() > 100) charges.remove(charges.size() - 1); + if (charges.size() > 0) for (Tag t : charges) existing.add(t); + tag.put("charges", existing); + } + return stack; + } + + public boolean hasCharges(ItemStack stack) { + CompoundTag tag = stack.getOrCreateTag(); + ListTag list = tag.getList("charges", Tag.TAG_COMPOUND); + return tag.contains("charges") && tag.getList("charges", Tag.TAG_COMPOUND).size() > 0; + } + + public ListTag getCharges(ItemStack stack) { + CompoundTag tag = stack.getOrCreateTag(); + return tag.contains("charges") ? tag.getList("charges", Tag.TAG_COMPOUND) : new ListTag(); + } + + public ItemStack consumeCharge(ItemStack stack, int index) { + ListTag list = getCharges(stack); + if (list.size() > index) list.remove(index); + stack.getOrCreateTag().put("charges", list); + return stack; + } + + public ItemStack addCharge(ItemStack stack, CompoundTag tag) { + ListTag list = getCharges(stack); + if (list.size() < 100) list.add(tag); + stack.getOrCreateTag().put("charges", list); + return stack; + } + + @Override + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + + if (hasCharges(stack)) { + if (player.isCrouching()) { + changeSelection(stack, 1); + CompoundTag tag = getCharges(stack).getCompound(getSelected(stack)); + ResourceLocation id = new ResourceLocation(tag.getString("id")); + String summonKey = "entity." + id.getNamespace() + "." + id.getPath(); + player.setItemInHand(hand, stack); + if (!world.isClientSide) { + ((ServerPlayer)player).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.tooltip.active_summon").append( + new TranslatableComponent(summonKey).withStyle(ChatFormatting.LIGHT_PURPLE) + ))); + player.playNotifySound(SoundEvents.UI_BUTTON_CLICK, SoundSource.PLAYERS, 0.5f, 1.0f); + } + return InteractionResultHolder.fail(stack); + } + player.startUsingItem(hand); + return InteractionResultHolder.consume(stack); + } + else return InteractionResultHolder.fail(stack); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + boolean charge = hasCharges(stack); + int selected = getSelected(stack); + String summonKey = "eidolon.tooltip.no_selected_summon"; + if (charge) { + CompoundTag tag = getCharges(stack).getCompound(selected); + String ids = tag.getString("id"); + ResourceLocation id = new ResourceLocation(tag.getString("id")); + summonKey = "entity." + id.getNamespace() + "." + id.getPath(); + } + tooltip.add(new TranslatableComponent("eidolon.tooltip.active_summon").append( + new TranslatableComponent(summonKey).withStyle(charge ? ChatFormatting.LIGHT_PURPLE : ChatFormatting.DARK_PURPLE) + )); + } +} diff --git a/src/main/java/elucent/eidolon/item/Tiers.java b/src/main/java/elucent/eidolon/item/Tiers.java index 1d27089..aa19cfd 100644 --- a/src/main/java/elucent/eidolon/item/Tiers.java +++ b/src/main/java/elucent/eidolon/item/Tiers.java @@ -141,4 +141,38 @@ public Ingredient getRepairIngredient() { public static SanguineTier INSTANCE = new SanguineTier(); } + + public static class NecroticTier implements Tier { + @Override + public int getUses() { + return 2161; + } + + @Override + public float getSpeed() { + return 8.0f; + } + + @Override + public float getAttackDamageBonus() { + return 3; + } + + @Override + public int getLevel() { + return 3; + } + + @Override + public int getEnchantmentValue() { + return 30; + } + + @Override + public Ingredient getRepairIngredient() { + return Ingredient.of(Registry.DEATH_ESSENCE.get()); + } + + public static MagicToolTier INSTANCE = new MagicToolTier(); + } } diff --git a/src/main/java/elucent/eidolon/item/TongsItem.java b/src/main/java/elucent/eidolon/item/TongsItem.java index 0d1ca32..240aa50 100644 --- a/src/main/java/elucent/eidolon/item/TongsItem.java +++ b/src/main/java/elucent/eidolon/item/TongsItem.java @@ -5,8 +5,6 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.Item.Properties; - public class TongsItem extends ItemBase { public TongsItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/TopHatItem.java b/src/main/java/elucent/eidolon/item/TopHatItem.java index a0c2845..1ad5f66 100644 --- a/src/main/java/elucent/eidolon/item/TopHatItem.java +++ b/src/main/java/elucent/eidolon/item/TopHatItem.java @@ -2,10 +2,10 @@ import java.util.List; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.model.TopHatModel; -import elucent.eidolon.item.model.WarlockArmorModel; import net.minecraft.client.Minecraft; import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.resources.language.I18n; @@ -29,7 +29,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.IItemRenderProperties; -import net.minecraft.world.item.Item.Properties; public class TopHatItem extends ArmorItem { private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; @@ -109,10 +108,10 @@ public TopHatModel getArmorModel(LivingEntity entity, ItemStack itemStack, Equip float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); float netHeadYaw = f1 - f; float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); - Registry.TOP_HAT_MODEL.slot = slot; - Registry.TOP_HAT_MODEL.copyFromDefault(_default); - Registry.TOP_HAT_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); - return Registry.TOP_HAT_MODEL; + ClientRegistry.TOP_HAT_MODEL.slot = slot; + ClientRegistry.TOP_HAT_MODEL.copyFromDefault(_default); + ClientRegistry.TOP_HAT_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return ClientRegistry.TOP_HAT_MODEL; } }); } diff --git a/src/main/java/elucent/eidolon/item/UnholySymbolItem.java b/src/main/java/elucent/eidolon/item/UnholySymbolItem.java index 3482fd7..0c70f0b 100644 --- a/src/main/java/elucent/eidolon/item/UnholySymbolItem.java +++ b/src/main/java/elucent/eidolon/item/UnholySymbolItem.java @@ -3,7 +3,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import elucent.eidolon.Eidolon; -import elucent.eidolon.item.model.UnholySymbolModel; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.ItemTransforms; @@ -15,8 +14,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraft.world.item.Item.Properties; - public class UnholySymbolItem extends ItemBase { public UnholySymbolItem(Properties builderIn) { super(builderIn); @@ -31,22 +28,4 @@ public boolean hasContainerItem(ItemStack stack) { public ItemStack getContainerItem(ItemStack stack) { return stack.copy(); } - - @OnlyIn(Dist.CLIENT) - public static class UnholySymbolItemRenderer extends BlockEntityWithoutLevelRenderer { - static final UnholySymbolModel MODEL = new UnholySymbolModel(); - - public UnholySymbolItemRenderer(BlockEntityRenderDispatcher berd, EntityModelSet ems) { - super(berd, ems); - } - - @Override - public void renderByItem(ItemStack stack, ItemTransforms.TransformType type, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay) { - RenderType rendertype = RenderType.entityCutoutNoCullZOffset(new ResourceLocation(Eidolon.MODID, "textures/item/unholy_symbol_base.png")); - matrixStack.pushPose(); - matrixStack.scale(1.0F, -1.0F, -1.0F); - MODEL.renderToBuffer(matrixStack, buffer.getBuffer(rendertype), combinedLight, combinedOverlay, 1, 1, 1, 1); - matrixStack.popPose(); - } - } } diff --git a/src/main/java/elucent/eidolon/item/WandItem.java b/src/main/java/elucent/eidolon/item/WandItem.java index 02f64a5..b4049eb 100644 --- a/src/main/java/elucent/eidolon/item/WandItem.java +++ b/src/main/java/elucent/eidolon/item/WandItem.java @@ -4,9 +4,7 @@ import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Item.Properties; - -public class WandItem extends ItemBase { +public class WandItem extends ItemBase implements IRechargeableWand { public WandItem(Properties properties) { super(properties); } @@ -22,4 +20,10 @@ public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchant) { || enchant == Enchantments.UNBREAKING || enchant == Enchantments.MENDING; } + + @Override + public ItemStack recharge(ItemStack stack) { + stack.setDamageValue(0); + return stack; + } } diff --git a/src/main/java/elucent/eidolon/item/WarlockRobesItem.java b/src/main/java/elucent/eidolon/item/WarlockRobesItem.java index 7df0523..6d0c9b7 100644 --- a/src/main/java/elucent/eidolon/item/WarlockRobesItem.java +++ b/src/main/java/elucent/eidolon/item/WarlockRobesItem.java @@ -1,5 +1,6 @@ package elucent.eidolon.item; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import elucent.eidolon.item.model.WarlockArmorModel; @@ -19,7 +20,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.IItemRenderProperties; import net.minecraftforge.common.extensions.IForgeItem; -import net.minecraft.world.item.Item.Properties; public class WarlockRobesItem extends ArmorItem implements IForgeItem { private static final int[] MAX_DAMAGE_ARRAY = new int[]{13, 15, 16, 11}; @@ -92,10 +92,10 @@ public WarlockArmorModel getArmorModel(LivingEntity entity, ItemStack itemStack, float f1 = Mth.rotLerp(pticks, entity.yHeadRotO, entity.yHeadRot); float netHeadYaw = f1 - f; float netHeadPitch = Mth.lerp(pticks, entity.xRotO, entity.getXRot()); - Registry.WARLOCK_ARMOR_MODEL.slot = slot; - Registry.WARLOCK_ARMOR_MODEL.copyFromDefault(_default); - Registry.WARLOCK_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); - return Registry.WARLOCK_ARMOR_MODEL; + ClientRegistry.WARLOCK_ARMOR_MODEL.slot = slot; + ClientRegistry.WARLOCK_ARMOR_MODEL.copyFromDefault(_default); + ClientRegistry.WARLOCK_ARMOR_MODEL.setupAnim(entity, entity.animationPosition, entity.animationSpeed, entity.tickCount + pticks, netHeadYaw, netHeadPitch); + return ClientRegistry.WARLOCK_ARMOR_MODEL; } }); } diff --git a/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java b/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java index 61723c9..23d2b06 100644 --- a/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java +++ b/src/main/java/elucent/eidolon/item/curio/AngelSightItem.java @@ -24,8 +24,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class AngelSightItem extends ItemBase { static Random random = new Random(); diff --git a/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java index 90fcd49..36d3656 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicAmuletItem.java @@ -14,8 +14,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.world.item.Item.Properties; - public class BasicAmuletItem extends Item { UUID ATTR_ID = new UUID(1821688469367197801l, 2986247575840977557l); public BasicAmuletItem(Properties properties) { diff --git a/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java b/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java index 88d2f9c..b2f4089 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicBeltItem.java @@ -14,8 +14,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.world.item.Item.Properties; - public class BasicBeltItem extends ItemBase { UUID ATTR_ID = new UUID(5892388994722937059l, 8235504439637777033l); public BasicBeltItem(Properties properties) { diff --git a/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java b/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java index 571160e..b488c4d 100644 --- a/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java +++ b/src/main/java/elucent/eidolon/item/curio/BasicRingItem.java @@ -14,8 +14,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.world.item.Item.Properties; - public class BasicRingItem extends Item { UUID ATTR_ID = new UUID(7207179027447911419l, 1628308750126455317l); public BasicRingItem(Properties properties) { diff --git a/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java b/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java index d1a147b..0144a16 100644 --- a/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java +++ b/src/main/java/elucent/eidolon/item/curio/EnervatingRingItem.java @@ -5,8 +5,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.world.item.Item.Properties; - public class EnervatingRingItem extends ItemBase { public EnervatingRingItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java b/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java index dc615a4..ff4fe5a 100644 --- a/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java +++ b/src/main/java/elucent/eidolon/item/curio/GlassHandItem.java @@ -11,8 +11,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class GlassHandItem extends ItemBase { public GlassHandItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java b/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java index 86816d2..2f8e63e 100644 --- a/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/GravityBeltItem.java @@ -19,8 +19,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class GravityBeltItem extends ItemBase { UUID ATTR_ID = new UUID(6937061617091731127l, 7120126291930051139l); public GravityBeltItem(Properties properties) { diff --git a/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java b/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java index 794b6b3..b306b9d 100644 --- a/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java +++ b/src/main/java/elucent/eidolon/item/curio/MindShieldingPlateItem.java @@ -15,8 +15,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class MindShieldingPlateItem extends ItemBase { public MindShieldingPlateItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java b/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java index a03e22c..3b2f6b0 100644 --- a/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java +++ b/src/main/java/elucent/eidolon/item/curio/PrestigiousPalmItem.java @@ -14,8 +14,6 @@ import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.world.item.Item.Properties; - public class PrestigiousPalmItem extends ItemBase { UUID ATTR_ID = new UUID(297661999713141389l, 6434109711109552363l); public PrestigiousPalmItem(Properties properties) { diff --git a/src/main/java/elucent/eidolon/item/curio/RavenCloakItem.java b/src/main/java/elucent/eidolon/item/curio/RavenCloakItem.java new file mode 100644 index 0000000..05768b6 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/RavenCloakItem.java @@ -0,0 +1,89 @@ +package elucent.eidolon.item.curio; + +import java.util.UUID; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.item.IWingsItem; +import elucent.eidolon.item.ItemBase; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.entity.living.LivingFallEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import top.theillusivec4.curios.api.CuriosApi; + +public class RavenCloakItem extends ItemBase implements IWingsItem { + UUID ATTR_ID = new UUID(261693807752044433L, 1154961640602571210L); + public RavenCloakItem(Properties properties) { + super(properties); + MinecraftForge.EVENT_BUS.addListener(RavenCloakItem::onFall); + } + + @SubscribeEvent + public static void onFall(LivingFallEvent event) { + if (CuriosApi.getCuriosHelper().findEquippedCurio(Registry.GRAVITY_BELT.get(), event.getEntityLiving()).isPresent()) { + event.setDistance(event.getDistance() / 4); + } + } + + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { + return new EidolonCurio(stack) { + @Override + public boolean canRightClickEquip() { + return true; + } + }; + } + + public static final int MAX_CHARGES = 12; + + @Override + public int getMaxCharges(ItemStack stack) { + return MAX_CHARGES; + } + + @Override + public void onFlap(Player player, Level level, ItemStack stack, int nCharges) { + player.setDeltaMovement(player.getDeltaMovement().add(player.getLookAngle().scale(0.25)).multiply(1, 0, 1).add(0, 0.5, 0)); + } + + @Override + public int getDashTicks(ItemStack stack) { + return 100; + } + + @Override + public void onDashStart(Player player, Level level, ItemStack stack) { + // + } + + @Override + public void onDashTick(Player player, Level level, ItemStack stack, int remainingTicks) { + float coeff = remainingTicks / (float)getDashTicks(stack); + coeff = 1 - (1 - coeff) * (1 - coeff) + 0.25f; + player.setDeltaMovement(player.getDeltaMovement().scale(0.8).add(player.getLookAngle().scale(coeff * 0.2))); + } + + @Override + public void onDashEnd(Player player, Level level, ItemStack stack) { + // + } + + @Override + public void onDashFlap(Player player, Level level, ItemStack stack, int dashTicks) { + player.getCapability(IPlayerData.INSTANCE).ifPresent(d -> d.setDashTicks(getDashTicks(stack))); + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/RavenCloakRenderer.java b/src/main/java/elucent/eidolon/item/curio/RavenCloakRenderer.java new file mode 100644 index 0000000..fd5a9d7 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/RavenCloakRenderer.java @@ -0,0 +1,40 @@ +package elucent.eidolon.item.curio; + +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.ClientRegistry; +import elucent.eidolon.Eidolon; +import elucent.eidolon.item.model.RavenCloakModel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import top.theillusivec4.curios.api.SlotContext; +import top.theillusivec4.curios.api.client.ICurioRenderer; + +public class RavenCloakRenderer implements ICurioRenderer { + public static final ResourceLocation TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/entity/raven_cloak.png"); + + RavenCloakModel model = null; + + @Override + public > void render(ItemStack stack, SlotContext slotContext, + PoseStack matrixStack, RenderLayerParent renderLayerParent, MultiBufferSource renderTypeBuffer, + int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, + float headPitch) { + if (model == null) { + model = new RavenCloakModel(Minecraft.getInstance().getEntityModels().bakeLayer(ClientRegistry.RAVEN_CLOAK_LAYER)); + } + LivingEntity entity = slotContext.entity(); + ICurioRenderer.followBodyRotations(entity, model); + ICurioRenderer.followHeadRotations(entity, model.getHead()); + model.setupAnim(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + model.renderToBuffer(matrixStack, renderTypeBuffer.getBuffer(RenderType.entityCutoutNoCull(TEXTURE)), light, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1); + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java b/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java index 065a9f1..470d246 100644 --- a/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java +++ b/src/main/java/elucent/eidolon/item/curio/ResoluteBeltItem.java @@ -24,8 +24,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class ResoluteBeltItem extends ItemBase { UUID ATTR_ID = new UUID(3701779382882225399l, 5035874982077300549l); diff --git a/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java index 7f61b44..f46f324 100644 --- a/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/SanguineAmuletItem.java @@ -5,15 +5,12 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.datafixers.util.Either; -import com.mojang.math.Matrix4f; - import elucent.eidolon.Registry; import elucent.eidolon.item.ItemBase; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.ThrownEnderpearl; @@ -23,21 +20,15 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -import net.minecraft.network.chat.FormattedText; -import net.minecraft.network.chat.TextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.client.event.RenderTooltipEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; -import net.minecraft.world.item.Item.Properties; - public class SanguineAmuletItem extends ItemBase { public SanguineAmuletItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/SoulboneAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/SoulboneAmuletItem.java new file mode 100644 index 0000000..8c94314 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/curio/SoulboneAmuletItem.java @@ -0,0 +1,55 @@ +package elucent.eidolon.item.curio; + +import elucent.eidolon.Registry; +import elucent.eidolon.capability.ISoul; +import elucent.eidolon.entity.SpellProjectileEntity; +import elucent.eidolon.item.ItemBase; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.SoulUpdatePacket; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.LlamaSpit; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.ShulkerBullet; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundSource; +import net.minecraft.sounds.SoundEvents; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import top.theillusivec4.curios.api.CuriosApi; + +public class SoulboneAmuletItem extends ItemBase { + public SoulboneAmuletItem(Properties properties) { + super(properties); + MinecraftForge.EVENT_BUS.addListener(SoulboneAmuletItem::onKill); + } + + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag unused) { + return new EidolonCurio(stack) { + @Override + public boolean canRightClickEquip() { + return true; + } + }; + } + + @SubscribeEvent + public static void onKill(LivingDeathEvent event) { + if (event.getSource().getEntity() instanceof LivingEntity e) { + if (CuriosApi.getCuriosHelper().findEquippedCurio(Registry.SOULBONE_AMULET.get(), e).isPresent()) { + e.getCapability(ISoul.INSTANCE).ifPresent((cap) -> { + cap.setMaxEtherealHealth(Math.max(Math.min(ISoul.getPersistentHealth(e), cap.getMaxEtherealHealth()), 2 * (int)Math.floor((cap.getEtherealHealth() + 3) / 2))); + cap.setEtherealHealth(cap.getEtherealHealth() + 2); + if (!e.level.isClientSide) Networking.sendToTracking(e.level, e.getOnPos(), new SoulUpdatePacket(e)); + }); + } + } + } +} diff --git a/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java b/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java index d1d31d3..0ba8774 100644 --- a/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java +++ b/src/main/java/elucent/eidolon/item/curio/TerminusMirrorItem.java @@ -15,8 +15,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class TerminusMirrorItem extends ItemBase { public TerminusMirrorItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java b/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java index 306452c..393d165 100644 --- a/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java +++ b/src/main/java/elucent/eidolon/item/curio/VoidAmuletItem.java @@ -20,8 +20,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class VoidAmuletItem extends ItemBase { public VoidAmuletItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java b/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java index 300c9de..0ce1237 100644 --- a/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java +++ b/src/main/java/elucent/eidolon/item/curio/WardedMailItem.java @@ -11,8 +11,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import top.theillusivec4.curios.api.CuriosApi; -import net.minecraft.world.item.Item.Properties; - public class WardedMailItem extends ItemBase { public WardedMailItem(Properties properties) { super(properties); diff --git a/src/main/java/elucent/eidolon/item/model/ArmorModel.java b/src/main/java/elucent/eidolon/item/model/ArmorModel.java index 56ce4d8..78fa189 100644 --- a/src/main/java/elucent/eidolon/item/model/ArmorModel.java +++ b/src/main/java/elucent/eidolon/item/model/ArmorModel.java @@ -3,8 +3,6 @@ // Paste this class into your mod and generate all required imports -import java.util.List; - import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -12,7 +10,6 @@ import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; -import net.minecraft.client.model.geom.builders.CubeDeformation; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; @@ -22,15 +19,6 @@ public abstract class ArmorModel extends HumanoidModel { public EquipmentSlot slot; ModelPart root, head, body, leftArm, rightArm, pelvis, leftLegging, rightLegging, leftFoot, rightFoot; -// public ModelPart copyWithoutBoxes(ModelPart box) { -// ModelPart newbox = new ModelPart(this); -// newbox.setPos(box.x, box.y, box.z); -// setRotationAngle(newbox, box.xRot, box.yRot, box.zRot); -// newbox.mirror = box.mirror; -// newbox.visible = box.visible; -// return newbox; -// } - public ArmorModel(ModelPart root) { super(root); this.root = root; @@ -86,10 +74,7 @@ public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int pac public void copyFromDefault(HumanoidModel model) { body.copyFrom(model.body); - pelvis.copyFrom(model.body); - head.copyFrom(model.head); - leftArm.copyFrom(model.leftArm); - rightArm.copyFrom(model.rightArm); + pelvis.copyFrom(body); leftLegging.copyFrom(leftLeg); rightLegging.copyFrom(rightLeg); leftFoot.copyFrom(leftLeg); diff --git a/src/main/java/elucent/eidolon/item/model/BonelordArmorModel.java b/src/main/java/elucent/eidolon/item/model/BonelordArmorModel.java new file mode 100644 index 0000000..22ffb7f --- /dev/null +++ b/src/main/java/elucent/eidolon/item/model/BonelordArmorModel.java @@ -0,0 +1,93 @@ +package elucent.eidolon.item.model; + +import elucent.eidolon.Registry; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.world.entity.LivingEntity; +import top.theillusivec4.curios.api.CuriosApi; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.util.Mth; + +public class BonelordArmorModel extends ArmorModel { + public BonelordArmorModel(ModelPart root) { + super(root); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition mesh = HumanoidModel.createMesh(new CubeDeformation(0), 0); + PartDefinition root = createHumanoidAlias(mesh); + + PartDefinition body = root.getChild("body"); + PartDefinition right_leg = root.getChild("right_legging"); + PartDefinition left_leg = root.getChild("left_legging"); + PartDefinition left_arm = root.getChild("left_arm"); + PartDefinition right_arm = root.getChild("right_arm"); + PartDefinition head = root.getChild("head"); + + PartDefinition chest = body.addOrReplaceChild("chest", CubeListBuilder.create().texOffs(0, 30).addBox(-5.5F, -24.0F, -4.5F, 11.0F, 6.0F, 8.0F, new CubeDeformation(0.0F)) + .texOffs(38, 30).addBox(-1.5F, -24.5F, 2.0F, 3.0F, 11.0F, 3.0F, new CubeDeformation(0.0F)) + .texOffs(0, 44).addBox(-5.0F, -18.0F, -3.25F, 10.0F, 4.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 24.0F, 0.0F)); + PartDefinition hood = chest.addOrReplaceChild("hood", CubeListBuilder.create().texOffs(38, 44).addBox(-6.5F, 0.0F, 0.0F, 13.0F, 4.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -28.0F, 5.0F, -0.2618F, 0.0F, 0.0F)); + PartDefinition cape = hood.addOrReplaceChild("cape", CubeListBuilder.create().texOffs(68, 9).addBox(-6.0F, 0.0F, 0.0F, 12.0F, 16.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(52, 9).addBox(2.0F, 16.0F, 0.0F, 4.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(52, 9).mirror().addBox(-6.0F, 16.0F, 0.0F, 4.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(0.0F, 4.0F, 0.0F, 0.3927F, 0.0F, 0.0F)); + PartDefinition left_point = cape.addOrReplaceChild("left_point", CubeListBuilder.create().texOffs(50, 29).addBox(0.0F, -1.0F, -1.5F, 8.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.5F, 14.75F, 1.0F, 0.0F, 0.0F, 0.5236F)); + PartDefinition right_point = cape.addOrReplaceChild("right_point", CubeListBuilder.create().texOffs(50, 29).mirror().addBox(-8.0F, -1.0F, -1.51F, 8.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(0.5F, 14.75F, 1.0F, 0.0F, 0.0F, -0.5236F)); + PartDefinition upper_right_rib = chest.addOrReplaceChild("upper_right_rib", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(45, 0).addBox(-7.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.5F, -15.0F, 2.0F, 0.0F, 0.2618F, 0.2618F)); + PartDefinition upper_right_rib_tip = upper_right_rib.addOrReplaceChild("upper_right_rib_tip", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -0.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-7.0F, -1.0F, -4.0F, -3.1416F, -0.8727F, 3.1416F)); + PartDefinition mid_right_rib = chest.addOrReplaceChild("mid_right_rib", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(45, 0).addBox(-7.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.5F, -14.25F, 2.0F, 0.0F, 0.2618F, -0.1309F)); + PartDefinition mid_right_rib_tip = mid_right_rib.addOrReplaceChild("mid_right_rib_tip", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -0.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-7.0F, -1.0F, -4.0F, -3.1416F, -0.8727F, 3.1416F)); + PartDefinition lower_right_rib = chest.addOrReplaceChild("lower_right_rib", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(45, 0).addBox(-7.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.5F, -13.5F, 2.0F, 0.0F, 0.2618F, -0.5236F)); + PartDefinition lower_right_rib_tip = lower_right_rib.addOrReplaceChild("lower_right_rib_tip", CubeListBuilder.create().texOffs(36, 8).addBox(-5.0F, -0.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-7.0F, -1.0F, -4.0F, -3.1416F, -0.8727F, 3.1416F)); + PartDefinition upper_left_rib = chest.addOrReplaceChild("upper_left_rib", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(45, 0).mirror().addBox(5.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-0.5F, -15.0F, 2.0F, 0.0F, -0.2618F, -0.2618F)); + PartDefinition upper_left_rib_tip = upper_left_rib.addOrReplaceChild("upper_left_rib_tip", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -1.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(7.0F, 0.0F, -4.0F, -3.1416F, 0.8727F, -3.1416F)); + PartDefinition mid_left_rib = chest.addOrReplaceChild("mid_left_rib", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(45, 0).mirror().addBox(5.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-0.5F, -14.25F, 2.0F, 0.0F, -0.2618F, 0.1309F)); + PartDefinition mid_left_rib_tip = mid_left_rib.addOrReplaceChild("mid_left_rib_tip", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -0.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(7.0F, -1.0F, -4.0F, -3.1416F, 0.8727F, -3.1416F)); + PartDefinition lower_left_rib = chest.addOrReplaceChild("lower_left_rib", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -2.0F, -1.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(45, 0).mirror().addBox(5.0F, -2.0F, -4.0F, 2.0F, 2.0F, 5.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-0.5F, -13.5F, 2.0F, 0.0F, -0.2618F, 0.5236F)); + PartDefinition lower_left_rib_tip = lower_left_rib.addOrReplaceChild("lower_left_rib_tip", CubeListBuilder.create().texOffs(36, 8).mirror().addBox(0.0F, -0.99F, -2.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(7.0F, -1.0F, -4.0F, -3.1416F, 0.8727F, -3.1416F)); + PartDefinition coccyx = chest.addOrReplaceChild("coccyx", CubeListBuilder.create().texOffs(30, 30).addBox(-1.0F, 0.0F, -2.5F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -13.0F, 5.0F, -0.1745F, 0.0F, 0.0F)); + PartDefinition left_greave = left_leg.addOrReplaceChild("left_greave", CubeListBuilder.create().texOffs(72, 27).addBox(0.0F, -0.5F, 0.0F, 4.0F, 8.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-2.0F, 2.0F, -3.0F, 0.0F, -0.0873F, 0.0F)); + PartDefinition left_knee = left_greave.addOrReplaceChild("left_knee", CubeListBuilder.create().texOffs(84, 27).addBox(-4.5F, -0.5F, 0.0F, 5.0F, 4.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(4.5F, -2.0F, -0.5F, 0.0F, -0.0873F, 0.0F)); + PartDefinition right_greave = right_leg.addOrReplaceChild("right_greave", CubeListBuilder.create().texOffs(72, 27).mirror().addBox(-4.0F, -0.5F, 0.0F, 4.0F, 8.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(2.0F, 2.0F, -3.0F, 0.0F, 0.0873F, 0.0F)); + PartDefinition right_knee = right_greave.addOrReplaceChild("right_knee", CubeListBuilder.create().texOffs(84, 27).mirror().addBox(-0.5F, -0.5F, 0.0F, 5.0F, 4.0F, 3.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-4.5F, -2.0F, -0.5F, 0.0F, 0.0873F, 0.0F)); + PartDefinition right_shoulder = right_arm.addOrReplaceChild("right_shoulder", CubeListBuilder.create().texOffs(44, 17).mirror().addBox(0.0F, 0.0F, -3.0F, 6.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offset(-4.5F, -2.0F, 0.0F)); + PartDefinition left_shoulder = left_arm.addOrReplaceChild("left_shoulder", CubeListBuilder.create().texOffs(44, 17).addBox(-6.0F, 0.0F, -3.0F, 6.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(4.5F, -2.0F, 0.0F)); + PartDefinition helm = head.addOrReplaceChild("helm", CubeListBuilder.create().texOffs(0, 16).addBox(-5.5F, -3.0F, -5.5F, 11.0F, 3.0F, 11.0F, new CubeDeformation(0.0F)) + .texOffs(0, 0).addBox(-4.5F, -9.0F, -4.5F, 9.0F, 7.0F, 9.0F, new CubeDeformation(0.01F)), PartPose.offset(0.0F, 1.0F, 0.0F)); + PartDefinition cowl = helm.addOrReplaceChild("cowl", CubeListBuilder.create().texOffs(33, 16).addBox(-2.0F, 0.0F, -1.5F, 5.0F, 4.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.5F, -3.5F, -4.5F, -0.2618F, 0.0F, 0.0F)); + PartDefinition right_prong = helm.addOrReplaceChild("right_prong", CubeListBuilder.create().texOffs(27, 0).mirror().addBox(-5.0F, -2.0F, 0.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-4.5F, -3.0F, -4.0F, 0.0F, 0.5236F, 0.5236F)); + PartDefinition back_right_prong = helm.addOrReplaceChild("back_right_prong", CubeListBuilder.create().texOffs(27, 4).mirror().addBox(-7.0F, -2.0F, 0.0F, 7.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-4.5F, -5.0F, 1.0F, 0.0F, 1.0472F, 0.7854F)); + PartDefinition left_prong = helm.addOrReplaceChild("left_prong", CubeListBuilder.create().texOffs(27, 0).addBox(0.0F, -2.0F, 0.0F, 5.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(4.5F, -3.0F, -4.0F, 0.0F, -0.5236F, -0.5236F)); + PartDefinition back_left_prong = helm.addOrReplaceChild("back_left_prong", CubeListBuilder.create().texOffs(27, 4).addBox(0.0F, -2.0F, 0.0F, 7.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(4.5F, -5.0F, 1.0F, 0.0F, -1.0472F, -0.7854F)); + + return LayerDefinition.create(mesh, 128, 64); + } + + @Override + public void setupAnim(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + float f = 1.0F; + if (entity.getFallFlyingTicks() > 4) { + f = (float)entity.getDeltaMovement().lengthSqr(); + f = f / 0.2F; + f = f * f * f; + } + if (f < 1.0F) { + f = 1.0F; + } + if (slot == EquipmentSlot.CHEST) { + body.getChild("chest").getChild("hood").getChild("cape").xRot = 0.3927F + Mth.abs(Mth.cos(limbSwing * 0.6662f) * 0.4f * limbSwingAmount / f); + } + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/RavenCloakModel.java b/src/main/java/elucent/eidolon/item/model/RavenCloakModel.java new file mode 100644 index 0000000..37546c4 --- /dev/null +++ b/src/main/java/elucent/eidolon/item/model/RavenCloakModel.java @@ -0,0 +1,196 @@ +package elucent.eidolon.item.model; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.item.IWingsItem; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; + +public class RavenCloakModel extends HumanoidModel { + ModelPart root, cloak, wings, leftWing, rightWing; + + public RavenCloakModel(ModelPart root) { + super(root); + this.root = root; + this.cloak = root.getChild("body").getChild("cloak"); + this.wings = root.getChild("body").getChild("wings"); + this.leftWing = wings.getChild("left_wing"); + this.rightWing = wings.getChild("right_wing"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition mesh = HumanoidModel.createMesh(new CubeDeformation(0), 0); + PartDefinition root = mesh.getRoot(); + PartDefinition body = root.addOrReplaceChild("body", new CubeListBuilder(), PartPose.ZERO); + PartDefinition head = root.addOrReplaceChild("head", new CubeListBuilder(), PartPose.ZERO); + + PartDefinition hood = head.addOrReplaceChild("hood", CubeListBuilder.create().texOffs(0, 0).addBox(-5.5F, -10.5F, -4.5F, 11.0F, 11.0F, 11.0F, new CubeDeformation(0.5F)), PartPose.offsetAndRotation(0.0F, 0.5F, 0.5F, 0.2618F, 0.0F, 0.0F)); + PartDefinition left_feather1 = hood.addOrReplaceChild("left_feather1", CubeListBuilder.create().texOffs(0, 16).mirror().addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(6.0F, -3.0F, -2.0F, 2.0944F, 0.0F, 0.5236F)); + PartDefinition left_feather2 = hood.addOrReplaceChild("left_feather2", CubeListBuilder.create().texOffs(0, 17).mirror().addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 8.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(6.0F, -3.0F, 1.0F, 1.5708F, 0.0F, 0.7854F)); + PartDefinition left_feather3 = hood.addOrReplaceChild("left_feather3", CubeListBuilder.create().texOffs(0, 16).mirror().addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 6.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(6.0F, -2.0F, 4.0F, 1.0472F, 0.0F, 0.5236F)); + PartDefinition right_feather1 = hood.addOrReplaceChild("right_feather1", CubeListBuilder.create().texOffs(0, 16).addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-6.0F, -3.0F, -2.0F, 2.0944F, 0.0F, -0.5236F)); + PartDefinition right_feather2 = hood.addOrReplaceChild("right_feather2", CubeListBuilder.create().texOffs(0, 17).addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 8.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-6.0F, -3.0F, 1.0F, 1.5708F, 0.0F, -0.7854F)); + PartDefinition right_feather3 = hood.addOrReplaceChild("right_feather3", CubeListBuilder.create().texOffs(0, 16).addBox(0.0F, -1.5F, 0.0F, 0.0F, 3.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-6.0F, -2.0F, 4.0F, 1.0472F, 0.0F, -0.5236F)); + PartDefinition beak = hood.addOrReplaceChild("beak", CubeListBuilder.create().texOffs(33, 0).addBox(-2.5F, 0.0F, -4.0F, 5.0F, 4.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -11.0F, -5.0F, 0.7854F, 0.0F, 0.0F)); + PartDefinition cloak = body.addOrReplaceChild("cloak", CubeListBuilder.create(), PartPose.offset(0.0F, 1.0F, 0.0F)); + PartDefinition left_cloak = cloak.addOrReplaceChild("left_cloak", CubeListBuilder.create().texOffs(0, 28).mirror().addBox(-0.5F, -4.0F, -4.0F, 12.0F, 20.0F, 12.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-0.5F, 1, -3.0F, 0.1309F, -0.1309F, -0.1309F)); + PartDefinition right_cloak = cloak.addOrReplaceChild("right_cloak", CubeListBuilder.create().texOffs(0, 28).addBox(-11.5F, -4.0F, -4.0F, 12.0F, 20.0F, 12.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.5F, 1, -3.0F, 0.1309F, 0.1309F, 0.1309F)); + PartDefinition wings = body.addOrReplaceChild("wings", CubeListBuilder.create(), PartPose.offset(0.0F, 1.0F, 0.0F)); + PartDefinition upper_left_cloak = wings.addOrReplaceChild("upper_left_cloak", CubeListBuilder.create().texOffs(0, 28).mirror().addBox(0.5F, -4.0F, -4.0F, 12.0F, 7.0F, 12.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-0.5F, 4, -3.0F, 0.1309F, -0.1309F, -0.5236F)); + PartDefinition upper_right_cloak = wings.addOrReplaceChild("upper_right_cloak", CubeListBuilder.create().texOffs(0, 28).addBox(-12.5F, -4.0F, -4.0F, 12.0F, 7.0F, 12.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.5F, 4, -3.0F, 0.1309F, 0.1309F, 0.5236F)); + PartDefinition left_wing = wings.addOrReplaceChild("left_wing", CubeListBuilder.create().texOffs(51, 0).addBox(0.0F, 0.0F, -2.0F, 12.0F, 8.0F, 2.0F, new CubeDeformation(0.0F)) + .texOffs(48, 41).addBox(-4.0F, 8.0F, -1.0F, 14.0F, 12.0F, 0.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -2, 5.0F, 0.0F, -0.5236F, -0.3927F)); + PartDefinition left_wing_mid = left_wing.addOrReplaceChild("left_wing_mid", CubeListBuilder.create().texOffs(72, 10).addBox(0.0F, 0.0F, -1.0F, 12.0F, 8.0F, 1.0F, new CubeDeformation(0.0F)) + .texOffs(44, 27).addBox(-1.0F, 8.0F, -0.5F, 14.0F, 12.0F, 0.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(12.5F, 0.0F, -0.5F, 0.0F, 0.2618F, 0.1309F)); + PartDefinition left_wing_tip = left_wing_mid.addOrReplaceChild("left_wing_tip", CubeListBuilder.create().texOffs(44, 11).addBox(0.0F, 0.0F, -1.0F, 14.0F, 16.0F, 0.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(11.5F, 0.0F, 0.5F, 0.0F, 0.5236F, -0.1309F)); + PartDefinition right_wing = wings.addOrReplaceChild("right_wing", CubeListBuilder.create().texOffs(51, 0).mirror().addBox(-12.0F, 0.0F, -2.0F, 12.0F, 8.0F, 2.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(48, 41).mirror().addBox(-10.0F, 8.0F, -1.0F, 14.0F, 12.0F, 0.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(0.0F, -2, 5.0F, 0.0F, 0.5236F, 0.3927F)); + PartDefinition right_wing_mid = right_wing.addOrReplaceChild("right_wing_mid", CubeListBuilder.create().texOffs(72, 10).mirror().addBox(-12.0F, 0.0F, -1.0F, 12.0F, 8.0F, 1.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(44, 27).mirror().addBox(-13.0F, 8.0F, -0.5F, 14.0F, 12.0F, 0.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-12.5F, 0.0F, -0.5F, 0.0F, -0.2618F, -0.1309F)); + PartDefinition right_wing_tip = right_wing_mid.addOrReplaceChild("right_wing_tip", CubeListBuilder.create().texOffs(44, 11).mirror().addBox(-14.0F, 0.0F, -1.0F, 14.0F, 16.0F, 0.0F, new CubeDeformation(0.0F)).mirror(false), PartPose.offsetAndRotation(-11.5F, 0.0F, 0.5F, 0.0F, -0.5236F, 0.1309F)); + + return LayerDefinition.create(mesh, 128, 64); + } + + @Override + public void setupAnim(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + if (entity instanceof Player p) { + float pticks = Minecraft.getInstance().getFrameTime(); + IPlayerData data = p.getCapability(IPlayerData.INSTANCE).resolve().get(); + float timeSinceFlying = Mth.clamp(p.level.getGameTime() - data.getFlightStartTime(p) + pticks, 0, 10); + float timeSinceFlapping = Mth.clamp(p.level.getGameTime() - data.getLastFlapTime(p) + pticks, 0.01F, 20); + + ModelPart leftMid = leftWing.getChild("left_wing_mid"); + ModelPart leftTip = leftMid.getChild("left_wing_tip"); + ModelPart rightMid = rightWing.getChild("right_wing_mid"); + ModelPart rightTip = rightMid.getChild("right_wing_tip"); + + float unfurl = 0; + timeSinceFlapping /= 20; + timeSinceFlapping -= 0.166666666666666F; + float flap1 = Mth.sin(Mth.PI * 2.4f * timeSinceFlapping) / (2.4f * Mth.PI * timeSinceFlapping); + timeSinceFlapping += 0.166666666666666F; + float flap2 = -Mth.sin(Mth.TWO_PI * Mth.sqrt(timeSinceFlapping)); + flap2 *= (1.5f - 0.5f * timeSinceFlapping); + if (data.isFlying(p)) { + cloak.visible = false; + wings.visible = true; + unfurl = (10 - timeSinceFlying) / 10.0f; + unfurl *= unfurl; + unfurl = 1 - unfurl; + } + else { + cloak.visible = timeSinceFlying >= 10; + wings.visible = timeSinceFlying < 10; + unfurl = (10 - timeSinceFlying) / 10.0f; + unfurl *= unfurl; + } + + float leftWingX = 0.7854F, leftWingY = -0.5236F, leftWingZ = -0.7854F; + float rightWingX = 0.7854F, rightWingY = 0.5236F, rightWingZ = 0.7854F; + float leftMidX = 0, leftMidY = 0.2618F; + float leftTipY = 0.5236F; + float rightMidX = 0, rightMidY = -0.2618F; + float rightTipY = -0.5236F; + + // dashing + + if (data.isDashing(p)) { + ItemStack wings = data.getWingsItem(p); + int maxDash = wings.getItem() instanceof IWingsItem i ? i.getDashTicks(wings) : 0; + int dashTicks = data.getDashTicks(p); + int sinceDashing = maxDash - dashTicks; + float dashStart = Mth.clamp(sinceDashing / 10.0f, 0.01f, 1); + + leftWingZ = Mth.lerp(dashStart, leftWingZ, 0); + rightWingZ = Mth.lerp(dashStart, rightWingZ, 0); + leftWingY = Mth.lerp(dashStart, leftWingZ, 0); + rightWingY = Mth.lerp(dashStart, rightWingZ, 0); + leftWingX = Mth.lerp(dashStart, leftWingX, 0.2618F); + rightWingX = Mth.lerp(dashStart, rightWingX, 0.2618F); + } + + // flapping + + leftWingX = Mth.lerp(flap1, leftWingX, 1.5708F); + leftWingY = Mth.lerp(flap1, leftWingY, 1.047F); + leftWingZ = Mth.lerp(flap1, leftWingZ, 0.5236F); + leftMidY = Mth.lerp(flap2, leftMidY, 0.7854F); + rightWingX = Mth.lerp(flap1, rightWingX, 1.5708F); + rightWingY = Mth.lerp(flap1, rightWingY, -1.047F); + rightWingZ = Mth.lerp(flap1, rightWingZ, -0.5236F); + rightMidY = Mth.lerp(flap2, rightMidY, -0.7854F); + + // unfurling + + leftWingX = Mth.lerp(unfurl, 0, leftWingX); + leftWingY = Mth.lerp(unfurl, 0.2618F, leftWingY); + leftWingZ = Mth.lerp(unfurl, -0.3927F, leftWingZ); + leftMidY = Mth.lerp(unfurl, 1.4399F, leftMidY); + leftTipY = Mth.lerp(unfurl, 1.5708F, leftTipY); + + rightWingX = Mth.lerp(unfurl, 0, rightWingX); + rightWingY = Mth.lerp(unfurl, -0.2618F, rightWingY); + rightWingZ = Mth.lerp(unfurl, 0.3927F, rightWingZ); + rightMidY = Mth.lerp(unfurl, -1.4399F, rightMidY); + rightTipY = Mth.lerp(unfurl, -1.5708F, rightTipY); + + // crouching + + if (p.isCrouching()) { + leftWingY += 0.3927F; + rightWingY -= 0.3927F; + leftWingZ += 0.3927F; + rightWingZ -= 0.3927F; + } + + // velocity + + float clampedDY = (float) Mth.clamp(p.getDeltaMovement().y, -0.5f, 0.5f); + leftWingZ += clampedDY * 0.5236F; + rightWingZ -= clampedDY * 0.5236F; + + leftWing.xRot = leftWingX; + leftWing.yRot = leftWingY; + leftWing.zRot = leftWingZ; + leftMid.yRot = leftMidY; + leftTip.yRot = leftTipY; + + rightWing.xRot = rightWingX; + rightWing.yRot = rightWingY; + rightWing.zRot = rightWingZ; + rightMid.yRot = rightMidY; + rightTip.yRot = rightTipY; + } + } + + @Override + protected Iterable headParts() { + return ImmutableList.of(root.getChild("head")); + } + + @Override + protected Iterable bodyParts() { + return ImmutableList.of(root.getChild("body")); + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + super.renderToBuffer(poseStack, buffer, packedLight, packedOverlay, red, green, blue, alpha); + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java b/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java index 839018e..0422902 100644 --- a/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java +++ b/src/main/java/elucent/eidolon/item/model/SilverArmorModel.java @@ -8,7 +8,6 @@ import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; -import net.minecraft.world.entity.EquipmentSlot; public class SilverArmorModel extends ArmorModel { public SilverArmorModel(ModelPart part) { diff --git a/src/main/java/elucent/eidolon/item/model/TopHatModel.java b/src/main/java/elucent/eidolon/item/model/TopHatModel.java index 124fc79..cbfac04 100644 --- a/src/main/java/elucent/eidolon/item/model/TopHatModel.java +++ b/src/main/java/elucent/eidolon/item/model/TopHatModel.java @@ -3,8 +3,6 @@ // Paste this class into your mod and generate all required imports -import com.google.common.collect.ImmutableList; - import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; @@ -14,7 +12,6 @@ import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.EquipmentSlot; public class TopHatModel extends ArmorModel { public TopHatModel(ModelPart part) { diff --git a/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java b/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java deleted file mode 100644 index f417ea7..0000000 --- a/src/main/java/elucent/eidolon/item/model/UnholySymbolModel.java +++ /dev/null @@ -1,228 +0,0 @@ -package elucent.eidolon.item.model; - -// Made with Blockbench 3.8.4 -// Exported for Minecraft version 1.15 - 1.16 -// Paste this class into your mod and generate all required imports - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; - -import net.minecraft.client.model.EntityModel; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.world.entity.Entity; - -public class UnholySymbolModel extends EntityModel { -// private final ModelPart model; -// private final ModelPart watchTop; -// private final ModelPart cube_r1; -// private final ModelPart cube_r2; -// private final ModelPart cube_r3; -// private final ModelPart cube_r4; -// private final ModelPart cube_r5; -// private final ModelPart cube_r6; -// private final ModelPart cube_r7; -// private final ModelPart cube_r8; -// private final ModelPart cube_r9; -// private final ModelPart cube_r10; -// private final ModelPart cube_r11; -// private final ModelPart cube_r12; -// private final ModelPart cube_r13; -// private final ModelPart cube_r14; -// private final ModelPart watchBottom; -// private final ModelPart cube_r15; -// private final ModelPart cube_r16; -// private final ModelPart cube_r17; -// private final ModelPart cube_r18; -// private final ModelPart cube_r19; -// private final ModelPart cube_r20; -// private final ModelPart cube_r21; -// private final ModelPart cube_r22; -// private final ModelPart cube_r23; -// private final ModelPart cube_r24; - - public UnholySymbolModel() { -// texWidth = 32; -// texHeight = 16; -// -// model = new ModelPart(this); -// model.setPos(0.0F, 29.0F, 2.0F); -// setRotationAngle(model, -1.5708F, 0.0F, 0.0F); -// model.texOffs(12, 4).addBox(-1.5F, 0.55F, 3.0F, 3.0F, 3.0F, 2.0F, 0.0F, false); -// -// watchTop = new ModelPart(this); -// watchTop.setPos(0.0F, 2.0F, 4.0F); -// model.addChild(watchTop); -// setRotationAngle(watchTop, 0.0436F, 0.0F, 0.0F); -// watchTop.texOffs(12, 0).addBox(-3.5F, 0.0F, -6.0F, 7.0F, 1.0F, 3.0F, 0.0F, false); -// watchTop.texOffs(22, 4).addBox(-1.5F, 0.0F, -3.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r1 = new ModelPart(this); -// cube_r1.setPos(0.5F, 1.5F, -1.0F); -// watchTop.addChild(cube_r1); -// setRotationAngle(cube_r1, 0.0F, -0.3142F, 0.0F); -// cube_r1.texOffs(12, 9).addBox(1.75F, -0.97F, -3.65F, 1.0F, 1.0F, 1.0F, 0.0F, true); -// -// cube_r2 = new ModelPart(this); -// cube_r2.setPos(3.5901F, 1.05F, -3.2292F); -// watchTop.addChild(cube_r2); -// setRotationAngle(cube_r2, 0.0F, -2.1991F, 0.0F); -// cube_r2.texOffs(12, 9).addBox(-3.275F, -0.53F, 3.1F, 1.0F, 1.0F, 1.0F, 0.0F, true); -// -// cube_r3 = new ModelPart(this); -// cube_r3.setPos(-3.5901F, 1.05F, -3.2292F); -// watchTop.addChild(cube_r3); -// setRotationAngle(cube_r3, 0.0F, 2.1991F, 0.0F); -// cube_r3.texOffs(12, 13).addBox(2.275F, -0.51F, 3.1F, 1.0F, 1.0F, 1.0F, 0.0F, false); -// -// cube_r4 = new ModelPart(this); -// cube_r4.setPos(-0.5F, 1.5F, -1.0F); -// watchTop.addChild(cube_r4); -// setRotationAngle(cube_r4, 0.0F, 0.3142F, 0.0F); -// cube_r4.texOffs(12, 13).addBox(-2.75F, -0.97F, -3.65F, 1.0F, 1.0F, 1.0F, 0.0F, false); -// -// cube_r5 = new ModelPart(this); -// cube_r5.setPos(0.091F, 0.0F, -1.8839F); -// watchTop.addChild(cube_r5); -// setRotationAngle(cube_r5, 0.0F, -0.7854F, 0.0F); -// cube_r5.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); -// -// cube_r6 = new ModelPart(this); -// cube_r6.setPos(0.0F, 0.0F, -2.0F); -// watchTop.addChild(cube_r6); -// setRotationAngle(cube_r6, 0.0F, 0.7854F, 0.0F); -// cube_r6.texOffs(22, 4).addBox(0.259F, -0.005F, -0.2339F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r7 = new ModelPart(this); -// cube_r7.setPos(0.091F, 0.0F, -7.1161F); -// watchTop.addChild(cube_r7); -// setRotationAngle(cube_r7, 0.0F, -2.3562F, 0.0F); -// cube_r7.texOffs(22, 4).addBox(0.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); -// -// cube_r8 = new ModelPart(this); -// cube_r8.setPos(-0.091F, 0.0F, -7.1161F); -// watchTop.addChild(cube_r8); -// setRotationAngle(cube_r8, 0.0F, 2.3562F, 0.0F); -// cube_r8.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r9 = new ModelPart(this); -// cube_r9.setPos(0.0F, 0.0F, -7.0F); -// watchTop.addChild(cube_r9); -// setRotationAngle(cube_r9, 0.0F, 3.1416F, 0.0F); -// cube_r9.texOffs(22, 4).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r10 = new ModelPart(this); -// cube_r10.setPos(2.25F, 1.0F, -7.5F); -// watchTop.addChild(cube_r10); -// setRotationAngle(cube_r10, 1.5708F, -0.3142F, 0.0F); -// cube_r10.texOffs(4, 8).addBox(-0.5F, -0.01F, -0.5F, 1.0F, 7.0F, 1.0F, 0.0F, true); -// -// cube_r11 = new ModelPart(this); -// cube_r11.setPos(2.25F, 1.0F, -7.5F); -// watchTop.addChild(cube_r11); -// setRotationAngle(cube_r11, 1.5708F, -0.9425F, 0.0F); -// cube_r11.texOffs(4, 8).addBox(-0.5F, 0.0F, -0.51F, 1.0F, 7.0F, 1.0F, 0.0F, true); -// -// cube_r12 = new ModelPart(this); -// cube_r12.setPos(-3.5F, 1.0F, -3.25F); -// watchTop.addChild(cube_r12); -// setRotationAngle(cube_r12, 1.5708F, 1.5708F, 0.0F); -// cube_r12.texOffs(0, 8).addBox(-0.45F, 0.0F, -0.52F, 1.0F, 7.0F, 1.0F, 0.0F, false); -// -// cube_r13 = new ModelPart(this); -// cube_r13.setPos(-2.25F, 1.0F, -7.5F); -// watchTop.addChild(cube_r13); -// setRotationAngle(cube_r13, 1.5708F, 0.9425F, 0.0F); -// cube_r13.texOffs(8, 8).addBox(-0.5F, 0.0F, -0.49F, 1.0F, 7.0F, 1.0F, 0.0F, false); -// -// cube_r14 = new ModelPart(this); -// cube_r14.setPos(-2.25F, 1.0F, -7.5F); -// watchTop.addChild(cube_r14); -// setRotationAngle(cube_r14, 1.5708F, 0.3142F, 0.0F); -// cube_r14.texOffs(0, 8).addBox(-0.5F, 0.0F, -0.53F, 1.0F, 7.0F, 1.0F, 0.0F, false); -// -// watchBottom = new ModelPart(this); -// watchBottom.setPos(0.0F, 0.0F, 0.0F); -// model.addChild(watchBottom); -// watchBottom.texOffs(12, 0).addBox(-3.5F, 0.0F, -2.0F, 7.0F, 1.0F, 3.0F, 0.0F, false); -// watchBottom.texOffs(22, 4).addBox(-1.5F, 0.0F, 1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r15 = new ModelPart(this); -// cube_r15.setPos(1.9F, 1.5F, -4.0F); -// watchBottom.addChild(cube_r15); -// setRotationAngle(cube_r15, 2.3562F, 0.0F, -1.5708F); -// cube_r15.texOffs(0, 4).addBox(-0.5F, 2.3207F, -5.45F, 1.0F, 3.0F, 1.0F, 0.0F, false); -// cube_r15.texOffs(8, 4).addBox(-0.5F, 2.3207F, 2.175F, 1.0F, 3.0F, 1.0F, 0.0F, false); -// -// cube_r16 = new ModelPart(this); -// cube_r16.setPos(1.9F, 1.5F, -4.0F); -// watchBottom.addChild(cube_r16); -// setRotationAngle(cube_r16, 0.7854F, 0.0F, -1.5708F); -// cube_r16.texOffs(0, 4).addBox(-0.5F, -0.3543F, 7.125F, 1.0F, 3.0F, 1.0F, 0.0F, false); -// cube_r16.texOffs(4, 4).addBox(-0.5F, -0.3543F, -0.5F, 1.0F, 3.0F, 1.0F, 0.0F, false); -// -// cube_r17 = new ModelPart(this); -// cube_r17.setPos(2.0F, 1.5F, -4.0F); -// watchBottom.addChild(cube_r17); -// setRotationAngle(cube_r17, 0.0F, 0.0F, -1.5708F); -// cube_r17.texOffs(8, 0).addBox(-0.5F, -4.0F, -0.6F, 1.0F, 4.0F, 1.0F, 0.0F, false); -// -// cube_r18 = new ModelPart(this); -// cube_r18.setPos(3.5F, 1.5F, -2.5F); -// watchBottom.addChild(cube_r18); -// setRotationAngle(cube_r18, 1.5708F, 0.0F, -1.5708F); -// cube_r18.texOffs(4, 0).addBox(-0.5F, 0.0F, 6.6F, 1.0F, 4.0F, 1.0F, 0.0F, false); -// cube_r18.texOffs(4, 0).addBox(-0.5F, 0.025F, -0.625F, 1.0F, 4.0F, 1.0F, 0.0F, false); -// -// cube_r19 = new ModelPart(this); -// cube_r19.setPos(-2.0F, 1.5F, 3.0F); -// watchBottom.addChild(cube_r19); -// setRotationAngle(cube_r19, 0.0F, 0.0F, -1.5708F); -// cube_r19.texOffs(0, 0).addBox(-0.5F, 0.0F, -0.375F, 1.0F, 4.0F, 1.0F, 0.0F, false); -// -// cube_r20 = new ModelPart(this); -// cube_r20.setPos(0.091F, 0.0F, 2.1161F); -// watchBottom.addChild(cube_r20); -// setRotationAngle(cube_r20, 0.0F, -0.7854F, 0.0F); -// cube_r20.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); -// -// cube_r21 = new ModelPart(this); -// cube_r21.setPos(0.0F, 0.0F, 2.0F); -// watchBottom.addChild(cube_r21); -// setRotationAngle(cube_r21, 0.0F, 0.7854F, 0.0F); -// cube_r21.texOffs(22, 4).addBox(0.259F, -0.005F, -0.2339F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r22 = new ModelPart(this); -// cube_r22.setPos(0.091F, 0.0F, -3.1161F); -// watchBottom.addChild(cube_r22); -// setRotationAngle(cube_r22, 0.0F, -2.3562F, 0.0F); -// cube_r22.texOffs(22, 4).addBox(0.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, true); -// -// cube_r23 = new ModelPart(this); -// cube_r23.setPos(-0.091F, 0.0F, -3.1161F); -// watchBottom.addChild(cube_r23); -// setRotationAngle(cube_r23, 0.0F, 2.3562F, 0.0F); -// cube_r23.texOffs(22, 4).addBox(-3.4F, -0.005F, -0.25F, 3.0F, 1.0F, 2.0F, 0.0F, false); -// -// cube_r24 = new ModelPart(this); -// cube_r24.setPos(0.0F, 0.0F, -3.0F); -// watchBottom.addChild(cube_r24); -// setRotationAngle(cube_r24, 0.0F, 3.1416F, 0.0F); -// cube_r24.texOffs(22, 4).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 1.0F, 2.0F, 0.0F, false); - } - - @Override - public void setupAnim(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){ - //previously the render function, render code was moved to a method below - } - - @Override - public void renderToBuffer(PoseStack matrixStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){ -// model.render(matrixStack, buffer, packedLight, packedOverlay); - } - - public void setRotationAngle(ModelPart modelRenderer, float x, float y, float z) { - modelRenderer.xRot = x; - modelRenderer.yRot = y; - modelRenderer.zRot = z; - } -} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java b/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java index 3b1d9f4..6df8749 100644 --- a/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java +++ b/src/main/java/elucent/eidolon/item/model/WarlockArmorModel.java @@ -1,10 +1,5 @@ package elucent.eidolon.item.model; -import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; - -import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; @@ -14,7 +9,6 @@ import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.util.Mth; diff --git a/src/main/java/elucent/eidolon/mixin/AbstractContainerMenuMixin.java b/src/main/java/elucent/eidolon/mixin/AbstractContainerMenuMixin.java new file mode 100644 index 0000000..d9467a1 --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/AbstractContainerMenuMixin.java @@ -0,0 +1,33 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; + +import net.minecraft.core.NonNullList; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; +import net.minecraft.world.level.levelgen.feature.StructureFeature; +import net.minecraft.world.phys.EntityHitResult; + +@Mixin(AbstractContainerMenu.class) +public interface AbstractContainerMenuMixin { + @Accessor + public NonNullList getLastSlots(); + + @Accessor + public NonNullList getRemoteSlots(); + + @Invoker + public Slot callAddSlot(Slot slot); +} diff --git a/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java b/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java index 08414ad..f872766 100644 --- a/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java +++ b/src/main/java/elucent/eidolon/mixin/LevelRendererMixin.java @@ -4,16 +4,26 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import elucent.eidolon.ClientEvents; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource.BufferSource; @Mixin(LevelRenderer.class) public class LevelRendererMixin { @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 1)) - private void customUpdateCameraAndRender(CallbackInfo ci) { + private void customRenderLevel(CallbackInfo ci) { ClientEvents.getDelayedRender().endBatch(RenderUtil.VAPOR_TRANSLUCENT); + ClientEvents.getDelayedRender().endBatch(RenderUtil.GLOWING_BLOCK_PARTICLE); } + +// @Inject(method = "renderLevel", at = @At(value = "INVOKE", +// target = "Lnet/minecraft/client/renderer/LevelRenderer;renderDebug(net/minecraft/client/Camera;)V", ordinal = 0)) +// private void customRenderLevel2(CallbackInfo ci) { +// ClientEvents.getDelayedRender().endBatch(RenderUtil.VAPOR_TRANSLUCENT); +// ClientEvents.getDelayedRender().endBatch(RenderUtil.GLOWING_BLOCK_PARTICLE); +// } } diff --git a/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java b/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java index bc12110..40194ef 100644 --- a/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java +++ b/src/main/java/elucent/eidolon/mixin/LivingEntityMixin.java @@ -1,36 +1,37 @@ package elucent.eidolon.mixin; +import java.util.Optional; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; -import elucent.eidolon.event.SpeedFactorEvent; -import elucent.eidolon.item.ReaperScytheItem; -import net.minecraft.world.entity.Entity; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.item.IWingsItem; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraftforge.common.MinecraftForge; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; @Mixin(LivingEntity.class) public class LivingEntityMixin { - @Inject(method = "getSpeedFactor()F", at = @At("RETURN"), cancellable = true) - private void customGetSpeedFactor(CallbackInfoReturnable cir) { - float factor = cir.getReturnValue(); - SpeedFactorEvent event = new SpeedFactorEvent((Entity)(Object)this, factor); - MinecraftForge.EVENT_BUS.post(event); - cir.setReturnValue(event.getSpeedFactor()); + @Inject(method = "getMobType", at = @At("HEAD"), cancellable = true) + public void getMobType(CallbackInfoReturnable ci) { + if (((LivingEntity)(Object)this).hasEffect(Registry.UNDEATH_EFFECT.get()) && !Eidolon.trueMobType) { + ci.setReturnValue(MobType.UNDEAD); + } } - @Inject(method = "dropFromLootTable", at = @At("HEAD"), cancellable = true) - protected void customDropFromLootTable(DamageSource source, boolean hitRecently, CallbackInfo ci) { - if (((LivingEntity)(Object)this).isInvertedHealAndHarm() - && (source.getMsgId() == Registry.RITUAL_DAMAGE.getMsgId() - || source.getEntity() instanceof LivingEntity - && ((LivingEntity) source.getEntity()).getMainHandItem().getItem() instanceof ReaperScytheItem)) { - ci.cancel(); - } + @Inject(method = "isFallFlying", at = @At("HEAD"), cancellable = true) + public void isFallFlying(CallbackInfoReturnable ci) { + if ((LivingEntity)(Object)this instanceof Player p) { + Optional opt = p.getCapability(IPlayerData.INSTANCE).resolve(); + if (opt.isPresent() && opt.get().isDashing(p)) ci.setReturnValue(true); + } } } diff --git a/src/main/java/elucent/eidolon/mixin/LocalPlayerMixin.java b/src/main/java/elucent/eidolon/mixin/LocalPlayerMixin.java new file mode 100644 index 0000000..ca0e671 --- /dev/null +++ b/src/main/java/elucent/eidolon/mixin/LocalPlayerMixin.java @@ -0,0 +1,30 @@ +package elucent.eidolon.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import elucent.eidolon.ClientEvents; +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobType; + +@Mixin(LocalPlayer.class) +public class LocalPlayerMixin { + @Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true) + public void getJumpRidingScale(CallbackInfoReturnable ci) { + if (ClientEvents.jumpTicks >= 5) + ci.setReturnValue((ClientEvents.jumpTicks - 5 + Minecraft.getInstance().getFrameTime()) / 15.0f); + } + + @Inject(method = "isRidingJumpable", at = @At("HEAD"), cancellable = true) + public void isRidingJumpable(CallbackInfoReturnable ci) { + if (ClientEvents.jumpTicks >= 5 && ClientEvents.isInGui) ci.setReturnValue(true); + } +} diff --git a/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java b/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java index 48a38c1..8800d3b 100644 --- a/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java +++ b/src/main/java/elucent/eidolon/mixin/PlayerRendererMixin.java @@ -12,6 +12,6 @@ public class PlayerRendererMixin { @Inject(method = "", at = @At("RETURN"), cancellable = true) public void constructor(CallbackInfo ci) { - // ((PlayerRenderer)(Object)this).addLayer(new RavenVariantLayer<>(((PlayerRenderer)(Object)this))); + ((PlayerRenderer)(Object)this).addLayer(new RavenVariantLayer<>(((PlayerRenderer)(Object)this))); } } diff --git a/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java b/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java index 7264d7c..4448bce 100644 --- a/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java +++ b/src/main/java/elucent/eidolon/mixin/StructureSettingsMixin.java @@ -2,18 +2,14 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; -import net.minecraft.world.entity.monster.ZombieVillager; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.StructureSettings; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.StructureFeature; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; @Mixin(StructureSettings.class) public interface StructureSettingsMixin { diff --git a/src/main/java/elucent/eidolon/network/AttemptCastPacket.java b/src/main/java/elucent/eidolon/network/AttemptCastPacket.java index 92dba22..1fc6dcc 100644 --- a/src/main/java/elucent/eidolon/network/AttemptCastPacket.java +++ b/src/main/java/elucent/eidolon/network/AttemptCastPacket.java @@ -7,8 +7,11 @@ import elucent.eidolon.capability.IKnowledge; import elucent.eidolon.entity.ChantCasterEntity; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; import elucent.eidolon.spell.Sign; import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; import net.minecraft.world.entity.player.Player; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -17,33 +20,31 @@ import net.minecraftforge.network.NetworkEvent; import net.minecraft.world.level.Level; - - public class AttemptCastPacket { - List signs = new ArrayList<>(); + List runes = new ArrayList<>(); UUID uuid; - public AttemptCastPacket(Player player, List signs) { - this.signs.addAll(signs); + public AttemptCastPacket(Player player, List runes) { + this.runes.addAll(runes); this.uuid = player.getUUID(); } - public AttemptCastPacket(UUID uuid, List signs) { - this.signs.addAll(signs); + public AttemptCastPacket(UUID uuid, List runes) { + this.runes.addAll(runes); this.uuid = uuid; } public static void encode(AttemptCastPacket object, FriendlyByteBuf buffer) { - buffer.writeInt(object.signs.size()); - for (int i = 0; i < object.signs.size(); i ++) buffer.writeUtf(object.signs.get(i).getRegistryName().toString(), 255); + buffer.writeInt(object.runes.size()); + for (int i = 0; i < object.runes.size(); i ++) buffer.writeUtf(object.runes.get(i).getRegistryName().toString(), 255); buffer.writeUUID(object.uuid); } public static AttemptCastPacket decode(FriendlyByteBuf buffer) { int n = buffer.readInt(); - List signs = new ArrayList<>(); - for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readUtf(255)))); - return new AttemptCastPacket(buffer.readUUID(), signs); + List runes = new ArrayList<>(); + for (int i = 0; i < n; i ++) runes.add(Runes.find(new ResourceLocation(buffer.readUtf(255)))); + return new AttemptCastPacket(buffer.readUUID(), runes); } public static void consume(AttemptCastPacket packet, Supplier ctx) { @@ -54,11 +55,10 @@ public static void consume(AttemptCastPacket packet, Supplier signs = packet.signs; - IKnowledge knowledge = player.getCapability(IKnowledge.INSTANCE, null).resolve().get(); - for (Sign sign : signs) if (!knowledge.knowsSign(sign)) return; - Vec3 placement = player.position().add(0, player.getBbHeight() * 2 / 3, 0).add(player.getLookAngle()); - ChantCasterEntity entity = new ChantCasterEntity(world, player, signs); + List runes = packet.runes; + for (Rune rune : runes) if (!KnowledgeUtil.knowsRune(player, rune)) return; + Vec3 placement = player.position().add(0, player.getBbHeight() * 2 / 3, 0).add(player.getLookAngle().scale(0.5f)); + ChantCasterEntity entity = new ChantCasterEntity(world, player, runes, player.getLookAngle()); entity.setPos(placement.x, placement.y, placement.z); world.addFreshEntity(entity); } diff --git a/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java b/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java index 3c402f0..881085a 100644 --- a/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/ChilledEffectPacket.java @@ -14,8 +14,6 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.level.Level; - - public class ChilledEffectPacket { double x, y, z; diff --git a/src/main/java/elucent/eidolon/network/DeathbringerSlashEffectPacket.java b/src/main/java/elucent/eidolon/network/DeathbringerSlashEffectPacket.java new file mode 100644 index 0000000..407f1ce --- /dev/null +++ b/src/main/java/elucent/eidolon/network/DeathbringerSlashEffectPacket.java @@ -0,0 +1,153 @@ +package elucent.eidolon.network; + +import java.util.function.Supplier; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.particle.Particles; +import elucent.eidolon.particle.SlashParticleData; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.Mth; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + +public class DeathbringerSlashEffectPacket { + float x1, y1, z1, x2, y2, z2; + int c1, c2, c3, c4; + + public DeathbringerSlashEffectPacket(double x1, double y1, double z1, double x2, double y2, double z2, int color1, int color2, int color3, int color4) { + this.x1 = (float)x1; + this.y1 = (float)y1; + this.z1 = (float)z1; + this.x2 = (float)x2; + this.y2 = (float)y2; + this.z2 = (float)z2; + this.c1 = color1; + this.c2 = color2; + this.c3 = color3; + this.c4 = color4; + } + + public static void encode(DeathbringerSlashEffectPacket object, FriendlyByteBuf buffer) { + buffer.writeFloat(object.x1).writeFloat(object.y1).writeFloat(object.z1); + buffer.writeFloat(object.x2).writeFloat(object.y2).writeFloat(object.z2); + buffer.writeInt(object.c1).writeInt(object.c2).writeInt(object.c3).writeInt(object.c4); + } + + public static DeathbringerSlashEffectPacket decode(FriendlyByteBuf buffer) { + return new DeathbringerSlashEffectPacket(buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), + buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readInt()); + } + + public static void consume(DeathbringerSlashEffectPacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; + + Level world = Eidolon.proxy.getWorld(); + if (world != null) { + double x = packet.x2, y = packet.y2, z = packet.z2; + + float r1 = ColorUtil.getRed(packet.c1) / 255.0f, g1 = ColorUtil.getGreen(packet.c1) / 255.0f, b1 = ColorUtil.getBlue(packet.c1) / 255.0f; + float r2 = ColorUtil.getRed(packet.c2) / 255.0f, g2 = ColorUtil.getGreen(packet.c2) / 255.0f, b2 = ColorUtil.getBlue(packet.c2) / 255.0f; + + float roll = Mth.PI / 6 - world.random.nextFloat() * (Mth.PI * 7 / 6); + float scale = 1.0f + world.random.nextFloat() * 0.2f; + + Vec3 horiz = new Vec3(x - packet.x1, 0, z - packet.z1); + float yaw = (float)Mth.atan2(x - packet.x1, z - packet.z1); + float pitch = (float)Mth.atan2(y - packet.y1, horiz.length()); + float right = yaw + Mth.PI / 2, up = pitch + Mth.PI / 2; + float sy = Mth.sin(yaw), cy = Mth.cos(yaw), sp = Mth.sin(pitch), cp = Mth.cos(pitch); + float sr = Mth.sin(right), cr = Mth.cos(right), su = Mth.sin(up), cu = Mth.cos(up); + float r = 0.5f; + float xax = r * sr * cp, xay = 0, xaz = r * cr * cp; + float yax = r * sy * cu, yay = r * su, yaz = r * cy * cu; + float zax = r * sy * cp, zay = r * sp, zaz = r * cy * cp; + float cro = Mth.cos(roll), sro = Mth.sin(roll); + float nxax = xax * cro - yax * sro; + float nxay = xay * cro - yay * sro; + float nxaz = xaz * cro - yaz * sro; + yax = xax * sro + yax * cro; + yay = xay * sro + yay * cro; + yaz = xaz * sro + yaz * cro; + xax = nxax; + xay = nxay; + xaz = nxaz; + for (float i = 0; i < 6; i ++) { + float c1 = (i + 0.5f) / 6; + float angle = -75 + c1 * 150; + float sa = Mth.sin(Mth.DEG_TO_RAD * angle), ca = Mth.cos(Mth.DEG_TO_RAD * angle); + float dx = sa * xax + ca * zax, dy = sa * xay + ca * zay, dz = sa * xaz + ca * zaz; + Particles.create(Registry.SMOKE_PARTICLE) + .randomVelocity(0.025f) + .addVelocity(dx * 0.25f, dy * 0.25f, dz * 0.25f) + .setColor(33.0f/255, 26.0f/255, 23.0f/255, 0.125f, 10.0f/255, 10.0f/255, 12.0f/255, 0) + .randomOffset(0.1f) + .setScale(0.375f, 0.125f) + .repeat(world, x - sy * cp + dx, y - sp + dy, z - cy * cp + dz, 4); + } + + SlashParticleData.create(Registry.GLOWING_SLASH_PARTICLE.get()) + .lookat(packet.x1, packet.y1, packet.z1, x, y, z) + .color(r1, g1, b1, r2, g2, b2) + .radius(0.9f * scale) + .angle(250) + .width(1f * scale) + .roll(roll) + .lifetime(11) + .spawn(world, x, y, z, 0, 0, 0); + + SlashParticleData.create(Registry.GLOWING_SLASH_PARTICLE.get()) + .lookat(packet.x1, packet.y1, packet.z1, x, y, z) + .color(r1, g1, b1, r2, g2, b2) + .radius(0.8f * scale) + .angle(250) + .width(0.75f * scale) + .roll(roll) + .lifetime(11) + .spawn(world, x, y, z, 0, 0, 0); + + SlashParticleData.create(Registry.GLOWING_SLASH_PARTICLE.get()) + .lookat(packet.x1, packet.y1, packet.z1, x, y, z) + .color(r1, g1, b1, r2, g2, b2) + .radius(0.7f * scale) + .angle(250) + .width(0.5f * scale) + .roll(roll) + .lifetime(13) + .spawn(world, x, y, z, 0, 0, 0); + + r1 = ColorUtil.getRed(packet.c3) / 255.0f; g1 = ColorUtil.getGreen(packet.c3) / 255.0f; b1 = ColorUtil.getBlue(packet.c3) / 255.0f; + r2 = ColorUtil.getRed(packet.c4) / 255.0f; g2 = ColorUtil.getGreen(packet.c4) / 255.0f; b2 = ColorUtil.getBlue(packet.c4) / 255.0f; + + SlashParticleData.create(Registry.GLOWING_SLASH_PARTICLE.get()) + .lookat(packet.x1, packet.y1, packet.z1, x, y, z) + .color(r1, g1, b1, r2, g2, b2) + .radius(0.8f * scale) + .angle(210) + .width(0.625f * scale) + .highlight(0.75f) + .alpha(0.75f, 0) + .roll(roll) + .lifetime(8) + .spawn(world, x, y, z, 0, 0, 0); + + SlashParticleData.create(Registry.GLOWING_SLASH_PARTICLE.get()) + .lookat(packet.x1, packet.y1, packet.z1, x, y, z) + .color(r1, g1, b1, r2, g2, b2) + .radius(0.9f * scale) + .angle(210) + .width(0.25f * scale) + .highlight(0.625f) + .roll(roll) + .lifetime(10) + .spawn(world, x, y, z, 0, 0, 0); + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java b/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java index 4d8622a..430967d 100644 --- a/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/ExtinguishEffectPacket.java @@ -13,8 +13,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class ExtinguishEffectPacket { BlockPos pos; diff --git a/src/main/java/elucent/eidolon/network/FlameEffectPacket.java b/src/main/java/elucent/eidolon/network/FlameEffectPacket.java index cc5be8d..14198af 100644 --- a/src/main/java/elucent/eidolon/network/FlameEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/FlameEffectPacket.java @@ -13,8 +13,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class FlameEffectPacket { BlockPos pos; float r, g, b; diff --git a/src/main/java/elucent/eidolon/network/IgniteEffectPacket.java b/src/main/java/elucent/eidolon/network/IgniteEffectPacket.java index bc715e0..a030d6d 100644 --- a/src/main/java/elucent/eidolon/network/IgniteEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/IgniteEffectPacket.java @@ -13,8 +13,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class IgniteEffectPacket { BlockPos pos; float r, g, b; diff --git a/src/main/java/elucent/eidolon/network/KnowledgeUpdatePacket.java b/src/main/java/elucent/eidolon/network/KnowledgeUpdatePacket.java index 3dff18d..7f57616 100644 --- a/src/main/java/elucent/eidolon/network/KnowledgeUpdatePacket.java +++ b/src/main/java/elucent/eidolon/network/KnowledgeUpdatePacket.java @@ -14,8 +14,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class KnowledgeUpdatePacket { UUID uuid; CompoundTag tag; diff --git a/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java b/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java index f6eb9c7..dce6447 100644 --- a/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/LifestealEffectPacket.java @@ -11,8 +11,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class LifestealEffectPacket { BlockPos src, dst; float r, g, b; diff --git a/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java b/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java index ac16321..ad8a2d4 100644 --- a/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java +++ b/src/main/java/elucent/eidolon/network/MagicBurstEffectPacket.java @@ -12,8 +12,6 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; - - public class MagicBurstEffectPacket { float x, y, z; int c1, c2; diff --git a/src/main/java/elucent/eidolon/network/Networking.java b/src/main/java/elucent/eidolon/network/Networking.java index caa68c7..1fe50e8 100644 --- a/src/main/java/elucent/eidolon/network/Networking.java +++ b/src/main/java/elucent/eidolon/network/Networking.java @@ -138,6 +138,54 @@ public static void init() { SpellCastPacket::decode, SpellCastPacket::consume ); + + INSTANCE.registerMessage( + ++ id, + ResearchActionPacket.class, + ResearchActionPacket::encode, + ResearchActionPacket::decode, + ResearchActionPacket::consume + ); + + INSTANCE.registerMessage( + ++ id, + DeathbringerSlashEffectPacket.class, + DeathbringerSlashEffectPacket::encode, + DeathbringerSlashEffectPacket::decode, + DeathbringerSlashEffectPacket::consume + ); + + INSTANCE.registerMessage( + ++ id, + SoulUpdatePacket.class, + SoulUpdatePacket::encode, + SoulUpdatePacket::decode, + SoulUpdatePacket::consume + ); + + INSTANCE.registerMessage( + ++ id, + WingsFlapPacket.class, + WingsFlapPacket::encode, + WingsFlapPacket::decode, + WingsFlapPacket::consume + ); + + INSTANCE.registerMessage( + ++ id, + WingsDashPacket.class, + WingsDashPacket::encode, + WingsDashPacket::decode, + WingsDashPacket::consume + ); + + INSTANCE.registerMessage( + ++ id, + WingsDataUpdatePacket.class, + WingsDataUpdatePacket::encode, + WingsDataUpdatePacket::decode, + WingsDataUpdatePacket::consume + ); } public static void sendToDimension(Level world, MSG msg, ResourceKey dimension) { diff --git a/src/main/java/elucent/eidolon/network/ResearchActionPacket.java b/src/main/java/elucent/eidolon/network/ResearchActionPacket.java new file mode 100644 index 0000000..183ffa3 --- /dev/null +++ b/src/main/java/elucent/eidolon/network/ResearchActionPacket.java @@ -0,0 +1,68 @@ +package elucent.eidolon.network; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; + +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.entity.ChantCasterEntity; +import elucent.eidolon.gui.ResearchTableContainer; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.world.level.Level; + +public class ResearchActionPacket { + public static enum Action { + SUBMIT_GOAL, STAMP + } + Action action; + int index; + + public ResearchActionPacket(Action action, int index) { + this.action = action; + this.index = index; + } + + public ResearchActionPacket(Action action) { + this(action, 0); + } + + public static void encode(ResearchActionPacket object, FriendlyByteBuf buffer) { + buffer.writeInt(object.action.ordinal()); + buffer.writeInt(object.index); + } + + public static ResearchActionPacket decode(FriendlyByteBuf buffer) { + Action action = Action.values()[buffer.readInt()]; + int index = buffer.readInt(); + return new ResearchActionPacket(action, index); + } + + public static void consume(ResearchActionPacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_SERVER; + + ServerPlayer player = ctx.get().getSender(); + AbstractContainerMenu menu = player.containerMenu; + Level world = ctx.get().getSender().level; + if (world != null && menu instanceof ResearchTableContainer rc) { + if (packet.action == Action.SUBMIT_GOAL) { + rc.trySubmitGoal(player, packet.index); + } + else if (packet.action == Action.STAMP) { + rc.tryStamp(player); + } + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/network/SoulUpdatePacket.java b/src/main/java/elucent/eidolon/network/SoulUpdatePacket.java new file mode 100644 index 0000000..50c9f9a --- /dev/null +++ b/src/main/java/elucent/eidolon/network/SoulUpdatePacket.java @@ -0,0 +1,82 @@ +package elucent.eidolon.network; + +import java.util.UUID; +import java.util.function.Supplier; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.ISoul; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + +public class SoulUpdatePacket { + boolean isPlayer; + UUID uuid; + int id; + CompoundTag tag; + + public SoulUpdatePacket(int id, CompoundTag tag) { + this.isPlayer = false; + this.id = id; + this.tag = tag; + } + + public SoulUpdatePacket(UUID uuid, CompoundTag tag) { + this.isPlayer = true; + this.uuid = uuid; + this.tag = tag; + } + + public SoulUpdatePacket(LivingEntity entity) { + this.isPlayer = entity instanceof Player; + if (isPlayer) this.uuid = entity.getUUID(); + else this.id = entity.getId(); + entity.getCapability(ISoul.INSTANCE, null).ifPresent((k) -> { + this.tag = ((INBTSerializable)k).serializeNBT(); + }); + } + + public SoulUpdatePacket(Player entity) { + this.isPlayer = true; + this.uuid = entity.getUUID(); + entity.getCapability(ISoul.INSTANCE, null).ifPresent((k) -> { + this.tag = ((INBTSerializable)k).serializeNBT(); + }); + } + + public static void encode(SoulUpdatePacket object, FriendlyByteBuf buffer) { + buffer.writeBoolean(object.isPlayer); + if (object.isPlayer) buffer.writeUUID(object.uuid); + else buffer.writeInt(object.id); + buffer.writeNbt(object.tag); + } + + public static SoulUpdatePacket decode(FriendlyByteBuf buffer) { + if (buffer.readBoolean()) { + return new SoulUpdatePacket(buffer.readUUID(), buffer.readNbt()); + } + else return new SoulUpdatePacket(buffer.readInt(), buffer.readNbt()); + } + + public static void consume(SoulUpdatePacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; + + Level world = Eidolon.proxy.getWorld(); + LivingEntity e = packet.isPlayer ? world.getPlayerByUUID(packet.uuid) : (LivingEntity)world.getEntity(packet.id); + if (e != null) { + e.getCapability(ISoul.INSTANCE, null).ifPresent((k) -> { + ((INBTSerializable)k).deserializeNBT(packet.tag); + }); + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/network/SpellCastPacket.java b/src/main/java/elucent/eidolon/network/SpellCastPacket.java index aa4b380..2a1d2f0 100644 --- a/src/main/java/elucent/eidolon/network/SpellCastPacket.java +++ b/src/main/java/elucent/eidolon/network/SpellCastPacket.java @@ -7,6 +7,7 @@ import elucent.eidolon.Eidolon; import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.SignSequence; import elucent.eidolon.spell.Signs; import elucent.eidolon.spell.Spell; import elucent.eidolon.spell.Spells; @@ -19,20 +20,20 @@ import net.minecraftforge.network.NetworkEvent; public class SpellCastPacket { - List signs = new ArrayList<>(); + SignSequence seq; Spell spell; BlockPos pos; UUID uuid; - public SpellCastPacket(Player player, BlockPos pos, Spell spell, List signs) { - this.signs.addAll(signs); + public SpellCastPacket(Player player, BlockPos pos, Spell spell, SignSequence seq) { + this.seq = seq; this.pos = pos; this.spell = spell; this.uuid = player.getUUID(); } - public SpellCastPacket(UUID uuid, BlockPos pos, ResourceLocation location, List signs) { - this.signs.addAll(signs); + public SpellCastPacket(UUID uuid, BlockPos pos, ResourceLocation location, SignSequence seq) { + this.seq = seq; this.pos = pos; this.spell = Spells.find(location); this.uuid = uuid; @@ -40,18 +41,15 @@ public SpellCastPacket(UUID uuid, BlockPos pos, ResourceLocation location, List< public static void encode(SpellCastPacket object, FriendlyByteBuf buffer) { buffer.writeUtf(object.spell.getRegistryName().toString()); - buffer.writeInt(object.signs.size()); - for (int i = 0; i < object.signs.size(); i ++) buffer.writeUtf(object.signs.get(i).getRegistryName().toString()); + buffer.writeNbt(object.seq.serializeNbt()); buffer.writeUUID(object.uuid); buffer.writeBlockPos(object.pos); } public static SpellCastPacket decode(FriendlyByteBuf buffer) { ResourceLocation spell = new ResourceLocation(buffer.readUtf()); - int n = buffer.readInt(); - List signs = new ArrayList<>(); - for (int i = 0; i < n; i ++) signs.add(Signs.find(new ResourceLocation(buffer.readUtf()))); - return new SpellCastPacket(buffer.readUUID(), buffer.readBlockPos(), spell, signs); + SignSequence seq = SignSequence.deserializeNbt(buffer.readNbt()); + return new SpellCastPacket(buffer.readUUID(), buffer.readBlockPos(), spell, seq); } public static void consume(SpellCastPacket packet, Supplier ctx) { @@ -62,7 +60,7 @@ public static void consume(SpellCastPacket packet, Supplier signs = packet.signs; + SignSequence signs = packet.seq; packet.spell.cast(world, packet.pos, player, signs); } } diff --git a/src/main/java/elucent/eidolon/network/WingsDashPacket.java b/src/main/java/elucent/eidolon/network/WingsDashPacket.java new file mode 100644 index 0000000..351a86e --- /dev/null +++ b/src/main/java/elucent/eidolon/network/WingsDashPacket.java @@ -0,0 +1,61 @@ +package elucent.eidolon.network; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; + +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.entity.ChantCasterEntity; +import elucent.eidolon.item.IWingsItem; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.world.level.Level; + +public class WingsDashPacket { + UUID uuid; + + public WingsDashPacket(Player player) { + this.uuid = player.getUUID(); + } + + public WingsDashPacket(UUID uuid) { + this.uuid = uuid; + } + + public static void encode(WingsDashPacket object, FriendlyByteBuf buffer) { + buffer.writeUUID(object.uuid); + } + + public static WingsDashPacket decode(FriendlyByteBuf buffer) { + return new WingsDashPacket(buffer.readUUID()); + } + + public static void consume(WingsDashPacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_SERVER; + + Level world = ctx.get().getSender().level; + if (world != null) { + Player player = world.getPlayerByUUID(packet.uuid); + if (player != null) { + player.getCapability(IPlayerData.INSTANCE).ifPresent((d) -> { + d.tryDash(player); + }); + } + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/network/WingsDataUpdatePacket.java b/src/main/java/elucent/eidolon/network/WingsDataUpdatePacket.java new file mode 100644 index 0000000..ded5db0 --- /dev/null +++ b/src/main/java/elucent/eidolon/network/WingsDataUpdatePacket.java @@ -0,0 +1,71 @@ +package elucent.eidolon.network; + +import java.util.UUID; +import java.util.function.Supplier; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.capability.ISoul; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; + +public class WingsDataUpdatePacket { + UUID uuid; + long lastFlapTime; + int dashTicks; + boolean isFlying; + + public WingsDataUpdatePacket(Player player) { + this.uuid = player.getUUID(); + player.getCapability(IPlayerData.INSTANCE).ifPresent((d) -> { + lastFlapTime = d.getLastFlapTime(player); + dashTicks = d.getDashTicks(player); + isFlying = d.isFlying(player); + }); + } + + public WingsDataUpdatePacket(UUID uuid, long lastFlapTime, int dashTicks, boolean isFlying) { + this.uuid = uuid; + this.lastFlapTime = lastFlapTime; + this.dashTicks = dashTicks; + this.isFlying = isFlying; + } + + public static void encode(WingsDataUpdatePacket object, FriendlyByteBuf buffer) { + buffer.writeUUID(object.uuid); + buffer.writeLong(object.lastFlapTime); + buffer.writeInt(object.dashTicks); + buffer.writeBoolean(object.isFlying); + } + + public static WingsDataUpdatePacket decode(FriendlyByteBuf buffer) { + return new WingsDataUpdatePacket(buffer.readUUID(), buffer.readLong(), buffer.readInt(), buffer.readBoolean()); + } + + public static void consume(WingsDataUpdatePacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT; + + Level world = Eidolon.proxy.getWorld(); + Player p = world.getPlayerByUUID(packet.uuid); + if (p != null && p != Minecraft.getInstance().player) { + p.getCapability(IPlayerData.INSTANCE, null).ifPresent((d) -> { + if (packet.isFlying && !d.isFlying(p)) d.startFlying(p); + else if (!packet.isFlying && d.isFlying(p)) d.stopFlying(p); + d.setLastFlapTime(packet.lastFlapTime); + d.setDashTicks(packet.dashTicks); + }); + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/network/WingsFlapPacket.java b/src/main/java/elucent/eidolon/network/WingsFlapPacket.java new file mode 100644 index 0000000..f86941f --- /dev/null +++ b/src/main/java/elucent/eidolon/network/WingsFlapPacket.java @@ -0,0 +1,61 @@ +package elucent.eidolon.network; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; + +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.capability.IPlayerData; +import elucent.eidolon.entity.ChantCasterEntity; +import elucent.eidolon.item.IWingsItem; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import elucent.eidolon.util.KnowledgeUtil; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraft.world.level.Level; + +public class WingsFlapPacket { + UUID uuid; + + public WingsFlapPacket(Player player) { + this.uuid = player.getUUID(); + } + + public WingsFlapPacket(UUID uuid) { + this.uuid = uuid; + } + + public static void encode(WingsFlapPacket object, FriendlyByteBuf buffer) { + buffer.writeUUID(object.uuid); + } + + public static WingsFlapPacket decode(FriendlyByteBuf buffer) { + return new WingsFlapPacket(buffer.readUUID()); + } + + public static void consume(WingsFlapPacket packet, Supplier ctx) { + ctx.get().enqueueWork(() -> { + assert ctx.get().getDirection() == NetworkDirection.PLAY_TO_SERVER; + + Level world = ctx.get().getSender().level; + if (world != null) { + Player player = world.getPlayerByUUID(packet.uuid); + if (player != null) { + player.getCapability(IPlayerData.INSTANCE).ifPresent((d) -> { + d.tryFlapWings(player); + }); + } + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/elucent/eidolon/particle/GenericParticleData.java b/src/main/java/elucent/eidolon/particle/GenericParticleData.java index 3f0fcbc..79611b2 100644 --- a/src/main/java/elucent/eidolon/particle/GenericParticleData.java +++ b/src/main/java/elucent/eidolon/particle/GenericParticleData.java @@ -9,8 +9,6 @@ import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; -import net.minecraft.core.particles.ParticleOptions.Deserializer; - public class GenericParticleData implements ParticleOptions { float r1 = 1, g1 = 1, b1 = 1, a1 = 1, r2 = 1, g2 = 1, b2 = 1, a2 = 0; float scale1 = 1, scale2 = 0; diff --git a/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java b/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java index fbd1722..2168eca 100644 --- a/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/GlowParticleRenderType.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Registry; import elucent.eidolon.util.RenderUtil; import net.minecraft.client.Minecraft; @@ -24,7 +25,7 @@ private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManage RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); - RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShader(ClientRegistry::getGlowingSpriteShader); RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); diff --git a/src/main/java/elucent/eidolon/particle/GlowingSlashParticle.java b/src/main/java/elucent/eidolon/particle/GlowingSlashParticle.java new file mode 100644 index 0000000..08552eb --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/GlowingSlashParticle.java @@ -0,0 +1,158 @@ +package elucent.eidolon.particle; + +import java.awt.Color; + +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.ClientConfig; +import elucent.eidolon.ClientEvents; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.particle.TextureSheetParticle; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; + +public class GlowingSlashParticle extends TextureSheetParticle { + SlashParticleData data; + float[] hsv1 = new float[3], hsv2 = new float[3]; + public GlowingSlashParticle(ClientLevel world, SlashParticleData data, double x, double y, double z, double vx, double vy, double vz) { + super(world, x, y, z, vx, vy, vz); + this.setPos(x, y, z); + this.data = data; + this.xd = vx; + this.yd = vy; + this.zd = vz; + this.setLifetime(data.lifetime); + Vec3 dir = Vec3.directionFromRotation(Mth.RAD_TO_DEG * -data.pitch, Mth.RAD_TO_DEG * -data.yaw); + xd += dir.x * (0.025f + world.random.nextFloat() * 0.025f); + yd += dir.y * (0.025f + world.random.nextFloat() * 0.025f); + zd += dir.z * (0.025f + world.random.nextFloat() * 0.025f); + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r1)), (int)(255 * Math.min(1.0f, data.g1)), (int)(255 * Math.min(1.0f, data.b1)), hsv1); + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r2)), (int)(255 * Math.min(1.0f, data.g2)), (int)(255 * Math.min(1.0f, data.b2)), hsv2); + updateTraits(); + } + + protected float getCoeff() { + return (float)this.age / this.lifetime; + } + + protected float getCoeff(float pticks) { + return ((float)this.age + pticks) / this.lifetime; + } + + protected float getSqInvCoeff(float pticks) { + float inv = (this.lifetime - (float)this.age + pticks) / this.lifetime; + return inv * inv; + } + + protected void updateTraits() { + float coeff = getCoeff(); + float h = Mth.rotLerp(coeff, 360 * hsv1[0], 360 * hsv2[0]) / 360; + float s = Mth.lerp(coeff, hsv1[1], hsv2[1]); + float v = Mth.lerp(coeff, hsv1[2], hsv2[2]); + int packed = Color.HSBtoRGB(h, s, v); + float r = FastColor.ARGB32.red(packed) / 255.0f; + float g = FastColor.ARGB32.green(packed) / 255.0f; + float b = FastColor.ARGB32.blue(packed) / 255.0f; + setColor(r, g, b); + setAlpha(Mth.lerp(coeff, data.a1, data.a2)); + } + + @Override + public void tick() { + updateTraits(); + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return GlowParticleRenderType.INSTANCE; + } + + private void decoVert(VertexConsumer vc, float u, float v, float alpha, int lmap) { + vc.uv(u, v).color(rCol, gCol, bCol, alpha).uv2(lmap).endVertex(); + } + + @Override + public void render(VertexConsumer vc, Camera info, float pticks) { + VertexConsumer b = ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.DELAYED_PARTICLE) : vc; + + float x = (float)(Mth.lerp((double)pticks, this.xo, this.x) - info.getPosition().x()); + float y = (float)(Mth.lerp((double)pticks, this.yo, this.y) - info.getPosition().y()); + float z = (float)(Mth.lerp((double)pticks, this.zo, this.z) - info.getPosition().z()); + float sy = Mth.sin(data.yaw), cy = Mth.cos(data.yaw), sp = Mth.sin(data.pitch), cp = Mth.cos(data.pitch); + float ox = x - sy * cp * data.rad, oy = y - sp * data.rad, oz = z - cy * cp * data.rad; + + float right = data.yaw + Mth.PI / 2, up = data.pitch + Mth.PI / 2; + float sr = Mth.sin(right), cr = Mth.cos(right), su = Mth.sin(up), cu = Mth.cos(up); + float r = data.rad; + float xax = r * sr * cp, xay = 0, xaz = r * cr * cp; + float yax = r * sy * cu, yay = r * su, yaz = r * cy * cu; + float zax = r * sy * cp, zay = r * sp, zaz = r * cy * cp; + float cro = Mth.cos(data.roll), sro = Mth.sin(data.roll); + float nxax = xax * cro - yax * sro; + float nxay = xay * cro - yay * sro; + float nxaz = xaz * cro - yaz * sro; + yax = xax * sro + yax * cro; + yay = xay * sro + yay * cro; + yaz = xaz * sro + yaz * cro; + xax = nxax; + xay = nxay; + xaz = nxaz; + float u0 = this.getU0(); + float u1 = this.getU1(); + float v0 = this.getV0(); + float v1 = this.getV1(); + int lmap = getLightColor(pticks); + float w = data.width / 2; + + float hlangle = -data.angle / 2 + getSqInvCoeff(pticks) * data.angle; + float hlwidth = 4 + 4 * getSqInvCoeff(pticks); + for (float i = 0; i < 18; i ++) { + float c1 = i / 18, c2 = (i + 1) / 18; + float basea = this.alpha - data.highlight; + float angle1 = -data.angle / 2 + c1 * data.angle, angle2 = -data.angle / 2 + c2 * data.angle; + float al1 = Mth.sin(c1 * Mth.PI), al2 = Mth.sin(c2 * Mth.PI); + float dangle1 = Mth.clamp((angle1 - hlangle) / data.angle, -1 / hlwidth, 1 / hlwidth), dangle2 = Mth.clamp((angle2 - hlangle) / data.angle, -1 / hlwidth, 1 / hlwidth); + float hl1 = (Mth.cos(hlwidth * Mth.PI * dangle1) + 1) / 2, hl2 = (Mth.cos(hlwidth * Mth.PI * dangle2) + 1) / 2; + al1 = (1 - data.highlight) * al1 + data.highlight * hl1; + al2 = (1 - data.highlight) * al2 + data.highlight * hl2; + al1 *= alpha; + al2 *= alpha; + float w1 = w * (0.25f + 0.75f * Mth.sin(c1 * Mth.PI)), w2 = w * (0.25f + 0.75f * Mth.sin(c2 * Mth.PI)); + w1 += data.highlight * 0.25f * w * hl1; + w2 += data.highlight * 0.25f * w * hl2; + + float sa1 = Mth.sin(angle1), ca1 = Mth.cos(angle1), sa2 = Mth.sin(angle2), ca2 = Mth.cos(angle2); + float dx1 = sa1 * xax + ca1 * zax, dy1 = sa1 * xay + ca1 * zay, dz1 = sa1 * xaz + ca1 * zaz; + float dx2 = sa2 * xax + ca2 * zax, dy2 = sa2 * xay + ca2 * zay, dz2 = sa2 * xaz + ca2 * zaz; + + // horiz + decoVert(b.vertex(ox + dx2 * r + dx2 * w2, oy + dy2 * r + dy2 * w2, oz + dz2 * r + dz2 * w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + dx2 * -w2, oy + dy2 * r + dy2 * -w2, oz + dz2 * r + dz2 * -w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * -w1, oy + dy1 * r + dy1 * -w1, oz + dz1 * r + dz1 * -w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * w1, oy + dy1 * r + dy1 * w1, oz + dz1 * r + dz1 * w1), u0, v1, al1, lmap); + + // horiz back + decoVert(b.vertex(ox + dx2 * r + dx2 * -w2, oy + dy2 * r + dy2 * -w2, oz + dz2 * r + dz2 * -w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + dx2 * w2, oy + dy2 * r + dy2 * w2, oz + dz2 * r + dz2 * w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * w1, oy + dy1 * r + dy1 * w1, oz + dz1 * r + dz1 * w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * -w1, oy + dy1 * r + dy1 * -w1, oz + dz1 * r + dz1 * -w1), u0, v1, al1, lmap); + + // vert + decoVert(b.vertex(ox + dx2 * r + yax * w2, oy + dy2 * r + yay * w2, oz + dz2 * r + yaz * w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + yax * -w2, oy + dy2 * r + yay * -w2, oz + dz2 * r + yaz * -w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * -w1, oy + dy1 * r + yay * -w1, oz + dz1 * r + yaz * -w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * w1, oy + dy1 * r + yay * w1, oz + dz1 * r + yaz * w1), u0, v1, al1, lmap); + + // vert back + decoVert(b.vertex(ox + dx2 * r + yax * -w2, oy + dy2 * r + yay * -w2, oz + dz2 * r + yaz * -w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + yax * w2, oy + dy2 * r + yay * w2, oz + dz2 * r + yaz * w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * w1, oy + dy1 * r + yay * w1, oz + dz1 * r + yaz * w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * -w1, oy + dy1 * r + yay * -w1, oz + dz1 * r + yaz * -w1), u0, v1, al1, lmap); + } + } +} diff --git a/src/main/java/elucent/eidolon/particle/GlowingSlashParticleType.java b/src/main/java/elucent/eidolon/particle/GlowingSlashParticleType.java new file mode 100644 index 0000000..f4b3459 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/GlowingSlashParticleType.java @@ -0,0 +1,35 @@ +package elucent.eidolon.particle; + +import com.mojang.serialization.Codec; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; + +public class GlowingSlashParticleType extends ParticleType { + public GlowingSlashParticleType() { + super(false, SlashParticleData.DESERIALIZER); + } + + @Override + public Codec codec() { + return SlashParticleData.codecFor(this); + } + + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; + + public Factory(SpriteSet sprite) { + this.sprite = sprite; + } + + @Override + public Particle createParticle(SlashParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { + GlowingSlashParticle ret = new GlowingSlashParticle(world, data, x, y, z, mx, my, mz); + ret.pickSprite(sprite); + return ret; + } + } +} diff --git a/src/main/java/elucent/eidolon/particle/RuneParticle.java b/src/main/java/elucent/eidolon/particle/RuneParticle.java new file mode 100644 index 0000000..1ee3c08 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/RuneParticle.java @@ -0,0 +1,150 @@ +package elucent.eidolon.particle; + +import java.awt.Color; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Quaternion; +import com.mojang.math.Vector3f; + +import elucent.eidolon.ClientConfig; +import elucent.eidolon.ClientEvents; +import elucent.eidolon.Eidolon; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.particle.TextureSheetParticle; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; + +public class RuneParticle extends TextureSheetParticle { + Rune rune; + float[] hsv1 = new float[3], hsv2 = new float[3]; + public RuneParticle(ClientLevel world, RuneParticleData data, double x, double y, double z, double vx, double vy, double vz) { + super(world, x, y, z, vx, vy, vz); + this.setPos(x, y, z); + this.rune = data.rune; + this.xd = vx; + this.yd = vy; + this.zd = vz; + this.setLifetime(20); + this.gravity = -0.05f; + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r1)), (int)(255 * Math.min(1.0f, data.g1)), (int)(255 * Math.min(1.0f, data.b1)), hsv1); + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r2)), (int)(255 * Math.min(1.0f, data.g2)), (int)(255 * Math.min(1.0f, data.b2)), hsv2); + if (hsv1[0] < 0.01) hsv1[0] = hsv2[0]; + if (hsv1[1] < 0.01) hsv1[1] = 0.01f; + updateTraits(); + } + + protected float getCoeff() { + float t = ((float)this.age + Minecraft.getInstance().getDeltaFrameTime()) / this.lifetime; + t = Mth.clamp(t, 0.001f, 0.999f); + float ic = (1 - t) * (1 - t); + return 1 - (Mth.sin(Mth.PI * 4 * t) * ic * 0.5f - 0.7f * t + 0.7f); + } + + protected void updateTraits() { + float coeff = getCoeff(); + float t = ((float)this.age + Minecraft.getInstance().getDeltaFrameTime()) / this.lifetime; + t = Mth.clamp(t, 0.001f, 0.999f); + float ic = (1 - t) * (1 - t); + quadSize = Mth.lerp(coeff, 0.125f, 0.0625f); + this.oRoll = roll; + this.roll = Mth.PI * Mth.sin(Mth.cos(Mth.PI * 4 * t) * ic) / 8; + setAlpha(Mth.lerp(coeff * coeff, 0.5f, 0)); + + float h = Mth.rotLerp(coeff, 360 * hsv1[0], 360 * hsv2[0]) / 360; + float s = Mth.lerp(coeff, hsv1[1], hsv2[1]); + float v = Mth.lerp(coeff, hsv1[2], hsv2[2]); + int packed = Color.HSBtoRGB(h, s, v); + float r = FastColor.ARGB32.red(packed) / 255.0f; + float g = FastColor.ARGB32.green(packed) / 255.0f; + float b = FastColor.ARGB32.blue(packed) / 255.0f; + setColor(r, g, b); + } + + @Override + public void tick() { + updateTraits(); + super.tick(); + xd *= 0.98; + yd *= 0.98; + zd *= 0.98; + } + + @Override + public void render(VertexConsumer b, Camera info, float pticks) { + b = ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.GLOWING_BLOCK_PARTICLE) : b; + Vec3 vec3 = info.getPosition(); + float f = (float)(Mth.lerp((double)pticks, this.xo, this.x) - vec3.x()); + float f1 = (float)(Mth.lerp((double)pticks, this.yo, this.y) - vec3.y()); + float f2 = (float)(Mth.lerp((double)pticks, this.zo, this.z) - vec3.z()); + Quaternion quaternion; + if (this.roll == 0.0F) { + quaternion = info.rotation(); + } else { + quaternion = new Quaternion(info.rotation()); + float f3 = Mth.lerp(pticks, this.oRoll, this.roll); + quaternion.mul(Vector3f.ZP.rotation(f3)); + } + + Vector3f vector3f1 = new Vector3f(-1.0F, -1.0F, 0.0F); + vector3f1.transform(quaternion); + Vector3f[] avector3f = new Vector3f[]{new Vector3f(-1.0F, -1.0F, 0.0F), new Vector3f(-1.0F, 1.0F, 0.0F), new Vector3f(1.0F, 1.0F, 0.0F), new Vector3f(1.0F, -1.0F, 0.0F)}; + float f4 = this.getQuadSize(pticks); + + for(int i = 0; i < 4; ++i) { + Vector3f vector3f = avector3f[i]; + vector3f.transform(quaternion); + vector3f.mul(f4); + vector3f.add(f, f1, f2); + } + + float f7 = this.getU0(); + float f8 = this.getU1(); + float f5 = this.getV0(); + float f6 = this.getV1(); + int j = this.getLightColor(pticks); + + + Vector3f offX = avector3f[0].copy(), offY = avector3f[1].copy(); + offX.sub(avector3f[2]); + offX.mul(0.5f); + offY.sub(avector3f[3]); + offY.mul(0.5f); + + TextureAtlasSprite aura = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation(Eidolon.MODID, "particle/aura")); + + for (int i = 0; i < 1; i ++) { +// float a = Mth.PI * i + Mth.PI * 2 * (age + pticks) / lifetime; +// float s = Mth.sin(a), c = Mth.cos(a); +// float dx = offX.x() * c + offY.x() * s; +// float dy = offX.y() * c + offY.y() * s; +// float dz = offX.z() * c + offY.z() * s; +// dx *= 0.25f; +// dy *= 0.25f; +// dz *= 0.25f; + b.vertex((double)avector3f[0].x() + offX.x(), (double)avector3f[0].y() + offX.y(), (double)avector3f[0].z() + offX.z()).uv(aura.getU1(), aura.getV1()).color(this.rCol, this.gCol, this.bCol, this.alpha * 0.25f).uv2(j).endVertex(); + b.vertex((double)avector3f[1].x() + offY.x(), (double)avector3f[1].y() + offY.y(), (double)avector3f[1].z() + offY.z()).uv(aura.getU1(), aura.getV0()).color(this.rCol, this.gCol, this.bCol, this.alpha * 0.25f).uv2(j).endVertex(); + b.vertex((double)avector3f[2].x() - offX.x(), (double)avector3f[2].y() - offX.y(), (double)avector3f[2].z() - offX.z()).uv(aura.getU0(), aura.getV0()).color(this.rCol, this.gCol, this.bCol, this.alpha * 0.25f).uv2(j).endVertex(); + b.vertex((double)avector3f[3].x() - offY.x(), (double)avector3f[3].y() - offY.y(), (double)avector3f[3].z() - offY.z()).uv(aura.getU0(), aura.getV1()).color(this.rCol, this.gCol, this.bCol, this.alpha * 0.25f).uv2(j).endVertex(); + } + + b.vertex((double)avector3f[0].x(), (double)avector3f[0].y(), (double)avector3f[0].z()).uv(f8, f6).color(this.rCol, this.gCol, this.bCol, this.alpha).uv2(j).endVertex(); + b.vertex((double)avector3f[1].x(), (double)avector3f[1].y(), (double)avector3f[1].z()).uv(f8, f5).color(this.rCol, this.gCol, this.bCol, this.alpha).uv2(j).endVertex(); + b.vertex((double)avector3f[2].x(), (double)avector3f[2].y(), (double)avector3f[2].z()).uv(f7, f5).color(this.rCol, this.gCol, this.bCol, this.alpha).uv2(j).endVertex(); + b.vertex((double)avector3f[3].x(), (double)avector3f[3].y(), (double)avector3f[3].z()).uv(f7, f6).color(this.rCol, this.gCol, this.bCol, this.alpha).uv2(j).endVertex(); + } + + @Override + public ParticleRenderType getRenderType() { + return RuneParticleRenderType.INSTANCE; + } +} diff --git a/src/main/java/elucent/eidolon/particle/RuneParticleData.java b/src/main/java/elucent/eidolon/particle/RuneParticleData.java new file mode 100644 index 0000000..f34ef91 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/RuneParticleData.java @@ -0,0 +1,102 @@ +package elucent.eidolon.particle; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import elucent.eidolon.Registry; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Runes; +import elucent.eidolon.spell.Sign; +import elucent.eidolon.spell.Signs; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.resources.ResourceLocation; + +public class RuneParticleData implements ParticleOptions { + Rune rune; + float r1, g1, b1, r2, g2, b2; + + public static Codec codecFor(ParticleType type) { + return RecordCodecBuilder.create(instance -> instance.group( + Codec.STRING.fieldOf("rune").forGetter((d) -> d.rune.getRegistryName().toString()), + Codec.FLOAT.fieldOf("r1").forGetter((d) -> d.r1), + Codec.FLOAT.fieldOf("g1").forGetter((d) -> d.g1), + Codec.FLOAT.fieldOf("b1").forGetter((d) -> d.b1), + Codec.FLOAT.fieldOf("r2").forGetter((d) -> d.r2), + Codec.FLOAT.fieldOf("g2").forGetter((d) -> d.g2), + Codec.FLOAT.fieldOf("b2").forGetter((d) -> d.b2) + ).apply(instance, (rune, r1, g1, b1, r2, g2, b2) -> { + RuneParticleData data = new RuneParticleData(Runes.find(new ResourceLocation(rune)), r1, g1, b1, r2, g2, b2); + return data; + })); + } + + public RuneParticleData(Rune rune, float r1, float g1, float b1, float r2, float g2, float b2) { + this.rune = rune; + this.r1 = r1; + this.g1 = g1; + this.b1 = b1; + this.r2 = r2; + this.g2 = g2; + this.b2 = b2; + } + + @Override + public ParticleType getType() { + return Registry.RUNE_PARTICLE.get(); + } + + @Override + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeUtf(rune.toString()); + buffer.writeFloat(r1); + buffer.writeFloat(g1); + buffer.writeFloat(b1); + buffer.writeFloat(r2); + buffer.writeFloat(g2); + buffer.writeFloat(b2); + } + + @Override + public String writeToString() { + return getClass().getSimpleName() + ":internal"; + } + + public static final Deserializer DESERIALIZER = new Deserializer() { + @Override + public RuneParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { + reader.expect(' '); + String loc = reader.readString(); + reader.expect(' '); + float r1 = reader.readFloat(); + reader.expect(' '); + float g1 = reader.readFloat(); + reader.expect(' '); + float b1 = reader.readFloat(); + reader.expect(' '); + float r2 = reader.readFloat(); + reader.expect(' '); + float g2 = reader.readFloat(); + reader.expect(' '); + float b2 = reader.readFloat(); + RuneParticleData data = new RuneParticleData(Runes.find(new ResourceLocation(loc)), r1, g1, b1, r2, g2, b2); + return data; + } + + @Override + public RuneParticleData fromNetwork(ParticleType type, FriendlyByteBuf buf) { + String loc = buf.readUtf(); + float r1 = buf.readFloat(); + float g1 = buf.readFloat(); + float b1 = buf.readFloat(); + float r2 = buf.readFloat(); + float g2 = buf.readFloat(); + float b2 = buf.readFloat(); + RuneParticleData data = new RuneParticleData(Runes.find(new ResourceLocation(loc)), r1, g1, b1, r2, g2, b2); + return data; + } + }; +} diff --git a/src/main/java/elucent/eidolon/particle/RuneParticleRenderType.java b/src/main/java/elucent/eidolon/particle/RuneParticleRenderType.java new file mode 100644 index 0000000..3a005e1 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/RuneParticleRenderType.java @@ -0,0 +1,45 @@ +package elucent.eidolon.particle; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.Minecraft; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat.Mode; + +import elucent.eidolon.ClientEvents; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureManager; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; + +public class RuneParticleRenderType extends SpriteParticleRenderType { + public static final RuneParticleRenderType INSTANCE = new RuneParticleRenderType(); + + private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManager textureManager) { + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); + bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); + } + + private static void endRenderCommon() { + Minecraft.getInstance().textureManager.getTexture(TextureAtlas.LOCATION_BLOCKS).restoreLastBlurMipmap(); + RenderSystem.depthMask(true); + } + + @Override + public void begin(BufferBuilder b, TextureManager tex) { + beginRenderCommon(b, tex); + } + + @Override + public void end(Tesselator t) { + t.end(); + RenderSystem.enableDepthTest(); + endRenderCommon(); + } +} diff --git a/src/main/java/elucent/eidolon/particle/RuneParticleType.java b/src/main/java/elucent/eidolon/particle/RuneParticleType.java new file mode 100644 index 0000000..4857b7b --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/RuneParticleType.java @@ -0,0 +1,48 @@ +package elucent.eidolon.particle; + +import java.util.Random; + +import com.mojang.serialization.Codec; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; + +public class RuneParticleType extends ParticleType { + public RuneParticleType() { + super(false, RuneParticleData.DESERIALIZER); + } + + @Override + public Codec codec() { + return RuneParticleData.codecFor(this); + } + + public static class Factory implements ParticleProvider { + public Factory() { + // + } + + @Override + public Particle createParticle(RuneParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { + RuneParticle ret = new RuneParticle(world, data, x, y, z, mx, my, mz); + ret.pickSprite(new SpriteSet() { + @Override + public TextureAtlasSprite get(int particleAge, int particleMaxAge) { + return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ret.rune.getSprite()); + } + + @Override + public TextureAtlasSprite get(Random rand) { + return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(ret.rune.getSprite()); + } + }); + return ret; + } + } +} diff --git a/src/main/java/elucent/eidolon/particle/SignParticleData.java b/src/main/java/elucent/eidolon/particle/SignParticleData.java index 485c6d9..8d3cdc0 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticleData.java +++ b/src/main/java/elucent/eidolon/particle/SignParticleData.java @@ -13,8 +13,6 @@ import net.minecraft.core.particles.ParticleType; import net.minecraft.resources.ResourceLocation; -import net.minecraft.core.particles.ParticleOptions.Deserializer; - public class SignParticleData implements ParticleOptions { Sign sign; diff --git a/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java b/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java index e9c82d1..6b8afb3 100644 --- a/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/SignParticleRenderType.java @@ -9,6 +9,7 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexFormat.Mode; +import elucent.eidolon.ClientEvents; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; import com.mojang.blaze3d.vertex.DefaultVertexFormat; @@ -21,6 +22,7 @@ private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManage RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); } diff --git a/src/main/java/elucent/eidolon/particle/SlashParticle.java b/src/main/java/elucent/eidolon/particle/SlashParticle.java new file mode 100644 index 0000000..3657897 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/SlashParticle.java @@ -0,0 +1,165 @@ +package elucent.eidolon.particle; + +import java.awt.Color; + +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.ClientConfig; +import elucent.eidolon.ClientEvents; +import elucent.eidolon.util.RenderUtil; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.particle.TextureSheetParticle; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; + +public class SlashParticle extends TextureSheetParticle { + SlashParticleData data; + float[] hsv1 = new float[3], hsv2 = new float[3]; + public SlashParticle(ClientLevel world, SlashParticleData data, double x, double y, double z, double vx, double vy, double vz) { + super(world, x, y, z, vx, vy, vz); + this.setPos(x, y, z); + this.data = data; + float sy = Mth.sin(data.yaw), cy = Mth.cos(data.yaw), sp = Mth.sin(data.pitch), cp = Mth.cos(data.pitch); + x -= sy * cp * data.width * 0.25f; + y -= sp * data.width * 0.25f; + z -= cy * cp * data.width * 0.25f; + setPos(x, y, z); + this.xd = vx; + this.yd = vy; + this.zd = vz; + Vec3 dir = Vec3.directionFromRotation(Mth.RAD_TO_DEG * data.pitch, Mth.RAD_TO_DEG * data.yaw); + xd += dir.x * (0.025f + world.random.nextFloat() * 0.025f); + yd += dir.y * (0.025f + world.random.nextFloat() * 0.025f); + zd += dir.z * (0.025f + world.random.nextFloat() * 0.025f); + this.setLifetime(data.lifetime); + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r1)), (int)(255 * Math.min(1.0f, data.g1)), (int)(255 * Math.min(1.0f, data.b1)), hsv1); + Color.RGBtoHSB((int)(255 * Math.min(1.0f, data.r2)), (int)(255 * Math.min(1.0f, data.g2)), (int)(255 * Math.min(1.0f, data.b2)), hsv2); + setSize(data.rad, data.rad); + updateTraits(); + } + + protected float getCoeff() { + return (float)this.age / this.lifetime; + } + + protected float getCoeff(float pticks) { + return ((float)this.age + pticks) / this.lifetime; + } + + protected float getSqInvCoeff(float pticks) { + float inv = (this.lifetime - (float)this.age + pticks) / this.lifetime; + return 1 - inv * inv * inv * inv; + } + + protected void updateTraits() { + float coeff = getCoeff(); + float h = Mth.rotLerp(coeff, 360 * hsv1[0], 360 * hsv2[0]) / 360; + float s = Mth.lerp(coeff, hsv1[1], hsv2[1]); + float v = Mth.lerp(coeff, hsv1[2], hsv2[2]); + int packed = Color.HSBtoRGB(h, s, v); + float r = FastColor.ARGB32.red(packed) / 255.0f; + float g = FastColor.ARGB32.green(packed) / 255.0f; + float b = FastColor.ARGB32.blue(packed) / 255.0f; + setColor(r, g, b); + setAlpha(Mth.lerp(coeff, data.a1, data.a2)); + } + + @Override + public void tick() { + updateTraits(); + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return SpriteParticleRenderType.INSTANCE; + } + + private void decoVert(VertexConsumer vc, float u, float v, float alpha, int lmap) { + vc.uv(u, v).color(rCol, gCol, bCol, alpha).uv2(lmap).endVertex(); + } + + @Override + public void render(VertexConsumer vc, Camera info, float pticks) { + VertexConsumer b = ClientConfig.BETTER_LAYERING.get() ? ClientEvents.getDelayedRender().getBuffer(RenderUtil.DELAYED_PARTICLE) : vc; + + float x = (float)(Mth.lerp((double)pticks, this.xo, this.x) - info.getPosition().x()); + float y = (float)(Mth.lerp((double)pticks, this.yo, this.y) - info.getPosition().y()); + float z = (float)(Mth.lerp((double)pticks, this.zo, this.z) - info.getPosition().z()); + float sy = Mth.sin(data.yaw), cy = Mth.cos(data.yaw), sp = Mth.sin(data.pitch), cp = Mth.cos(data.pitch); + float ox = x - sy * cp * data.rad, oy = y - sp * data.rad, oz = z - cy * cp * data.rad; + + float right = data.yaw + Mth.PI / 2, up = data.pitch + Mth.PI / 2; + float sr = Mth.sin(right), cr = Mth.cos(right), su = Mth.sin(up), cu = Mth.cos(up); + float r = data.rad; + float xax = r * sr * cp, xay = 0, xaz = r * cr * cp; + float yax = r * sy * cu, yay = r * su, yaz = r * cy * cu; + float zax = r * sy * cp, zay = r * sp, zaz = r * cy * cp; + float cro = Mth.cos(data.roll), sro = Mth.sin(data.roll); + float nxax = xax * cro - yax * sro; + float nxay = xay * cro - yay * sro; + float nxaz = xaz * cro - yaz * sro; + yax = xax * sro + yax * cro; + yay = xay * sro + yay * cro; + yaz = xaz * sro + yaz * cro; + xax = nxax; + xay = nxay; + xaz = nxaz; + float u0 = this.getU0(); + float u1 = this.getU1(); + float v0 = this.getV0(); + float v1 = this.getV1(); + int lmap = getLightColor(pticks); + float w = data.width / 2; + + float hlangle = -data.angle / 2 + getSqInvCoeff(pticks) * data.angle; + float hlwidth = 4 + 4 * getSqInvCoeff(pticks); + + for (float i = 0; i < 18; i ++) { + float c1 = i / 18, c2 = (i + 1) / 18; + float basea = this.alpha - data.highlight; + float angle1 = -data.angle / 2 + c1 * data.angle, angle2 = -data.angle / 2 + c2 * data.angle; + float al1 = Mth.sin(c1 * Mth.PI), al2 = Mth.sin(c2 * Mth.PI); + float dangle1 = Mth.clamp((angle1 - hlangle) / data.angle, -1 / hlwidth, 1 / hlwidth), dangle2 = Mth.clamp((angle2 - hlangle) / data.angle, -1 / hlwidth, 1 / hlwidth); + float hl1 = (Mth.cos(hlwidth * Mth.PI * dangle1) + 1) / 2, hl2 = (Mth.cos(hlwidth * Mth.PI * dangle2) + 1) / 2; + al1 = (1 - data.highlight) * al1 + data.highlight * hl1; + al2 = (1 - data.highlight) * al2 + data.highlight * hl2; + al1 *= alpha; + al2 *= alpha; + float w1 = w * (0.25f + 0.75f * Mth.sin(c1 * Mth.PI)), w2 = w * (0.25f + 0.75f * Mth.sin(c2 * Mth.PI)); + w1 += data.highlight * 0.25f * w * hl1; + w2 += data.highlight * 0.25f * w * hl2; + + float sa1 = Mth.sin(angle1), ca1 = Mth.cos(angle1), sa2 = Mth.sin(angle2), ca2 = Mth.cos(angle2); + float dx1 = sa1 * xax + ca1 * zax, dy1 = sa1 * xay + ca1 * zay, dz1 = sa1 * xaz + ca1 * zaz; + float dx2 = sa2 * xax + ca2 * zax, dy2 = sa2 * xay + ca2 * zay, dz2 = sa2 * xaz + ca2 * zaz; + + // horiz + decoVert(b.vertex(ox + dx2 * r + dx2 * w2, oy + dy2 * r + dy2 * w2, oz + dz2 * r + dz2 * w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + dx2 * -w2, oy + dy2 * r + dy2 * -w2, oz + dz2 * r + dz2 * -w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * -w1, oy + dy1 * r + dy1 * -w1, oz + dz1 * r + dz1 * -w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * w1, oy + dy1 * r + dy1 * w1, oz + dz1 * r + dz1 * w1), u0, v1, al1, lmap); + + // horiz back + decoVert(b.vertex(ox + dx2 * r + dx2 * -w2, oy + dy2 * r + dy2 * -w2, oz + dz2 * r + dz2 * -w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + dx2 * w2, oy + dy2 * r + dy2 * w2, oz + dz2 * r + dz2 * w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * w1, oy + dy1 * r + dy1 * w1, oz + dz1 * r + dz1 * w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + dx1 * -w1, oy + dy1 * r + dy1 * -w1, oz + dz1 * r + dz1 * -w1), u0, v1, al1, lmap); + + // vert + decoVert(b.vertex(ox + dx2 * r + yax * w2 * 0.5f, oy + dy2 * r + yay * w2 * 0.5f, oz + dz2 * r + yaz * w2 * 0.5f), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + yax * -w2 * 0.5f, oy + dy2 * r + yay * -w2 * 0.5f, oz + dz2 * r + yaz * -w2 * 0.5f), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * -w1 * 0.5f, oy + dy1 * r + yay * -w1 * 0.5f, oz + dz1 * r + yaz * -w1 * 0.5f), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * w1 * 0.5f, oy + dy1 * r + yay * w1 * 0.5f, oz + dz1 * r + yaz * w1 * 0.5f), u0, v1, al1, lmap); + + // vert back + decoVert(b.vertex(ox + dx2 * r + yax * -w2, oy + dy2 * r + yay * -w2, oz + dz2 * r + yaz * -w2), u1, v1, al2, lmap); + decoVert(b.vertex(ox + dx2 * r + yax * w2, oy + dy2 * r + yay * w2, oz + dz2 * r + yaz * w2), u1, v0, al2, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * w1, oy + dy1 * r + yay * w1, oz + dz1 * r + yaz * w1), u0, v0, al1, lmap); + decoVert(b.vertex(ox + dx1 * r + yax * -w1, oy + dy1 * r + yay * -w1, oz + dz1 * r + yaz * -w1), u0, v1, al1, lmap); + } + } +} diff --git a/src/main/java/elucent/eidolon/particle/SlashParticleData.java b/src/main/java/elucent/eidolon/particle/SlashParticleData.java new file mode 100644 index 0000000..e2ee13c --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/SlashParticleData.java @@ -0,0 +1,265 @@ +package elucent.eidolon.particle; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; + +public class SlashParticleData implements ParticleOptions { + float r1 = 1, g1 = 1, b1 = 1, a1 = 1, r2 = 1, g2 = 1, b2 = 1, a2 = 0; + float width = 0.625f, rad = 1, pitch = 0, yaw = 0, roll = 0, angle = 0; + int lifetime = 10; + float highlight = 0; + + public static Codec codecFor(ParticleType type) { + return RecordCodecBuilder.create(instance -> instance.group( + Codec.FLOAT.fieldOf("r1").forGetter(d -> d.r1), + Codec.FLOAT.fieldOf("g1").forGetter(d -> d.g1), + Codec.FLOAT.fieldOf("b1").forGetter(d -> d.b1), + Codec.FLOAT.fieldOf("a1").forGetter(d -> d.a1), + Codec.FLOAT.fieldOf("r2").forGetter(d -> d.r2), + Codec.FLOAT.fieldOf("g2").forGetter(d -> d.g2), + Codec.FLOAT.fieldOf("b2").forGetter(d -> d.b2), + Codec.FLOAT.fieldOf("a2").forGetter(d -> d.a2), + Codec.FLOAT.fieldOf("width").forGetter(d -> d.width), + Codec.FLOAT.fieldOf("rad").forGetter(d -> d.rad), + Codec.FLOAT.fieldOf("pitch").forGetter(d -> d.pitch), + Codec.FLOAT.fieldOf("yaw").forGetter(d -> d.yaw), + Codec.FLOAT.fieldOf("roll").forGetter(d -> d.roll), + Codec.FLOAT.fieldOf("angle").forGetter(d -> d.angle), + Codec.INT.fieldOf("lifetime").forGetter(d -> d.lifetime), + Codec.FLOAT.fieldOf("highlight").forGetter(d -> d.highlight) + ).apply(instance, (r1, g1, b1, a1, r2, g2, b2, a2, width, rad, + pitch, yaw, roll, angle, lifetime, highlight) -> { + SlashParticleData data = new SlashParticleData(type); + data.r1 = r1; data.g1 = g1; data.b1 = b1; data.a1 = a1; + data.r2 = r2; data.g2 = g2; data.b2 = b2; data.a2 = a2; + data.width = width; + data.rad = rad; + data.pitch = pitch; + data.yaw = yaw; + data.roll = roll; + data.angle = angle; + data.lifetime = lifetime; + data.highlight = highlight; + return data; + })); + } + + ParticleType type; + + public SlashParticleData(ParticleType type) { + this.type = type; + } + + @Override + public ParticleType getType() { + return type; + } + + @Override + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeFloat(r1).writeFloat(g1).writeFloat(b1).writeFloat(a1); + buffer.writeFloat(r2).writeFloat(g2).writeFloat(b2).writeFloat(a2); + buffer.writeFloat(width).writeFloat(rad); + buffer.writeFloat(pitch).writeFloat(yaw).writeFloat(roll).writeFloat(angle); + buffer.writeInt(lifetime); + } + + @Override + public String writeToString() { + return getClass().getSimpleName() + ":internal"; + } + + public static final Deserializer DESERIALIZER = new Deserializer() { + @Override + public SlashParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { + reader.expect(' '); + float r1 = reader.readFloat(); + reader.expect(' '); + float g1 = reader.readFloat(); + reader.expect(' '); + float b1 = reader.readFloat(); + reader.expect(' '); + float a1 = reader.readFloat(); + reader.expect(' '); + float r2 = reader.readFloat(); + reader.expect(' '); + float g2 = reader.readFloat(); + reader.expect(' '); + float b2 = reader.readFloat(); + reader.expect(' '); + float a2 = reader.readFloat(); + reader.expect(' '); + float width = reader.readFloat(); + reader.expect(' '); + float rad = reader.readFloat(); + reader.expect(' '); + float pitch = reader.readFloat(); + reader.expect(' '); + float yaw = reader.readFloat(); + reader.expect(' '); + float roll = reader.readFloat(); + reader.expect(' '); + float angle = reader.readFloat(); + reader.expect(' '); + int lifetime = reader.readInt(); + reader.expect(' '); + float highlight = reader.readFloat(); + SlashParticleData data = new SlashParticleData(type); + data.r1 = r1; + data.g1 = g1; + data.b1 = b1; + data.a1 = a1; + data.r2 = r2; + data.g2 = g2; + data.b2 = b2; + data.a2 = a2; + data.width = width; + data.rad = rad; + data.pitch = pitch; + data.yaw = yaw; + data.roll = roll; + data.angle = angle; + data.lifetime = lifetime; + data.highlight = highlight; + return data; + } + + @Override + public SlashParticleData fromNetwork(ParticleType type, FriendlyByteBuf buf) { + float r1 = buf.readFloat(); + float g1 = buf.readFloat(); + float b1 = buf.readFloat(); + float a1 = buf.readFloat(); + float r2 = buf.readFloat(); + float g2 = buf.readFloat(); + float b2 = buf.readFloat(); + float a2 = buf.readFloat(); + float width = buf.readFloat(); + float rad = buf.readFloat(); + float pitch = buf.readFloat(); + float yaw = buf.readFloat(); + float roll = buf.readFloat(); + float angle = buf.readFloat(); + int lifetime = buf.readInt(); + float highlight = buf.readFloat(); + SlashParticleData data = new SlashParticleData(type); + data.r1 = r1; + data.g1 = g1; + data.b1 = b1; + data.a1 = a1; + data.r2 = r2; + data.g2 = g2; + data.b2 = b2; + data.a2 = a2; + data.width = width; + data.rad = rad; + data.pitch = pitch; + data.roll = roll; + data.yaw = yaw; + data.angle = angle; + data.lifetime = lifetime; + data.highlight = highlight; + return data; + } + }; + + public static SlashParticleData create(ParticleType type) { + SlashParticleData data = new SlashParticleData(type); + return data; + } + + public SlashParticleData color(float r, float g, float b) { + return color(r, g, b, a1, r, g, b, a2); + } + + public SlashParticleData color(float r, float g, float b, float a) { + return color(r, g, b, a, r, g, b, a); + } + + public SlashParticleData color(float r1, float g1, float b1, float r2, float g2, float b2) { + return color(r1, g1, b1, a1, r2, g2, b2, a2); + } + + public SlashParticleData color(float r1, float g1, float b1, float a1, float r2, float g2, float b2, float a2) { + this.r1 = r1; + this.g1 = g1; + this.b1 = b1; + this.a1 = a1; + this.r2 = r2; + this.g2 = g2; + this.b2 = b2; + this.a2 = a2; + return this; + } + + public SlashParticleData alpha(float a) { + this.a1 = this.a2 = a; + return this; + } + + public SlashParticleData alpha(float a1, float a2) { + this.a1 = a1; + this.a2 = a2; + return this; + } + + public SlashParticleData width(float w) { + this.width = w; + return this; + } + + public SlashParticleData lookat(double x1, double y1, double z1, double x2, double y2, double z2) { + Vec3 horiz = new Vec3(x2 - x1, 0, z2 - z1); + this.yaw = (float)Mth.atan2(x2 - x1, z2 - z1); + this.pitch = (float)Mth.atan2(y2 - y1, horiz.length()); + return this; + } + + public SlashParticleData pitch(float pitch) { + this.pitch = pitch; + return this; + } + + public SlashParticleData yaw(float yaw) { + this.yaw = yaw; + return this; + } + + public SlashParticleData roll(float roll) { + this.roll = roll; + return this; + } + + public SlashParticleData highlight(float highlight) { + this.highlight = highlight; + return this; + } + + public SlashParticleData angle(float angle) { + this.angle = Mth.DEG_TO_RAD * angle; + return this; + } + + public SlashParticleData radius(float rad) { + this.rad = rad; + return this; + } + + public SlashParticleData lifetime(int ticks) { + this.lifetime = ticks; + return this; + } + + public void spawn(Level level, double x, double y, double z, double vx, double vy, double vz) { + level.addParticle(this, x, y, z, vx, vy, vz); + } +} diff --git a/src/main/java/elucent/eidolon/particle/SlashParticleType.java b/src/main/java/elucent/eidolon/particle/SlashParticleType.java new file mode 100644 index 0000000..5de61b6 --- /dev/null +++ b/src/main/java/elucent/eidolon/particle/SlashParticleType.java @@ -0,0 +1,35 @@ +package elucent.eidolon.particle; + +import com.mojang.serialization.Codec; + +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ParticleType; + +public class SlashParticleType extends ParticleType { + public SlashParticleType() { + super(false, SlashParticleData.DESERIALIZER); + } + + @Override + public Codec codec() { + return SlashParticleData.codecFor(this); + } + + public static class Factory implements ParticleProvider { + private final SpriteSet sprite; + + public Factory(SpriteSet sprite) { + this.sprite = sprite; + } + + @Override + public Particle createParticle(SlashParticleData data, ClientLevel world, double x, double y, double z, double mx, double my, double mz) { + SlashParticle ret = new SlashParticle(world, data, x, y, z, mx, my, mz); + ret.pickSprite(sprite); + return ret; + } + } +} diff --git a/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java b/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java index 1c83dc8..c80cc40 100644 --- a/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java +++ b/src/main/java/elucent/eidolon/particle/SpriteParticleRenderType.java @@ -11,6 +11,7 @@ import com.mojang.blaze3d.vertex.VertexFormat.Mode; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Registry; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; @@ -23,7 +24,7 @@ private static void beginRenderCommon(BufferBuilder bufferBuilder, TextureManage RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - RenderSystem.setShader(Registry::getGlowingSpriteShader); + RenderSystem.setShader(ClientRegistry::getSpriteParticleShader); RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); ClientEvents.particleMVMatrix = RenderSystem.getModelViewMatrix(); bufferBuilder.begin(Mode.QUADS, DefaultVertexFormat.PARTICLE); diff --git a/src/main/java/elucent/eidolon/potion/AnchoredEffect.java b/src/main/java/elucent/eidolon/potion/AnchoredEffect.java index d6c93ee..f27f118 100644 --- a/src/main/java/elucent/eidolon/potion/AnchoredEffect.java +++ b/src/main/java/elucent/eidolon/potion/AnchoredEffect.java @@ -2,14 +2,11 @@ import elucent.eidolon.Eidolon; import elucent.eidolon.util.ColorUtil; -import net.minecraft.client.Minecraft; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeMobEffect; import net.minecraftforge.event.entity.EntityTeleportEvent; diff --git a/src/main/java/elucent/eidolon/potion/ChilledEffect.java b/src/main/java/elucent/eidolon/potion/ChilledEffect.java index 5f80d04..8d9712d 100644 --- a/src/main/java/elucent/eidolon/potion/ChilledEffect.java +++ b/src/main/java/elucent/eidolon/potion/ChilledEffect.java @@ -36,10 +36,6 @@ static int packColor(int alpha, int red, int green, int blue) { public ChilledEffect() { super(MobEffectCategory.HARMFUL, packColor(255, 147, 189, 245)); MinecraftForge.EVENT_BUS.addListener(this::chill); - DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> { - MinecraftForge.EVENT_BUS.addListener(ChilledEffect::renderChill); - return null; - }); } @SubscribeEvent @@ -49,74 +45,4 @@ public void chill(LivingHealEvent event) { event.setCanceled(true); } } - - protected static final ResourceLocation ICONS_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/gui/icons.png"); - protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/chilled.png"); - -// @OnlyIn(Dist.CLIENT) -// @Override -// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { -// Minecraft mc = Minecraft.getInstance(); -// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); -// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); -// } -// -// @OnlyIn(Dist.CLIENT) -// @Override -// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { -// Minecraft mc = Minecraft.getInstance(); -// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); -// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); -// } - - @OnlyIn(Dist.CLIENT) - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void renderChill(RenderGameOverlayEvent.Post event) { - Minecraft mc = Minecraft.getInstance(); - LocalPlayer player = mc.player; - if (event.getType() == RenderGameOverlayEvent.ElementType.ALL - && player.hasEffect(Registry.CHILLED_EFFECT.get())) { - - PoseStack mStack = event.getMatrixStack(); - mStack.pushPose(); - mStack.translate(0, 0, 0.01); - - int health = Mth.ceil(player.getHealth()); - float absorb = Mth.ceil(player.getAbsorptionAmount()); - AttributeInstance attrMaxHealth = player.getAttribute(Attributes.MAX_HEALTH); - float healthMax = (float)attrMaxHealth.getValue(); - - int ticks = mc.gui.getGuiTicks(); - - int regen = -1; - if (player.hasEffect(MobEffects.REGENERATION)) regen = ticks % 25; - - Random rand = new Random(); - rand.setSeed((long)(ticks * 312871)); - - int left = event.getWindow().getGuiScaledWidth() / 2 - 91; - int top = event.getWindow().getGuiScaledHeight() - ((ForgeIngameGui)Minecraft.getInstance().gui).left_height; - - int healthRows = Mth.ceil((healthMax + absorb) / 2.0F / 10.0F); - int rowHeight = Math.max(10 - (healthRows - 2), 3); - - RenderSystem.setShaderTexture(0, ICONS_TEXTURE); - for (int i = Mth.ceil((healthMax) / 2.0F) - 1; i >= 0; -- i) { - int row = Mth.ceil((float)(i + 1) / 10.0F) - 1; - int x = left + i % 10 * 8; - int y = top + rowHeight * 2 - 2; // we don't need to worry about rowHeight, the usual health rendering already added it to top - - if (health <= 4) y += rand.nextInt(2); - if (i == regen) y -= 2; - - RenderSystem.enableBlend(); - if (i * 2 + 1 < health) - mc.gui.blit(mStack, x, y, 0, 0, 9, 9); - else if (i * 2 + 1 == health) - mc.gui.blit(mStack, x, y, 9, 0, 9, 9); - RenderSystem.disableBlend(); - } - mStack.popPose(); - } - } } diff --git a/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java b/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java index 49d8cb1..8df5097 100644 --- a/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java +++ b/src/main/java/elucent/eidolon/potion/ReinforcedEffect.java @@ -2,15 +2,10 @@ import elucent.eidolon.Eidolon; import elucent.eidolon.util.ColorUtil; -import net.minecraft.client.Minecraft; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeMobEffect; -import net.minecraftforge.eventbus.api.SubscribeEvent; public class ReinforcedEffect extends MobEffect implements IForgeMobEffect { public ReinforcedEffect() { diff --git a/src/main/java/elucent/eidolon/potion/UndeathEffect.java b/src/main/java/elucent/eidolon/potion/UndeathEffect.java new file mode 100644 index 0000000..86c9e11 --- /dev/null +++ b/src/main/java/elucent/eidolon/potion/UndeathEffect.java @@ -0,0 +1,33 @@ +package elucent.eidolon.potion; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeMobEffect; + +public class UndeathEffect extends MobEffect implements IForgeMobEffect { + public UndeathEffect() { + super(MobEffectCategory.HARMFUL, ColorUtil.packColor(255, 51, 39, 42)); + } + + protected static final ResourceLocation EFFECT_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/mob_effect/undeath.png"); + +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderInventoryEffect(EffectInstance effect, DisplayEffectsScreen gui, MatrixStack mStack, int x, int y, float z) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +// +// @OnlyIn(Dist.CLIENT) +// @Override +// public void renderHUDEffect(EffectInstance effect, AbstractGui gui, MatrixStack mStack, int x, int y, float z, float alpha) { +// Minecraft mc = Minecraft.getInstance(); +// mc.getTextureManager().bindTexture(EFFECT_TEXTURE); +// AbstractGui.blit(mStack, x, y, 18, 18, 0, 0, 18, 18, 18, 18); +// } +} diff --git a/src/main/java/elucent/eidolon/potion/VulnerableEffect.java b/src/main/java/elucent/eidolon/potion/VulnerableEffect.java index ada1e8d..fe9c852 100644 --- a/src/main/java/elucent/eidolon/potion/VulnerableEffect.java +++ b/src/main/java/elucent/eidolon/potion/VulnerableEffect.java @@ -2,15 +2,10 @@ import elucent.eidolon.Eidolon; import elucent.eidolon.util.ColorUtil; -import net.minecraft.client.Minecraft; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeMobEffect; -import net.minecraftforge.eventbus.api.SubscribeEvent; public class VulnerableEffect extends MobEffect implements IForgeMobEffect { public VulnerableEffect() { diff --git a/src/main/java/elucent/eidolon/research/Research.java b/src/main/java/elucent/eidolon/research/Research.java new file mode 100644 index 0000000..0357d0c --- /dev/null +++ b/src/main/java/elucent/eidolon/research/Research.java @@ -0,0 +1,58 @@ +package elucent.eidolon.research; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; + +public class Research { + ResourceLocation rl; + int stars; + Map> specialTasks = new HashMap<>(); + + public Research(ResourceLocation rl, int stars) { + this.rl = rl; + this.stars = stars; + if (stars <= 0) throw new IllegalArgumentException("Research difficulty must be at least one star!"); + if (stars > 10) throw new IllegalArgumentException("Research difficulty cannot exceed ten stars!"); + } + + public Research addSpecialTasks(int step, ResearchTask... tasks) { + specialTasks.put(step, List.of(tasks)); + return this; + } + + public ResourceLocation getRegistryName() { + return rl; + } + + public int getStars() { + return stars; + } + + public String getName() { + return I18n.get("research." + rl.getNamespace() + "." + rl.getPath()); + } + + public List getTasks(int rootSeed, int done) { + if (specialTasks.containsKey(done)) return specialTasks.get(done); + List tasks = new ArrayList<>(); + Random random = new Random(); + int seed = getSeed(rootSeed, done); + random.setSeed(seed); + for (int i = 0; i < 3; i ++) { + tasks.add(Researches.getRandomTask(random)); + } + return tasks; + } + + public int getSeed(int rootSeed, int done) { + return rl.hashCode() * 384780223 ^ done * 844955129 ^ rootSeed * 112041199 + 6; + } +} diff --git a/src/main/java/elucent/eidolon/research/ResearchReward.java b/src/main/java/elucent/eidolon/research/ResearchReward.java new file mode 100644 index 0000000..5ed6ff4 --- /dev/null +++ b/src/main/java/elucent/eidolon/research/ResearchReward.java @@ -0,0 +1,5 @@ +package elucent.eidolon.research; + +public class ResearchReward { + +} diff --git a/src/main/java/elucent/eidolon/research/ResearchTask.java b/src/main/java/elucent/eidolon/research/ResearchTask.java new file mode 100644 index 0000000..e4c4b5e --- /dev/null +++ b/src/main/java/elucent/eidolon/research/ResearchTask.java @@ -0,0 +1,312 @@ +package elucent.eidolon.research; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.mojang.blaze3d.vertex.PoseStack; + +import elucent.eidolon.Registry; +import elucent.eidolon.mixin.AbstractContainerMenuMixin; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class ResearchTask { + public abstract CompoundTag write(); + public abstract void read(CompoundTag tag); + public abstract CompletenessResult isComplete(AbstractContainerMenu menu, Player player, int slotStart); + public abstract void onComplete(AbstractContainerMenu menu, Player player, int slotStart); + + @OnlyIn(Dist.CLIENT) + public abstract int getWidth(); + + @OnlyIn(Dist.CLIENT) + public abstract void drawIcon(PoseStack stack, int x, int y); + + @OnlyIn(Dist.CLIENT) + public int drawCustom(PoseStack stack, int x, int y) { return 0; } + + @OnlyIn(Dist.CLIENT) + public int getDefaultWidth() { + return 64; + } + + @OnlyIn(Dist.CLIENT) + public void drawTooltip(PoseStack stack, AbstractContainerScreen gui, double mouseX, double mouseY) {} + + public static record CompletenessResult(int nextSlot, boolean complete) {}; + + public int getSlotCount() { + return 0; + } + + public void modifyContainer(AbstractContainerMenu menu, int x, int y) {} + + public static class Items extends ResearchTask { + List items; + InternalContainer container; + + class InternalContainer implements Container { + List items = new ArrayList<>(); + + protected void updateItems() { + while (items.size() < Items.this.items.size()) items.add(ItemStack.EMPTY); + } + + @Override + public void clearContent() { + items.clear(); + } + + @Override + public int getContainerSize() { + return Items.this.items.size(); + } + + @Override + public boolean isEmpty() { + for (ItemStack s : items) if (!s.isEmpty()) return false; + return true; + } + + @Override + public ItemStack getItem(int slot) { + updateItems(); + return items.get(slot); + } + + @Override + public ItemStack removeItem(int slot, int amount) { + updateItems(); + ItemStack stack = ContainerHelper.removeItem(this.items, slot, amount); + if (!stack.isEmpty()) { + this.setChanged(); + } + return stack; + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + updateItems(); + ItemStack itemstack = this.items.get(slot); + if (itemstack.isEmpty()) { + return ItemStack.EMPTY; + } else { + this.items.set(slot, ItemStack.EMPTY); + return itemstack; + } + } + + @Override + public void setItem(int slot, ItemStack stack) { + updateItems(); + items.set(slot, stack); + } + + @Override + public void setChanged() { + // stub. should this be implemented? + } + + @Override + public boolean stillValid(Player p_18946_) { + return true; + } + } + + public Items() { + this.items = new ArrayList(); + this.container = new InternalContainer(); + } + + public Items(ItemStack... stacks) { + this.items = List.of(stacks); + this.container = new InternalContainer(); + } + + @Override + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.put("stacks", new ListTag()); + return items.stream().map(s -> s.save(new CompoundTag())).reduce(tag, (t, s) -> { + t.getList("stacks", Tag.TAG_COMPOUND).add(s); + return t; + }); + } + + @Override + public void read(CompoundTag tag) { + ListTag list = tag.getList("stacks", Tag.TAG_COMPOUND); + for (Tag t : list) { + items.add(ItemStack.of((CompoundTag)t)); + } + } + + @Override + public int getWidth() { + return getDefaultWidth() + 8 + 17 * items.size(); + } + + @Override + public void drawIcon(PoseStack stack, int x, int y) { + int offset = (items.size() - 1) * -4; + ItemRenderer ir = Minecraft.getInstance().getItemRenderer(); + for (int i = 0; i < items.size(); i ++) { + ir.renderAndDecorateItem(items.get(i), x + i * 8 + offset, y); + ir.renderGuiItemDecorations(Minecraft.getInstance().font, items.get(i), x + i * 8 + offset, y, null); + } + } + + @Override + public int drawCustom(PoseStack stack, int x, int y) { + Gui.blit(stack, x, y, 0, 88, 224, 1, 32, 256, 256); + x += 1; + for (int i = 0; i < items.size(); i ++) { + if (items.size() == 1) { + Gui.blit(stack, x, y, 0, 192, 0, 22, 32, 256, 256); + x += 22; + } + else if (i == 0) { + Gui.blit(stack, x, y, 0, 192, 32, 20, 32, 256, 256); + x += 19; + } + else if (i == items.size() - 1) { + Gui.blit(stack, x, y, 0, 228, 32, 20, 32, 256, 256); + x += 20; + } + else { + Gui.blit(stack, x, y, 0, 211, 32, 18, 32, 256, 256); + x += 17; + } + } + Gui.blit(stack, x, y, 0, 88, 224, 2, 32, 256, 256); + x += 2; + return 8 + 17 * items.size(); + } + + @Override + public void drawTooltip(PoseStack stack, AbstractContainerScreen gui, double mouseX, double mouseY) { + List tooltip = gui.getTooltipFromItem(items.get(0)); + gui.renderComponentTooltip(stack, tooltip, (int)mouseX, (int)mouseY); + } + + @Override + public int getSlotCount() { + return items.size(); + } + + @Override + public void modifyContainer(AbstractContainerMenu menu, int x, int y) { + for (int i = 0; i < items.size(); i ++) ((AbstractContainerMenuMixin)(Object)menu).callAddSlot(new Slot(container, i, x + 11 + 17 * i, y + 7)); + } + + @Override + public CompletenessResult isComplete(AbstractContainerMenu menu, Player player, int slotStart) { + boolean isMatching = true; + for (int i = 0; i < items.size() && isMatching; i ++) { + if (menu.getItems().size() <= slotStart + i) { + isMatching = false; + continue; + } + ItemStack slot = menu.getSlot(slotStart + i).getItem(); + if (!ItemStack.isSameItemSameTags(items.get(i), slot)) isMatching = false; + if (slot.getCount() < items.get(i).getCount()) isMatching = false; + } + return new CompletenessResult(slotStart + items.size(), isMatching); + } + + @Override + public void onComplete(AbstractContainerMenu menu, Player player, int slotStart) { + for (int i = 0; i < items.size(); i ++) { + menu.getSlot(slotStart + i).remove(items.get(i).getCount()); + } + } + }; + + public static class ScrivenerItems extends Items { + static List> ITEM_POOL = List.of( + (random) -> new ItemStack(Registry.MAGIC_INK.get(), random.nextInt(1, 3)), + (random) -> new ItemStack(net.minecraft.world.item.Items.FEATHER), + (random) -> new ItemStack(Registry.PARCHMENT.get(), random.nextInt(1, 3)), + (random) -> new ItemStack(Registry.CANDLE.get()), + (random) -> new ItemStack(net.minecraft.world.item.Items.CHARCOAL, random.nextInt(1, 3)), + (random) -> new ItemStack(net.minecraft.world.item.Items.BOOK) + ); + + public ScrivenerItems(Random random) { + items = List.of(ITEM_POOL.get(random.nextInt(ITEM_POOL.size())).apply(random)); + } + } + + public static class XP extends ResearchTask { + int levels; + + public XP(Random random) { + levels = random.nextInt(1, 6); // 1-5 XP levels as cost + } + + @Override + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.putInt("levels", levels); + return tag; + } + + @Override + public void read(CompoundTag tag) { + this.levels = tag.getInt("levels"); + } + + @Override + public int getWidth() { + return getDefaultWidth(); + } + + @Override + public void drawIcon(PoseStack stack, int x, int y) { + int offY = Minecraft.getInstance().player.experienceLevel < levels ? 16 : 0; + Gui.blit(stack, x, y, 0, (levels - 1) * 16, 224 + offY, 16, 16, 256, 256); + } + + @Override + public CompletenessResult isComplete(AbstractContainerMenu menu, Player player, int slotStart) { + return new CompletenessResult(slotStart, player.experienceLevel >= levels); + } + + @Override + public void drawTooltip(PoseStack stack, AbstractContainerScreen gui, double mouseX, double mouseY) { + MutableComponent tooltip; + if (levels == 1) { + tooltip = new TranslatableComponent("container.enchant.level.one"); + } else { + tooltip = new TranslatableComponent("container.enchant.level.many", levels); + } + + gui.renderTooltip(stack, tooltip, (int)mouseX, (int)mouseY); + } + + @Override + public void onComplete(AbstractContainerMenu menu, Player player, int slotStart) { + player.giveExperienceLevels(-levels); + } + } +} diff --git a/src/main/java/elucent/eidolon/research/Researches.java b/src/main/java/elucent/eidolon/research/Researches.java new file mode 100644 index 0000000..2f18e8c --- /dev/null +++ b/src/main/java/elucent/eidolon/research/Researches.java @@ -0,0 +1,78 @@ +package elucent.eidolon.research; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.function.Function; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Block; + +public class Researches { + static Map researches = new HashMap<>(); + static Multimap blockResearches = HashMultimap.create(); + static Multimap entityResearches = HashMultimap.create(); + static List> taskPool = new ArrayList<>(); + + public static Research register(Research r, Object... sources) { + researches.put(r.getRegistryName(), r); + for (Object o : sources) { + if (o instanceof Block b) { + blockResearches.put(b.getRegistryName(), r); + } + else if (o instanceof EntityType e) { + entityResearches.put(e.getRegistryName(), r); + } + } + return r; + } + + public static void addTask(Function task) { + taskPool.add(task); + } + + @Nullable + public static Collection getBlockResearches(Block b) { + return blockResearches.get(b.getRegistryName()); + } + + @Nullable + public static Collection getEntityResearches(Entity e) { + return entityResearches.get(e.getType().getRegistryName()); + } + + public static Collection getResearches() { + return researches.values(); + } + + @Nullable + public static Research find(ResourceLocation location) { + return researches.getOrDefault(location, null); + } + + public static ResearchTask getRandomTask(Random random) { + return taskPool.get(random.nextInt(taskPool.size())).apply(random); + } + + public static void init() { + addTask(ResearchTask.ScrivenerItems::new); + addTask(ResearchTask.ScrivenerItems::new); + addTask(ResearchTask.ScrivenerItems::new); + addTask(ResearchTask.ScrivenerItems::new); + addTask(ResearchTask.XP::new); + addTask(ResearchTask.XP::new); + register(new Research(new ResourceLocation(Eidolon.MODID, "gluttony"), 5), EntityType.PIG); + } +} diff --git a/src/main/java/elucent/eidolon/ritual/AbsorptionRitual.java b/src/main/java/elucent/eidolon/ritual/AbsorptionRitual.java new file mode 100644 index 0000000..18edc96 --- /dev/null +++ b/src/main/java/elucent/eidolon/ritual/AbsorptionRitual.java @@ -0,0 +1,74 @@ +package elucent.eidolon.ritual; + +import java.util.List; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.item.IRechargeableWand; +import elucent.eidolon.item.SummoningStaffItem; +import elucent.eidolon.network.CrystallizeEffectPacket; +import elucent.eidolon.network.MagicBurstEffectPacket; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.RitualConsumePacket; +import elucent.eidolon.util.ColorUtil; +import elucent.eidolon.util.EntityUtil; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.Entity.RemovalReason; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class AbsorptionRitual extends Ritual { + public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/absorption_ritual"); + + public AbsorptionRitual() { + super(SYMBOL, ColorUtil.packColor(255, 123, 140, 70)); + } + + @Override + public RitualResult start(Level world, BlockPos pos) { + List tiles = Ritual.getTilesWithinAABB(IRitualItemFocus.class, world, getSearchBounds(pos)); + BlockPos toRecharge = null; + if (!tiles.isEmpty()) for (int i = 0; i < tiles.size(); i ++) { + ItemStack stack = tiles.get(i).provide(); + if (stack.getItem() instanceof SummoningStaffItem s) { + toRecharge = ((BlockEntity)tiles.get(i)).getBlockPos(); + break; + } + } + + List entities = world.getEntitiesOfClass(LivingEntity.class, getSearchBounds(pos), (e) -> Eidolon.getTrueMobType(e) == MobType.UNDEAD && !EntityUtil.isEnthralled(e) && e.getHealth() <= e.getMaxHealth() / 5); + ListTag entityTags = new ListTag(); + for (LivingEntity e : entities) { + e.setHealth(e.getMaxHealth()); + if (!world.isClientSide) { + Networking.sendToTracking(world, e.blockPosition(), new MagicBurstEffectPacket(e.getX(), e.getY() + 0.1, e.getZ(), + ColorUtil.packColor(255, 61, 70, 35), ColorUtil.packColor(255, 36, 24, 41))); + if (toRecharge != null) { + Networking.sendToTracking(world, toRecharge, new RitualConsumePacket(e.blockPosition().above(), toRecharge, getRed(), getGreen(), getBlue())); + } + } + CompoundTag eTag = e.serializeNBT(); + entityTags.add(eTag); + entityTags.add(eTag); + entityTags.add(eTag); + entityTags.add(eTag); + entityTags.add(eTag); + e.remove(RemovalReason.KILLED); + } + if (!tiles.isEmpty()) for (int i = 0; i < tiles.size(); i ++) { + ItemStack stack = tiles.get(i).provide(); + if (stack.getItem() instanceof SummoningStaffItem s) { + tiles.get(i).replace(s.addCharges(stack, entityTags)); + break; + } + } + return RitualResult.TERMINATE; + } +} diff --git a/src/main/java/elucent/eidolon/ritual/CrystalRitual.java b/src/main/java/elucent/eidolon/ritual/CrystalRitual.java index 7b5580b..ba8404b 100644 --- a/src/main/java/elucent/eidolon/ritual/CrystalRitual.java +++ b/src/main/java/elucent/eidolon/ritual/CrystalRitual.java @@ -23,7 +23,7 @@ public CrystalRitual() { @Override public RitualResult start(Level world, BlockPos pos) { - List entities = world.getEntitiesOfClass(LivingEntity.class, getSearchBounds(pos), (e) -> e.isInvertedHealAndHarm() && e.canChangeDimensions()); + List entities = world.getEntitiesOfClass(LivingEntity.class, getSearchBounds(pos), (e) -> e.isInvertedHealAndHarm()); for (LivingEntity e : entities) { e.hurt(Registry.RITUAL_DAMAGE, e.getMaxHealth() * 1000); if (!world.isClientSide) { diff --git a/src/main/java/elucent/eidolon/ritual/FocusItemPresentRequirement.java b/src/main/java/elucent/eidolon/ritual/FocusItemPresentRequirement.java new file mode 100644 index 0000000..61c129b --- /dev/null +++ b/src/main/java/elucent/eidolon/ritual/FocusItemPresentRequirement.java @@ -0,0 +1,41 @@ +package elucent.eidolon.ritual; + +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.RitualConsumePacket; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.tags.Tag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +public class FocusItemPresentRequirement extends FocusItemRequirement { + public FocusItemPresentRequirement(ItemStack item) { + super(item); + } + + public FocusItemPresentRequirement(Item item) { + super(item); + } + + public FocusItemPresentRequirement(Block block) { + super(block); + } + + public FocusItemPresentRequirement(Tag item) { + super(item); + } + + public FocusItemPresentRequirement(Function item) { + super(item); + } + + public void whenMet(Ritual ritual, Level world, BlockPos pos, RequirementInfo info) { + // + } +} diff --git a/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java b/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java index c82e234..f378c49 100644 --- a/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java +++ b/src/main/java/elucent/eidolon/ritual/FocusItemRequirement.java @@ -1,6 +1,8 @@ package elucent.eidolon.ritual; import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; import elucent.eidolon.network.Networking; import elucent.eidolon.network.RitualConsumePacket; @@ -31,10 +33,13 @@ public FocusItemRequirement(Tag item) { this.match = item; } + public FocusItemRequirement(Function item) { + this.match = item; + } + @Override public RequirementInfo isMet(Ritual ritual, Level world, BlockPos pos) { - List tiles = Ritual.getTilesWithinAABB(IRitualItemProvider.class, world, ritual.getSearchBounds(pos)); - System.out.println(tiles.size()); + List tiles = Ritual.getTilesWithinAABB(IRitualItemFocus.class, world, ritual.getSearchBounds(pos)); if (tiles.isEmpty()) return RequirementInfo.FALSE; for (int i = 0; i < tiles.size(); i ++) { ItemStack stack = tiles.get(i).provide(); @@ -48,6 +53,9 @@ else if (match instanceof Item && stack.getItem() == (Item)match) { else if (match instanceof Tag && ((Tag)match).contains(stack.getItem())) { return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); } + else if (match instanceof Function && ((Function)match).apply(stack)) { + return new RequirementInfo(true, ((BlockEntity)tiles.get(i)).getBlockPos()); + } } return RequirementInfo.FALSE; diff --git a/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java b/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java index 33bf705..f466be6 100644 --- a/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java +++ b/src/main/java/elucent/eidolon/ritual/IRitualItemFocus.java @@ -1,3 +1,7 @@ package elucent.eidolon.ritual; -public interface IRitualItemFocus extends IRitualItemProvider {} +import net.minecraft.world.item.ItemStack; + +public interface IRitualItemFocus extends IRitualItemProvider { + void replace(ItemStack stack); +} diff --git a/src/main/java/elucent/eidolon/ritual/RechargingRitual.java b/src/main/java/elucent/eidolon/ritual/RechargingRitual.java new file mode 100644 index 0000000..7860a48 --- /dev/null +++ b/src/main/java/elucent/eidolon/ritual/RechargingRitual.java @@ -0,0 +1,42 @@ +package elucent.eidolon.ritual; + +import java.util.List; +import java.util.function.Predicate; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.item.IRechargeableWand; +import elucent.eidolon.network.Networking; +import elucent.eidolon.network.RitualConsumePacket; +import elucent.eidolon.util.ColorUtil; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.Tag; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class RechargingRitual extends Ritual { + public static final ResourceLocation SYMBOL = new ResourceLocation(Eidolon.MODID, "particle/recharge_ritual"); + + public RechargingRitual() { + super(SYMBOL, ColorUtil.packColor(255, 220, 180, 701)); + } + + @Override + public RitualResult start(Level world, BlockPos pos) { + List tiles = Ritual.getTilesWithinAABB(IRitualItemFocus.class, world, getSearchBounds(pos)); + if (!tiles.isEmpty()) for (int i = 0; i < tiles.size(); i ++) { + ItemStack stack = tiles.get(i).provide(); + if (stack.getItem() instanceof IRechargeableWand) { + tiles.get(i).replace(((IRechargeableWand)stack.getItem()).recharge(stack)); + if (!world.isClientSide && tiles.get(i) instanceof BlockEntity b) { + Networking.sendToTracking(world, b.getBlockPos(), new RitualConsumePacket(pos.above(2), b.getBlockPos(), getRed(), getGreen(), getBlue())); + } + break; + } + } + return RitualResult.TERMINATE; + } +} diff --git a/src/main/java/elucent/eidolon/ritual/RitualRegistry.java b/src/main/java/elucent/eidolon/ritual/RitualRegistry.java index cd47230..4c1808e 100644 --- a/src/main/java/elucent/eidolon/ritual/RitualRegistry.java +++ b/src/main/java/elucent/eidolon/ritual/RitualRegistry.java @@ -15,6 +15,7 @@ import elucent.eidolon.codex.Page; import elucent.eidolon.codex.RitualPage; import elucent.eidolon.gui.jei.RecipeWrappers; +import elucent.eidolon.item.IRechargeableWand; import elucent.eidolon.util.RecipeUtil; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -172,8 +173,9 @@ public static Ritual find(Level world, BlockPos pos, ItemStack sacrifice) { SUMMON_ZOMBIE, SUMMON_SKELETON, SUMMON_PHANTOM, SUMMON_HUSK, SUMMON_DROWNED, SUMMON_STRAY, SUMMON_WITHER_SKELETON, SUMMON_WRAITH, ALLURE_RITUAL, REPELLING_RITUAL, DECEIT_RITUAL, DAYLIGHT_RITUAL, MOONLIGHT_RITUAL, - PURIFY_RITUAL, - SANGUINE_SWORD, SANGUINE_AMULET; + PURIFY_RITUAL, RECHARGE_SOULFIRE_RITUAL, RECHARGE_BONECHILL_RITUAL, + SANGUINE_SWORD, SANGUINE_AMULET, + ABSORB_RITUAL; public static void init() { CRYSTAL_RITUAL = register(Items.BONE_MEAL, new CrystalRitual().setRegistryName(Eidolon.MODID, "crystal") @@ -273,5 +275,24 @@ public static void init() { .addRequirement(new ItemRequirement(Tags.Items.DUSTS_REDSTONE)) .addRequirement(new ItemRequirement(Registry.LESSER_SOUL_GEM.get())) .addRequirement(new HealthRequirement(40))); + + RECHARGE_SOULFIRE_RITUAL = register(Registry.LESSER_SOUL_GEM.get(), new RechargingRitual().setRegistryName(Eidolon.MODID, "recharging") + .addRequirement(new ItemRequirement(Items.BLAZE_POWDER)) + .addRequirement(new ItemRequirement(Items.BLAZE_POWDER)) + .addRequirement(new ItemRequirement(Tags.Items.DUSTS_REDSTONE)) + .addInvariant(new FocusItemPresentRequirement(Registry.SOULFIRE_WAND.get()))); + + RECHARGE_BONECHILL_RITUAL = register(Registry.LESSER_SOUL_GEM.get(), new RechargingRitual().setRegistryName(Eidolon.MODID, "recharging") + .addRequirement(new ItemRequirement(Items.SNOWBALL)) + .addRequirement(new ItemRequirement(Items.SNOWBALL)) + .addRequirement(new ItemRequirement(Tags.Items.DUSTS_REDSTONE)) + .addInvariant(new FocusItemPresentRequirement(Registry.BONECHILL_WAND.get()))); + + ABSORB_RITUAL = register(Registry.DEATH_ESSENCE.get(), new AbsorptionRitual().setRegistryName(Eidolon.MODID, "absorption") + .addRequirement(new ItemRequirement(Registry.TATTERED_CLOTH.get())) + .addRequirement(new ItemRequirement(Registry.TATTERED_CLOTH.get())) + .addRequirement(new ItemRequirement(Items.BONE)) + .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get())) + .addRequirement(new ItemRequirement(Registry.SOUL_SHARD.get()))); } } diff --git a/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java b/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java deleted file mode 100644 index 410066a..0000000 --- a/src/main/java/elucent/eidolon/spell/KnowledgeUtil.java +++ /dev/null @@ -1,49 +0,0 @@ -package elucent.eidolon.spell; - -import elucent.eidolon.capability.IKnowledge; -import elucent.eidolon.network.KnowledgeUpdatePacket; -import elucent.eidolon.network.Networking; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.network.chat.TranslatableComponent; - -public class KnowledgeUtil { - public static void grantSign(Entity entity, Sign sign) { - if (!(entity instanceof Player)) return; - entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { - if (k.knowsSign(sign)) return; - k.addSign(sign); - - ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_sign", new TranslatableComponent(sign.key.getNamespace() + ".sign." + sign.key.getPath())))); - Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); - }); - } - - public static void grantFact(Entity entity, ResourceLocation fact) { - if (!(entity instanceof Player)) return; - entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { - if (k.knowsFact(fact)) return; - k.addFact(fact); - - ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_fact"))); - Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); - }); - } - - public static boolean knowsSign(Player player, Sign sign) { - if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { - return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsSign(sign); - } - return false; - } - - public static boolean knowsFact(Player player, ResourceLocation fact) { - if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { - return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsFact(fact); - } - return false; - } -} diff --git a/src/main/java/elucent/eidolon/spell/PrayerSpell.java b/src/main/java/elucent/eidolon/spell/PrayerSpell.java index f739c51..0d69b49 100644 --- a/src/main/java/elucent/eidolon/spell/PrayerSpell.java +++ b/src/main/java/elucent/eidolon/spell/PrayerSpell.java @@ -49,7 +49,6 @@ public void cast(Level world, BlockPos pos, Player player) { world.getCapability(IReputation.INSTANCE, null).ifPresent((rep) -> { rep.pray(player, getRegistryName(), world.getGameTime()); double prev = rep.getReputation(player, deity.getId()); - KnowledgeUtil.grantSign(player, Signs.FLAME_SIGN); rep.addReputation(player, deity.getId(), 1.0 + 0.25 * info.getPower()); }); } diff --git a/src/main/java/elucent/eidolon/spell/Rune.java b/src/main/java/elucent/eidolon/spell/Rune.java new file mode 100644 index 0000000..42b7f58 --- /dev/null +++ b/src/main/java/elucent/eidolon/spell/Rune.java @@ -0,0 +1,42 @@ +package elucent.eidolon.spell; + +import net.minecraft.resources.ResourceLocation; + +public abstract class Rune { + ResourceLocation key, sprite; + ResourceLocation registryName; + + public Rune(ResourceLocation registryName) { + this.key = registryName; + this.sprite = new ResourceLocation(key.getNamespace(), "rune/" + key.getPath()); + } + + public Rune(ResourceLocation registryName, ResourceLocation sprite) { + this.key = registryName; + this.sprite = sprite; + } + + public ResourceLocation getRegistryName() { + return key; + } + + public ResourceLocation getSprite() { + return sprite; + } + + public enum RuneResult { + PASS, FAIL + } + + public abstract RuneResult doEffect(SignSequence seq); + + @Override + public boolean equals(Object other) { + return other instanceof Sign && ((Sign)other).key.equals(key); + } + + @Override + public int hashCode() { + return key.hashCode(); + } +} diff --git a/src/main/java/elucent/eidolon/spell/Runes.java b/src/main/java/elucent/eidolon/spell/Runes.java new file mode 100644 index 0000000..ac7171b --- /dev/null +++ b/src/main/java/elucent/eidolon/spell/Runes.java @@ -0,0 +1,44 @@ +package elucent.eidolon.spell; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import elucent.eidolon.Eidolon; +import net.minecraft.resources.ResourceLocation; + +public class Runes { + static Map runes = new HashMap<>(); + + public static void register(Rune rune) { + runes.put(rune.getRegistryName(), rune); + } + + public static Rune find(ResourceLocation rl) { + return runes.getOrDefault(rl, null); + } + + public static Collection getRunes() { + return runes.values(); + } + + public static void init() { + register(new Rune(new ResourceLocation(Eidolon.MODID, "sin")) { + @Override + public RuneResult doEffect(SignSequence seq) { + seq.addRight(Signs.WICKED_SIGN); + return RuneResult.PASS; + } + }); + register(new Rune(new ResourceLocation(Eidolon.MODID, "crimson_rose")) { + @Override + public RuneResult doEffect(SignSequence seq) { + if (seq.removeRightmostN(Signs.WICKED_SIGN, 2)) { + seq.addRight(Signs.BLOOD_SIGN); + return RuneResult.PASS; + } + return RuneResult.FAIL; + } + }); + } +} diff --git a/src/main/java/elucent/eidolon/spell/SignSequence.java b/src/main/java/elucent/eidolon/spell/SignSequence.java new file mode 100644 index 0000000..b1cd5a9 --- /dev/null +++ b/src/main/java/elucent/eidolon/spell/SignSequence.java @@ -0,0 +1,175 @@ +package elucent.eidolon.spell; + +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import org.abego.treelayout.internal.util.java.lang.IterableUtil; + +import com.mojang.math.Vector3f; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; + +public class SignSequence { + public Deque seq = new ArrayDeque<>(); + public Sign last = null; + + public SignSequence() {} + + public SignSequence(Collection signs) { + seq.addAll(signs); + } + + public SignSequence(Sign... signs) { + for (Sign s : signs) seq.addLast(s); + } + + public void addLeft(Sign s) { + seq.addFirst(s); + } + + public void addRight(Sign s) { + seq.addLast(s); + } + + public void removeLeft() { + last = seq.getFirst(); + seq.removeFirst(); + } + + public void removeRight() { + last = seq.getLast(); + seq.removeLast(); + } + + private int count(Sign s) { + int count = 0; + Iterator iterator = seq.iterator(); + while (iterator.hasNext()) { + if (s.equals(iterator.next())) count ++; + } + return count; + } + + private boolean contains(Sign s) { + Iterator iterator = seq.iterator(); + while (iterator.hasNext()) { + if (s.equals(iterator.next())) return true; + } + return false; + } + + private boolean containsN(Sign s, int n) { + Iterator iterator = seq.iterator(); + int count = 0; + while (iterator.hasNext()) { + if (s.equals(iterator.next())) count ++; + if (count >= n) return true; + } + return false; + } + + public boolean removeLeftmost(Sign s) { + if (!seq.contains(s)) return false; + last = s; + seq.removeFirstOccurrence(s); + return true; + } + + public boolean removeRightmost(Sign s) { + if (!seq.contains(s)) return false; + last = s; + seq.removeLastOccurrence(s); + return true; + } + + public int removeAll(Sign s) { + int count = count(s); + if (seq.contains(s)) last = s; + seq.removeIf((i) -> i.equals(s)); + return count; + } + + public boolean removeLeftmostN(Sign s, int n) { + if (n == 0) return true; + if (!containsN(s, n)) return false; + last = s; + for (int i = 0; i < n; i ++) seq.removeFirstOccurrence(s); + return true; + } + + public boolean removeRightmostN(Sign s, int n) { + if (n == 0) return true; + if (!containsN(s, n)) return false; + last = s; + for (int i = 0; i < n; i ++) seq.removeLastOccurrence(s); + return true; + } + + public void map(Function tf) { + int n = seq.size(); + for (int i = 0; i < n; i ++) { + seq.addLast(tf.apply(seq.getFirst())); + } + } + + @Nullable + public Sign getLast() { + return last; + } + + public CompoundTag serializeNbt() { + CompoundTag tag = new CompoundTag(); + ListTag list = new ListTag(); + for (Sign s : seq) list.add(StringTag.valueOf(s.key.toString())); + tag.put("seq", list); + if (last != null) tag.putString("last", last.getRegistryName().toString()); + return tag; + } + + public static SignSequence deserializeNbt(CompoundTag tag) { + SignSequence s = new SignSequence(); + ListTag list = tag.getList("seq", Tag.TAG_STRING); + for (int i = 0; i < list.size(); i ++) { + Sign t = Signs.find(new ResourceLocation(list.getString(i))); + if (t != null) s.seq.addLast(t); + } + s.last = tag.contains("last") ? Signs.find(new ResourceLocation(tag.getString("last"))) : null; + return s; + } + + public Vector3f getAverageColor() { + float r = 1, g = 1, b = 1; + for (Sign s : seq) { + r += s.getRed(); + g += s.getGreen(); + b += s.getBlue(); + } + r /= seq.size() + 1; + g /= seq.size() + 1; + b /= seq.size() + 1; + return new Vector3f(r, g, b); + } + + @Override + public boolean equals(Object other) { + if (other instanceof SignSequence s) { + if (s.seq.size() != seq.size()) return false; + Iterator a = seq.iterator(), b = s.seq.iterator(); + while (a.hasNext() && b.hasNext()) { + Sign sa = a.next(), sb = b.next(); + if (!sa.equals(sb)) return false; + } + return true; + } + return false; + } +} diff --git a/src/main/java/elucent/eidolon/spell/Signs.java b/src/main/java/elucent/eidolon/spell/Signs.java index 48e2726..51a6ba9 100644 --- a/src/main/java/elucent/eidolon/spell/Signs.java +++ b/src/main/java/elucent/eidolon/spell/Signs.java @@ -53,19 +53,34 @@ public static List getSigns() { new ResourceLocation(Eidolon.MODID, "particle/mind_sign"), ColorUtil.packColor(255, 90, 121, 255) )), - WARDING_SIGN = register(new Sign( - new ResourceLocation(Eidolon.MODID, "warding"), - new ResourceLocation(Eidolon.MODID, "particle/warding_sign"), - ColorUtil.packColor(255, 190, 212, 184) - )), - ENERGY_SIGN = register(new Sign( - new ResourceLocation(Eidolon.MODID, "energy"), - new ResourceLocation(Eidolon.MODID, "particle/energy_sign"), - ColorUtil.packColor(255, 145, 250, 100) - )), FLAME_SIGN = register(new Sign( new ResourceLocation(Eidolon.MODID, "flame"), new ResourceLocation(Eidolon.MODID, "particle/flame_sign"), ColorUtil.packColor(255, 255, 128, 64) + )), + WINTER_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "winter"), + new ResourceLocation(Eidolon.MODID, "particle/winter_sign"), + ColorUtil.packColor(255, 112, 149, 210) + )), + HARMONY_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "harmony"), + new ResourceLocation(Eidolon.MODID, "particle/harmony_sign"), + ColorUtil.packColor(255, 141, 141, 195) + )), + DEATH_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "death"), + new ResourceLocation(Eidolon.MODID, "particle/death_sign"), + ColorUtil.packColor(255, 123, 140, 70) + )), + WARDING_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "warding"), + new ResourceLocation(Eidolon.MODID, "particle/warding_sign"), + ColorUtil.packColor(255, 118, 204, 175) + )), + MAGIC_SIGN = register(new Sign( + new ResourceLocation(Eidolon.MODID, "magic"), + new ResourceLocation(Eidolon.MODID, "particle/magic_sign"), + ColorUtil.packColor(255, 167, 85, 192) )); } diff --git a/src/main/java/elucent/eidolon/spell/Spell.java b/src/main/java/elucent/eidolon/spell/Spell.java index 5448924..9b8857a 100644 --- a/src/main/java/elucent/eidolon/spell/Spell.java +++ b/src/main/java/elucent/eidolon/spell/Spell.java @@ -17,7 +17,7 @@ public ResourceLocation getRegistryName() { return registryName; } - public abstract boolean matches(List signs); - public abstract boolean canCast(Level world, BlockPos pos, Player player, List signs); - public abstract void cast(Level world, BlockPos pos, Player player, List signs); + public abstract boolean matches(SignSequence signs); + public abstract boolean canCast(Level world, BlockPos pos, Player player, SignSequence signs); + public abstract void cast(Level world, BlockPos pos, Player player, SignSequence signs); } diff --git a/src/main/java/elucent/eidolon/spell/Spells.java b/src/main/java/elucent/eidolon/spell/Spells.java index a4e9a1d..1a74964 100644 --- a/src/main/java/elucent/eidolon/spell/Spells.java +++ b/src/main/java/elucent/eidolon/spell/Spells.java @@ -17,7 +17,7 @@ public static Spell find(ResourceLocation loc) { return spellMap.getOrDefault(loc, null); } - public static Spell find(List signs) { + public static Spell find(SignSequence signs) { for (Spell spell : spells) if (spell.matches(signs)) return spell; return null; } diff --git a/src/main/java/elucent/eidolon/spell/StaticSpell.java b/src/main/java/elucent/eidolon/spell/StaticSpell.java index eb50839..a9d7623 100644 --- a/src/main/java/elucent/eidolon/spell/StaticSpell.java +++ b/src/main/java/elucent/eidolon/spell/StaticSpell.java @@ -9,31 +9,29 @@ import net.minecraft.world.level.Level; public abstract class StaticSpell extends Spell { - List signs; + SignSequence signs; public StaticSpell(ResourceLocation name, Sign... signs) { super(name); - this.signs = Arrays.asList(signs); + this.signs = new SignSequence(signs); } @Override - public boolean matches(List signs) { - if (this.signs.size() != signs.size()) return false; - for (int i = 0; i < signs.size(); i ++) if (this.signs.get(i) != signs.get(i)) return false; - return true; + public boolean matches(SignSequence signs) { + return this.signs.equals(signs); } public abstract boolean canCast(Level world, BlockPos pos, Player player); @Override - public boolean canCast(Level world, BlockPos pos, Player player, List signs) { + public boolean canCast(Level world, BlockPos pos, Player player, SignSequence signs) { return canCast(world, pos, player); } public abstract void cast(Level world, BlockPos pos, Player player); @Override - public void cast(Level world, BlockPos pos, Player player, List signs) { + public void cast(Level world, BlockPos pos, Player player, SignSequence signs) { cast(world, pos, player); } } diff --git a/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java b/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java index d0ed0f2..18ff8a3 100644 --- a/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/BrazierTileEntity.java @@ -17,7 +17,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionHand; @@ -93,14 +92,12 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { tag.put("stack", stack.save(new CompoundTag())); tag.putBoolean("burning", burning); if (ritual != null) tag.putString("ritual", ritual.getRegistryName().toString()); tag.putInt("step", step); tag.putBoolean("ritualDone", ritualDone); - return tag; } protected void complete() { diff --git a/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java b/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java index c21778e..e01b959 100644 --- a/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/BrazierTileRenderer.java @@ -12,7 +12,6 @@ import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.core.BlockPos; import com.mojang.math.Vector3f; diff --git a/src/main/java/elucent/eidolon/tile/CabinetModel.java b/src/main/java/elucent/eidolon/tile/CabinetModel.java new file mode 100644 index 0000000..f575e88 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/CabinetModel.java @@ -0,0 +1,54 @@ +package elucent.eidolon.tile; +// Made with Blockbench 4.1.3 +// Exported for Minecraft version 1.17 with Mojang mappings +// Paste this class into your mod and generate all required imports + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import elucent.eidolon.Eidolon; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; + +public class CabinetModel extends EntityModel { + // This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into this model's constructor + public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(new ResourceLocation(Eidolon.MODID, "cabinet"), "main"); + private final ModelPart left_door; + private final ModelPart right_door; + + public CabinetModel(ModelPart root) { + this.left_door = root.getChild("left_door"); + this.right_door = root.getChild("right_door"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition left_door = partdefinition.addOrReplaceChild("left_door", CubeListBuilder.create().texOffs(0, 0).addBox(0.0F, -12.0F, -2.0F, 5.0F, 22.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(-5.0F, 8.0F, -5.0F)); + + PartDefinition right_door = partdefinition.addOrReplaceChild("right_door", CubeListBuilder.create().texOffs(14, 0).addBox(-5.0F, -12.0F, -2.0F, 5.0F, 22.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(5.0F, 8.0F, -5.0F)); + + return LayerDefinition.create(meshdefinition, 32, 32); + } + + @Override + public void setupAnim(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) { + left_door.render(poseStack, buffer, packedLight, packedOverlay); + right_door.render(poseStack, buffer, packedLight, packedOverlay); + } +} \ No newline at end of file diff --git a/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java b/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java index 0201700..a0b74a8 100644 --- a/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/CrucibleTileEntity.java @@ -5,6 +5,7 @@ import java.util.Random; import java.util.function.Predicate; +import elucent.eidolon.Config; import elucent.eidolon.Registry; import elucent.eidolon.network.CrucibleFailPacket; import elucent.eidolon.network.CrucibleSuccessPacket; @@ -156,8 +157,7 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { ListTag steps = new ListTag(); for (CrucibleStep step : this.steps) steps.add(step.write()); tag.put("steps", steps); @@ -165,7 +165,6 @@ public CompoundTag save(CompoundTag tag) { tag.putBoolean("hasWater", hasWater); tag.putInt("stirs", stirs); tag.putInt("stirTicks", stirTicks); - return tag; } public void tick() { @@ -252,7 +251,7 @@ else if (!boiling && isHeated) { } else { level.playSound(null, worldPosition, SoundEvents.BREWING_STAND_BREW, SoundSource.BLOCKS, 1.0f, 1.0f); // try continue - stepCounter = 100; + stepCounter = Config.CRUCIBLE_STEP_DURATION.get(); } stirs = 0; sync(); @@ -263,7 +262,7 @@ else if (!boiling && isHeated) { if (!level.isClientSide && stepCounter == 0 && steps.size() == 0 && hasWater && boiling && level.getGameTime() % 100 == 0) { List items = level.getEntitiesOfClass(ItemEntity.class, new AABB(worldPosition).deflate(0.125)); - if (items.size() > 0) stepCounter = 40; + if (items.size() > 0) stepCounter = Config.CRUCIBLE_STEP_DURATION.get() / 2; } } } diff --git a/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java b/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java index b6adab3..4d45f25 100644 --- a/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/CrucibleTileRenderer.java @@ -4,15 +4,22 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; import net.minecraft.client.Minecraft; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.util.FastColor.ARGB32; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; @@ -21,14 +28,22 @@ import net.minecraft.client.renderer.BiomeColors; public class CrucibleTileRenderer implements BlockEntityRenderer { -// private final ModelPart stirrer; + private final ModelPart stirrer; public static final ResourceLocation STIRRER_TEXTURE = new ResourceLocation(Eidolon.MODID, "textures/block/crucible_stirrer.png"); + + public static LayerDefinition createModelLayer() { + MeshDefinition mesh = new MeshDefinition(); + + PartDefinition root = mesh.getRoot(); + PartDefinition stirrer = root.addOrReplaceChild("stirrer", CubeListBuilder.create() + .texOffs(0, 8).addBox(-1.5F, 0.0F, -1.5F, 3.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)) + .texOffs(0, 0).addBox(-1.0F, 3.0F, -1.0F, 2.0F, 6.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 0.0F, 0.0F)); + + return LayerDefinition.create(mesh, 16, 16); + } public CrucibleTileRenderer() { -// stirrer = new ModelPart(16, 16, 0, 0); -// stirrer.setPos(0.0F, 0.0F, 0.0F); -// stirrer.texOffs(0, 8).addBox(-1.5F, 0.0F, -1.5F, 3.0F, 3.0F, 3.0F, 0.0F, false); -// stirrer.texOffs(0, 0).addBox(-1.0F, 3.0F, -1.0F, 2.0F, 6.0F, 2.0F, 0.0F, false); + this.stirrer = Minecraft.getInstance().getEntityModels().bakeLayer(ClientRegistry.CRUCIBLE_STIRRER_LAYER).getChild("stirrer"); } @Override @@ -41,8 +56,8 @@ public void render(CrucibleTileEntity tile, float partialTicks, PoseStack matrix matrixStackIn.translate(0.5, 0.625, 0.5); matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(45 + coeff * 360)); matrixStackIn.translate(0, -0.125 * Math.sin(coeff * Math.PI), 0.125); -// stirrer.xRot = (float) Math.PI / 8 * (1.0f - (float) Math.sin(coeff * Math.PI)); -// stirrer.render(matrixStackIn, bufferIn.getBuffer(RenderType.entitySolid(STIRRER_TEXTURE)), combinedLightIn, combinedOverlayIn); + stirrer.xRot = (float) Math.PI / 8 * (1.0f - (float) Math.sin(coeff * Math.PI)); + stirrer.render(matrixStackIn, bufferIn.getBuffer(RenderType.entitySolid(STIRRER_TEXTURE)), combinedLightIn, combinedOverlayIn); matrixStackIn.popPose(); } if (tile.hasWater) { diff --git a/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java b/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java index 0999d4f..fb74b51 100644 --- a/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/EffigyTileEntity.java @@ -30,9 +30,7 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { tag.putLong("previous", previous); - return tag; } } diff --git a/src/main/java/elucent/eidolon/tile/GobletTileEntity.java b/src/main/java/elucent/eidolon/tile/GobletTileEntity.java index e71056d..9f77fcb 100644 --- a/src/main/java/elucent/eidolon/tile/GobletTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/GobletTileEntity.java @@ -32,9 +32,7 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { if (type != null) tag.putString("type", type.getRegistryName().toString()); - return tag; } } diff --git a/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java b/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java index b96e361..3419a04 100644 --- a/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/GobletTileRenderer.java @@ -9,7 +9,6 @@ import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.resources.ResourceLocation; import com.mojang.math.Matrix4f; diff --git a/src/main/java/elucent/eidolon/tile/HandTileEntity.java b/src/main/java/elucent/eidolon/tile/HandTileEntity.java index e358f72..bd2b068 100644 --- a/src/main/java/elucent/eidolon/tile/HandTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/HandTileEntity.java @@ -56,10 +56,8 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { tag.put("stack", stack.save(new CompoundTag())); - return tag; } @Override diff --git a/src/main/java/elucent/eidolon/tile/HandTileRenderer.java b/src/main/java/elucent/eidolon/tile/HandTileRenderer.java index dac242c..9032e4b 100644 --- a/src/main/java/elucent/eidolon/tile/HandTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/HandTileRenderer.java @@ -7,7 +7,6 @@ import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import com.mojang.math.Vector3f; public class HandTileRenderer implements BlockEntityRenderer { diff --git a/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java b/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java index c1d7162..8ed4f89 100644 --- a/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/NecroticFocusTileEntity.java @@ -56,10 +56,8 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { tag.put("stack", stack.save(new CompoundTag())); - return tag; } @Override @@ -72,4 +70,10 @@ public void take() { stack = ItemStack.EMPTY; if (!level.isClientSide) sync(); } + + @Override + public void replace(ItemStack stack) { + this.stack = stack; + if (!level.isClientSide) sync(); + } } diff --git a/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java b/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java index 43adea3..ce78ff0 100644 --- a/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/NecroticFocusTileRenderer.java @@ -8,7 +8,6 @@ import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.core.Direction; import com.mojang.math.Vector3f; diff --git a/src/main/java/elucent/eidolon/tile/ResearchTableTileEntity.java b/src/main/java/elucent/eidolon/tile/ResearchTableTileEntity.java new file mode 100644 index 0000000..9af48a5 --- /dev/null +++ b/src/main/java/elucent/eidolon/tile/ResearchTableTileEntity.java @@ -0,0 +1,271 @@ +package elucent.eidolon.tile; + +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; + +import javax.annotation.Nullable; + +import elucent.eidolon.Eidolon; +import elucent.eidolon.Registry; +import elucent.eidolon.block.WoodenStandBlock; +import elucent.eidolon.gui.ResearchTableContainer; +import elucent.eidolon.gui.WoodenBrewingStandContainer; +import elucent.eidolon.research.Research; +import elucent.eidolon.research.Researches; +import elucent.eidolon.research.ResearchTask; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.BrewingStandBlock; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.WorldlyContainer; +import net.minecraft.world.Containers; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.Nameable; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.alchemy.PotionBrewing; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.core.Direction; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.core.NonNullList; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.common.Tags; +import net.minecraftforge.common.util.LazyOptional; + +public class ResearchTableTileEntity extends TileEntityBase implements WorldlyContainer, MenuProvider { + private static final int[] SLOTS = new int[]{0, 1}; + private NonNullList stacks = NonNullList.withSize(2, ItemStack.EMPTY); + private NonNullList tasks = NonNullList.create(); + private Component name; + private int progress; + private int worldSeed; + private List listeners = new ArrayList<>(); + + static final int SEED = 1418644859; + + public final ContainerData dataAccess = new ContainerData() { + @Override + public int get(int index) { + switch(index) { + case 0: + return ResearchTableTileEntity.this.progress; + case 1: + return ResearchTableTileEntity.this.worldSeed; + default: + return 0; + } + } + + @Override + public void set(int index, int value) { + switch(index) { + case 0: + ResearchTableTileEntity.this.progress = value; + break; + case 1: + break; // can't set seed + } + } + + @Override + public int getCount() { + return 2; + } + }; + + public ResearchTableTileEntity(BlockPos pos, BlockState state) { + super(Registry.RESEARCH_TABLE_TILE_ENTITY, pos, state); + progress = 0; + } + + @Override + public void onLoad() { + super.onLoad(); + if (!level.isClientSide) worldSeed = SEED + 978060631 * (int)((ServerLevel)level).getSeed(); + } + + protected Component getDefaultName() { + return new TranslatableComponent("container." + Eidolon.MODID + ".research_table"); + } + + public void addListener(ContainerListener listener) { + this.listeners.add(listener); + } + + public void removeListener(ContainerListener listener) { + this.listeners.remove(listener); + } + + @Override + public int getContainerSize() { + return this.stacks.size(); + } + + @Override + public boolean isEmpty() { + for(ItemStack itemstack : this.stacks) { + if (!itemstack.isEmpty()) { + return false; + } + } + return true; + } + + @Override + public void onDestroyed(BlockState state, BlockPos pos) { + for (ItemStack stack : stacks) { + if (!stack.isEmpty()) Containers.dropItemStack(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stack); + } + } + + public void tick() { + if (progress < 0) { + progress = 0; + sync(); + } + if (progress > 0) { + if (stacks.get(0).isEmpty() || stacks.get(0).getItem() != Registry.RESEARCH_NOTES.get()) { + progress = 0; + sync(); + for (ContainerListener listener : listeners) + listener.dataChanged((AbstractContainerMenu)listener, 0, progress); + return; + } + progress --; + if (progress == 0) { + ItemStack notes = stacks.get(0); + CompoundTag notesTag = notes.getTag(); + Research r = Researches.find(new ResourceLocation(notesTag.getString("research"))); + int done = notesTag.getInt("stepsDone"); + done ++; + notesTag.putInt("stepsDone", done); + for (ContainerListener listener : listeners) + listener.slotChanged((AbstractContainerMenu)listener, 0, stacks.get(0)); + } + sync(); + for (ContainerListener listener : listeners) + listener.dataChanged((AbstractContainerMenu)listener, 0, progress); + } + } + + @Override + public void load(CompoundTag nbt) { + super.load(nbt); + this.stacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + ContainerHelper.loadAllItems(nbt, this.stacks); + this.progress = nbt.getInt("progress"); + this.worldSeed = nbt.getInt("worldSeed"); + } + + @Override + public void saveAdditional(CompoundTag compound) { + super.saveAdditional(compound); + compound.putInt("progress", this.progress); + compound.putInt("worldSeed", worldSeed); + ContainerHelper.saveAllItems(compound, this.stacks); + } + + @Override + public ItemStack getItem(int index) { + return index >= 0 && index < this.stacks.size() ? this.stacks.get(index) : ItemStack.EMPTY; + } + + @Override + public ItemStack removeItem(int index, int count) { + return ContainerHelper.removeItem(this.stacks, index, count); + } + + @Override + public ItemStack removeItemNoUpdate(int index) { + return ContainerHelper.takeItem(this.stacks, index); + } + + @Override + public void setItem(int index, ItemStack stack) { + if (index >= 0 && index < this.stacks.size()) { + this.stacks.set(index, stack); + } + } + + @Override + public boolean stillValid(Player player) { + if (this.level.getBlockEntity(this.worldPosition) != this) { + return false; + } else { + return !(player.distanceToSqr((double)this.worldPosition.getX() + 0.5D, (double)this.worldPosition.getY() + 0.5D, (double)this.worldPosition.getZ() + 0.5D) > 64.0D); + } + } + + @Override + public boolean canPlaceItem(int index, ItemStack stack) { + if (index == 0) { + return stack.is(Registry.RESEARCH_NOTES.get()); + } else if (index == 1) { + return stack.is(Registry.ARCANE_SEAL.get()); + } + return false; + } + + @Override + public int[] getSlotsForFace(Direction side) { + return SLOTS; + } + + @Override + public boolean canPlaceItemThroughFace(int index, ItemStack itemStackIn, @Nullable Direction direction) { + return this.canPlaceItem(index, itemStackIn); + } + + @Override + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { + if (index == 0) { + return stack.is(Registry.COMPLETED_RESEARCH.get()); + } else { + return false; + } + } + + @Override + public void clearContent() { + this.stacks.clear(); + } + + @Override + public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { + return new ResearchTableContainer(id, inv, this, this.dataAccess); + } + + net.minecraftforge.common.util.LazyOptional handler = + LazyOptional.of(() -> new net.minecraftforge.items.wrapper.InvWrapper(this)); + + @Override + public net.minecraftforge.common.util.LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { + if (!this.remove && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return handler.cast(); + } + return super.getCapability(capability, facing); + } + + @Override + public void setRemoved() { + super.setRemoved(); + handler.invalidate(); + } + + @Override + public Component getDisplayName() { + return new TextComponent(""); // Not rendered in the GUI. + } +} diff --git a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java index a51a372..e92b100 100644 --- a/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/SoulEnchanterTileRenderer.java @@ -13,7 +13,6 @@ import net.minecraft.client.resources.model.Material; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import com.mojang.math.Vector3f; diff --git a/src/main/java/elucent/eidolon/tile/TileEntityBase.java b/src/main/java/elucent/eidolon/tile/TileEntityBase.java index ce922da..61e4963 100644 --- a/src/main/java/elucent/eidolon/tile/TileEntityBase.java +++ b/src/main/java/elucent/eidolon/tile/TileEntityBase.java @@ -29,20 +29,24 @@ public InteractionResult onActivated(BlockState state, BlockPos pos, Player play public void sync() { setChanged(); - if (level.isClientSide) - Networking.INSTANCE.sendToServer(new TESyncPacket(worldPosition, save(new CompoundTag()))); - else - Networking.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(worldPosition)), new TESyncPacket(worldPosition, save(new CompoundTag()))); +// if (level.isClientSide) +// Networking.INSTANCE.sendToServer(new TESyncPacket(worldPosition, save(new CompoundTag()))); +// else + CompoundTag tag = new CompoundTag(); + saveAdditional(tag); + Networking.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(worldPosition)), new TESyncPacket(worldPosition, tag)); } @Override public CompoundTag getUpdateTag() { - return this.save(new CompoundTag()); + CompoundTag tag = new CompoundTag(); + this.saveAdditional(tag); + return tag; } @Override public ClientboundBlockEntityDataPacket getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this); // (this.worldPosition, 3, this.getUpdateTag()); + return ClientboundBlockEntityDataPacket.create(this, (e) -> e.getUpdateTag()); // (this.worldPosition, 3, this.getUpdateTag()); } @Override diff --git a/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java b/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java index ef7beb9..f60a663 100644 --- a/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/WoodenStandTileEntity.java @@ -202,11 +202,10 @@ public void load(CompoundTag nbt) { } @Override - public CompoundTag save(CompoundTag compound) { - super.save(compound); + public void saveAdditional(CompoundTag compound) { + super.saveAdditional(compound); compound.putShort("BrewTime", (short)this.brewTime); ContainerHelper.saveAllItems(compound, this.brewingItemStacks); - return compound; } @Override diff --git a/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java b/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java index af454b4..81560ca 100644 --- a/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/reagent/CisternTileRenderer.java @@ -10,7 +10,6 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; public class CisternTileRenderer implements BlockEntityRenderer { diff --git a/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java b/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java index 2656237..1597a16 100644 --- a/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java +++ b/src/main/java/elucent/eidolon/tile/reagent/PipeTileRenderer.java @@ -11,7 +11,6 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.core.Direction; public class PipeTileRenderer implements BlockEntityRenderer { diff --git a/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java b/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java index a64a8a9..e39d260 100644 --- a/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java +++ b/src/main/java/elucent/eidolon/tile/reagent/ReagentTankTileEntity.java @@ -9,7 +9,6 @@ import elucent.eidolon.tile.TileEntityBase; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.core.BlockPos; @@ -31,10 +30,9 @@ public void load(CompoundTag tag) { } @Override - public CompoundTag save(CompoundTag tag) { - tag = super.save(tag); + public void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); tag.put("tank", tank.write()); - return tag; } public void tick() { diff --git a/src/main/java/elucent/eidolon/util/KnowledgeUtil.java b/src/main/java/elucent/eidolon/util/KnowledgeUtil.java new file mode 100644 index 0000000..974e9f4 --- /dev/null +++ b/src/main/java/elucent/eidolon/util/KnowledgeUtil.java @@ -0,0 +1,157 @@ +package elucent.eidolon.util; + +import elucent.eidolon.capability.IKnowledge; +import elucent.eidolon.network.KnowledgeUpdatePacket; +import elucent.eidolon.network.Networking; +import elucent.eidolon.research.Researches; +import elucent.eidolon.spell.Rune; +import elucent.eidolon.spell.Sign; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.TranslatableComponent; + +public class KnowledgeUtil { + public static void grantSign(Entity entity, Sign sign) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (k.knowsSign(sign)) return; + k.addSign(sign); + + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_sign", new TranslatableComponent(sign.getRegistryName().getNamespace() + ".sign." + sign.getRegistryName().getPath())))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void grantFact(Entity entity, ResourceLocation fact) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (k.knowsFact(fact)) return; + k.addFact(fact); + + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_fact"))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void grantResearch(Entity entity, ResourceLocation research) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (k.knowsResearch(research)) return; + k.addResearch(research); + + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_research", ChatFormatting.GOLD + Researches.find(research).getName()))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void grantRune(Entity entity, Rune rune) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (k.knowsRune(rune)) return; + k.addRune(rune); + + ((ServerPlayer)entity).connection.send(new ClientboundSetActionBarTextPacket(new TranslatableComponent("eidolon.title.new_rune", new TranslatableComponent(rune.getRegistryName().getNamespace() + ".rune." + rune.getRegistryName().getPath())))); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static boolean knowsSign(Player player, Sign sign) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsSign(sign); + } + return false; + } + + public static boolean knowsFact(Player player, ResourceLocation fact) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsFact(fact); + } + return false; + } + + public static boolean knowsResearch(Player player, ResourceLocation research) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsResearch(research); + } + return false; + } + + public static boolean knowsRune(Player player, Rune rune) { + if (player.getCapability(IKnowledge.INSTANCE).isPresent()) { + return player.getCapability(IKnowledge.INSTANCE).resolve().get().knowsRune(rune); + } + return false; + } + + public static void removeSign(Entity entity, Sign sign) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (!k.knowsSign(sign)) return; + k.removeSign(sign); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void removeFact(Entity entity, ResourceLocation fact) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (!k.knowsFact(fact)) return; + k.removeFact(fact); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void removeResearch(Entity entity, ResourceLocation research) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (!k.knowsResearch(research)) return; + k.removeResearch(research); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void removeRune(Entity entity, Rune rune) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + if (!k.knowsRune(rune)) return; + k.removeRune(rune); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void resetSigns(Entity entity) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + k.resetSigns(); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void resetFacts(Entity entity) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + k.resetFacts(); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void resetResearch(Entity entity) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + k.resetResearch(); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } + + public static void resetRunes(Entity entity) { + if (!(entity instanceof ServerPlayer)) return; + entity.getCapability(IKnowledge.INSTANCE, null).ifPresent((k) -> { + k.resetRunes(); + Networking.sendTo((Player)entity, new KnowledgeUpdatePacket((Player)entity, true)); + }); + } +} diff --git a/src/main/java/elucent/eidolon/util/RecipeUtil.java b/src/main/java/elucent/eidolon/util/RecipeUtil.java index 536a032..0458df6 100644 --- a/src/main/java/elucent/eidolon/util/RecipeUtil.java +++ b/src/main/java/elucent/eidolon/util/RecipeUtil.java @@ -9,11 +9,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.server.MinecraftServer; import net.minecraft.tags.Tag; -import net.minecraftforge.common.util.LogicalSidedProvider; import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.server.ServerLifecycleHooks; public class RecipeUtil { diff --git a/src/main/java/elucent/eidolon/util/RenderUtil.java b/src/main/java/elucent/eidolon/util/RenderUtil.java index 8e7f649..ae06588 100644 --- a/src/main/java/elucent/eidolon/util/RenderUtil.java +++ b/src/main/java/elucent/eidolon/util/RenderUtil.java @@ -2,8 +2,6 @@ import java.util.Random; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; @@ -11,6 +9,7 @@ import com.mojang.blaze3d.vertex.VertexFormat.Mode; import elucent.eidolon.ClientEvents; +import elucent.eidolon.ClientRegistry; import elucent.eidolon.Eidolon; import elucent.eidolon.Registry; import net.minecraft.client.Minecraft; @@ -27,8 +26,6 @@ import com.mojang.math.Quaternion; import net.minecraft.world.phys.Vec3; import com.mojang.math.Vector3f; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; public class RenderUtil { public static final RenderStateShard.TransparencyStateShard ADDITIVE_TRANSPARENCY = new RenderStateShard.TransparencyStateShard("lightning_transparency", () -> { @@ -75,7 +72,7 @@ public class RenderUtil { .setLightmapState(new RenderStateShard.LightmapStateShard(false)) .setTransparencyState(ADDITIVE_TRANSPARENCY) .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) - .setShaderState(new ShaderStateShard(Registry::getGlowingSpriteShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getGlowingSpriteShader)) .createCompositeState(false) ), GLOWING = RenderType.create( Eidolon.MODID + ":glowing", @@ -85,7 +82,7 @@ public class RenderUtil { .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) .setLightmapState(new RenderStateShard.LightmapStateShard(false)) .setTransparencyState(ADDITIVE_TRANSPARENCY) - .setShaderState(new ShaderStateShard(Registry::getGlowingShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getGlowingShader)) .createCompositeState(false) ), DELAYED_PARTICLE = RenderType.create( Eidolon.MODID + ":delayed_particle", @@ -95,7 +92,7 @@ public class RenderUtil { .setWriteMaskState(new RenderStateShard.WriteMaskStateShard(true, false)) .setTransparencyState(NORMAL_TRANSPARENCY) .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_PARTICLES, false, false)) - .setShaderState(new ShaderStateShard(GameRenderer::getParticleShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getSpriteParticleShader)) .createCompositeState(false) ), GLOWING_PARTICLE = RenderType.create( Eidolon.MODID + ":glowing_particle", @@ -106,7 +103,7 @@ public class RenderUtil { .setLightmapState(new RenderStateShard.LightmapStateShard(false)) .setTransparencyState(ADDITIVE_TRANSPARENCY) .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_PARTICLES, false, false)) - .setShaderState(new ShaderStateShard(Registry::getGlowingParticleShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getGlowingParticleShader)) .createCompositeState(false) ), GLOWING_BLOCK_PARTICLE = RenderType.create( Eidolon.MODID + ":glowing_particle", @@ -117,7 +114,7 @@ public class RenderUtil { .setLightmapState(new RenderStateShard.LightmapStateShard(false)) .setTransparencyState(ADDITIVE_TRANSPARENCY) .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) - .setShaderState(new ShaderStateShard(Registry::getGlowingParticleShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getGlowingParticleShader)) .createCompositeState(false) ), VAPOR_TRANSLUCENT = RenderType.create( Eidolon.MODID + ":vapor_translucent", @@ -127,13 +124,13 @@ public class RenderUtil { .setLightmapState(new RenderStateShard.LightmapStateShard(false)) .setTransparencyState(NORMAL_TRANSPARENCY) .setTextureState(new RenderStateShard.TextureStateShard(TextureAtlas.LOCATION_BLOCKS, false, false)) - .setShaderState(new ShaderStateShard(Registry::getVaporShader)) + .setShaderState(new ShaderStateShard(ClientRegistry::getVaporShader)) .createCompositeState(false) ); static double ticks = 0; - public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, TextureAtlasSprite sprite) { + public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, float a, TextureAtlasSprite sprite) { VertexConsumer builder = buffer.getBuffer(GLOWING_SPRITE); float f7 = sprite.getU0(); @@ -141,10 +138,14 @@ public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, float f5 = sprite.getV0(); float f6 = sprite.getV1(); Matrix4f mat = mStack.last().pose(); - builder.vertex(mat, (float)x, (float)y + (float)h, 0).uv(f7, f6).color(r, g, b, 1.0f).endVertex(); - builder.vertex(mat, (float)x + (float)w, (float)y + (float)h, 0).uv(f8, f6).color(r, g, b, 1.0f).endVertex(); - builder.vertex(mat, (float)x + (float)w, (float)y, 0).uv(f8, f5).color(r, g, b, 1.0f).endVertex(); - builder.vertex(mat, (float)x, (float)y, 0).uv(f7, f5).color(r, g, b, 1.0f).endVertex(); + builder.vertex(mat, (float)x, (float)y + (float)h, 0).uv(f7, f6).color(r, g, b, a).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y + (float)h, 0).uv(f8, f6).color(r, g, b, a).endVertex(); + builder.vertex(mat, (float)x + (float)w, (float)y, 0).uv(f8, f5).color(r, g, b, a).endVertex(); + builder.vertex(mat, (float)x, (float)y, 0).uv(f7, f5).color(r, g, b, a).endVertex(); + } + + public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, TextureAtlasSprite sprite) { + litQuad(mStack, buffer, x, y, w, h, r, g, b, 1.0f, sprite); } public static void litQuad(PoseStack mStack, MultiBufferSource buffer, double x, double y, double w, double h, float r, float g, float b, float u, float v, float uw, float vh) { diff --git a/src/main/java/elucent/eidolon/world/BasicPiece.java b/src/main/java/elucent/eidolon/world/BasicPiece.java index 465b198..54dd5a7 100644 --- a/src/main/java/elucent/eidolon/world/BasicPiece.java +++ b/src/main/java/elucent/eidolon/world/BasicPiece.java @@ -2,25 +2,19 @@ import java.util.Random; -import com.mojang.serialization.Dynamic; - import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; import net.minecraft.world.level.block.Mirror; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Rotation; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.RuinedPortalPiece; import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.levelgen.feature.StructurePieceType; import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; public class BasicPiece extends TemplateStructurePiece { diff --git a/src/main/java/elucent/eidolon/world/CatacombPieces.java b/src/main/java/elucent/eidolon/world/CatacombPieces.java index acbbe04..8574b0d 100644 --- a/src/main/java/elucent/eidolon/world/CatacombPieces.java +++ b/src/main/java/elucent/eidolon/world/CatacombPieces.java @@ -6,7 +6,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.Mirror; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Rotation; import net.minecraft.core.BlockPos; import net.minecraft.world.level.levelgen.feature.StructurePieceType; diff --git a/src/main/java/elucent/eidolon/world/CatacombStructure.java b/src/main/java/elucent/eidolon/world/CatacombStructure.java index fde708c..a7b75ca 100644 --- a/src/main/java/elucent/eidolon/world/CatacombStructure.java +++ b/src/main/java/elucent/eidolon/world/CatacombStructure.java @@ -15,29 +15,18 @@ import elucent.eidolon.Config; import elucent.eidolon.Eidolon; -import elucent.eidolon.world.LabStructure.LabPieceGenerator; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.Vec3i; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.StructureFeature; import net.minecraft.world.level.levelgen.structure.StructurePiece; -import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; -import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator.Context; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; diff --git a/src/main/java/elucent/eidolon/world/LabStructure.java b/src/main/java/elucent/eidolon/world/LabStructure.java index 86ba033..231c93a 100644 --- a/src/main/java/elucent/eidolon/world/LabStructure.java +++ b/src/main/java/elucent/eidolon/world/LabStructure.java @@ -2,41 +2,20 @@ import java.util.Random; -import com.google.common.base.Optional; import com.mojang.serialization.Codec; import elucent.eidolon.Config; import elucent.eidolon.Eidolon; import elucent.eidolon.WorldGen; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.Mirror; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.feature.StructurePieceType; import net.minecraft.world.level.levelgen.feature.StructureFeature; -import net.minecraft.world.level.levelgen.structure.StructureStart; -import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; -import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; public class LabStructure extends StructureFeature { public LabStructure(Codec codec) { diff --git a/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java b/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java index 8e7d64d..2ee259c 100644 --- a/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java +++ b/src/main/java/elucent/eidolon/world/RandomlyRotatedPiece.java @@ -5,7 +5,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.Mirror; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Rotation; import net.minecraft.core.BlockPos; import net.minecraft.world.level.levelgen.feature.StructurePieceType; diff --git a/src/main/java/elucent/eidolon/world/StrayTowerStructure.java b/src/main/java/elucent/eidolon/world/StrayTowerStructure.java index 02a4c0e..0d87330 100644 --- a/src/main/java/elucent/eidolon/world/StrayTowerStructure.java +++ b/src/main/java/elucent/eidolon/world/StrayTowerStructure.java @@ -7,37 +7,17 @@ import elucent.eidolon.Config; import elucent.eidolon.Eidolon; import elucent.eidolon.WorldGen; -import elucent.eidolon.world.LabStructure.LabPieceGenerator; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.Mirror; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.NoiseColumn; import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.feature.StructurePieceType; import net.minecraft.world.level.levelgen.feature.StructureFeature; -import net.minecraft.world.level.levelgen.structure.StructureStart; -import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; -import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator.Context; -import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; public class StrayTowerStructure extends StructureFeature { public StrayTowerStructure(Codec codec) { @@ -46,13 +26,14 @@ public StrayTowerStructure(Codec codec) { @Override public GenerationStep.Decoration step() { - return GenerationStep.Decoration.UNDERGROUND_STRUCTURES; + return GenerationStep.Decoration.SURFACE_STRUCTURES; } static Random rand = new Random(); static boolean isFeatureChunk(PieceGeneratorSupplier.Context ctx) { - int i = ctx.chunkPos().x >> 4; + if (!ctx.validBiomeOnTop(Types.WORLD_SURFACE)) return false; + int i = ctx.chunkPos().x >> 4; int j = ctx.chunkPos().z >> 4; rand.setSeed((long) (i ^ j << 4) * 1556190469); double prob = rand.nextInt(10000) / 10000.0f; @@ -64,7 +45,11 @@ public static class StrayTowerPieceGenerator implements PieceGenerator ctx) { int i = ctx.chunkPos().x * 16; int j = ctx.chunkPos().z * 16; - pieces.addPiece(new RandomlyRotatedPiece(WorldGen.STRAY_TOWER_PIECE, PART, ctx.structureManager(), new BlockPos(i, ctx.chunkGenerator().getBaseHeight(i, j, Heightmap.Types.WORLD_SURFACE_WG, ctx.heightAccessor()), j), ctx.random())); + int minH = 999; + for (int xx = -3; xx < 4; xx ++) for (int yy = -3; yy < 4; yy ++) { + minH = Math.min(minH, ctx.chunkGenerator().getBaseHeight(i + xx, j + yy, Types.WORLD_SURFACE_WG, ctx.heightAccessor())); + } + pieces.addPiece(new RandomlyRotatedPiece(WorldGen.STRAY_TOWER_PIECE, PART, ctx.structureManager(), new BlockPos(i, minH - 9, j), ctx.random())); } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index ace7d6b..4c2bf10 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,9 +1,13 @@ public net.minecraft.world.level.levelgen.structure.TemplateStructurePiece f_73658_ # templatePosition public net.minecraft.world.level.levelgen.feature.StructureFeature f_67032_ # structureList -public-f net.minecraft.world.level.levelgen.feature.StructureFeature m_67067_(Lnet/minecraft/world/level/levelgen/feature/configurations/StructureFeatureConfiguration;JLnet/minecraft/world/level/levelgen/WorldgenRandom;II)Lnet/minecraft/world/level/ChunkPos; #findPosForPos +public-f net.minecraft.world.level.levelgen.feature.StructureFeature m_67067_(Lnet/minecraft/world/level/levelgen/feature/configurations/StructureFeatureConfiguration;JLnet/minecraft/world/level/levelgen/WorldgenRandom;II)Lnet/minecraft/world/level/ChunkPos; # findPosForPos public-f net.minecraft.world.level.levelgen.StructureSettings f_64582_ # field_236193_d_ public-f net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings f_70349_ # STRUCTURES public net.minecraft.world.gen.DimensionSettings field_242740_q # INSTANCE public-f net.minecraft.world.level.levelgen.StructureSettings f_64580_ # DEFAULT_STRUCTURES public-f net.minecraft.world.level.levelgen.feature.StructureFeature f_67031_ # field_236384_t_ -public net.minecraft.world.gen.SpellcastingIllagerEntity field_193089_bx # activeSpell \ No newline at end of file +public net.minecraft.world.gen.SpellcastingIllagerEntity field_193089_bx # activeSpell +public-f net.minecraft.world.level.levelgen.feature.StructureFeature f_67031_ # NOISE_AFFECTING_FEATURES +public-f net.minecraft.world.level.levelgen.StructureSettings f_64580_ # DEFAULTS +public-f net.minecraft.world.level.levelgen.StructureSettings f_64582_ # structureConfig +public-f net.minecraft.world.level.levelgen.StructureSettings f_189361_ # configuredStructures \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/bone_pile.json b/src/main/resources/assets/eidolon/blockstates/bone_pile.json new file mode 100644 index 0000000..591cace --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/bone_pile.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/bone_pile" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/bone_pile_slab.json b/src/main/resources/assets/eidolon/blockstates/bone_pile_slab.json new file mode 100644 index 0000000..588d77e --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/bone_pile_slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "eidolon:item/bone_pile_slab" + }, + "type=double": { + "model": "eidolon:item/bone_pile" + }, + "type=top": { + "model": "eidolon:block/bone_pile_slab_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/bone_pile_stairs.json b/src/main/resources/assets/eidolon/blockstates/bone_pile_stairs.json new file mode 100644 index 0000000..5c77212 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/bone_pile_stairs.json @@ -0,0 +1,209 @@ +{ + "variants": { + "facing=east,half=bottom,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner" + }, + "facing=east,half=bottom,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer" + }, + "facing=east,half=bottom,shape=straight": { + "model": "eidolon:item/bone_pile_stairs" + }, + "facing=east,half=top,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "x": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=south,half=bottom,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner" + }, + "facing=south,half=bottom,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer" + }, + "facing=south,half=bottom,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_left": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_right": { + "model": "eidolon:block/bone_pile_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=outer_left": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=outer_right": { + "model": "eidolon:block/bone_pile_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=straight": { + "model": "eidolon:item/bone_pile_stairs", + "x": 180, + "y": 180, + "uvlock": true + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_bricks.json b/src/main/resources/assets/eidolon/blockstates/elder_bricks.json new file mode 100644 index 0000000..6db5031 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_bricks.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/elder_bricks" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_bricks_eye.json b/src/main/resources/assets/eidolon/blockstates/elder_bricks_eye.json new file mode 100644 index 0000000..8877019 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_bricks_eye.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/elder_bricks_eye" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_bricks_slab.json b/src/main/resources/assets/eidolon/blockstates/elder_bricks_slab.json new file mode 100644 index 0000000..374bb14 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_bricks_slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "eidolon:item/elder_bricks_slab" + }, + "type=double": { + "model": "eidolon:item/elder_bricks" + }, + "type=top": { + "model": "eidolon:block/elder_bricks_slab_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_bricks_stairs.json b/src/main/resources/assets/eidolon/blockstates/elder_bricks_stairs.json new file mode 100644 index 0000000..d9bf67a --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_bricks_stairs.json @@ -0,0 +1,209 @@ +{ + "variants": { + "facing=east,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner" + }, + "facing=east,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer" + }, + "facing=east,half=bottom,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs" + }, + "facing=east,half=top,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "x": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=south,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner" + }, + "facing=south,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer" + }, + "facing=south,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_left": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_right": { + "model": "eidolon:block/elder_bricks_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=outer_left": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=outer_right": { + "model": "eidolon:block/elder_bricks_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=straight": { + "model": "eidolon:item/elder_bricks_stairs", + "x": 180, + "y": 180, + "uvlock": true + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_bricks_wall.json b/src/main/resources/assets/eidolon/blockstates/elder_bricks_wall.json new file mode 100644 index 0000000..be0e6c9 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_bricks_wall.json @@ -0,0 +1,90 @@ +{ + "multipart": [ + { + "when": { + "up": "true" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_post" + } + }, + { + "when": { + "north": "low" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side", + "uvlock": true + } + }, + { + "when": { + "east": "low" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side", + "y": 90, + "uvlock": true + } + }, + { + "when": { + "south": "low" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side", + "y": 180, + "uvlock": true + } + }, + { + "when": { + "west": "low" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side", + "y": 270, + "uvlock": true + } + }, + { + "when": { + "north": "tall" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side_tall", + "uvlock": true + } + }, + { + "when": { + "east": "tall" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side_tall", + "y": 90, + "uvlock": true + } + }, + { + "when": { + "south": "tall" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side_tall", + "y": 180, + "uvlock": true + } + }, + { + "when": { + "west": "tall" + }, + "apply": { + "model": "eidolon:block/elder_bricks_wall_side_tall", + "y": 270, + "uvlock": true + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_masonry.json b/src/main/resources/assets/eidolon/blockstates/elder_masonry.json new file mode 100644 index 0000000..f30d2de --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_masonry.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/elder_masonry" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_masonry_slab.json b/src/main/resources/assets/eidolon/blockstates/elder_masonry_slab.json new file mode 100644 index 0000000..e6046b1 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_masonry_slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "eidolon:item/elder_masonry_slab" + }, + "type=double": { + "model": "eidolon:item/elder_masonry" + }, + "type=top": { + "model": "eidolon:block/elder_masonry_slab_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_masonry_stairs.json b/src/main/resources/assets/eidolon/blockstates/elder_masonry_stairs.json new file mode 100644 index 0000000..9de5f4a --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_masonry_stairs.json @@ -0,0 +1,209 @@ +{ + "variants": { + "facing=east,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner" + }, + "facing=east,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer" + }, + "facing=east,half=bottom,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs" + }, + "facing=east,half=top,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "x": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=south,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner" + }, + "facing=south,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer" + }, + "facing=south,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_left": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_right": { + "model": "eidolon:block/elder_masonry_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=outer_left": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=outer_right": { + "model": "eidolon:block/elder_masonry_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=straight": { + "model": "eidolon:item/elder_masonry_stairs", + "x": 180, + "y": 180, + "uvlock": true + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/elder_pillar.json b/src/main/resources/assets/eidolon/blockstates/elder_pillar.json new file mode 100644 index 0000000..a5aba43 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/elder_pillar.json @@ -0,0 +1,16 @@ +{ + "variants": { + "top=false,bottom=false": { + "model": "eidolon:item/elder_pillar" + }, + "top=true,bottom=false": { + "model": "eidolon:block/elder_pillar_bottom" + }, + "top=true,bottom=true": { + "model": "eidolon:block/elder_pillar_mid" + }, + "top=false,bottom=true": { + "model": "eidolon:block/elder_pillar_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_bark.json b/src/main/resources/assets/eidolon/blockstates/illwood_bark.json new file mode 100644 index 0000000..537b4e2 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_bark.json @@ -0,0 +1,16 @@ +{ + "variants": { + "axis=x": { + "model": "eidolon:block/illwood_bark_horizontal", + "x": 90, + "y": 90 + }, + "axis=y": { + "model": "eidolon:item/illwood_bark" + }, + "axis=z": { + "model": "eidolon:block/illwood_bark_horizontal", + "x": 90 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_leaves.json b/src/main/resources/assets/eidolon/blockstates/illwood_leaves.json new file mode 100644 index 0000000..4638239 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_leaves.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/illwood_leaves" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_log.json b/src/main/resources/assets/eidolon/blockstates/illwood_log.json new file mode 100644 index 0000000..20ce5df --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_log.json @@ -0,0 +1,16 @@ +{ + "variants": { + "axis=x": { + "model": "eidolon:block/illwood_log_horizontal", + "x": 90, + "y": 90 + }, + "axis=y": { + "model": "eidolon:item/illwood_log" + }, + "axis=z": { + "model": "eidolon:block/illwood_log_horizontal", + "x": 90 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_planks.json b/src/main/resources/assets/eidolon/blockstates/illwood_planks.json new file mode 100644 index 0000000..21d92cd --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_planks.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/illwood_planks" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence.json b/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence.json new file mode 100644 index 0000000..91e7074 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence.json @@ -0,0 +1,48 @@ +{ + "multipart": [ + { + "apply": { + "model": "eidolon:block/illwood_planks_fence_post" + } + }, + { + "when": { + "north": "true" + }, + "apply": { + "model": "eidolon:block/illwood_planks_fence_side", + "uvlock": true + } + }, + { + "when": { + "east": "true" + }, + "apply": { + "model": "eidolon:block/illwood_planks_fence_side", + "y": 90, + "uvlock": true + } + }, + { + "when": { + "south": "true" + }, + "apply": { + "model": "eidolon:block/illwood_planks_fence_side", + "y": 180, + "uvlock": true + } + }, + { + "when": { + "west": "true" + }, + "apply": { + "model": "eidolon:block/illwood_planks_fence_side", + "y": 270, + "uvlock": true + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence_gate.json b/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence_gate.json new file mode 100644 index 0000000..1f963c2 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_planks_fence_gate.json @@ -0,0 +1,80 @@ +{ + "variants": { + "facing=east,in_wall=false,open=false": { + "uvlock": true, + "y": 270, + "model": "eidolon:item/illwood_planks_fence_gate" + }, + "facing=east,in_wall=false,open=true": { + "uvlock": true, + "y": 270, + "model": "eidolon:block/illwood_planks_fence_gate_open" + }, + "facing=east,in_wall=true,open=false": { + "uvlock": true, + "y": 270, + "model": "eidolon:block/illwood_planks_fence_gate_wall" + }, + "facing=east,in_wall=true,open=true": { + "uvlock": true, + "y": 270, + "model": "eidolon:block/illwood_planks_fence_gate_wall_open" + }, + "facing=north,in_wall=false,open=false": { + "uvlock": true, + "y": 180, + "model": "eidolon:item/illwood_planks_fence_gate" + }, + "facing=north,in_wall=false,open=true": { + "uvlock": true, + "y": 180, + "model": "eidolon:block/illwood_planks_fence_gate_open" + }, + "facing=north,in_wall=true,open=false": { + "uvlock": true, + "y": 180, + "model": "eidolon:block/illwood_planks_fence_gate_wall" + }, + "facing=north,in_wall=true,open=true": { + "uvlock": true, + "y": 180, + "model": "eidolon:block/illwood_planks_fence_gate_wall_open" + }, + "facing=south,in_wall=false,open=false": { + "uvlock": true, + "model": "eidolon:item/illwood_planks_fence_gate" + }, + "facing=south,in_wall=false,open=true": { + "uvlock": true, + "model": "eidolon:block/illwood_planks_fence_gate_open" + }, + "facing=south,in_wall=true,open=false": { + "uvlock": true, + "model": "eidolon:block/illwood_planks_fence_gate_wall" + }, + "facing=south,in_wall=true,open=true": { + "uvlock": true, + "model": "eidolon:block/illwood_planks_fence_gate_wall_open" + }, + "facing=west,in_wall=false,open=false": { + "uvlock": true, + "y": 90, + "model": "eidolon:item/illwood_planks_fence_gate" + }, + "facing=west,in_wall=false,open=true": { + "uvlock": true, + "y": 90, + "model": "eidolon:block/illwood_planks_fence_gate_open" + }, + "facing=west,in_wall=true,open=false": { + "uvlock": true, + "y": 90, + "model": "eidolon:block/illwood_planks_fence_gate_wall" + }, + "facing=west,in_wall=true,open=true": { + "uvlock": true, + "y": 90, + "model": "eidolon:block/illwood_planks_fence_gate_wall_open" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_planks_slab.json b/src/main/resources/assets/eidolon/blockstates/illwood_planks_slab.json new file mode 100644 index 0000000..435605b --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_planks_slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "eidolon:item/illwood_planks_slab" + }, + "type=double": { + "model": "eidolon:item/illwood_planks" + }, + "type=top": { + "model": "eidolon:block/illwood_planks_slab_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_planks_stairs.json b/src/main/resources/assets/eidolon/blockstates/illwood_planks_stairs.json new file mode 100644 index 0000000..83f7bd7 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_planks_stairs.json @@ -0,0 +1,209 @@ +{ + "variants": { + "facing=east,half=bottom,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner" + }, + "facing=east,half=bottom,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer" + }, + "facing=east,half=bottom,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs" + }, + "facing=east,half=top,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "x": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=south,half=bottom,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner" + }, + "facing=south,half=bottom,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer" + }, + "facing=south,half=bottom,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_left": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_right": { + "model": "eidolon:block/illwood_planks_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=outer_left": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=outer_right": { + "model": "eidolon:block/illwood_planks_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=straight": { + "model": "eidolon:item/illwood_planks_stairs", + "x": 180, + "y": 180, + "uvlock": true + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/illwood_sapling.json b/src/main/resources/assets/eidolon/blockstates/illwood_sapling.json new file mode 100644 index 0000000..3a6ca8d --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/illwood_sapling.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:block/illwood_sapling" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/magic_candle.json b/src/main/resources/assets/eidolon/blockstates/magic_candle.json new file mode 100644 index 0000000..eeeceb0 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/magic_candle.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:block/magic_candle" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/magic_candlestick.json b/src/main/resources/assets/eidolon/blockstates/magic_candlestick.json new file mode 100644 index 0000000..e1b3204 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/magic_candlestick.json @@ -0,0 +1,23 @@ +{ + "variants": { + "facing=up": { + "model": "eidolon:block/magic_candlestick" + }, + "facing=north": { + "model": "eidolon:block/magic_candlestick_wall", + "y": 180 + }, + "facing=west": { + "model": "eidolon:block/magic_candlestick_wall", + "y": 90 + }, + "facing=south": { + "model": "eidolon:block/magic_candlestick_wall", + "y": 0 + }, + "facing=east": { + "model": "eidolon:block/magic_candlestick_wall", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/mossy_smooth_stone_bricks.json b/src/main/resources/assets/eidolon/blockstates/mossy_smooth_stone_bricks.json new file mode 100644 index 0000000..ed17f95 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/mossy_smooth_stone_bricks.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/mossy_smooth_stone_bricks" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/research_table.json b/src/main/resources/assets/eidolon/blockstates/research_table.json new file mode 100644 index 0000000..7ca6610 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/research_table.json @@ -0,0 +1,19 @@ +{ + "variants": { + "facing=north": { + "model": "eidolon:item/research_table", + "y": 180 + }, + "facing=west": { + "model": "eidolon:item/research_table", + "y": 90 + }, + "facing=south": { + "model": "eidolon:item/research_table" + }, + "facing=east": { + "model": "eidolon:item/research_table", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/smooth_stone_arch.json b/src/main/resources/assets/eidolon/blockstates/smooth_stone_arch.json new file mode 100644 index 0000000..f367c41 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/smooth_stone_arch.json @@ -0,0 +1,16 @@ +{ + "variants": { + "top=false,bottom=false": { + "model": "eidolon:item/smooth_stone_arch" + }, + "top=true,bottom=false": { + "model": "eidolon:block/smooth_stone_arch_bottom" + }, + "top=true,bottom=true": { + "model": "eidolon:block/smooth_stone_arch_mid" + }, + "top=false,bottom=true": { + "model": "eidolon:block/smooth_stone_arch_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry.json b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry.json new file mode 100644 index 0000000..fc6af3b --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "eidolon:item/smooth_stone_masonry" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_slab.json b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_slab.json new file mode 100644 index 0000000..79e4f6d --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "eidolon:item/smooth_stone_masonry_slab" + }, + "type=double": { + "model": "eidolon:item/smooth_stone_masonry" + }, + "type=top": { + "model": "eidolon:block/smooth_stone_masonry_slab_top" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_stairs.json b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_stairs.json new file mode 100644 index 0000000..d9eca03 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/smooth_stone_masonry_stairs.json @@ -0,0 +1,209 @@ +{ + "variants": { + "facing=east,half=bottom,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner" + }, + "facing=east,half=bottom,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=east,half=bottom,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer" + }, + "facing=east,half=bottom,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs" + }, + "facing=east,half=top,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=east,half=top,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=east,half=top,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "x": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=north,half=bottom,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 270, + "uvlock": true + }, + "facing=north,half=bottom,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=north,half=top,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "uvlock": true + }, + "facing=north,half=top,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=south,half=bottom,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner" + }, + "facing=south,half=bottom,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer" + }, + "facing=south,half=bottom,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=south,half=bottom,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=south,half=top,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=south,half=top,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "x": 180, + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 90, + "uvlock": true + }, + "facing=west,half=bottom,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "y": 180, + "uvlock": true + }, + "facing=west,half=bottom,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=inner_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_inner", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=outer_left": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 180, + "uvlock": true + }, + "facing=west,half=top,shape=outer_right": { + "model": "eidolon:block/smooth_stone_masonry_stairs_outer", + "x": 180, + "y": 270, + "uvlock": true + }, + "facing=west,half=top,shape=straight": { + "model": "eidolon:item/smooth_stone_masonry_stairs", + "x": 180, + "y": 180, + "uvlock": true + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/stripped_illwood_bark.json b/src/main/resources/assets/eidolon/blockstates/stripped_illwood_bark.json new file mode 100644 index 0000000..81fd39b --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/stripped_illwood_bark.json @@ -0,0 +1,16 @@ +{ + "variants": { + "axis=x": { + "model": "eidolon:block/stripped_illwood_bark_horizontal", + "x": 90, + "y": 90 + }, + "axis=y": { + "model": "eidolon:item/stripped_illwood_bark" + }, + "axis=z": { + "model": "eidolon:block/stripped_illwood_bark_horizontal", + "x": 90 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/blockstates/stripped_illwood_log.json b/src/main/resources/assets/eidolon/blockstates/stripped_illwood_log.json new file mode 100644 index 0000000..889f643 --- /dev/null +++ b/src/main/resources/assets/eidolon/blockstates/stripped_illwood_log.json @@ -0,0 +1,16 @@ +{ + "variants": { + "axis=x": { + "model": "eidolon:block/stripped_illwood_log_horizontal", + "x": 90, + "y": 90 + }, + "axis=y": { + "model": "eidolon:item/stripped_illwood_log" + }, + "axis=z": { + "model": "eidolon:block/stripped_illwood_log_horizontal", + "x": 90 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/lang/en_us.json b/src/main/resources/assets/eidolon/lang/en_us.json index 19affbb..58b4d3f 100644 --- a/src/main/resources/assets/eidolon/lang/en_us.json +++ b/src/main/resources/assets/eidolon/lang/en_us.json @@ -21,6 +21,11 @@ "lore.eidolon.athame": "It feels red-powerful.", "lore.eidolon.angels_sight": "It seems to be judging you.", "lore.eidolon.terminus_mirror": "Gaze into whirling infinite.", + "lore.eidolon.deathbringer_scythe": "Gives you a sinking feeling.", + "lore.eidolon.soulbone_amulet": "It has an ineffable quality.", + "lore.eidolon.withered_heart": "It feels hollow in your hand.", + "lore.eidolon.grape_candy": "Grim Grape", + "lore.eidolon.red_candy": "Reaping Raspberry", "item.eidolon.lead_ingot": "Lead Ingot", "item.eidolon.raw_lead": "Raw Lead", @@ -127,6 +132,26 @@ "item.minecraft.splash_potion.effect.strong_vulnerable": "Splash Potion of Vulnerability", "item.minecraft.tipped_arrow.effect.strong_vulnerable": "Arrow of Vulnerability", "item.minecraft.lingering_potion.effect.strong_vulnerable": "Lingering Potion of Vulnerability", + "item.minecraft.potion.effect.undeath": "Potion of Undeath", + "item.minecraft.splash_potion.effect.undeath": "Splash Potion of Undeath", + "item.minecraft.tipped_arrow.effect.undeath": "Arrow of Undeath", + "item.minecraft.lingering_potion.effect.undeath": "Lingering Potion of Undeath", + "item.minecraft.potion.effect.long_undeath": "Potion of Undeath", + "item.minecraft.splash_potion.effect.long_undeath": "Splash Potion of Undeath", + "item.minecraft.tipped_arrow.effect.long_undeath": "Arrow of Undeath", + "item.minecraft.lingering_potion.effect.long_undeath": "Lingering Potion of Undeath", + "item.minecraft.potion.effect.decay": "Potion of Decay", + "item.minecraft.splash_potion.effect.decay": "Splash Potion of Decay", + "item.minecraft.tipped_arrow.effect.decay": "Arrow of Decay", + "item.minecraft.lingering_potion.effect.decay": "Lingering Potion of Decay", + "item.minecraft.potion.effect.long_decay": "Potion of Decay", + "item.minecraft.splash_potion.effect.long_decay": "Splash Potion of Decay", + "item.minecraft.tipped_arrow.effect.long_decay": "Arrow of Decay", + "item.minecraft.lingering_potion.effect.long_decay": "Lingering Potion of Decay", + "item.minecraft.potion.effect.strong_decay": "Potion of Decay", + "item.minecraft.splash_potion.effect.strong_decay": "Splash Potion of Decay", + "item.minecraft.tipped_arrow.effect.strong_decay": "Arrow of Decay", + "item.minecraft.lingering_potion.effect.strong_decay": "Lingering Potion of Decay", "item.eidolon.spawn_raven": "Spawn Raven", "item.eidolon.raven_feather": "Raven Feather", "item.eidolon.alchemists_tongs": "Alchemist's Tongs", @@ -135,6 +160,25 @@ "item.eidolon.angels_sight": "Archangel's Sight", "item.eidolon.merammer_resin": "Merammer Resin", "item.eidolon.enervating_ring": "Enervating Ring", + "item.eidolon.parchment": "Parchment", + "item.eidolon.magic_ink": "Magic Ink", + "item.eidolon.magicians_wax": "Magician's Wax", + "item.eidolon.arcane_seal": "Arcane Seal", + "item.eidolon.notetaking_tools": "Note-taking Tools", + "item.eidolon.research_notes": "Research Notes", + "item.eidolon.completed_research": "Completed Research", + "item.eidolon.summoning_staff": "Summoning Staff", + "item.eidolon.deathbringer_scythe": "Deathbringer's Scythe", + "item.eidolon.soulbone_amulet": "Soulbone Amulet", + "item.eidolon.imbued_bones": "Imbued Bones", + "item.eidolon.bonelord_helm": "Bone Paladin Helm", + "item.eidolon.bonelord_chestplate": "Bone Paladin Chestplate", + "item.eidolon.bonelord_greaves": "Bone Paladin Greaves", + "item.eidolon.withered_heart": "Withered Heart", + "item.eidolon.grape_candy": "Soul Candy", + "item.eidolon.red_candy": "Soul Candy", + "item.eidolon.raven_cloak": "Raven Cloak", + "item.eidolon.elder_brick": "Ancient Brick", "block.eidolon.lead_block": "Lead Block", "block.eidolon.lead_ore": "Lead Ore", @@ -148,9 +192,14 @@ "block.eidolon.arcane_gold_block": "Arcane Gold Block", "block.eidolon.shadow_gem_block": "Shadow Gem Block", "block.eidolon.smooth_stone_bricks": "Smooth Stone Bricks", + "block.eidolon.mossy_smooth_stone_bricks": "Mossy Smooth Stone Bricks", "block.eidolon.smooth_stone_bricks_slab": "Smooth Stone Bricks Slab", "block.eidolon.smooth_stone_bricks_stairs": "Smooth Stone Bricks Stairs", "block.eidolon.smooth_stone_bricks_wall": "Smooth Stone Bricks Wall", + "block.eidolon.smooth_stone_masonry": "Smooth Stone Masonry", + "block.eidolon.smooth_stone_masonry_slab": "Smooth Stone Masonry Slab", + "block.eidolon.smooth_stone_masonry_stairs": "Smooth Stone Masonry Stairs", + "block.eidolon.smooth_stone_arch": "Smooth Stone Arch", "block.eidolon.smooth_stone_tiles": "Smooth Stone Tiles", "block.eidolon.smooth_stone_tiles_slab": "Smooth Stone Tiles Slab", "block.eidolon.smooth_stone_tiles_stairs": "Smooth Stone Tiles Stairs", @@ -177,6 +226,8 @@ "block.eidolon.stone_altar": "Stone Altar", "block.eidolon.candle": "Candle", "block.eidolon.candlestick": "Candlestick", + "block.eidolon.magic_candle": "Magic Candle", + "block.eidolon.magic_candlestick": "Magic Candlestick", "block.eidolon.goblet": "Goblet", "block.eidolon.unholy_effigy": "Elder Statue", "block.eidolon.straw_effigy": "Straw Effigy", @@ -186,6 +237,31 @@ "block.eidolon.incubator": "Vesseler Jar", "block.eidolon.glass_tube": "Glass Tube", "block.eidolon.cistern": "Cistern", + "block.eidolon.research_table": "Research Table", + "block.eidolon.illwood_log": "Illwood Log", + "block.eidolon.illwood_bark": "Illwood Bark", + "block.eidolon.illwood_leaves": "Illwood Leaves", + "block.eidolon.stripped_illwood_log": "Stripped Illwood Log", + "block.eidolon.stripped_illwood_bark": "Illwood", + "block.eidolon.illwood_planks_fence_gate": "Illwood Fence Gate", + "block.eidolon.illwood_planks_fence": "Illwood Fence", + "block.eidolon.illwood_planks_slab": "Illwood Slab", + "block.eidolon.illwood_planks_stairs": "Illwood Stairs", + "block.eidolon.illwood_planks": "Illwood Planks", + "block.eidolon.illwood_sapling": "Illwood Sapling", + "block.eidolon.elder_bricks": "Ancient Bricks", + "block.eidolon.elder_bricks_masonry": "Ancient Bricks Masonry", + "block.eidolon.elder_bricks_slab": "Ancient Bricks Slab", + "block.eidolon.elder_bricks_stairs": "Ancient Bricks Stairs", + "block.eidolon.elder_bricks_wall": "Ancient Bricks Wall", + "block.eidolon.elder_bricks_eye": "Ancient Eye", + "block.eidolon.elder_pillar": "Ancient Pillar", + "block.eidolon.elder_masonry": "Ancient Masonry", + "block.eidolon.elder_masonry_slab": "Ancient Masonry Slab", + "block.eidolon.elder_masonry_stairs": "Ancient Masonry Stairs", + "block.eidolon.bone_pile": "Pile of Bones", + "block.eidolon.bone_pile_slab": "Bone Pile Slab", + "block.eidolon.bone_pile_stairs": "Bone Pile Stairs", "entity.eidolon.zombie_brute": "Zombie Brute", "entity.eidolon.wraith": "Wraith", @@ -193,6 +269,7 @@ "entity.eidolon.soulfire_projectile": "Soulfire Projectile", "entity.eidolon.bonechill_projectile": "Bonechill Projectile", "entity.eidolon.chant_caster": "Chant Caster", + "entity.eidolon.raven": "Raven", "entity.eidolon.slimy_slug": "Slug", "death.attack.ritual": "%s got too involved in a ritual", @@ -204,6 +281,10 @@ "effect.eidolon.anchored": "Anchored", "effect.eidolon.reinforced": "Reinforced", "effect.eidolon.vulnerable": "Vulnerable", + "effect.eidolon.undeath": "Undeath", + + "eidolon.persistent_soul_hearts": "Persistent Soul Health", + "eidolon.max_soul_hearts": "Max Soul Health", "eidolon.subtitle.cast_soulfire": "Soulfire spell", "eidolon.subtitle.cast_bonechill": "Bonechill spell", @@ -218,9 +299,13 @@ "jei.eidolon.ritual": "Brazier", "eidolon.tooltip.necrotic": "Necrotic", + "eidolon.tooltip.active_summon": "Selected: ", + "eidolon.tooltip.no_selected_summon": "None", "eidolon.title.new_fact": "Acquired new knowledge", "eidolon.title.new_sign": "Unlocked: %s Sign", + "eidolon.title.new_research": "Learned about %s", + "eidolon.title.new_rune": "Unlocked: %s Rune", "eidolon.sign.wicked": "Wicked", "eidolon.sign.sacred": "Sacred", "eidolon.sign.blood": "Blood", @@ -228,6 +313,9 @@ "eidolon.sign.mind": "Mind", "eidolon.sign.flame": "Flame", + "eidolon.rune.sin": "Sin", + "eidolon.rune.crimson_rose": "Crimson Rose", + "eidolon.codex.chant_hover": "Chant", "eidolon.codex.cancel_hover": "Clear", "eidolon.codex.sign_suffix": "%s Sign", @@ -235,6 +323,11 @@ "container.eidolon.enchant.shard.one": "%s Soul Shard", "container.eidolon.enchant.shard.many": "%s Soul Shards", "container.eidolon.wooden_brewing_stand": "Apothecary Stand", + + "research.eidolon.gluttony": "Gluttony", + + "commands.eidolon.knowledge.success.single": "Updated %s's knowledge", + "commands.eidolon.knowledge.success.multiple": "Updated knowledge of %s players", "eidolon.codex.chapter.monsters": "Monsters", "eidolon.codex.page.monsters.zombie_brute.title": "Zombie Brute", @@ -484,5 +577,9 @@ "eidolon.codex.chapter.mind_sign": "Mind Sign", "eidolon.codex.page.mind_sign.title": "Mind Sign", "eidolon.codex.page.mind_sign": "The mind is what separates intelligent beings from the world's other creatures. It is only with the mind, and the use of the mind sign, that complex magic becomes possible for the mortal practitioner.", - "eidolon.codex.category.signs": "Mystical Signs" + "eidolon.codex.category.signs": "Mystical Signs", + + "eidolon.codex.rune.sin": "A vile and wicked sigil. Adds one Wicked sign to the end of the spell.", + "eidolon.codex.rune.crimson_rose": "Thrives upon bloodshed. Consumes two Wicked signs from the end of the spell, and adds one Blood sign in their place.", + "eidolon.codex.category.runes": "Runecraft" } \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/bone_pile_slab_top.json b/src/main/resources/assets/eidolon/models/block/bone_pile_slab_top.json new file mode 100644 index 0000000..2c0b61f --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/bone_pile_slab_top.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab_top", + "textures": { + "bottom": "eidolon:block/bone_pile", + "top": "eidolon:block/bone_pile", + "side": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_inner.json b/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_inner.json new file mode 100644 index 0000000..cc9949c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_inner.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/inner_stairs", + "textures": { + "bottom": "eidolon:block/bone_pile", + "top": "eidolon:block/bone_pile", + "side": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_outer.json b/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_outer.json new file mode 100644 index 0000000..b634a23 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/bone_pile_stairs_outer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/outer_stairs", + "textures": { + "bottom": "eidolon:block/bone_pile", + "top": "eidolon:block/bone_pile", + "side": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/cabinet_bottom.json b/src/main/resources/assets/eidolon/models/block/cabinet_bottom.json new file mode 100644 index 0000000..bc5c179 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/cabinet_bottom.json @@ -0,0 +1,100 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "eidolon:block/cabinet_bottom_front", + "1": "eidolon:block/cabinet_bottom_side", + "5": "eidolon:block/cabinet_bottom", + "particle": "eidolon:block/cabinet_bottom_front" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [4, 2, 4], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [12, 0, 2], + "to": [14, 2, 4], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [2, 0, 12], + "to": [4, 2, 14], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [12, 0, 12], + "to": [14, 2, 14], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [0, 2, 0], + "to": [16, 6, 16], + "faces": { + "north": {"uv": [0, 10, 16, 14], "texture": "#0"}, + "east": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "south": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "west": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#5"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#5"} + } + }, + { + "from": [0, 6, 0], + "to": [3, 16, 16], + "faces": { + "north": {"uv": [13, 0, 16, 10], "texture": "#0"}, + "east": {"uv": [0, 0, 16, 10], "texture": "#0"}, + "south": {"uv": [0, 0, 3, 10], "texture": "#1"}, + "west": {"uv": [0, 0, 16, 10], "texture": "#1"}, + "up": {"uv": [0, 10, 16, 13], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [13, 6, 0], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [16, 0, 13, 10], "texture": "#0"}, + "east": {"uv": [16, 0, 0, 10], "texture": "#1"}, + "south": {"uv": [3, 0, 0, 10], "texture": "#1"}, + "west": {"uv": [16, 0, 0, 10], "texture": "#0"}, + "up": {"uv": [0, 13, 16, 10], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [3, 6, 13], + "to": [13, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [13, 0, 3, 10], "texture": "#0"}, + "south": {"uv": [13, 0, 3, 10], "texture": "#1"}, + "up": {"uv": [3, 13, 13, 10], "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/cabinet_top.json b/src/main/resources/assets/eidolon/models/block/cabinet_top.json new file mode 100644 index 0000000..fa00bbd --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/cabinet_top.json @@ -0,0 +1,58 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "1": "eidolon:block/cabinet_bottom_side", + "2": "eidolon:block/cabinet_top", + "3": "eidolon:block/cabinet_top_front", + "4": "eidolon:block/cabinet_top_side", + "5": "eidolon:block/cabinet_bottom", + "particle": "eidolon:block/cabinet_bottom_front" + }, + "elements": [ + { + "from": [0, 12, 0], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 4], "texture": "#3"}, + "east": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "south": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "west": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#5"} + } + }, + { + "from": [3, 0, 13], + "to": [13, 12, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [13, 4, 3, 16], "texture": "#3"}, + "south": {"uv": [13, 4, 3, 16], "texture": "#4"}, + "down": {"uv": [3, 13, 13, 10], "texture": "#1"} + } + }, + { + "from": [0, 0, 0], + "to": [3, 12, 16], + "faces": { + "north": {"uv": [13, 4, 16, 16], "texture": "#3"}, + "east": {"uv": [0, 4, 16, 16], "texture": "#3"}, + "south": {"uv": [0, 4, 3, 16], "texture": "#4"}, + "west": {"uv": [0, 4, 16, 16], "texture": "#4"}, + "down": {"uv": [0, 10, 16, 13], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [13, 0, 0], + "to": [16, 12, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [16, 6, 13, 16], "texture": "#3"}, + "east": {"uv": [16, 4, 0, 16], "texture": "#4"}, + "south": {"uv": [3, 4, 0, 16], "texture": "#4"}, + "west": {"uv": [16, 4, 0, 16], "texture": "#3"}, + "down": {"uv": [0, 13, 16, 10], "rotation": 270, "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_slab_top.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_slab_top.json new file mode 100644 index 0000000..25f4f4e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_slab_top.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab_top", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_inner.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_inner.json new file mode 100644 index 0000000..e43c3cb --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_inner.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/inner_stairs", + "textures": { + "bottom": "eidolon:block/elder_bricks", + "top": "eidolon:block/elder_bricks", + "side": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_outer.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_outer.json new file mode 100644 index 0000000..da579db --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_stairs_outer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/outer_stairs", + "textures": { + "bottom": "eidolon:block/elder_bricks", + "top": "eidolon:block/elder_bricks", + "side": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_post.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_post.json new file mode 100644 index 0000000..7a41e08 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_post.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_wall_post", + "textures": { + "wall": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side.json new file mode 100644 index 0000000..2cd2f09 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_wall_side", + "textures": { + "wall": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side_tall.json b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side_tall.json new file mode 100644 index 0000000..242bd9c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_bricks_wall_side_tall.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_wall_side_tall", + "textures": { + "wall": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_masonry_slab_top.json b/src/main/resources/assets/eidolon/models/block/elder_masonry_slab_top.json new file mode 100644 index 0000000..25f4f4e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_masonry_slab_top.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab_top", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_inner.json b/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_inner.json new file mode 100644 index 0000000..92bf41a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_inner.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/inner_stairs", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_outer.json b/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_outer.json new file mode 100644 index 0000000..1b00abf --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_masonry_stairs_outer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/outer_stairs", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_pillar_bottom.json b/src/main/resources/assets/eidolon/models/block/elder_pillar_bottom.json new file mode 100644 index 0000000..ed8f7eb --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_pillar_bottom.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/elder_pillar_end", + "side": "eidolon:block/elder_pillar_bottom_side" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_pillar_mid.json b/src/main/resources/assets/eidolon/models/block/elder_pillar_mid.json new file mode 100644 index 0000000..52b44ab --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_pillar_mid.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/elder_pillar_end", + "side": "eidolon:block/elder_pillar_side" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/elder_pillar_top.json b/src/main/resources/assets/eidolon/models/block/elder_pillar_top.json new file mode 100644 index 0000000..2b97136 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/elder_pillar_top.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/elder_pillar_end", + "side": "eidolon:block/elder_pillar_top_side" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_bark_horizontal.json b/src/main/resources/assets/eidolon/models/block/illwood_bark_horizontal.json new file mode 100644 index 0000000..5f38ef8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_bark_horizontal.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column_horizontal", + "textures": { + "end": "eidolon:block/illwood_log", + "side": "eidolon:block/illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_log_horizontal.json b/src/main/resources/assets/eidolon/models/block/illwood_log_horizontal.json new file mode 100644 index 0000000..a8ddbb4 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_log_horizontal.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column_horizontal", + "textures": { + "end": "eidolon:block/illwood_log_top", + "side": "eidolon:block/illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_open.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_open.json new file mode 100644 index 0000000..f9a29e2 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_open.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_fence_gate_open", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall.json new file mode 100644 index 0000000..e9980d9 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_fence_gate_wall", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall_open.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall_open.json new file mode 100644 index 0000000..a31d173 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_gate_wall_open.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_fence_gate_wall_open", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_post.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_post.json new file mode 100644 index 0000000..d163492 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_post.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/fence_post", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_side.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_side.json new file mode 100644 index 0000000..feed77a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_fence_side.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/fence_side", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_slab_top.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_slab_top.json new file mode 100644 index 0000000..a6136c7 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_slab_top.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab_top", + "textures": { + "bottom": "eidolon:block/illwood_planks", + "top": "eidolon:block/illwood_planks", + "side": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_inner.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_inner.json new file mode 100644 index 0000000..d447292 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_inner.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/inner_stairs", + "textures": { + "bottom": "eidolon:block/illwood_planks", + "top": "eidolon:block/illwood_planks", + "side": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_outer.json b/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_outer.json new file mode 100644 index 0000000..e93de1c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_planks_stairs_outer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/outer_stairs", + "textures": { + "bottom": "eidolon:block/illwood_planks", + "top": "eidolon:block/illwood_planks", + "side": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/illwood_sapling.json b/src/main/resources/assets/eidolon/models/block/illwood_sapling.json new file mode 100644 index 0000000..256edf9 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/illwood_sapling.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cross", + "textures": { + "cross": "eidolon:block/illwood_sapling" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/magic_candle.json b/src/main/resources/assets/eidolon/models/block/magic_candle.json new file mode 100644 index 0000000..c0667ff --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/magic_candle.json @@ -0,0 +1,36 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/magic_candle", + "particle": "eidolon:block/magic_candle" + }, + "elements": [ + { + "from": [6.5, 0, 6.5], + "to": [9.5, 7, 9.5], + "rotation": {"angle": 0, "axis": "y", "origin": [14.5, 8, 16.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "south": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "up": {"uv": [6, 0, 9, 3], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 3], "texture": "#0"} + } + }, + { + "from": [7.5, 7, 7.5], + "to": [8.5, 8, 8.5], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 15, 15.5]}, + "faces": { + "north": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "east": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "south": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "west": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "up": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "down": {"uv": [9, 0, 10, 1], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/magic_candlestick.json b/src/main/resources/assets/eidolon/models/block/magic_candlestick.json new file mode 100644 index 0000000..25d0b2c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/magic_candlestick.json @@ -0,0 +1,73 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/magic_candle", + "particle": "eidolon:block/magic_candle" + }, + "elements": [ + { + "from": [6.5, 5, 6.5], + "to": [9.5, 12, 9.5], + "rotation": {"angle": 0, "axis": "y", "origin": [14.5, 13, 16.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "south": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "up": {"uv": [6, 0, 9, 3], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 3], "texture": "#0"} + } + }, + { + "from": [7.5, 12, 7.5], + "to": [8.5, 13, 8.5], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 20, 15.5]}, + "faces": { + "north": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "east": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "south": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "west": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "up": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "down": {"uv": [9, 0, 10, 1], "texture": "#0"} + } + }, + { + "from": [6, 3, 6], + "to": [10, 5, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 12, 14]}, + "faces": { + "north": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "east": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "south": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "west": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "up": {"uv": [0, 12, 4, 16], "texture": "#0"}, + "down": {"uv": [4, 12, 8, 16], "texture": "#0"} + } + }, + { + "from": [7, 1, 7], + "to": [9, 3, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 10, 14]}, + "faces": { + "north": {"uv": [1, 9, 3, 11], "texture": "#0"}, + "east": {"uv": [1, 9, 3, 11], "texture": "#0"}, + "south": {"uv": [1, 9, 3, 11], "texture": "#0"}, + "west": {"uv": [1, 9, 3, 11], "texture": "#0"} + } + }, + { + "from": [6.5, 0, 6.5], + "to": [9.5, 1, 9.5], + "rotation": {"angle": 0, "axis": "y", "origin": [14.5, 8, 16.5]}, + "faces": { + "north": {"uv": [0, 11, 3, 12], "texture": "#0"}, + "east": {"uv": [0, 11, 3, 12], "texture": "#0"}, + "south": {"uv": [0, 11, 3, 12], "texture": "#0"}, + "west": {"uv": [0, 11, 3, 12], "texture": "#0"}, + "up": {"uv": [3, 9, 6, 12], "texture": "#0"}, + "down": {"uv": [3, 9, 6, 12], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/magic_candlestick_wall.json b/src/main/resources/assets/eidolon/models/block/magic_candlestick_wall.json new file mode 100644 index 0000000..4d0c9ab --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/magic_candlestick_wall.json @@ -0,0 +1,85 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/magic_candle", + "particle": "eidolon:block/magic_candle" + }, + "elements": [ + { + "from": [6.5, 7, 1.5], + "to": [9.5, 14, 4.5], + "rotation": {"angle": 0, "axis": "y", "origin": [14.5, 15, 11.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "south": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 7], "texture": "#0"}, + "up": {"uv": [6, 0, 9, 3], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 3], "texture": "#0"} + } + }, + { + "from": [7.5, 14, 2.5], + "to": [8.5, 15, 3.5], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 22, 10.5]}, + "faces": { + "north": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "east": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "south": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "west": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "up": {"uv": [9, 0, 10, 1], "texture": "#0"}, + "down": {"uv": [9, 0, 10, 1], "texture": "#0"} + } + }, + { + "from": [6, 5, 1], + "to": [10, 7, 5], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 14, 9]}, + "faces": { + "north": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "east": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "south": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "west": {"uv": [0, 7, 4, 9], "texture": "#0"}, + "up": {"uv": [0, 12, 4, 16], "texture": "#0"}, + "down": {"uv": [4, 12, 8, 16], "texture": "#0"} + } + }, + { + "from": [7, 3, 2], + "to": [9, 5, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 14, 9]}, + "faces": { + "north": {"uv": [8, 10, 10, 12], "texture": "#0"}, + "east": {"uv": [6, 10, 8, 12], "texture": "#0"}, + "south": {"uv": [8, 10, 10, 12], "texture": "#0"}, + "west": {"uv": [8, 10, 6, 12], "texture": "#0"}, + "down": {"uv": [1, 9, 3, 11], "texture": "#0"} + } + }, + { + "from": [7, 3, 1], + "to": [9, 5, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [14, 14, 8]}, + "faces": { + "east": {"uv": [3, 9, 2, 11], "texture": "#0"}, + "west": {"uv": [3, 9, 2, 11], "texture": "#0"}, + "up": {"uv": [3, 9, 1, 10], "texture": "#0"}, + "down": {"uv": [3, 10, 1, 11], "texture": "#0"} + } + }, + { + "from": [6.5, 2.5, 0], + "to": [9.5, 5.5, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [14.5, -4.5, 8]}, + "faces": { + "north": {"uv": [3, 9, 6, 12], "rotation": 180, "texture": "#0"}, + "east": {"uv": [0, 11, 3, 12], "rotation": 270, "texture": "#0"}, + "south": {"uv": [3, 9, 6, 12], "texture": "#0"}, + "west": {"uv": [0, 11, 3, 12], "rotation": 90, "texture": "#0"}, + "up": {"uv": [0, 11, 3, 12], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 11, 3, 12], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_bottom.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_bottom.json new file mode 100644 index 0000000..2f32255 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_bottom.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/smooth_stone_bricks", + "side": "eidolon:block/smooth_stone_arch_bottom" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_mid.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_mid.json new file mode 100644 index 0000000..b20a22c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_mid.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/smooth_stone_bricks", + "side": "eidolon:block/smooth_stone_arch_mid" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_top.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_top.json new file mode 100644 index 0000000..09c7be5 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_arch_top.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/smooth_stone_bricks", + "side": "eidolon:block/smooth_stone_arch_top" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_slab_top.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_slab_top.json new file mode 100644 index 0000000..036184b --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_slab_top.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab_top", + "textures": { + "bottom": "eidolon:block/smooth_stone_masonry", + "top": "eidolon:block/smooth_stone_masonry", + "side": "eidolon:block/smooth_stone_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_inner.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_inner.json new file mode 100644 index 0000000..1eda631 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_inner.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/inner_stairs", + "textures": { + "bottom": "eidolon:block/smooth_stone_masonry", + "top": "eidolon:block/smooth_stone_masonry", + "side": "eidolon:block/smooth_stone_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_outer.json b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_outer.json new file mode 100644 index 0000000..3c57030 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/smooth_stone_masonry_stairs_outer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/outer_stairs", + "textures": { + "bottom": "eidolon:block/smooth_stone_masonry", + "top": "eidolon:block/smooth_stone_masonry", + "side": "eidolon:block/smooth_stone_masonry" + } +} diff --git a/src/main/resources/assets/eidolon/models/block/stripped_illwood_bark_horizontal.json b/src/main/resources/assets/eidolon/models/block/stripped_illwood_bark_horizontal.json new file mode 100644 index 0000000..2c73708 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/stripped_illwood_bark_horizontal.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column_horizontal", + "textures": { + "end": "eidolon:block/stripped_illwood_log", + "side": "eidolon:block/stripped_illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/stripped_illwood_log_horizontal.json b/src/main/resources/assets/eidolon/models/block/stripped_illwood_log_horizontal.json new file mode 100644 index 0000000..7d02820 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/block/stripped_illwood_log_horizontal.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column_horizontal", + "textures": { + "end": "eidolon:block/stripped_illwood_log_top", + "side": "eidolon:block/stripped_illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/arcane_seal.json b/src/main/resources/assets/eidolon/models/item/arcane_seal.json new file mode 100644 index 0000000..65d5757 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/arcane_seal.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/arcane_seal" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/archive.json b/src/main/resources/assets/eidolon/models/item/archive.json new file mode 100644 index 0000000..348084d --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/archive.json @@ -0,0 +1,219 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/archive_bottom", + "1": "eidolon:block/archive_side", + "2": "eidolon:block/archive_top", + "3": "eidolon:block/archive_detail", + "particle": "eidolon:block/archive_bottom" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#0"} + } + }, + { + "from": [-2, 19, 3.5], + "to": [0, 25, 5.5], + "rotation": {"angle": 45, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [10, 0, 12, 6], "texture": "#3"}, + "east": {"uv": [10, 0, 12, 6], "texture": "#3"}, + "south": {"uv": [10, 0, 12, 6], "texture": "#3"}, + "west": {"uv": [10, 0, 12, 6], "texture": "#3"}, + "up": {"uv": [8, 1, 10, 3], "texture": "#3"}, + "down": {"uv": [8, 4, 10, 6], "texture": "#3"} + } + }, + { + "from": [-1.5, 25, 4], + "to": [-0.5, 26, 5], + "rotation": {"angle": 45, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "east": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "south": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "west": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "up": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "down": {"uv": [9, 0, 10, 1], "texture": "#3"} + } + }, + { + "from": [4, 23, 3.5], + "to": [5, 24, 4.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "east": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "south": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "west": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "up": {"uv": [9, 0, 10, 1], "texture": "#3"}, + "down": {"uv": [9, 0, 10, 1], "texture": "#3"} + } + }, + { + "from": [-2, 16, 3.5], + "to": [0, 17, 5.5], + "rotation": {"angle": 45, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [6, 6, 8, 7], "texture": "#3"}, + "east": {"uv": [6, 6, 8, 7], "texture": "#3"}, + "south": {"uv": [6, 6, 8, 7], "texture": "#3"}, + "west": {"uv": [6, 6, 8, 7], "texture": "#3"}, + "up": {"uv": [6, 4, 8, 6], "texture": "#3"}, + "down": {"uv": [6, 4, 8, 6], "texture": "#3"} + } + }, + { + "from": [-1.5, 17, 4], + "to": [-0.5, 18, 5], + "rotation": {"angle": 45, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "east": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "south": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "west": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "up": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "down": {"uv": [5, 4, 6, 5], "texture": "#3"} + } + }, + { + "from": [-2.5, 18, 3], + "to": [0.5, 19, 6], + "rotation": {"angle": 45, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "east": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "south": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "west": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "up": {"uv": [4, 0, 7, 3], "texture": "#3"}, + "down": {"uv": [4, 0, 7, 3], "texture": "#3"} + } + }, + { + "from": [3.5, 18, 3], + "to": [5.5, 23, 5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [8, 1, 10, 6], "texture": "#3"}, + "east": {"uv": [8, 1, 10, 6], "texture": "#3"}, + "south": {"uv": [8, 1, 10, 6], "texture": "#3"}, + "west": {"uv": [8, 1, 10, 6], "texture": "#3"}, + "up": {"uv": [8, 1, 10, 3], "texture": "#3"}, + "down": {"uv": [8, 4, 10, 6], "texture": "#3"} + } + }, + { + "from": [4, 16, 3.5], + "to": [5, 17, 4.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "east": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "south": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "west": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "up": {"uv": [5, 4, 6, 5], "texture": "#3"}, + "down": {"uv": [5, 4, 6, 5], "texture": "#3"} + } + }, + { + "from": [3, 17, 2.5], + "to": [6, 18, 5.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "east": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "south": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "west": {"uv": [4, 3, 7, 4], "texture": "#3"}, + "up": {"uv": [4, 0, 7, 3], "texture": "#3"}, + "down": {"uv": [4, 0, 7, 3], "texture": "#3"} + } + }, + { + "from": [7, 16.1, 6], + "to": [11, 16.1, 12], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, -0.4, 0]}, + "faces": { + "north": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "east": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "south": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "west": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "up": {"uv": [12, 0, 16, 6], "texture": "#3"}, + "down": {"uv": [12, 0, 16, 6], "texture": "#3"} + } + }, + { + "from": [6, 16.1, 7], + "to": [12, 16.1, 11], + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, -0.4, 0]}, + "faces": { + "north": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "east": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "south": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "west": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "up": {"uv": [12, 0, 16, 6], "rotation": 270, "texture": "#3"}, + "down": {"uv": [12, 0, 16, 6], "rotation": 90, "texture": "#3"} + } + }, + { + "from": [7, 16.2, -3], + "to": [15, 16.2, 3], + "rotation": {"angle": -45, "axis": "y", "origin": [0, -0.4, 0]}, + "faces": { + "north": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "east": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "south": {"uv": [0, 0, 6, 0], "texture": "#missing"}, + "west": {"uv": [0, 0, 4, 0], "texture": "#missing"}, + "up": {"uv": [6, 8, 12, 16], "rotation": 90, "texture": "#3"}, + "down": {"uv": [6, 8, 12, 16], "rotation": 90, "texture": "#3"} + } + }, + { + "from": [10.5, 22.5, 2], + "to": [15.5, 23.5, 7], + "rotation": {"angle": 22.5, "axis": "x", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "east": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "south": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "west": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "up": {"uv": [0, 4, 5, 9], "texture": "#3"}, + "down": {"uv": [0, 4, 5, 9], "texture": "#3"} + } + }, + { + "from": [11.5, 6.48109, 27.00647], + "to": [14.5, 6.48109, 29.00647], + "rotation": {"angle": -45, "axis": "x", "origin": [2, -4.51891, 8.00647]}, + "faces": { + "north": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "east": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "south": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "west": {"uv": [0, 9, 5, 10], "texture": "#3"}, + "up": {"uv": [0, 14, 3, 16], "texture": "#3"}, + "down": {"uv": [3, 14, 6, 16], "texture": "#3"} + } + }, + { + "from": [11, 16, 11], + "to": [15, 17, 15], + "faces": { + "north": {"uv": [0, 10, 4, 11], "texture": "#3"}, + "east": {"uv": [0, 10, 4, 11], "texture": "#3"}, + "south": {"uv": [0, 10, 4, 11], "texture": "#3"}, + "west": {"uv": [0, 10, 4, 11], "texture": "#3"}, + "up": {"uv": [0, 10, 4, 14], "texture": "#3"}, + "down": {"uv": [0, 10, 4, 14], "texture": "#3"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bone_pile.json b/src/main/resources/assets/eidolon/models/item/bone_pile.json new file mode 100644 index 0000000..ec798f6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bone_pile.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bone_pile_slab.json b/src/main/resources/assets/eidolon/models/item/bone_pile_slab.json new file mode 100644 index 0000000..bf6a4bb --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bone_pile_slab.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab", + "textures": { + "bottom": "eidolon:block/bone_pile", + "top": "eidolon:block/bone_pile", + "side": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bone_pile_stairs.json b/src/main/resources/assets/eidolon/models/item/bone_pile_stairs.json new file mode 100644 index 0000000..e7d67d7 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bone_pile_stairs.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/stairs", + "textures": { + "bottom": "eidolon:block/bone_pile", + "top": "eidolon:block/bone_pile", + "side": "eidolon:block/bone_pile" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bonelord_chestplate.json b/src/main/resources/assets/eidolon/models/item/bonelord_chestplate.json new file mode 100644 index 0000000..b93240f --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bonelord_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/bonelord_chestplate" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bonelord_greaves.json b/src/main/resources/assets/eidolon/models/item/bonelord_greaves.json new file mode 100644 index 0000000..db7abc8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bonelord_greaves.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/bonelord_greaves" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/bonelord_helm.json b/src/main/resources/assets/eidolon/models/item/bonelord_helm.json new file mode 100644 index 0000000..517d3b6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/bonelord_helm.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/bonelord_helm" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/cabinet.json b/src/main/resources/assets/eidolon/models/item/cabinet.json new file mode 100644 index 0000000..73849a1 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/cabinet.json @@ -0,0 +1,148 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "eidolon:block/cabinet_bottom_front", + "1": "eidolon:block/cabinet_bottom_side", + "2": "eidolon:block/cabinet_top", + "3": "eidolon:block/cabinet_top_front", + "4": "eidolon:block/cabinet_top_side", + "5": "eidolon:block/cabinet_bottom", + "particle": "eidolon:block/cabinet_bottom_front" + }, + "elements": [ + { + "from": [2, 0, 2], + "to": [4, 2, 4], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [12, 0, 2], + "to": [14, 2, 4], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [2, 0, 12], + "to": [4, 2, 14], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [12, 0, 12], + "to": [14, 2, 14], + "faces": { + "north": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "east": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "south": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "west": {"uv": [2, 14, 4, 16], "texture": "#0"}, + "down": {"uv": [2, 12, 4, 14], "texture": "#5"} + } + }, + { + "from": [0, 2, 0], + "to": [16, 6, 16], + "faces": { + "north": {"uv": [0, 10, 16, 14], "texture": "#0"}, + "east": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "south": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "west": {"uv": [0, 10, 16, 14], "texture": "#1"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#5"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#5"} + } + }, + { + "from": [0, 28, 0], + "to": [16, 32, 16], + "faces": { + "north": {"uv": [0, 0, 16, 4], "texture": "#3"}, + "east": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "south": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "west": {"uv": [0, 0, 16, 4], "texture": "#4"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#5"} + } + }, + { + "from": [0, 6, 0], + "to": [3, 16, 16], + "faces": { + "north": {"uv": [13, 0, 16, 10], "texture": "#0"}, + "east": {"uv": [0, 0, 16, 10], "texture": "#0"}, + "south": {"uv": [0, 0, 3, 10], "texture": "#1"}, + "west": {"uv": [0, 0, 16, 10], "texture": "#1"}, + "up": {"uv": [0, 10, 16, 13], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [13, 6, 0], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [16, 0, 13, 10], "texture": "#0"}, + "east": {"uv": [16, 0, 0, 10], "texture": "#1"}, + "south": {"uv": [3, 0, 0, 10], "texture": "#1"}, + "west": {"uv": [16, 0, 0, 10], "texture": "#0"}, + "up": {"uv": [0, 13, 16, 10], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [3, 6, 13], + "to": [13, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [13, 0, 3, 10], "texture": "#0"}, + "south": {"uv": [13, 0, 3, 10], "texture": "#1"}, + "up": {"uv": [3, 13, 13, 10], "texture": "#1"} + } + }, + { + "from": [3, 16, 13], + "to": [13, 28, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [13, 4, 3, 16], "texture": "#3"}, + "south": {"uv": [13, 4, 3, 16], "texture": "#4"}, + "down": {"uv": [3, 13, 13, 10], "texture": "#1"} + } + }, + { + "from": [0, 16, 0], + "to": [3, 28, 16], + "faces": { + "north": {"uv": [13, 4, 16, 16], "texture": "#3"}, + "east": {"uv": [0, 4, 16, 16], "texture": "#3"}, + "south": {"uv": [0, 4, 3, 16], "texture": "#4"}, + "west": {"uv": [0, 4, 16, 16], "texture": "#4"}, + "down": {"uv": [0, 10, 16, 13], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [13, 16, 0], + "to": [16, 28, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [16, 4, 13, 16], "texture": "#3"}, + "east": {"uv": [16, 4, 0, 16], "texture": "#4"}, + "south": {"uv": [3, 4, 0, 16], "texture": "#4"}, + "west": {"uv": [16, 4, 0, 16], "texture": "#3"}, + "down": {"uv": [0, 13, 16, 10], "rotation": 270, "texture": "#1"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/completed_research.json b/src/main/resources/assets/eidolon/models/item/completed_research.json new file mode 100644 index 0000000..a80b6a9 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/completed_research.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/completed_research" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/deathbringer_scythe.json b/src/main/resources/assets/eidolon/models/item/deathbringer_scythe.json new file mode 100644 index 0000000..67d0ead --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/deathbringer_scythe.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/deathbringer_scythe" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_brick.json b/src/main/resources/assets/eidolon/models/item/elder_brick.json new file mode 100644 index 0000000..f8194df --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_brick.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/elder_brick" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_bricks.json b/src/main/resources/assets/eidolon/models/item/elder_bricks.json new file mode 100644 index 0000000..6576cff --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_bricks.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_bricks_eye.json b/src/main/resources/assets/eidolon/models/item/elder_bricks_eye.json new file mode 100644 index 0000000..a610b93 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_bricks_eye.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/elder_bricks", + "side": "eidolon:block/elder_bricks_eye" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_bricks_slab.json b/src/main/resources/assets/eidolon/models/item/elder_bricks_slab.json new file mode 100644 index 0000000..c3bd1d1 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_bricks_slab.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab", + "textures": { + "bottom": "eidolon:block/elder_bricks", + "top": "eidolon:block/elder_bricks", + "side": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_bricks_stairs.json b/src/main/resources/assets/eidolon/models/item/elder_bricks_stairs.json new file mode 100644 index 0000000..58c8c98 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_bricks_stairs.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/stairs", + "textures": { + "bottom": "eidolon:block/elder_bricks", + "top": "eidolon:block/elder_bricks", + "side": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_bricks_wall.json b/src/main/resources/assets/eidolon/models/item/elder_bricks_wall.json new file mode 100644 index 0000000..22830a3 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_bricks_wall.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/wall_inventory", + "textures": { + "wall": "eidolon:block/elder_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_masonry.json b/src/main/resources/assets/eidolon/models/item/elder_masonry.json new file mode 100644 index 0000000..9ba8516 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_masonry.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_masonry_slab.json b/src/main/resources/assets/eidolon/models/item/elder_masonry_slab.json new file mode 100644 index 0000000..17aff02 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_masonry_slab.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_masonry_stairs.json b/src/main/resources/assets/eidolon/models/item/elder_masonry_stairs.json new file mode 100644 index 0000000..b3f4acf --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_masonry_stairs.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/stairs", + "textures": { + "bottom": "eidolon:block/elder_masonry", + "top": "eidolon:block/elder_masonry", + "side": "eidolon:block/elder_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/elder_pillar.json b/src/main/resources/assets/eidolon/models/item/elder_pillar.json new file mode 100644 index 0000000..2c7bb60 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/elder_pillar.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/elder_pillar_end", + "side": "eidolon:block/elder_pillar_both_side" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/grape_candy.json b/src/main/resources/assets/eidolon/models/item/grape_candy.json new file mode 100644 index 0000000..6dfbe7e --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/grape_candy.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/grape_candy" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_bark.json b/src/main/resources/assets/eidolon/models/item/illwood_bark.json new file mode 100644 index 0000000..1dfd1fa --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_bark.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/illwood_log", + "side": "eidolon:block/illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_leaves.json b/src/main/resources/assets/eidolon/models/item/illwood_leaves.json new file mode 100644 index 0000000..9da11db --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_leaves.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/illwood_leaves" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_log.json b/src/main/resources/assets/eidolon/models/item/illwood_log.json new file mode 100644 index 0000000..2d04ce3 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_log.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/illwood_log_top", + "side": "eidolon:block/illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_planks.json b/src/main/resources/assets/eidolon/models/item/illwood_planks.json new file mode 100644 index 0000000..126775d --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_planks.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_planks_fence.json b/src/main/resources/assets/eidolon/models/item/illwood_planks_fence.json new file mode 100644 index 0000000..1fcd68d --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_planks_fence.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/fence_inventory", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_planks_fence_gate.json b/src/main/resources/assets/eidolon/models/item/illwood_planks_fence_gate.json new file mode 100644 index 0000000..3227c11 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_planks_fence_gate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/template_fence_gate", + "textures": { + "texture": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_planks_slab.json b/src/main/resources/assets/eidolon/models/item/illwood_planks_slab.json new file mode 100644 index 0000000..9e644ae --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_planks_slab.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab", + "textures": { + "bottom": "eidolon:block/illwood_planks", + "top": "eidolon:block/illwood_planks", + "side": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_planks_stairs.json b/src/main/resources/assets/eidolon/models/item/illwood_planks_stairs.json new file mode 100644 index 0000000..ed99892 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_planks_stairs.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/stairs", + "textures": { + "bottom": "eidolon:block/illwood_planks", + "top": "eidolon:block/illwood_planks", + "side": "eidolon:block/illwood_planks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/illwood_sapling.json b/src/main/resources/assets/eidolon/models/item/illwood_sapling.json new file mode 100644 index 0000000..126fe7a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/illwood_sapling.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:block/illwood_sapling" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/imbued_bones.json b/src/main/resources/assets/eidolon/models/item/imbued_bones.json new file mode 100644 index 0000000..bacfc0f --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/imbued_bones.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/imbued_bones" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/magic_candle.json b/src/main/resources/assets/eidolon/models/item/magic_candle.json new file mode 100644 index 0000000..5f71c8b --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/magic_candle.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/magic_candle" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/magic_candlestick.json b/src/main/resources/assets/eidolon/models/item/magic_candlestick.json new file mode 100644 index 0000000..37b0718 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/magic_candlestick.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/magic_candlestick" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/magic_ink.json b/src/main/resources/assets/eidolon/models/item/magic_ink.json new file mode 100644 index 0000000..d334202 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/magic_ink.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/magic_ink" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/magicians_wax.json b/src/main/resources/assets/eidolon/models/item/magicians_wax.json new file mode 100644 index 0000000..adc5072 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/magicians_wax.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/magicians_wax" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/mossy_smooth_stone_bricks.json b/src/main/resources/assets/eidolon/models/item/mossy_smooth_stone_bricks.json new file mode 100644 index 0000000..997ccf5 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/mossy_smooth_stone_bricks.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/mossy_smooth_stone_bricks" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/notetaking_tools.json b/src/main/resources/assets/eidolon/models/item/notetaking_tools.json new file mode 100644 index 0000000..5b4032a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/notetaking_tools.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/notetaking_tools" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/parchment.json b/src/main/resources/assets/eidolon/models/item/parchment.json new file mode 100644 index 0000000..09c9b06 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/parchment.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/parchment" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/raven_cloak.json b/src/main/resources/assets/eidolon/models/item/raven_cloak.json new file mode 100644 index 0000000..f62a68a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/raven_cloak.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/raven_cloak" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/red_candy.json b/src/main/resources/assets/eidolon/models/item/red_candy.json new file mode 100644 index 0000000..74a827c --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/red_candy.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/red_candy" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/research_notes.json b/src/main/resources/assets/eidolon/models/item/research_notes.json new file mode 100644 index 0000000..4b122bc --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/research_notes.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/research_notes" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/block/inscription_table.json b/src/main/resources/assets/eidolon/models/item/research_table.json similarity index 97% rename from src/main/resources/assets/eidolon/models/block/inscription_table.json rename to src/main/resources/assets/eidolon/models/item/research_table.json index b7fc2d5..815cb74 100644 --- a/src/main/resources/assets/eidolon/models/block/inscription_table.json +++ b/src/main/resources/assets/eidolon/models/item/research_table.json @@ -2,12 +2,12 @@ "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "0": "eidolon:block/inscription_table_bottom", - "1": "eidolon:block/inscription_table_mid", - "2": "eidolon:block/inscription_table_side", - "3": "eidolon:block/inscription_table_top", - "4": "eidolon:block/inscription_table_detail", - "particle": "eidolon:block/inscription_table_bottom" + "0": "eidolon:block/research_table_bottom", + "1": "eidolon:block/research_table_mid", + "2": "eidolon:block/research_table_side", + "3": "eidolon:block/research_table_top", + "4": "eidolon:block/research_table_detail", + "particle": "eidolon:block/research_table_bottom" }, "elements": [ { diff --git a/src/main/resources/assets/eidolon/models/item/scriptorium.json b/src/main/resources/assets/eidolon/models/item/scriptorium.json new file mode 100644 index 0000000..1c011b8 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/scriptorium.json @@ -0,0 +1,217 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "eidolon:block/scriptorium_detail", + "1": "eidolon:block/scriptorium_top", + "2": "eidolon:block/scriptorium_legs", + "particle": "eidolon:block/scriptorium_detail" + }, + "elements": [ + { + "from": [0, 4.87917, 8.20119], + "to": [16, 8.87917, 20.20119], + "rotation": {"angle": -22.5, "axis": "x", "origin": [0, -2.12083, 0.20119]}, + "faces": { + "north": {"uv": [0, 12, 16, 16], "texture": "#1"}, + "east": {"uv": [0, 0, 12, 4], "texture": "#2"}, + "south": {"uv": [0, 12, 16, 16], "texture": "#1"}, + "west": {"uv": [12, 0, 0, 4], "texture": "#2"}, + "up": {"uv": [0, 12, 16, 0], "texture": "#1"}, + "down": {"uv": [0, 12, 16, 0], "texture": "#1"} + } + }, + { + "from": [1, 0, 11], + "to": [4, 12, 14], + "faces": { + "north": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "east": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "south": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "west": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "up": {"uv": [0, 4, 3, 7], "texture": "#2"}, + "down": {"uv": [0, 4, 3, 7], "texture": "#2"} + } + }, + { + "from": [12, 0, 11], + "to": [15, 12, 14], + "faces": { + "north": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "east": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "south": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "west": {"uv": [3, 4, 6, 16], "texture": "#2"}, + "up": {"uv": [0, 4, 3, 7], "texture": "#2"}, + "down": {"uv": [0, 4, 3, 7], "texture": "#2"} + } + }, + { + "from": [12, 0, 5], + "to": [15, 9, 8], + "faces": { + "north": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "east": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "south": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "west": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "up": {"uv": [0, 4, 3, 7], "texture": "#2"}, + "down": {"uv": [0, 4, 3, 7], "texture": "#2"} + } + }, + { + "from": [1, 0, 5], + "to": [4, 9, 8], + "faces": { + "north": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "east": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "south": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "west": {"uv": [0, 7, 3, 16], "texture": "#2"}, + "up": {"uv": [0, 4, 3, 7], "texture": "#2"}, + "down": {"uv": [0, 4, 3, 7], "texture": "#2"} + } + }, + { + "from": [-1.5, 8, 1], + "to": [7.5, 10, 7], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [6, 14, 15, 16], "texture": "#2"}, + "east": {"uv": [16, 0, 12, 2], "texture": "#2"}, + "south": {"uv": [6, 14, 15, 16], "texture": "#2"}, + "west": {"uv": [12, 0, 16, 2], "texture": "#2"}, + "up": {"uv": [6, 14, 15, 8], "texture": "#2"}, + "down": {"uv": [6, 8, 15, 14], "texture": "#2"} + } + }, + { + "from": [8.5, 7.99, 1], + "to": [17.5, 9.99, 7], + "rotation": {"angle": -22.5, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [15, 14, 6, 16], "texture": "#2"}, + "east": {"uv": [16, 0, 12, 2], "texture": "#2"}, + "south": {"uv": [15, 14, 6, 16], "texture": "#2"}, + "west": {"uv": [12, 0, 16, 2], "texture": "#2"}, + "up": {"uv": [15, 4, 6, 10], "texture": "#2"}, + "down": {"uv": [15, 10, 6, 4], "texture": "#2"} + } + }, + { + "from": [12, 3, 8], + "to": [14, 10, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "east": {"uv": [16, 9, 13, 16], "texture": "#0"}, + "west": {"uv": [16, 9, 13, 16], "texture": "#0"}, + "up": {"uv": [13, 16, 16, 14], "rotation": 90, "texture": "#0"}, + "down": {"uv": [13, 16, 16, 14], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [2, 3, 8], + "to": [4, 10, 11], + "faces": { + "east": {"uv": [13, 9, 16, 16], "texture": "#0"}, + "west": {"uv": [13, 9, 16, 16], "texture": "#0"}, + "up": {"uv": [13, 14, 16, 16], "rotation": 90, "texture": "#0"}, + "down": {"uv": [13, 14, 16, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-1, 10, 1.5], + "to": [3, 13, 5.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 4, 4, 7], "texture": "#0"}, + "east": {"uv": [0, 4, 4, 7], "texture": "#0"}, + "south": {"uv": [0, 4, 4, 7], "texture": "#0"}, + "west": {"uv": [0, 4, 4, 7], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 4], "texture": "#0"} + } + }, + { + "from": [4.5, 10, -0.25], + "to": [7.5, 12, 2.75], + "faces": { + "north": {"uv": [6, 10, 9, 12], "texture": "#0"}, + "east": {"uv": [6, 10, 9, 12], "texture": "#0"}, + "south": {"uv": [6, 10, 9, 12], "texture": "#0"}, + "west": {"uv": [6, 10, 9, 12], "texture": "#0"}, + "up": {"uv": [6, 7, 9, 10], "texture": "#0"}, + "down": {"uv": [6, 7, 9, 10], "texture": "#0"} + } + }, + { + "from": [5, 12, 0.25], + "to": [7, 13, 2.25], + "faces": { + "north": {"uv": [5, 6, 7, 7], "texture": "#0"}, + "east": {"uv": [5, 6, 7, 7], "texture": "#0"}, + "south": {"uv": [5, 6, 7, 7], "texture": "#0"}, + "west": {"uv": [5, 6, 7, 7], "texture": "#0"}, + "up": {"uv": [5, 4, 7, 6], "texture": "#0"}, + "down": {"uv": [5, 4, 7, 6], "texture": "#0"} + } + }, + { + "from": [-0.5, 13, 2], + "to": [2.5, 14, 5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [4, 3, 7, 4], "texture": "#0"}, + "east": {"uv": [4, 3, 7, 4], "texture": "#0"}, + "south": {"uv": [4, 3, 7, 4], "texture": "#0"}, + "west": {"uv": [4, 3, 7, 4], "texture": "#0"}, + "up": {"uv": [4, 0, 7, 3], "texture": "#0"} + } + }, + { + "from": [3.08678, 14, 0.8509], + "to": [3.08678, 22, 6.8509], + "rotation": {"angle": -22.5, "axis": "y", "origin": [-1.66322, 0, -0.3991]}, + "faces": { + "east": {"uv": [6, 8, 0, 16], "texture": "#0"}, + "west": {"uv": [0, 8, 6, 16], "texture": "#0"} + } + }, + { + "from": [9, 10, 1.5], + "to": [17, 11, 5.5], + "rotation": {"angle": -22.5, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "east": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "south": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "west": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "up": {"uv": [8, 0, 16, 4], "texture": "#0"}, + "down": {"uv": [8, 0, 16, 4], "texture": "#0"} + } + }, + { + "from": [7, 11, -1.5], + "to": [15, 12, 2.5], + "rotation": {"angle": 22.5, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "east": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "south": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "west": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "up": {"uv": [8, 0, 16, 4], "texture": "#0"}, + "down": {"uv": [8, 0, 16, 4], "texture": "#0"} + } + }, + { + "from": [8, 11.01, -0.25], + "to": [16, 11.01, 3.75], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "east": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "south": {"uv": [8, 4, 16, 5], "texture": "#0"}, + "west": {"uv": [8, 5, 12, 6], "texture": "#0"}, + "up": {"uv": [8, 0, 16, 4], "texture": "#0"}, + "down": {"uv": [8, 0, 16, 4], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/smooth_stone_arch.json b/src/main/resources/assets/eidolon/models/item/smooth_stone_arch.json new file mode 100644 index 0000000..5e7c451 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/smooth_stone_arch.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/smooth_stone_bricks", + "side": "eidolon:block/smooth_stone_arch" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry.json b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry.json new file mode 100644 index 0000000..68743b4 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "eidolon:block/smooth_stone_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_slab.json b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_slab.json new file mode 100644 index 0000000..e63268a --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_slab.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/slab", + "textures": { + "bottom": "eidolon:block/smooth_stone_masonry", + "top": "eidolon:block/smooth_stone_masonry", + "side": "eidolon:block/smooth_stone_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_stairs.json b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_stairs.json new file mode 100644 index 0000000..f9bf8ba --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/smooth_stone_masonry_stairs.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/stairs", + "textures": { + "bottom": "eidolon:block/smooth_stone_masonry", + "top": "eidolon:block/smooth_stone_masonry", + "side": "eidolon:block/smooth_stone_masonry" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/soulbone_amulet.json b/src/main/resources/assets/eidolon/models/item/soulbone_amulet.json new file mode 100644 index 0000000..a515cf6 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/soulbone_amulet.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/soulbone_amulet" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/stripped_illwood_bark.json b/src/main/resources/assets/eidolon/models/item/stripped_illwood_bark.json new file mode 100644 index 0000000..e25f9d3 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/stripped_illwood_bark.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/stripped_illwood_log", + "side": "eidolon:block/stripped_illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/stripped_illwood_log.json b/src/main/resources/assets/eidolon/models/item/stripped_illwood_log.json new file mode 100644 index 0000000..e737f87 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/stripped_illwood_log.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "eidolon:block/stripped_illwood_log_top", + "side": "eidolon:block/stripped_illwood_log" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/summoning_staff.json b/src/main/resources/assets/eidolon/models/item/summoning_staff.json new file mode 100644 index 0000000..6bfabfa --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/summoning_staff.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "eidolon:item/summoning_staff" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/unholy_symbol.json b/src/main/resources/assets/eidolon/models/item/unholy_symbol.json index 98ceefb..7d1ee7f 100644 --- a/src/main/resources/assets/eidolon/models/item/unholy_symbol.json +++ b/src/main/resources/assets/eidolon/models/item/unholy_symbol.json @@ -1,47 +1,6 @@ { - "parent": "builtin/entity", + "parent": "minecraft:item/generated", "textures": { - "particle": "eidolon:item/unholy_symbol" - }, - "display": { - "thirdperson_righthand": { - "rotation": [-18, -180, 0], - "translation": [0, 4, 0], - "scale": [0.55, 0.55, 0.55] - }, - "thirdperson_lefthand": { - "rotation": [-18, -180, 0], - "translation": [0, 4, 0], - "scale": [0.55, 0.55, 0.55] - }, - "firstperson_righthand": { - "rotation": [-15, 135, 9], - "translation": [-1.5, 6.5, 3], - "scale": [0.7, 0.7, 0.7] - }, - "firstperson_lefthand": { - "rotation": [-15, 135, 9], - "translation": [-1.5, 6.5, 3], - "scale": [0.7, 0.7, 0.7] - }, - "ground": { - "rotation": [0, 0, 15], - "translation": [0, 2, 0], - "scale": [0.625, 0.625, 0.625] - }, - "gui": { - "rotation": [0, 165, 15], - "translation": [1, 4, 0], - "scale": [1.25, 1.25, 1.25] - }, - "head": { - "rotation": [0, 180, 0], - "translation": [0, 13, 7] - }, - "fixed": { - "rotation": [0, -15, 15], - "translation": [0, 4, -3], - "scale": [1.25, 1.25, 1.25] - } + "layer0": "eidolon:item/unholy_symbol" } } \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/models/item/withered_heart.json b/src/main/resources/assets/eidolon/models/item/withered_heart.json new file mode 100644 index 0000000..f2bace7 --- /dev/null +++ b/src/main/resources/assets/eidolon/models/item/withered_heart.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "eidolon:item/withered_heart" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/particles/glowing_slash_particle.json b/src/main/resources/assets/eidolon/particles/glowing_slash_particle.json new file mode 100644 index 0000000..d0b1a24 --- /dev/null +++ b/src/main/resources/assets/eidolon/particles/glowing_slash_particle.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "eidolon:beam" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/particles/rune_particle.json b/src/main/resources/assets/eidolon/particles/rune_particle.json new file mode 100644 index 0000000..0ad9fe1 --- /dev/null +++ b/src/main/resources/assets/eidolon/particles/rune_particle.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "eidolon:wisp" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/particles/slash_particle.json b/src/main/resources/assets/eidolon/particles/slash_particle.json new file mode 100644 index 0000000..d0b1a24 --- /dev/null +++ b/src/main/resources/assets/eidolon/particles/slash_particle.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "eidolon:beam" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/eidolon/shaders/core/sprite_particle.fsh b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.fsh new file mode 100644 index 0000000..95ab1f5 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.fsh @@ -0,0 +1,24 @@ +#version 150 + +#moj_import + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; + +in float vertexDistance; +in vec2 texCoord0; +in vec4 vertexColor; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0) * vertexColor * ColorModulator; + if (color.a < 0.001) { + discard; + } + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/main/resources/assets/eidolon/shaders/core/sprite_particle.json b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.json new file mode 100644 index 0000000..fba6ffe --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.json @@ -0,0 +1,27 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "eidolon:sprite_particle", + "fragment": "eidolon:sprite_particle", + "attributes": [ + "Position", + "UV0", + "Color", + "UV2" + ], + "samplers": [ + { "name": "Sampler0" }, + { "name": "Sampler2" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] } + ] +} diff --git a/src/main/resources/assets/eidolon/shaders/core/sprite_particle.vsh b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.vsh new file mode 100644 index 0000000..db98217 --- /dev/null +++ b/src/main/resources/assets/eidolon/shaders/core/sprite_particle.vsh @@ -0,0 +1,23 @@ +#version 150 + +in vec3 Position; +in vec2 UV0; +in vec4 Color; +in ivec2 UV2; + +uniform sampler2D Sampler2; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out float vertexDistance; +out vec2 texCoord0; +out vec4 vertexColor; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + + vertexDistance = length((ModelViewMat * vec4(Position, 1.0)).xyz); + texCoord0 = UV0; + vertexColor = Color; +} diff --git a/src/main/resources/assets/eidolon/sounds.json b/src/main/resources/assets/eidolon/sounds.json index 4f19cc4..0218393 100644 --- a/src/main/resources/assets/eidolon/sounds.json +++ b/src/main/resources/assets/eidolon/sounds.json @@ -19,9 +19,9 @@ "subtitle": "eidolon.subtitle.splash_bonechill", "sounds": [ "eidolon:splash_bonechill" ] }, - "select_sign": { + "select_rune": { "category": "neutral", - "sounds": [ "eidolon:select_sign" ] + "sounds": [ "eidolon:select_rune" ] }, "chant_word": { "category": "neutral", diff --git a/src/main/resources/assets/eidolon/sounds/select_sign.ogg b/src/main/resources/assets/eidolon/sounds/select_rune.ogg similarity index 100% rename from src/main/resources/assets/eidolon/sounds/select_sign.ogg rename to src/main/resources/assets/eidolon/sounds/select_rune.ogg diff --git a/src/main/resources/assets/eidolon/textures/block/Sprite-0001.aseprite b/src/main/resources/assets/eidolon/textures/block/Sprite-0001.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..381791e1336f9732bbae97c18a5e6dffec17153c GIT binary patch literal 783 zcmb`F?@Lor7{`y(U3)Q|6x`5+omNyt@ymUAG&-iiSL}s$w&!)@neV zt`$_(c7rvIA3@`Q0G^l%gRcX>K>TGw^3!E6SPS66}O%k1C-wHovvHG)3d zGtkk00JJx$1TzkhCVqE{28X~2pbvM5!y3x)g)B^=2}cOR4r=g%6pWxFx(EU+pn!aY zBN?&CL?F@-r4W-SuKQm>fuxgzb#154(R>CDQo6h+;8K=L{4Fjz&-OjaknEMEZSbT@ zB-=~pa_ByHud=;VnOMtrm#vBT*Inhv>+ZewPXbHrhPd)sp33`W?+Gj2m>vneT zR=o1>Y5HVw=hiQd$qKlL#Wy}Osn@bHAG3++8jXg^GZQ@?u0Gma=nnPnudID3Ka}u} zI{Pm)Z{%|MSk?~nv69$}30FsCGM>#_`S9g8HD}h}ykBHdGaVn~g9cMwM$gD&qjNgb z5D(`FrqhFSH`vd1#=3R--Mr0_c*4ynejRbWCB|D;_hRK&eO}C9Yt?`0EAkeEUDoeQ J!|c$H&Oai`{9*tA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/archive_bottom.png b/src/main/resources/assets/eidolon/textures/block/archive_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..72b1d7f3c36daff97f971c9dda01d8311d8b3465 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|=6Jd|hFJ6- zo$Sqb$bg4+`C3Im?Yu*M%?1BW#UCg;$xd}GaCMEErF2ARv3Xyz<<-RfugzY!sm8n) zWVD#4$I{DSk@?}#rbE7m6}Fe!iE>C~Ze?B&`n2cV4*RC&s=)X99b1_Px%7fD1xR5*==l0RruQ5431F9wpnMob`S^Fm1?#vw>z=@L2^Y}dA^6u~KU7c&Y< zz{Sz2;@}`o6_FMZL`A_r6_HeGV>5IqH3>ColaMCQ^d;$X9nw7e@|1qdz4zSnedm7X zT!}su=VyiNcLU(O{7||*5#v>*Dc($;qn0ldeso9AZ8vwZ^a}vIc>Duf&;vj+5)e<$ zc&O#e0Mxd&SXo$PWnmGmypOe??23m;B@9B~=PGE0svgrcK|?*DrgpI8O90gKB|_t4NJl*bI?)vm)5%qMck3GfBVIe(J8h<4 z-$X0#15hoNu)5-5n&(phd?>b=3EpF1^sdy(q=YT#L6#*nO;A%i0N5SF*d5(s^3b5s z!dagMDu1m2Os%d;0G}S*XX^S5a8DRLw=ya5>{nf^3015KRkSiGVV=wXVclEa;A-MC zG`fM(VdYltsjxeS4ax21E(5`9l0g8V@$sceSu5{T$b6xG*mY+>(f1|+om8meOD^dZ z+&%@jPXW3e4~>tR1$yHGP!e;HT+#{a=`7J$g!Ob50KfN`7aWD#rx1-9*MGs<$yGRY zaTPx$xk*GpR5*>5l0A>pFc`;waea9!RjX2|R0#1RbQ8LXkqHJSBt8HeUyO+jJ^%v~ z3m_H-1|$x_m8(wbr5EMW*iGUvnB9%e%Wanx zT3c8Zu-=qbKx>26HZTt4r7%E!*M({}H5_FH%kz{yX`SRn#pFt#aUcoZ9#MAD zEV-L;7Y5jq4$Jctup%|H-jqnsv(3=j5M>3Y`*#VZ;YHmiYqIyB0GO|0V8}R-c%HBV zgFujEhV`c8@zaL@+`MxGfFFlPyk<#s{Q!XA*JtLdnElz5Br~Y8qUHbPm!Eb~&$Wxw z6968F?q_RW0pQw)j~qz1bzxo_qS-y$pW_7p!(9QeZ#;D*lV?v_WlRo_c=zU8Cvzi^ zWTx3fRl(aAuR52MHv?eo*nCN58rQO308DO883f%rZ~uYdDyt+X++tcy{Ju;Wc|HK4 z+iQu`Kk!T|Lbu<<#rEOI^HF8hfonlkR!xGM`3=*g#lWGp{8Rt{002ovPDHLkV1ncy B>J9(^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/archive_top.png b/src/main/resources/assets/eidolon/textures/block/archive_top.png new file mode 100644 index 0000000000000000000000000000000000000000..84006c1407b75d296f512c2243e36cc6abd7bf91 GIT binary patch literal 346 zcmV-g0j2(lP)Px$6iGxuR5*>5lR-|zFbqXMuG3nrs?K5-EI0@U;V>MU1qe}+c4}CJWZX0}5`U8> zwx7SF^x^g8`3HaUUI75>swm|g0RTj3ch0G>R%DgpX?2buLJ_d83V#7YP|VAA6VkU0 zx{e?mYeWc~Y=@w`B&!fKpM{_hraW@aOr6W(QYp`0;-2j6wu{w0Xf@JxbbyrmyMSAe ze*tO``z;(-uGzFRTgbd@=-Vb=AfRC9C_fHcSlXWk!uho8w|CID&B1;G&C7=KiShZZ z89WUH=Ljqk9VDx@m)N%rLw#?f?J)07*qoM6N<$f=s%Rg8%>k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/bone_pile.png b/src/main/resources/assets/eidolon/textures/block/bone_pile.png new file mode 100644 index 0000000000000000000000000000000000000000..28277fa3b31a81ba231551e761fabfc765127db8 GIT binary patch literal 684 zcmV;d0#p5oP)Px%W=TXrR5*=olTm9EK@i7(jfG0NCB17Pp>RDSMVb&vV`+-sW0CfyFMb(c{R;gi zq6jS|P%MWMA7UUxg}|{nkREJqQ}z&{()ti@so*~C&g|^`X6C<3CnvA&I;|$vstdqr zF9P7ct*|RKqf%M7zSCYr>F6M|hcwkFHKWsN(%5d`xivhuMw)6mttJ3U&6vn3X{rf) zpHkExTF3dtCG~nhW4mE9JMM~?nW%7RX-i4YD^e~9PS z76kumnz!Z>cH4MvjZ9w=^@qqLq0?#-cH5+>Cev3e1Antc936xVMq`9_b#;}Mm51Ek-C|6>ASm=-%)EGAsTuc|QZs~bkV!%u zO8}O>kKW#;skSmMMh4iAlU*CUvS1>o7?az-0#Hg*%|uSARMsgpQLhI!Yqjbklf;q* zzR%vX1M4qk*M_j$1|aZ#vbn}vbJ^|eAcVtdFG2{1!Dwt1n(H4p?gsD9&iDhc5k>SU SbKIl=0000Px#-bqA3R5*>zQo9bqFbup<7h7H6PuTbn{(nYdD?*@zCJIBzvnhy;n`-sWv3;jb z$AcfX9ReOt2LKq2#-0V*c}S;XU2_Ql&bK>^orO$^Fd7X2&^FbVd*ba`<_5+(OxC|; z4m%mp!c{*C9vIlvq{(_{YZhW{O(ssDH1<42Pbvy(^rRvutV-eMPKKr^2U7 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cabinet_bottom_front.png b/src/main/resources/assets/eidolon/textures/block/cabinet_bottom_front.png new file mode 100644 index 0000000000000000000000000000000000000000..6e495cc839db0c8991f6f1977395afe54afcd872 GIT binary patch literal 377 zcmV-<0fzpGP)Px$Gf6~2R5*=|Qn60MFciEvFT7N!kVx&o$U?_1d_fmJhL1*KL828YR3vfo95YmQ zoyL*4DZY0;-#aCFeR;OuzXRT?9{>PT3M~e`ScJ$Z@iPE;EbnlCt3XZ=4tufw0swEw zbkRC^gV<}KIbdQ^s4P>_flG7!eT`^>|6KG5!h0fhdEP)Px$HAzH4R5*==QbBIQFc2KV20N831qq}cdgsWcFW}P0^vC@GhoS~#LDtxDdWamy zU|=q`Rx{&S@6NuzK6?Nt%L0d^!>T6e)?>XSXzjobkOZ&;R24badH_Iy42<#6+CeFT zq*%)#Yam2{(>a=)&K^Q!si16iVgkgro+gkoeL>P-!tP!)<>qq%Q0ig01XPyy9^n($ zO9HcpwI0TJs48-UjzT16kIS_KKv>m;!_k4A8x2?Wkmz#l!0bm2>DJ?LjE!3Bp%mfc zeUYSMj=XRRQGgn46XL$H*f$n$i+NHX(xvyywF50x2~`z$Q+NjEVWhhCpztxjO=eyX z5H!a4xJY4DA8p)}V@%vk`q?w&d^VD%y*|TVdy{y#-SoTdrhg^8<&7=WLV~-OdPovU Z;(tCJp-da(hZ6t*002ovPDHLkV1m+TrrH1i literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cabinet_top.png b/src/main/resources/assets/eidolon/textures/block/cabinet_top.png new file mode 100644 index 0000000000000000000000000000000000000000..95273e02a4ac35abcda07dfafbdcd1085ec77b1b GIT binary patch literal 337 zcmV-X0j~auP)Px$3rR#lR5*>5Q@d^iAq<>YSPMF#C`JAxe~?efucwHV;uN81At2`p&MYju#ks@w zj2~m3KHlH{y(3slc*J59gjHay0jwp&D9Bk53t-I&=pJLP1#=b<^9BZhl;pIk#&Q;f zP{2$u>d*=R@bg>W%R&?BzC)uVq> jSX-U`6pkSlWBs`|J6?>)oq^^u00000NkvXXu0mjf&_R=n literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cabinet_top_front.png b/src/main/resources/assets/eidolon/textures/block/cabinet_top_front.png new file mode 100644 index 0000000000000000000000000000000000000000..2532bfdf6205e75e09758d00fb92d3d1ed8ec07a GIT binary patch literal 315 zcmV-B0mS}^P)Px#^+`lQR5*>DQbBISAPk&ZMB{^O8^1DG-|Ndm3rB3?yNjdW4c%Cm(6L(9@0Onv|W N002ovPDHLkV1jY`hLivR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/cabinet_top_side.png b/src/main/resources/assets/eidolon/textures/block/cabinet_top_side.png new file mode 100644 index 0000000000000000000000000000000000000000..55ee5f2a5de544aeaef1717e0c1dbb2b084ace96 GIT binary patch literal 361 zcmV-v0ha!WP)Px$BS}O-R5*>DlTl8?Fc3svoi*MfMJf_U;SL;zd-F>xD-buX;lo`wX#=X5AIIyR z-N}x@q z@*W3N0%J}yiQ$*d%bYPMWEb=tssY!Pwc<~AvjVhsDL>%O@)-|+3u(7H6INi!rsgn|)p-DjNztoPF=qN+AZEa|q6Xv1HPKMJE{n`zyc@4< z^3OYIN-WlIZ>?SJZ+F0CdVibKTo`lRSeGX8kLT^ZYcBi%Be{9V`Kx&M00000NkvXX Hu0mjf#mt{r literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/elder_bricks.png b/src/main/resources/assets/eidolon/textures/block/elder_bricks.png new file mode 100644 index 0000000000000000000000000000000000000000..df435d9835526532535140e372d554105a3d6cc5 GIT binary patch literal 521 zcmV+k0`~ohP)Px$!%0LzR5*=ol1*;gFc5{m7*r%s7Gx{1;sQa^B8viDbdlbocjz^GgB~$x7ySX+ z0RDq12^0y*T%-#{l!SOTq=qx2_ujmVZ(qMW^AftKajnIghQq#Ol`putza_o81fV*e zP}@DE^2f! zFKPgfbT)3*m6@D}eTg*0#wH93&PxIpQrw`8nQU((Q);ga{(zt6H<@&q$`0$=e zDFD(eBU#S9Xnj=26S}DR`QtZt@784Nob>9F>Ucu*@MIj}T8r9R)OKhNLP@fmlPu?~ z@&(yC2jI`+69BWZKmhq-^QKPnd|2>0l3;iH#nn4HCU`>OJBXm*Iw9eD*(TPea zqA;LR%CEC&9Z?u~Y5-Xp?lxsFJ-ZhhTkH4_FTe&(4z`F300000 LNkvXXu0mjfd++Wz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/elder_bricks_eye.png b/src/main/resources/assets/eidolon/textures/block/elder_bricks_eye.png new file mode 100644 index 0000000000000000000000000000000000000000..5c5c835b7681333638961338956a2669fdf9432a GIT binary patch literal 584 zcmV-O0=NB%P)Px%0!c(cR5*=olR<0SKoEt$6v;ADgyc1nZ7@k=8)|Y0v^}*w_S!#D`fGac-|4X! z3QfR};(+bgCD7QSiiM&@st)Nv-nBzBr(Jg5%$xUS559c<^pO1dOL}(?!1(-%X9W0F;F!j#JVk1K|4d1^}7m z7z(Ho2E!h1;}EY|!wW)^XblL&mgU80tl0nX0LtF|vwEvrreWvISU+1Vs%DI2y W9sZ~G^P95(0000Px$s7XXYR5*=glR$RqzQqm0TrPdz0u*SkFH_N; zgNg`qh^TG}-5erq*Pt=so4Nq|`7{BbI$bdGUQji<&SPdc5h3Zioy7{Mz2n|OQ1)$i z@7}*Hj~Ww6S89Kt<^V*F*9~3Y|JS9=Px$s!2paR5*==lRg$+9jndS@5uLyYoA=7F8F%!lPF(K(2F_xp^CXJ zfWNcvC(}>JHjcCNS3tjLxv7Z~5g&}tm>SzSlvD&N|eK>!!4~;5|-9bQT7{Ft0G@DNdRfMKJh49cK=#2`G=GY}ZJ~E%+ m>as)zvWGo*3Sm3ecKiWZ^2(#Q#QFgM0000Px$Gf6~2R5*>LQ$25kFciE*(4Y_mr3z^!#85i4Q-;p`i~RLg9ZJ81)Fu(82(SPT z$pAQpAd1wREWf++`T2RW@z#gC`&$4&ObBe(L4((4ACKNcRSQc1K;VBtH_fX4@`fn} zpv>f%;cI> z8;}Gv%lWj$gdiq__b3ia&R1qKrsC*szqhC8gdmBtvtCpQE7-1s$;MkBmX^Uc_q*Sg zK-1NhQI{(%Eu-~;Y}e_11rg210_tZ>q7>TYqL?2`!T^J9;>5L?sL!PCX-P|9!w X#%+=Y2WNPp00000NkvXXu0mjf`gN#y literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/elder_pillar_end.png b/src/main/resources/assets/eidolon/textures/block/elder_pillar_end.png new file mode 100644 index 0000000000000000000000000000000000000000..373427179c4b2b1699bce1efd2cedd101b13b59b GIT binary patch literal 345 zcmV-f0jBPx$6G=otR5*>5lTB{JAP|LLEh7*ZA$w8v7Ck|3k^66}Zg3D78L>zgbR6T5MEQ2+ zF^~E4$NBVq)kc93oZ%H~$^ZcG7WCRE2+m-p33?ow0e%huu<3pdaMl7wp%Yvw=Cq>b&(006k4%nrYP)Px#%t=H+R5*>LlD!TAQ4obc8#gPXknAI%K%-E53(u}1LL?{@3X{F2pz*WIweH60 zW-@c;%$aG-rsHdW&;{VIJJ28XcwjMKGMNqmI2|tlY?m84S%!IKz1owg8g*e_(Q}Tf z(X88?``17bM^aVXN?kA~?G~LZL)EGYe&ItwXyQ9^Z@5&R@m~s5jYQ=4)GCw|6dex5 zL4x8Ryn7JiNu>uN1x3=*70hdtAO|oBSBU Y8}=SbK;LKlI{*Lx07*qoM6N<$g5acbJpcdz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/elder_pillar_top_side.png b/src/main/resources/assets/eidolon/textures/block/elder_pillar_top_side.png new file mode 100644 index 0000000000000000000000000000000000000000..cf5420a16e1138292b6688413e32d645642e0d9d GIT binary patch literal 421 zcmV;W0b2fvP)Px$Ur9tkR5*>bQ$bF{Fc6%g7+dRDCPr4H1+1<7yEX>e7(|ZHc0JN*3c)QNA94^e zR9~^C8OCsG=d-z2HoCpOSeSze0KmRvzDo$fnfJmNg^=$}R9ddd&$Ggt>r^^URn`D7 zjG(lH;7iHj?An;66l+nrxR#jD3PeQACnznEPE)^;JS&Fx;1=8{f-?{?>^O%>iWRa- zVkj*UUa5Px%P)S5VR5*=glg(<|FaXDYO6`@!9}BA2z#LL1hm4TJ2084|2MFXD`Vf1Ho%ayE z@3cZ6V27~=+CwqqP^YCXq|1aG$Bfnv+9B9WH(ewlq5r2uzZvL`ne+bL8*Z-dnJB?1 zumG6G3DPl8X+h6#08sbpeERxB033D)x+X1)C^z|X_LJz*rW~iU4CxpEoZQA@8Yi^g z?p5c9-GNqFhA0_G$6%ra(y~xlM#s!KxsAoRw0I*oDh;oym)RnOSV%+j|&u>(YZ_`#; z_RJH2p5I`xT;aJk(>S3Pz}SgufML6n<>^O@ibJqj$OV^9m{Gf_rTdQtc4l}3Pecb|tB z4a&RHvY5sR$KkawD(AC|*M_Fu-RJz`?k^gF?!*Zl$3Qg$UCNSM3kGGIMag9-!H}a#T_awkdCooaMVB0o@+nL7x?dgY%?ll7yzDYR~=Ak wQkCU6ycPicW}t^sGYST}e0-t=;e00k0A?pd0@o^0XaE2J07*qoM6N<$g2a_Iga7~l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/illwood_log.png b/src/main/resources/assets/eidolon/textures/block/illwood_log.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ffe9e0b43935c2193eb8b737f5d4498349017d GIT binary patch literal 411 zcmV;M0c8G(P)Px$RY^oaR5*=gQ^{@vAq;&PY#1g{7xmDpJ@o(oty0=3nFSlAhlvSfII%sy1+)8n zd%q4bKr}-{!AxLssK+=hV5YLJ&pQAR&0un1CWt6RGsbCYiijwf91hVpg*yXTWm^w1 zAh1K=m5rIoTr>j!UY`bZB8rrA*)#^byhz^IviTx;wO|qr1OUA!^q$I@0c_7mx;mV~ zz=Xfc0`{wgTK?nMeSdsi&2#O~Sce$!ybqX@7SMT0#cF34MRNllVgNJYc^`^=1KTJW z)FBzzif!!O?)9D^dMjXZOig`xPFk`!PpS0GoD_%X@2_AXrJNh4<7vdtaoi9rl2;1` zFe^=vno*ypoJ*$~A=RlKqKAm$GOumyoom#+90vTJ$EGNG=L*0+(-6bvFW4(sQ6{&B z$V}Mxp?GFm1GBz(RPh*cC!);{tJzG=@ibzQd!N+Z`w#Te(u!A~!yNzs002ovPDHLk FV1kxbu?_$L literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/illwood_log_top.png b/src/main/resources/assets/eidolon/textures/block/illwood_log_top.png new file mode 100644 index 0000000000000000000000000000000000000000..6aae949d940325b574c1e19e5bdac653622cb1fe GIT binary patch literal 565 zcmV-50?Pe~P)Px$?@2^KR5*=glgn<~Fc3wLOb#v4Qe3+MiWWtI0{#CF>ZY465~NMy*rF*833b6p zKvJ&wy2HzJ$>z()PqXi~0BprDX(3!EL@Z(rnhOA`nZu1|X_sq4HDg6A0Q=pR)>(Y- z5os{S5~K3Ig-hW166rg~1+Zcbw+GMA?*I^K7AbuK1oogfapI7-QU|9s&0!wWWCCp1nBA9?^{QjD>*u37s4T4v%UGxW8X zwlkUwb^!=bO2!yVDVb8)tsI7(11#Y>Bc?&)MBh0!i&#vvidAQfu^3|!X#hBn2{8?& zWW<5A_2A7`%sPN-?|5*CX^641Xj@s=RcAy5jZ-bKfLciVozx9weiPr~WDx>PTCkUE z`Y-GEqEa%gt1hJ762{6UTqicFc_m#+UKjT_?llcr#W5)&4O(W-p}yA5A`}sZUWiHG z6!E*7|8k`T^x$71idgRNPlQns5sn9smYLH_B8PG!)(H>KWBm(#=lF99 z9FJ**xW92L2fwTK!>Gih3_Hi;-!qdIL@dpZuis_>&4t^&U#%_CE+E4>0&or!F=ZyL zFU>AAMJ%Ur;xtZZE{HXR>qIIAXAH})Rn7QryYBf11X%xz2?Rrt00000NkvXXu0mjf D0wDC$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/illwood_planks.png b/src/main/resources/assets/eidolon/textures/block/illwood_planks.png new file mode 100644 index 0000000000000000000000000000000000000000..fec63e66d2451471c4389eb30f13de81647753ce GIT binary patch literal 385 zcmV-{0e=38P)Px$J4r-AR5*=wQ%P>aFbo`tRFPwDxwH@Iy)Wqh|Iid|Vp|lY90Y2ylK~7H6o<=< z<-Wf@3jl}~#BD<^9^PdT6NngwKn~BqMpjKACS)lfCWsUOsU@mnDriM{jnb2n0`T=P z^p1OCEtn8D1^@osDuD@-v{z?3kR<6Lk1v;VCA`8oFg3n)G0yZOz-#FO#J8 f@UORhUkLpG=uX9Z&OCDj00000NkvXXu0mjfCGVZ` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/illwood_sapling.png b/src/main/resources/assets/eidolon/textures/block/illwood_sapling.png new file mode 100644 index 0000000000000000000000000000000000000000..6244ba50e35ca8fdbd10cbb458a23e7e35f4fc30 GIT binary patch literal 469 zcmV;`0V@89P)Px$k4Z#9R5*>rl1*wGK@f$%8Fvvh^2l*VV3QFUj|l;xO~8u;d;^_9hsaTK2%jN0 z2*f*QAq-wv4#a_g7+F6vgXoDm3)78+C6is=s=Awc{p!7f|BYb%FzBZC;`&F>?<5vr zWCY!8k{1Qnzwd%=1mXIj-P-5Vhu%LoZxHl5iH+J3t{EUN3NkSax~X-lwh|1wsnxOK z>iaLovjx+-!pMqD3_4b{Tl;+Zc^?3rpZ4teY0r}>SLE}Wkr75YM2#0-iN-RXE$DX= z>y&-H9r}@c(LFk`0MokSuobZ?A3w>&0Prq(3Bb+$1Atc)y7|wvB@=_lqo^q1Jyt`n`8%V zmgWy4ifLT|5Lw|&Thar_d?r00000 LNkvXXu0mjfVfN1F literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/magic_candle.png b/src/main/resources/assets/eidolon/textures/block/magic_candle.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b263e3cd4c49a61b794c48f76a14434be478dd GIT binary patch literal 503 zcmVPx$u}MThR5*>5lFv&UK@@<$*<`b^6^-!+q*&ZQg@Q(UsOUv0NN)xIg3@CTEeM_k zPo8@ApOAtciXaM>kP1RHF(D{|q@jwsN!IKl(M>ShgSu3^8{%9ZGjG1{y~m6wfBRzB z{}j;+8o5K0ye<(9H<)<;3i)L(=ZPFMsz>LGw|*Om6gv=5{RqxoE=ohFn<03 z;2?D-wl|OeyEqfyaTWNN<~JCLr2)ufON>vc487?gmoC|li@6FE#V6wNQybvZ>{|f4 zs$CN5l3N^KBlhrUgnaVk0bIGL6Y7$wT-2Kj6t$P2I>u{t zn}hFZGT9PT?hZiPCPrg@Q? t`|#koGTD;T3Ba#{DfYE0i)%?&!C#qvpg-~CN$vmu002ovPDHLkV1n{2<5&Oy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/mossy_smooth_stone_bricks.png b/src/main/resources/assets/eidolon/textures/block/mossy_smooth_stone_bricks.png new file mode 100644 index 0000000000000000000000000000000000000000..12eb4c2c2dc26fcbdb0e348187689e2841691d6d GIT binary patch literal 758 zcmVPx%ut`KgR5*=YlWl7gX%vR9gn7x6iJ2s}RFa@6lGLz4_60=}tXs0Ab}8+G9Zb_^GGk|+J~P4D4?~Bt_s7FIJlDDJ^W@R-;;9{Pzxw3^+lA$x8YxmFq zjG_j>&p$llQXRKX5J|drkAq;3f|cX8euoc}cNDA~>-7zSK$3rd@`fl}@O1Sj3Z_ZH zGW_K({D9Dj9)oHWM9jd~iJQk=PG9345dT4}9ZDl>FXaDqb~HlLs!e|6ZM z?_@gzd^032?B{_30ktv%sRrK#!v^TWR^fj?-S^fsI$+%;a?~>;a=$h z`5=%S8=u*o?;wPk9n2-!RgJw7Q#buDjcAS2*$i#$jR07R8px93DEcQm?V&TEWwZg1 oQc+&k@ux8@qs{c(#ji~G50ZO1{71))djJ3c07*qoM6N<$f+av`VgLXD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_bottom.png b/src/main/resources/assets/eidolon/textures/block/research_table_bottom.png similarity index 100% rename from src/main/resources/assets/eidolon/textures/block/inscription_table_bottom.png rename to src/main/resources/assets/eidolon/textures/block/research_table_bottom.png diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_detail.png b/src/main/resources/assets/eidolon/textures/block/research_table_detail.png similarity index 100% rename from src/main/resources/assets/eidolon/textures/block/inscription_table_detail.png rename to src/main/resources/assets/eidolon/textures/block/research_table_detail.png diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_mid.png b/src/main/resources/assets/eidolon/textures/block/research_table_mid.png similarity index 100% rename from src/main/resources/assets/eidolon/textures/block/inscription_table_mid.png rename to src/main/resources/assets/eidolon/textures/block/research_table_mid.png diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_side.png b/src/main/resources/assets/eidolon/textures/block/research_table_side.png similarity index 100% rename from src/main/resources/assets/eidolon/textures/block/inscription_table_side.png rename to src/main/resources/assets/eidolon/textures/block/research_table_side.png diff --git a/src/main/resources/assets/eidolon/textures/block/inscription_table_top.png b/src/main/resources/assets/eidolon/textures/block/research_table_top.png similarity index 100% rename from src/main/resources/assets/eidolon/textures/block/inscription_table_top.png rename to src/main/resources/assets/eidolon/textures/block/research_table_top.png diff --git a/src/main/resources/assets/eidolon/textures/block/scriptorium_detail.png b/src/main/resources/assets/eidolon/textures/block/scriptorium_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..1d0f7266bdc3d7799111fefe62698308f7cf85f1 GIT binary patch literal 504 zcmVPx$vPnciR5*==lD|(AVHn3hZ|_pdu^bf*o((Au{916**cwR~H6g^INn_&Z!0IR? ze*mj4#KD*_sRILxsqruljVMX42nk1H-eNp#HKZC6c^SyPxgNCrF7Nw%pZELxe8sZs zD<^9MApItV@)N9)Apq?8XF>(<)VB{VL(WyA2xOhHJ9!chbHjKgiS(OpR{TL0RN7D z5Xkz4Em&6uFn8n$8Rv|g$)%x8TluxkUA}(WVr0197NB-;mOy+~e^hDX7XVJyrf|&` ze>WEuK>v*;vHf~Uh1mmHXMBE9w6(A!Pqg8cBmj-~p623$I669)U0+43>h#Wx6V1k< zvIj2-KyRiS&IRx)Rho@Mwcav1ie{(BRd`QC9Uom+?d?fz&*akjbM>qs6yLi)tDWI? zdIpG#y-JlrKHqV0DYH-C698}5Tt-J7P2TPz21pq~pLzz9QxkZVD&YpY!AcsW`%SE* ufhZIotJPP}dy1lXaC2H&NrTq$e@+1!8l4arnFhN60000Px$BuPX;R5*>DlRZwvFc5{mIL15cL^oaJoGJmS6uF~U~FmddG9l<^Z<%)Pzqip?82Px$0!c(cR5*>DlD$sEFc5@4oOSFAvgjyz1v(yt_pcBILML%jq>CNr424N9KM*XY zv9voov+~Z(^V8$!!@Xe*YZUhYx}xne$qHz#XuHJmG%U!*DBM92W5R#8 znz}+6qb8DbLX3$Jwyq&0VoW$E3sIRn1C#n(cogshI9O~VAtbCU*Io~gwGa}oZ#~8+ ztYlGHllJgaU!D8Q?$932{e^wY0!#w#P_8xSN>f+(0sN4#a=pTDu)>s^rmm2?TZPtY zN}em(fSgb(AftQR0WVM$u5+prvqB~S00001r;P)Px$`$S9*Eaw>dHjfGy-qO*sE7)aX-vIV$6Ct+0BbEt zvLF%yr4*y_n6vW>q*O?$I6J>!HlMRLhDZqVTw|>TpfH=yvDQ*51x%(fNwT0+3W(#F zT&@5pi-=~k#!@cHbB)%sK%R*{9E67!C#-Avsk!TN~q*`KP}a1OPM|RjH^w zV53C94<^qwv)LBt;948pz<2H7&D(ePyAB~jq*MqI(r8pYRBPjl?8f{8l-?$o*c%)f P00000NkvXXu0mjfPx$xJg7oR5*=wlFe${Koo_)6oDdH0god?a44Y&LJ1`h5=ft-i$b2DbkX+;-4wd$ zQ?!uMMJWZ-ge0bVBIrR(DXAwSd-!tLs~Wz<+WFSJ$`1ai1)kp;SehN`^y$=idGE_b-yY z7Y$)~2dBqJ03>_x?fVZ-kB@32wao$bcR6P+=bc02xZiljE2Lx~1X(s?cV|H!jYb^- zmmdhxiM@7ENQpL@veX>DdfEI&AthN+(CY>K{in&Y8P9hEfQ6NnssJcUO`0wQow(Kp zx9~PL-o5|u*iJ-Ih*A|%6cWe%MpSFlT+;6O4@*f1KPEQw^Z)<=07*qoM6N<$f`aJd AtpET3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_mid.png b/src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_mid.png new file mode 100644 index 0000000000000000000000000000000000000000..267d7f1d910883958eacee3744d50cfd7cdcc266 GIT binary patch literal 458 zcmV;*0X6=KP)Px$gh@m}R5*=wl0i$uKoo>OOCTmjFttKaQ6%8OgCHLK7ajzErBK9w;Xyoz6pIyY zv`uN66iu^P_MivZH8ts+_U)UQo%h(4>rUr;7)1=;-#H8dn!Znxrd)MyDC6?toTl&d z7KV(*WA=7;*>1OKoB4Ghr$3=V_9q|^@qSUQSEp69H4UM0a-mer2dD9#P}xCw?w8jAj$_yE z;N^8dtF=KK&j1KNMmUa*rRRR=J`(I77{UJ?oSmKk5bVS4-92ZgClpftEm5P8k|a$l z2?{CA4{fzJ%%8E6G^OeL#PN)scD)!d_f6kls2k;CnHWGwfslfaXlV9e3;?n$H^ewe zDhBhps5Q2_PkmE#pZa*7Tc1EkCX?TUp643w55!OMQ8n>GDgXcg07*qoM6N<$f++aW AegFUf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_top.png b/src/main/resources/assets/eidolon/textures/block/smooth_stone_arch_top.png new file mode 100644 index 0000000000000000000000000000000000000000..4e64a4083235c6ac38edea34c39b1119f1c87b41 GIT binary patch literal 548 zcmV+<0^9wGP)Px$-bqA3R5*=&l3z~~K@`P*HcPhM&Nh^`p+d0YCL}bG#Q5MBCVmv755@#BAW=eD zx|FcpHtp<8C-a~Wb%r9<`*i=zJ@=kF=h^$?<6lt}0icv38;$s%?R2}i_r+vF;2eO3 zG2}(T^X+YVdwaz7Isk*48|G4Sdv`|^MJ$Z*?*r#3rO-xmkR)t1n~$be!;oqi5(~j_ zl(F00VPOo`+9d#hHkyWL_~t>Ha(Q(Pz^j)p=(Ji?!;pq(FdSvHnk}rgQ~<2C@3=YBk9VGOYll%>X63qWu`9%HSgRtp)9GV**%trn7H8Ks;9 zP!}Px$o=HSOR5*=olgn<~Fc3vg0Rrq$Y~hEp$;v<%MT-LcTYsO>B=*937^%n!SM5R= zT24DFk>U*RJ)HS)JRbi54AVg0Uzz8OMT`LvPtyqE1uaTSTGt^2T+W#g0^$V`rENEe zms-S8|- z`5Dzh+ivcP*=6&baSsn$VhjLP`dcXs(@-V%{S}eLd*5I07`b-0ADjs-8_pIa?TihH%tTKg<%^00cUZ!OvD(f zRe%t}4dS=2U+xlAONF#f67lroxGcsI)q;yLR0ivV_H66sS=-d2TrLyN671%x;$1JK zq=?UT-?%tSG`S+aTCi^mlW%)52He``JZD6FwGcvJmPx$Y)M2xR5*=glTmiuAPhyXBV?K%UW$glK@nKCL)q9*J%3y9y^cEt*@I%YD&$XNW$g`kDZ*o zUgMazB2aifGG2nzf`QVlHoKuyw;la(EuywSUU~5ncwPaj#re!&4DJ4=dzc3CjTia;{X5v07*qoM6N<$f_L)1yZ`_I literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/block/stripped_illwood_log_top.png b/src/main/resources/assets/eidolon/textures/block/stripped_illwood_log_top.png new file mode 100644 index 0000000000000000000000000000000000000000..a90f2e96b8f5067da44b34159a1169ee69e8d624 GIT binary patch literal 468 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 LNkvXXu0mjfwpm>c literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/giant_skeleton.png b/src/main/resources/assets/eidolon/textures/entity/giant_skeleton.png new file mode 100644 index 0000000000000000000000000000000000000000..7d5b17b5d77d96b94fb374b730d19df1994ce2a6 GIT binary patch literal 2662 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 vM0O_u=8@6qI00000NkvXXu0mjfZiTLx literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/entity/tall_archive_doors.png b/src/main/resources/assets/eidolon/textures/entity/tall_archive_doors.png new file mode 100644 index 0000000000000000000000000000000000000000..4b71729c8c626158af558a9d7cc9463757a1fdd8 GIT binary patch literal 592 zcmV-W0Px%3Q0skR9J=WmQQZeKoo~R+hfnvk<|oMqD5?a0aU@F8`J}E2D<94+B>l13RFle z;09?IET~8#tI6209Ttuq|4VASLP8?n?v3X6<~K8%dCy?Y$Mzf-+ zPG0f4Lz3}$%CouACPL0$^7m~YsPK{LGmD*3(=RUL2+=qYb6;w-d zTeA6mic)Q*YE6gTf4Xhg`+zpOnt|f3yVP~1Ob!Rl+BUU70C~@scSB;+6S|JYG^mSR z$3jPdAK`fd&x2o+sMbS1Rk(x_5*@E_fr-CNMLW9KjNgk07VF?4%v&_qvC@WA$WDF3 eo;`d1U;Y5NI{?`u_Oc5A0000Px_c}YY;RCt{2T~TWrS(g4h7?x!nt75FZ3Q=N6hloaw90(b9V{k$eiJjS}rLmWp zo_`6^ypvzhGY#>>g!B$+8hUqDyD;7THnV9u-ex+D=Or}6vV>8H1MWDC?#Lu1 zCol6<^B{j$r>?4`k}X?OZ+~Dc)xCAAROj4t&OPVcQ$rX~q%&u{^z<|U;92<*j;2mE zeJ(98qf~e})U%uH5Ko^z^#H(iU1+VLl)``i<~Mlvz4rot!~C_Yp8P)Q90q{U{y`Yt z!~OOY&UoB>jwu!RS@szONWvFZ3IKq~si{cklK7osU>P8$6rPnIH65>Mjhfb`&!8cd zN&x^eQ<*v=6bg~f+jd{N26`TbkBn)=37qUl&wR{*qE2Lmes2xmM#kTbm%NPMaT*L8hNAQ41-9w!sD z!ay@XO>0B^5hn%!c;(g*Q_9!Y&yX`6s1v=gQt%Nkt`bHiNW@hFDxu8r!b$;|sf-yX z3I>`1h~)7k-0hd<^X503J-(y8!JfJG?{&gn&gGz#G6W{^wboDxWsWJOpjCS&_+A(9 zI}&azEO@J{tKQS6PrVxp3xWDC3TlGG$0m*hey&BF1%m_>-koF)&+?)c{5sTbB)Wn9De-PTb}H9 z<;s;^8Eww!q1~L;cTh?->F>Bov?V5=AMJ*y7?vm71B{I)apL48etL2enW>CN;w&vK zdH*DYiE*gUcsOza#OOC~x ziyr&U{Oo5)rBZnR)-C9r>rld^GiN+n_9IRVuiTm$qm@X1zVRmjenxP{Sk>dp&k11tT%ButPEJ`MjOab`4gk%Crg|KHH#w-#|s{or|sZ*Cj6 z{t8uHK~bDLeJSgWI5BK~vsoAU59%{Ac|2*xqUe4Gz`a|y1=8ov0sy}H=k5w&Q_IBhS0^86`zzOlgLTRNd+{PkM_iBg(ejs zPvphkxbj9IVe|RCSGN)BYT$A%7r3k|tQ3qs1Aub53;;NP;i5T4m9qHZM|f6#gqTuB zH@jO^)U-zW+*#9hG<6EU{rB7EzS8H;dH}He#XWOu?(KPx%#u8wMCrlTKEsgl1S#^# zcqBHNC3!q~AS(^(a9z=et3>1b4$=Sb^UnbQMR87CC43Sit`aD&toZtbp=lLBD5Z?} zzp=33*|Yn`!h$z5GXtQZpX_lA=L+JJJI#+xH1`3T4L*0PisieX86Uq*jG$G3GkVB) z2AA)C*3>Sq;cmY)k|nI)en^0*&=pNzkO4h`0F2rgbq*T?Qa@;v>FNkFigEpkfU@( zW4*lAWc?FlocU{4z1LE&V{&Q==Pz9Jg1C;lNd_(og#unny$--{bA0$8{~7sVr_Y_m z@)!32_(eb4qCj4Y%#qHV@xqQr8ni=1vDPJ|ZdXc~=SvAt)fJW) zdtpqlcyrMU6Yl_;yjeU}SZTD!Rl-=WRb6Sh&UUw|#=vVA>@h|p!e?*TwK_e%7jSKF zmU-fNu9w%$B%x&=2HF6f<^>D~S?*K;lT%Yox>7iyZsL z!h*+{(Mi5s7_R->&y6Z@w_m~;J%l^I{Kc-uU0q%ENLabVqqPsz)53H`Bb&?m`pDnQ zNyv%I=X3h>>HbRyiDI3$f?THh#Uw$2tf*)UM8&`|025ZC z9^Wl!@G-y?h9CauC!X{a$_S+NT1GJzTP<(9ZO`;Q14vJ0KA-nFn#RVHCKHL@yA4|T zGJ5EY9`en6Mi1pag_u%?3D`GEEJ6A=4kD$kZy6vc3pSIXB({3y^nNyASDtb&qH z_Cq4{owtlm9>;N-h|JtWptYs{fktHTS@}`R z*o8A5H@OCOHj~X9l}VWkZA4V z4CZ=PI}=+NrUqb=QrclZ@)7!u0i?hC$>XAL7E6OKObvwfk z=h|OzI{qy`ryf256**NyzQdw$T>m36$H_?CsWJ;}f!fw_UIOhJpKW zG8yFb>C;29!p5;<$A(r{S3RIPDWn}1Z!UVA^?M0b4;uRVhf1f=$G`p97;!+NDuE7nO^0Lo%t8R=?Z=Ej@v>4~XYmn`Yl( zD$2!BpV7|fp_aRY0Qfeiew)zD06P!A)vRWpb|F=^by5o`l}h<4VT_F@>s~>*epfm$ z8c2_y9P2x@MyL(I9VxAj$5jH0Hy1r_VgTwyms`QZ#%TpRn#W97?jX{-QNpGZtN%MR z<9k(I!S#2p53#TS5Iyah9yUsf$*C#i^LbNV=KO_=W{cU4g#~Z%=AxI+=RIx==>)sY zdv66DR&@o1LIE=~Gnko~!P3%_#|o6xsf9wbYn76O`TYMf_phc+<#GTTIqdB`ZFV&* z6QSeA)rkH8I(SOf8ebNnl8CzdmwAG=??7h%nBUUIztC$8Ge-{aSL}HI)-5w*sdr`B z61Fj7M>TN$o$Et1Af@rg>$F=9(2AE~UAZdY|5jz`BlVitF+3U~XZsZ!Dl3pmcEwnKj%i95@3= z4_{cmpACxoDCN&3O3TZkZ5ySc*@i`ZZf4;p{=RnAu~tqaX&bPf5wm`o8qV*${?XK_ zmiM}!*jKAlhFA&4-R;=EowOO$W>Ug-oITwL+om&TJQ9M$wFx8JYZ3DVIWDnLDq{Kv z|75-|-~G&dceh{m?EOYvlK>3IK6zX;0T|9$G65}k+lwa&YzKU(9$2^d$>U<=3RqEL zuLhFGlfDx4Ktp9jwcK}zX_%{2csS&Y$2}=QN)Ns^OxLTITXl^AxNHmCuu;_&GyA!5 z1MnMp<`@edCX{a#Kq#e9Tv;*SS!R~!b|M)hVWLP?gaWCntS%Z%AaR8i4i^Pik^uSIKrPJ4keG6=3hMwOF z6hSG{J0?MTC)lzIGiS2S%bNR zF#rHgXy3nM3;+yZmjPg90WaHuBM0CG0yEaq0LuH$5dc6K(7toqG%$S~i;Ux03SHXl zC-xCJ*h`s@UtW_*KY6x^<)o!>c;s8IXkCNLpYJ>_lbJB&_AM2x zii*4nW_O$%X6E^IdU$wRj`Qefd)QD-8UhmdpByNik~G5kmcuWk?EZW&?ANZ^wdxCn zRirLt?{ue5s1T5K>)ewEHA@(Zt6RG#-1SHcUf0vt9C|0-Z*jRNn;FYPJ5h@j(Y7S1 zz_y)2cWW_ssZ1!zKR`^p3cXp&B!0VxlNPqTTCbswo+a&IFm#vrJ6r%ta;7CZXAQ9o zlhD4(e9L0CkMFRf@PZ5tNBIbdyw+s|j6}Ys;UK*yaPB(~jv@0u)0a8Qz|*tt z7aK!AX(G|#4FDv@0;u~r8JkOvGJJ_`OpxK+EOGkR`6B?}0^*`1CX#N>DPs3pAJ9AG zZqKZF!t?shg<76+WCF5y-ZQiq?jn_|sVRabyJ+Bjny|2TF%*fJ&tUG=ha$K0h`*_< zt(=!MJ+n{uWrT#!a@w0u9_ext*1C9E!_@hX{gnebIv3b};er6eIZyZF2S^Y=J_7s) z70C*=4`2Ov_rLk@Z$glIrah(NMHnZL%EtuC#pOF-)1vYJO;<0bU_n;{0|k1I|23p% z{s9|%k^iV$(6O-~m5pZvoLTas9$+ODJFz^e;Apa|x%KLxdaN zkH0zQ^?=eSKJqm{H;*ECIG8|0^is!>ep;iurvY_NpxY08^5$NyxM-L39+s3b0Dji% zcE5OC`DACSkcu`508CG+0GHAzpXt4WDcA-5o|K}e`=<)ONWl$J5;XAkzOOUuE!e&j zT)=sHn*~r`7-U4nGxZ*a9&|#^vpM5lKUdXvu>T^IY<;M z1jyFQR={qwu99C8*y>=U3ko<2{RzF+WD#Mq@%GEC&~8|zXJt7&J)BS2b@%-<2EZu& zgN9VP%D#qVx2xCFuv?4Or)(x+M|hDvZ?4M|xItQL+xmj^Z2a~XEmJ3+I6>8hD?g}x z9A;M@dbMZq>Qu&s6^!PODd~fsi~T&eUP4%T>!HF!Dp>cP$)v;Ql%%C&q7O(a6(y21 zWm8=ovcH<BV|NB3Ax!{?%#QM7l*s@1~LT14A8P z-h4yYi=%1uMrF}<%U1`pRgdCF$cjmy0LmnuWnA zyF1VB1bse}AE_a^X~{xYX=>(&CGEr0-__W~Mul5Y}^iOkuUAMXhD3Sm9k@_p}61&DHkn<%Kjk@t8Q-j5^9<<(cH>u%j zIs&?2Huu8ej)NbZ(txMWW_aGEH)ASyaHdKaWKgJH zykAgAj^ygnR?=MmBDHZW590<43BrHWLFzN3jpN0Jks2M?7ryrTh%eCYziMtMB@Lip+41IYlEKsT%m(H$U4) z>F}t2;T#z`vxYcVCnl}0zYu~I;NqX=Ez#7RN_s`$9K(J*7$&2+W~6C51X+{qU*B%- z3%&J<#z-89F$LCsJk2nMYnHFx9(O!AJkk}_&h)TMqs#IQ8gi2eM&nL9=_LtO@@AKq ze%I25i!s#N^Ftqw9SNZa^6jYonFf)OsE~DsEHScS!?i2(Vb0jsE$%_8E~dN?pnU(~ z;aj&Tl=aqW`Xz%*_`5FxS%% zS}->C2#&Sx$X0&O2FX>?^kN;LT9yXKAT986dH3u;(0(U5vyrW8<}c^7kEus zB!tDx6~3nU(hxlE7E8Y8hZeTW7daqan`(I3GHuzW0kbJt1;}g&hDOY&3tO+>;Ns#L zJHz7Urr;xeq^ZAmz!Xl<0#JEv9dr=eNaCuW9($%x6FO5tmvpzR2BBLeJtQaNNK1ki zKZ0~J24_+y(jw)?${H|w??KVtNB<`1-j`X~{0dHlhWZtd{W>m{G-7o(2Y|}}$S}uX ztc3PlxGbz*eJd7vUt6boed5Ex3f($e(&~7h+4Kf@9pqe@``JR!Frp$jHFDgyE zL!x^9Q3H`^byZo>@~$E_$ZB~@Ckhq9NbgpmD&ECg9jcwJ6Ko(xCChXN_kR=hNBa{S za!m|Fk;oNYPGZ@^z1PNv5v##5&-u#iN-qiKCZon(AoWC+keI(_PZe?S+%TWsBur41WsaK||xnP)(bP zu3|@UgN#b=$O6hCRL%!0y|(D0jdpUbhhsUVZSpu-%H1d9*K8vV*CtljA^6E)@0B*Q zrD}zko@u;>&B5)~9Q))Xm}1L^j=qO1F^t^Uad`1>-n6y-fu zg8YftrWhB%TRi%iAle3l7A~6|^n;{8*9VHp>u3FH#`$ayy{)RHcOtCFJiin^b=a}6 z2K5JKlKVIIMU5#Xp2fK-?;>gVE9=5*WQC>*vl|=PtV}>pS|w>ecwOxc;nxk=_5vR+ z;dgJ^;a}DZqU<*ndzw@jdy+>85#bxQsJE++MzGB~$n9U^#`H~2jP(U=Om&;m@pJrA z%^PQi^M&$nfQw?}?x?9vJ+(&-L;!l5iY~OWc=P*@a`b@IM3ec79yYdWUyT;~gX&3A94tyloh=4vT$ZxO5PAfpb4eW1KNxVzVOE1vZ;_gdJG%eQj`%NY5IIS;>ghrf329@ ze@z#DcfuC`V#R8>LrogTZ*sKmer=CJT5h}l2RW`k{pmUBMKqgsdx^K_5GSX&zq7_v zoC|lTNj@(TT`Um{Dd2;&_#)67cWb3oEm-ewJ9Czm=ec>R-6$7+ct{EP6El>lVv~ed zv5Gvw^*Pbak6?i!KsI(6ehU{)BVVV_VoZl}wpY1*%cK4$;Uh zzvfwiAEW3lLaX-nJ1q{Ddc6~R#Q{$P-#5vf8vek{jm{K(I=t?lM?P}H`9_ST*A?(W z1xEPDyes9eANh9{R1v}z`010(c70<%gcDa5T5;Du7*a0|E5DlFd}$|-DxeCuq$1oiy1g@{xsJ4QpXPpbpbpQhq2!1 zS>I@kA~4b|anMc}|Akm#nBF2NnTZE|tCXNE>Zw|6BIkS;G}9=0^bx$ZPyfnX*%fTr zmF64En5I*gX)a+z{MbwM<46f-F4rq1)i!&evQpmv$}CnwY(<)8a~b`5Zu!;|p?SA_ zR_!Ac2(FkzM4sNA`2@jjGTIjQi;rNjrI|;=&zg6qHoxumE9a=WrJ!pOH|$vDR9Fgh z>oi1KK~>mq&ndC^70VKsQ;d}-(r{lZ5z6O;9Stk-Ap!w88b zciu)A=FD9mpG=8E=Ml{Q7TVdi-+z}RO{3EPbXf|ZN`4|ZkrN(BlMJx(nsA+CaOV3%eJ;>*vuPE$r$zC`(iSIoy}Bj=R8B7p~U++ z->X>8ieHAH@_ws8aO0)>jZ)3O#KY)hVr%`B3yoKHH~AW$5gcBj%r`(Fzy92X(vw9| z3{V=3jLoFYo1v=Nm?JwX>z6%pclY=8yKJ07bB3|0??d?i59f-MxGqo=Elkp8rcC9BUgu@HI4y(G{Y`BOx(J&fMg26Zk} zta$p8EDxenC`pm&ewsY8od-D)VIcTq)0QK(r-^E}E>90}gybEju*n42`4*nIp2FOe z0@XQvZiCnSP}VvLcEOqtT*-VtS@nmloP8`0K}Idy@AtVON@oo1Tu2{8X7#$#o+;%X ztuBy6>vHsj&$4^u<^gdrgcZ`n>>IUf34mDyI=F=`Uy#<@p+2~>P3M*R|v z2!TTql~2Y+5g>9M)4$u*KI^fbO@WnW)>H6rAa(J!;u7M(8!1GK{R7a*`P0(ssLcc# zlG>g3XiBW~(VpV>JSx1ivV7lrifDbT4(amy(^}y}XT4VsdR@+1r?;wn{bD|*`GaITC!X-z<~$>G)5)KpI2RD1LtrIh2dW$X*vBUC1# zb$8-IO8P3@#8+&8Q}y`IG+N)}MCw%+x)_k^dAG!L^X(k}8k_}Eyb&kJ zZB!xXL_D|Q_O#RjIX1N1t8hdWT4QbQr;n7jdsVbFuYMwg_3$yBJ;Oo{?c2}b4PW^O z5RS3BRl6RKrY6dSk_zRUb?-KAC#emVSea{M$fAUa?2<^7M#s(%=(~Exj_&oLl&g*` zzHg;i1!8N-W!XYk5oYLq^7 z?UVQnaq-I2FMB<*xElMmtTeHkD@(nT^zDCumLC>}OEI2}CHxG&`Yf&grJwc%JyOG&966j)M zsMkR8y-9WN)oAk1zK1wWf#keEU25w)6@zttxCw8dYo z>QXZe148EvRR!TLzD>0{i8R82ni=n-pVZiErFLn>5mr+xSS};IO^Pa1z1#2TBa|`n zG?El-!(DAW6U2big|xDT=WX=oTsSi1_K-GwV7*`~_cxK%^s6!UC zi-Ea^!YNPiaiEZnP6!GzNM>uAFlVYh>?OH* zz@w2FU)jMBYl&%t1vLYb4a}TZlUvyDb|}ZoK8jDgezQYaXB;E3Q83=}hqMcK=DZw& zn2CI!di|#!{v*0f)<;a}`p}i=j9xd%7AV?=eBd>gYo`+Ws&m@=>z32MarnD zm1TV!h6*<>%;a6|XOio{Zv%njl(4%WAR7lsb+Sz9aB-bC3-32b5WsKYQ%{QE~A?!hx*>?a<}$WBN&45QtlQ;%uK-a|3dG3M3d9g^CozF z=E3)OW!V+XLVeu3fKcV{Mz8uJmG4;rPs>2Fk5xY2^v?FCIeBR+ z`JnlosHMnE?`apc1F>iU=VAWR_wgstlpX!N5&qJ_Ot{_PpzaU1yvgb7Tqi)xU5X~3 zSjq?j=?^4__``D^O>@4JV&$Qm;rCxw)i(`nE>sY8%WSd9WI=jJ?BZL8n+Qnq_>XjV z`s-BH=7&?rXOo}R+E)jzh6XE4=!0~H5wnIB4BUVD#*g~RXAwhmIMH?ZfWc$cFp4;$9sCH0++EKfw%)N8=` zOpQtJ=M;W~!QI`u3X^~GAnpFhMohkAW9S;*Y1ryMy(6fUVfG?IBx|CQCdWhHe+$a` z2M{uAe+m%+w^dAY?ag7+XruSJdln9Wy|-b7jIDM4==o9&1f*LfLbeu~efE=rfk;w8 zEh@REu|kOm6x}Qo{>UZVk9)l;$v|Dn!^0Egs^)36KZk4U%p0~pD95DMT9p}_=Ab3TQb`i& zi~XQJ!Da)>*e&ukW5mC)KmyDv?k+shP#3LL8d?={%BpFvU0S6cZta+ZuieBScsi^KA5$O6c{=;~ z_(CCBA~;FTglf0!t6ncTxPt^EGvyN-+;o3@`hj(6mVvS3L8+~A!o^{gghW3ZgFl8k z{AOaupVTk(L5+pzvW^GD0u_QN+{~5NZpbk=%74Shx*2)PSdQs%<%i&X6_{H}9=>RR zL=PuU`@Q0lLB*JP(%WOXQySI^dEcdBhdV4~R5F`Hr z4^2#4YC$jDzQMCxH`vZNGo4E=owhX@IIL1!Yk2rgP(USJh6dLTE|yeoq@ZB032T_u zVM1*NIWz!0E2|CnPB!`8!v?7R^e}vZ+JAWkP(Ph|1yV4ela>=>S!ixxs2*`ug+W5e zhQ2tY{&p)}Za)S?hK<(`^gWOFEBE$8oOx;MnVg_~HEhR`GcO}3q`2atax;*B1}X9I zP?V5{|1c0rKMLm&u@4gl0JFBqo%Hv{&R_6#SFwk4-EU~Jdzb9RnRx6DsRxgS?yCHL zo4FcLQ>&f5>S=paJR*-tB7JSj-)4Bxw6sGJ)utxvx>z73{kLYNsz^%jz@(P*qB-W7 zc0_!6LCWY)0?{xpMGJl6%LF(z4Aph_O}NXwPmoL~XKhh+b&HM253Rg8`ahmF!q{(Z zmb-Xb$NmucJw^P&kzi%B-=^B;KcbGRe}Y)UDNFBh0l50oN+A43&O802s} z&#neI-LY^j#V6AEiiD|wi5&S{wsl;G4{+3ExEyjrAda?*)acb^3Jm0(j!`DZum7Y`P}%o767wvF*JMf zQ|eDu5-jB?FcwimLeuNyP3DsyqI-^~#w$x1Q!TCS&s3Vk z$>g^6h^c0ILPpop%IS%UgzTQ4*%OSIKw+3U#y`B~oY2VYF#5yi(qGvM_mHco%9;F@ z8of&`O&Xj4=(M@yB$vXFutxm-;K@3jbe0JodPLM*d>eGrtmpOXhl{pPH?zC2axPLHVFu|SV) zpLzf0$mt^-!W@}mvWK1Z?%S~ICex}M=kBgwcfJDV^i0E*s44Td$KnndnY<6JYpF+R zgD-a7D#0HWrVV3bYFLeZ8}$M;ccCwl87@(^XEML84yMf|`Gcz`;SwzfzM004yLHS+ zO~;sB!5igxCI1$S!=6t@u2!M-8EHqbeYIxaJvgiZe>ZB*%q6$c| zUP9zFbmwrc=kF=n)x7B4$(+uoUpL1h>1owmwJ?}ZbEnC6HS>G{yM9MjFTu2rS(Ohp ztM83iRrc4rph#4McW1nW66bGWz58qXT$e|kDPG}OzOrno?gv&J#BTl#aS2$=%qq#f z2g^-Nh4dmpmKQOYY>O@hW0Wdmg9YrD4(|Dvd-w7k&+(0+AN4Ee(%Umk*V4r8d%oQc zX1LrctPT`qfs}rd57rjgy-^DY-a1FYLhOTqi%aI}Bun(a1SVPVBL~kQzhV zhkBpARI*nXQ~M`i?r#9WgCtSJ#T+dAxi`vxd`6KuGcN(AD2c7IGPWI0i^T?7pWZlf zf(+<|D>k!mAZszON#VAKC_f0?YeyG9#(N`yvk~px$(Ek_s(!W65$eEAfHLUguXUyh z{^dg!8hyr&H4rDi*$+y8{SP2S=1I`RH|t(LT8sfNExDAPC*W1=R3zyPz2gFirR}{g z0DyWLhv2(L6#!)asJ~3;n5`b9Kf6K}#wId`<3byML0~YG+zj1uGPD9k)GD3K4(5<0 zTL?t8&rt&Km9IO0IEfP1%Dg9}k)KwNI8PtrPVWH2j_2b$7j${)nDZa>WQ!8+u%;S< zc|Rk_;^ol4>zX4@eT3|*gvY`!>Tkb^M2{aAKCWuKH{W657G{#Ea}+CJ;Sz~*OiB00 z^L;eE;^k44aPLDX3E|>ltayEdpop(8O5n9CmT-$mP5S#@F<7bHY}!5TGzQh7)q17@ ztHS`^Dy7>FIWBsyUHC_R@kR2k8&B!M^%^Zw%|#gw>p6;#T&I} zj1QN@@lpG4KYAP74H|ymQ+;!QeDg%B24c!vd;Ov6>8Dt=Ao8#Ko-YETG)e}ElD}R6 zjyW!$*Mz@hm36=g!giaAO(N=Ba60cXrh*y70}yUePPHg{p_O)iqSxIfLt~Al5gHcd z+UJaBXJ7|Y?P?!u&VOGUIw>@Mf$9}IVo+sRtO0eLI-gVI*I3F@D2L~k=)I>9*e4`> z>@-pWrj(V4hhOf$t~)8Xi1Pj&0+aOjN4iNWB<>_NG^nkvw)!iYRlRp42Kr$2vpxT@ znC^lH7&dB}CV9Ytb5~$2V%p;wM-4cYu>{HqMLJd1@JHC=WCU3@gZ1(zy(z$|@lgOi zS8LakQ{_S~Hk)UmMj7C{qWzcdQ_xJQKrY+HG8=DN2ltA>m^)?V`l*`8hJ>A9@cDr$ z&-I|`p2i=+Rp$N0P85}R+Y>fX0Z~PglSJUgH!sFpo8}nXn@V}aCqF$n4V5Tg{l5RG zu7g#7ICH(kiJ+k%ZJAoVvXPYCO_FxD9;Xw=+6{LaJVlBwsFpWgmmNv|n7p41#|@;{ z`V14}42#z})Vq1)bnrrOab&(8$Oovvfzj z$6UrZ_ogZe3f+ zNU}J#&QWh#iG|d32>_=UHTebkM_ckmD8TP;f#EB2{%BJU#Kox2YZ>XLvn#J&MrnHyBvjatCTY9Yq{gV73DO>Z}S)fyYBlQpvaXx0pE2dVICLLyinkTJ~_#l z^3oI^mvj=yJb3x&gf+kM@QFU@5OLhfIJg}3lqVnx&{Wd#1Vu}Mv%FDabkMqxc$@xn zvE!3IF+8t-yn4gR(_t@3D2zFI96>eh+dIr=>n9~w~OdmA~H*ixmOnCrY|<8LD{|3QuG zL2D3zGG>aQ4c(iHd-a)R~;_QS;}KYIPwq!Mp7USNN;w8ivGo zbkMi{7pvV+(csE|BG{lJUE%7R|5{e@U#*ki*-6Rr@=+dDFgCzp`dI2 zPb!A~PX-u)k+I!`oDCIH=L!dmLbt)s{Kpkc|7nTSe-HS7mVMmG3f`uwHGBS?t~odrf%Za9o$o#g8cNos zcaXZ>wecO|SHUvu7}4r+h=9213)N3sM)q|WxTS^kuO;Yj<08*!8)qM z4?$;GmYn)J<6@o)6qMahyKZ`X>U{Kr;sEHxXY+WFat*s{F7~fWFPwYx-szT7@%Pb_ z+6Go^jpE7{)7=#Qb&mbSY0&*2Q{|{bXPfK0{dES2faFs5WUFV3DPN|y^lo2=&J+~f zQ@|S8ZEEN@R*vh{D7T0OF}7?}Kci4Vw?nbNrFuR8&*MeUS~C-q+z%i4u|$hug9g0N zz=xNdNzI{C=i5vh|2j`TU`&t2mj8WkTsW~+TiUAfCp@e3aG_aTE$Fev`L_i5&6AZQ zPkG%{t2D3?3!mN(67BU|K##}6574&0PGhN0n|qI@D4{zF(qZ0mYh|fXO)glAgkJ|e zKfHcTtLmJ8bGI>K+^<@>#r#TFeW=*aLvePFf@j3)P<_Vns1gi3)!%J&4d=b?DNvlO zLbyKXt^3$h3h!Q}{Gu52tTV6tISp3aIq7=H{fYJXJZ|ru)$dkELniP@^dFq;(eu2u zpx=+9%zjBFf#Q%6x&N-IhyTnt_RlNsp+;wcBy5^&vpWFdi^o$)aB-K+Gk zAezg4w^t|g>|BkpR){r8aP`@=W_iH304qdZgxosE1Jed9B+hNO3Ln4nidU^DI?7{$ z00PDQ=ukuWH`^4J{)6N)H`*&u7fMC~;8{!lQ|xh?pW%KQ#-R_ObHs~=Zk1;6Z+kUE z$~UuXD^476d@p|ang@Jw66k8@&m>&rX2_XUOK$$3`ebUmK7AzambXlQycZkkFdhBW z(H4YOrKdpD_L3?zpW9P&2i@6;yxeH^t!#kEb=s2|)W82L57RC>)c0NS?R$r2 N?;6}G*RX&7KLFsHvc~`b literal 12020 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/gui/codex_rune_page.png b/src/main/resources/assets/eidolon/textures/gui/codex_rune_page.png new file mode 100644 index 0000000000000000000000000000000000000000..3aec0262ca42be4efd3efe817a940e7556d98d8f GIT binary patch literal 3766 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/gui/icons.png b/src/main/resources/assets/eidolon/textures/gui/icons.png index 1bde5269d5163693feccd78e3c87798dda6986a6..988a84212e95254a09d3a239c090e2ec887d33ac 100644 GIT binary patch delta 489 zcmV4cH7zgkt!KD?cNJ^yyL>e%tbQBk-5a{41 zaC3C&=xnE(0{zwSS0+^|h6F{ozv_?Vm?P z#L@nF+<9;#*4I|bV4eY*uU!mzvFnPi{4l5TV}0E*-_aic0000QY-j5r?Q9*Se4dp7 zny(e{v)IdzR^#;J$%VkP&HJ^PVjXC%@;iXK^5-s-0h*&75pgy-uDw`YpOpccs~r)s zxxLZK3w|~^j(^SVjq;dZmjRlsd<3W#JTHG;2AD%z&-ecLmj5yt0H6tm{XrV`2PvPc zM&oH3ji)J}fd(7)2dUTTrlp0&H0%%3(!yfub-KT70;BOX^*Y_u>vU5-|I2#^{$6X? zAEd8mU&@8k@84qi`mOT+-Ojyu`SxABc=~W==FR)hF-LrS(}zLOFztMyTI^XalL4;2 z3mX9NpQ%3g7r)|tK#>`Zr?naH0ALPOH-WtTh3Y1t{4i&VO`xv)g<=y>ewahQD}O=x f0gKB}v=V zxjo+*x+zIAbW@J!ecGn}7RwH>ebo}mVXqC{_~B2LZ~fYv?*jD)lK}$OlMn(T7f6y1 XM+8HHJPlQ000000NkvXXu0mjf><&(7 diff --git a/src/main/resources/assets/eidolon/textures/gui/inscription_table.png b/src/main/resources/assets/eidolon/textures/gui/inscription_table.png new file mode 100644 index 0000000000000000000000000000000000000000..750050c846a4412dd8b169a636339463fd5e7518 GIT binary patch literal 1221 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;3=Aywo-U3d z6?5L+-RKvcF46GtexOy_iyNy?h>7m#K4ISUWa0D+z1#<1#U^NNi(^%8cAs!(p`ur; zrsY<~xVO&Yh~)#e%-^v?f>_%FZ}39{cg<<>MbupU>y3kg15`) z^YfecTjoQG+P+D=Q*1kP*z0f^;n`|imMx+;=3F;OuhurWe3L8Z+{N=B3#!WPm_Q*(ELwZu znap3AvUF{O{JymZ;Km=A{prWI`I*aXSmvBf+k7@_Yf<6D-kHDn63VKoeyw3|T>gad ufyw{xOu6%(ihTHT=MS*3!3PdZ{vqAB^HfUv{CPh>>O5WjT-G@yGywq2;F`Js literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/gui/mana_bar.png b/src/main/resources/assets/eidolon/textures/gui/mana_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..f79f80b2309c646170078726893d648f1c202120 GIT binary patch literal 4077 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 F`!Cn+lJWom literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/gui/research_table.png b/src/main/resources/assets/eidolon/textures/gui/research_table.png new file mode 100644 index 0000000000000000000000000000000000000000..a44c3ba44db4785f30acf3105d351aef6c28cd87 GIT binary patch literal 8313 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/eidolon/textures/gui/soul_enchanter.png b/src/main/resources/assets/eidolon/textures/gui/soul_enchanter.png index 79316573a0d86130f960d173dc44089e1e9d15fa..45eef2956bf37f000d4412a3f3c4a531ff5a3537 100644 GIT binary patch delta 3726 zcmY*bc|6qJ+y2hj$`VzSyG4?Pek^8kD=6r$b=@_e5qe5$~IA!s8HD=(x|~m zJt0Y!F=ZQ!tdALtG0eg{J@4}QyyvfT?$5cdbD#UZ?sFfe>Z)qC0jOyB;^lGh z$`C8LbCsNGaOvTsSm@6aZo7NL)dc-h6_vzJkDSr*+Z%pOoc#94fN=V8xkXs|$i)IK z#Yi}AVEfHmuEF*_RH#pm!Q#GtS*U@0r?rIZk@Ux@sS#%IR!gd7^dtfCouY@C<192L zVz3C9v^0vsi9xCpQAi4XE{4LH95l~N>6q+cLLB92h;pjQIzseT-`t>;!&l~3mvZ0& zCq=)j<9I*!u>K+E;vaugBrYfPub+e2e`IKB0yjSf(=vt6S~)mmz$;r@1J9dg=Y{1+ zUdFcPhgFtBgR9hVbfNtoHHXO}D=$5f$kHV%%d|1Vw*E;+q4vd#l8#*_R^-zoj6M)? z@WR12WgiWzUca8*L$V7!0>Bqox4^E1`z(+_%f(-oI<~n|grlEmZ7$bl-pO3(cfg0=_FL$Ud%@*DzH)P%JE&S>})A%?m2Y zNr!Y+bfftE?*z5sS9Tk1`3m6BB1)hRJxXwqM%&m9^6)SW=@ZiT4id7&VDRaL5t_O8 z^q225?}6!_9wv|jrAF+krRwC9rt#IqOA{Qdt?eCCQ&Z_- za___9_ek7&E`K#NI9QgJmR6G`RQqN z)GTL6&}FP+IITZ^JU~9!6e!OhJdqNtKi^ATx@1pDTzVW8YjhbClf@0dzo;R$zVSxH zpMP>)<;w8v)%B&HZ!+A;XC%g(KNSMmX)V5jWAXKVxv}QAW-;RvzSZ(%qHLR}0tq|6 z_#c?MzTEFKKuhzs2AvKT90x;tX|rU_wQNA<+5vz>A}vn%Y7;xeu)k`wHt|tjPEJk( zCxCZ?0?&VQMcX5XLaTYtT+hz+m9kWPyuH8DSy}NxadB}2o9UYktIK4SYcKRqc z%Y4Ikth3;c^<#c8PLD1y$=za9)zo+%md!11MqvRe?h%NAep%!2j$7#O7F7cP$IP2z zDJ3N;Uf$lbZ2c6igL4r;4s7AU%Z3Jbb8~aIEEy+}n;%v2P=Wnj)d8s_(u+~Wh_VtY zi!08fyx=Yth07Ghv9@7-hP{w0E#- z;7OzasPF-8tM?kT+gZ;$Fg}0f2S3ejipk~fW26^PM2g~GQAEp7e=P<=E7;+gBfL1zs@?kL)?jBN#~@O>1c!!(9x@@#4@L%M zwoieaXJR8ttF6{}mhi2=nAe-)QCR#|7?`A*Ox=@GSa?9_*2mpu*=cFQaTttt?9@$G zQz%_37K5oa`ECF?i~LRorn^H``ifx+#FiWK?Oq-pWwghgl_g6q)ISQX2C|PugchoF zIR`mI0B)ERkP;GaEcDp%%5Gt6LpeZVXOpglm*^2Bke>c15C!aH66jFZdFa1oplYHH z0H1OvM9=Yyl_@3&O)cMH8dLS1tI$7LA#3Gaoqwe(R9ILz)ZhQn)_}{n6NKRRzB&2M2`(cWeq;9Z7Jrqp@Gt*HBsU{7Dog$eAH@F=# zXj}fh#h&u19X6tic`!Kr|DvL1%)eg!a}F=&=Vhq=R}ANYRKQKSyU18mILps?JM81S$fh%?t2?g)`=SWBsY~S#sjBvVUVgMq=$I{GxkfZdn)$ZnSY51~+;1Lsy{qt#Qo{Kj`ygBvTY)#E5