From 770a5b40464374b003887007262720edb9aa6cf1 Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 18 May 2022 23:56:18 +0200 Subject: [PATCH] Reorganized Imports/Packages --- .../java/org/betterx/betterend/BetterEnd.java | 82 + .../betterend/api/BetterEndPlugin.java | 38 + .../betterend/blocks/AeterniumAnvil.java | 27 + .../betterend/blocks/AeterniumBlock.java | 30 + .../betterend/blocks/AmaranitaCapBlock.java | 28 +- .../blocks/AmaranitaHymenophoreBlock.java | 22 + .../betterend/blocks/AmaranitaStemBlock.java | 26 +- .../betterx}/betterend/blocks/AmberBlock.java | 26 +- .../blocks/AncientEmeraldIceBlock.java | 89 + .../betterend/blocks/AuroraCrystalBlock.java | 131 + .../betterend/blocks/BlueVineBlock.java | 24 + .../blocks/BlueVineLanternBlock.java | 57 + .../betterend/blocks/BlueVineSeedBlock.java | 81 + .../betterend/blocks/BoluxMushroomBlock.java | 53 + .../betterend/blocks/BrimstoneBlock.java | 106 + .../betterend/blocks/BubbleCoralBlock.java | 56 + .../betterend/blocks/BulbVineBlock.java | 48 + .../blocks/BulbVineLanternBlock.java | 86 + .../blocks/BulbVineLanternColoredBlock.java | 40 + .../betterend/blocks/BulbVineSeedBlock.java | 49 + .../betterend/blocks/CavePumpkinBlock.java | 72 + .../blocks/CavePumpkinVineBlock.java | 79 + .../betterend/blocks/ChandelierBlock.java | 117 + .../betterend/blocks/CharcoalBlock.java | 28 +- .../betterend/blocks/CharniaBlock.java | 17 + .../betterend/blocks/ChorusGrassBlock.java | 17 + .../blocks/DenseEmeraldIceBlock.java | 39 + .../betterend/blocks/DenseSnowBlock.java | 26 +- .../blocks/DragonTreeSaplingBlock.java | 26 + .../betterend/blocks/EmeraldIceBlock.java | 100 + .../betterend/blocks/EndBlockProperties.java | 131 + .../betterend/blocks/EndLilyBlock.java | 126 + .../betterend/blocks/EndLilySeedBlock.java | 53 + .../betterend/blocks/EndLotusFlowerBlock.java | 65 + .../betterend/blocks/EndLotusLeafBlock.java | 82 + .../betterend/blocks/EndLotusSeedBlock.java | 138 + .../betterend/blocks/EndLotusStemBlock.java | 109 + .../betterx/betterend/blocks/EndPedestal.java | 31 + .../betterend/blocks/EndPortalBlock.java | 218 ++ .../betterend/blocks/EndStoneSmelter.java | 182 ++ .../betterx/betterend/blocks/EnderBlock.java | 30 + .../betterend/blocks/EndstoneDustBlock.java | 52 + .../betterend/blocks/EternalPedestal.java | 142 + .../betterend/blocks/FilaluxBlock.java | 11 + .../betterend/blocks/FilaluxLanternBlock.java | 17 + .../betterend/blocks/FilaluxWingsBlock.java | 51 + .../betterend/blocks/FlamaeaBlock.java | 64 + .../betterend/blocks/FlammalixBlock.java | 44 + .../betterend/blocks/FlowerPotBlock.java | 453 +++ .../blocks/GlowingHymenophoreBlock.java | 17 + .../betterend/blocks/GlowingMossBlock.java | 32 + .../blocks/GlowingPillarLuminophorBlock.java | 59 + .../blocks/GlowingPillarRootsBlock.java | 37 + .../blocks/GlowingPillarSeedBlock.java | 82 + .../blocks/HelixTreeLeavesBlock.java | 84 + .../blocks/HelixTreeSaplingBlock.java | 26 + .../betterend/blocks/HydraluxBlock.java | 97 + .../betterend/blocks/HydraluxPetalBlock.java | 35 + .../blocks/HydraluxPetalColoredBlock.java | 43 + .../blocks/HydraluxSaplingBlock.java | 75 + .../blocks/HydrothermalVentBlock.java | 155 + .../betterend/blocks/InfusionPedestal.java | 101 + .../betterend/blocks/JellyshroomCapBlock.java | 106 + .../blocks/LacugroveSaplingBlock.java | 27 + .../betterend/blocks/LanceleafBlock.java | 74 + .../betterend/blocks/LanceleafSeedBlock.java | 61 + .../betterend/blocks/LargeAmaranitaBlock.java | 77 + .../blocks/LucerniaSaplingBlock.java | 26 + .../betterend/blocks/LumecornBlock.java | 113 + .../betterend/blocks/LumecornSeedBlock.java | 38 + .../betterend/blocks/MengerSpongeBlock.java | 136 + .../blocks/MengerSpongeWetBlock.java | 128 + .../betterend/blocks/MissingTileBlock.java | 13 + .../blocks/MossyDragonBoneBlock.java | 69 + .../blocks/MossyGlowshroomCapBlock.java | 47 + .../blocks/MossyGlowshroomSaplingBlock.java | 27 + .../betterend/blocks/MossyObsidian.java | 68 + .../betterend/blocks/MurkweedBlock.java | 50 + .../betterend/blocks/NeedlegrassBlock.java | 58 + .../betterend/blocks/NeonCactusBlock.java | 13 + .../blocks/NeonCactusPlantBlock.java | 429 +++ .../betterend/blocks/PallidiumBlock.java | 74 + .../betterend/blocks/PedestalVanilla.java | 34 + .../betterend/blocks/PondAnemoneBlock.java | 56 + .../blocks/PythadendronSaplingBlock.java | 26 + .../betterend/blocks/RespawnObeliskBlock.java | 214 ++ .../betterend/blocks/RunedFlavolite.java | 56 + .../betterend/blocks/ShadowBerryBlock.java | 25 + .../betterend/blocks/ShadowGrassBlock.java | 47 + .../betterend/blocks/SilkMothHiveBlock.java | 131 + .../betterend/blocks/SilkMothNestBlock.java | 194 ++ .../betterend/blocks/SmallAmaranitaBlock.java | 90 + .../blocks/SmallJellyshroomBlock.java | 128 + .../blocks/SmaragdantCrystalBlock.java | 20 + .../blocks/SmaragdantCrystalShardBlock.java | 104 + .../betterend/blocks/SulphurCrystalBlock.java | 121 + .../betterend/blocks/TenaneaFlowersBlock.java | 83 + .../betterend/blocks/TenaneaSaplingBlock.java | 26 + .../betterend/blocks/TerrainPlantBlock.java | 25 + .../blocks/TwistedUmbrellaMossBlock.java | 51 + .../blocks/TwistedUmbrellaMossTallBlock.java | 34 + .../betterend/blocks/UmbrellaMossBlock.java | 50 + .../blocks/UmbrellaMossTallBlock.java | 34 + .../blocks/UmbrellaTreeClusterBlock.java | 79 + .../blocks/UmbrellaTreeClusterEmptyBlock.java | 47 + .../blocks/UmbrellaTreeMembraneBlock.java | 91 + .../blocks/UmbrellaTreeSaplingBlock.java | 32 + .../blocks/VentBubbleColumnBlock.java | 169 ++ .../betterend/blocks/basis/EndAnvilBlock.java | 23 + .../blocks/basis/EndLanternBlock.java | 136 + .../betterend/blocks/basis/EndPlantBlock.java | 59 + .../blocks/basis/EndPlantWithAgeBlock.java | 27 + .../blocks/basis/EndTerrainBlock.java | 25 + .../blocks/basis/EndTripleTerrain.java | 13 + .../blocks/basis/EndUnderwaterPlantBlock.java | 27 + .../basis/EndUnderwaterWallPlantBlock.java | 25 + .../blocks/basis/EndWallMushroom.java | 18 + .../blocks/basis/EndWallPlantBlock.java | 24 + .../betterend/blocks/basis/FurBlock.java | 94 + .../betterend/blocks/basis/LitBaseBlock.java | 27 + .../blocks/basis/LitPillarBlock.java | 25 + .../betterend/blocks/basis/PedestalBlock.java | 462 +++ .../blocks/basis/PottableCropBlock.java | 31 + .../blocks/basis/PottableFeatureSapling.java | 19 + .../blocks/basis/PottableLeavesBlock.java | 26 + .../blocks/basis/StoneLanternBlock.java | 63 + .../entities/BlockEntityHydrothermalVent.java | 91 + .../entities/EndStoneSmelterBlockEntity.java | 476 +++ .../entities/EternalPedestalEntity.java | 54 + .../entities/InfusionPedestalEntity.java | 71 + .../blocks/entities/PedestalBlockEntity.java | 125 + .../betterend/client/BetterEndClient.java | 79 + .../betterend/client/ClientOptions.java | 50 + .../gui/EndStoneSmelterRecipeBookScreen.java | 110 + .../client/gui/EndStoneSmelterScreen.java | 151 + .../gui/EndStoneSmelterScreenHandler.java | 200 ++ .../client/gui/slot/SmelterFuelSlot.java | 26 + .../client/gui/slot/SmelterOutputSlot.java | 49 + .../betterend/client/models/Patterns.java | 150 + .../client/render/ArmoredElytraLayer.java | 69 + .../betterend/client/render/BeamRenderer.java | 238 ++ .../client/render/BetterEndSkyRenderer.java | 425 +++ .../client/render/EndCrystalRenderer.java | 84 + .../client/render/EternalCrystalRenderer.java | 135 + .../client/render/PedestalItemRenderer.java | 96 + .../complexmaterials/ColoredMaterial.java | 77 + .../CrystalSubblocksMaterial.java | 135 + .../EndWoodenComplexMaterial.java | 48 + .../complexmaterials/MetalMaterial.java | 508 ++++ .../complexmaterials/StoneMaterial.java | 191 ++ .../org/betterx/betterend/config/Configs.java | 37 + .../betterx/betterend/effects/EndPotions.java | 32 + .../betterend/effects/EndStatusEffects.java | 36 + .../enchantment/EndVeilEnchantment.java | 17 + .../effects/status/EndVeilEffect.java | 16 + .../betterend/entity/CubozoaEntity.java | 155 + .../betterend/entity/DragonflyEntity.java | 214 ++ .../betterend/entity/EndFishEntity.java | 175 ++ .../betterend/entity/EndSlimeEntity.java | 431 +++ .../betterend/entity/ShadowWalkerEntity.java | 149 + .../betterend/entity/SilkMothEntity.java | 321 ++ .../entity/model/CubozoaEntityModel.java | 102 + .../entity/model/DragonflyEntityModel.java | 144 + .../entity/model/EndFishEntityModel.java | 106 + .../entity/model/EndSlimeEntityModel.java | 153 + .../entity/model/SilkMothEntityModel.java | 183 ++ .../entity/render/RendererEntityCubozoa.java | 74 + .../render/RendererEntityDragonfly.java | 32 + .../entity/render/RendererEntityEndFish.java | 73 + .../entity/render/RendererEntityEndSlime.java | 161 + .../render/RendererEntityShadowWalker.java | 24 + .../entity/render/SilkMothEntityRenderer.java | 23 + .../betterend/events/ItemTooltipCallback.java | 36 + .../events/PlayerAdvancementsCallback.java | 21 + .../integration/EndBiomeIntegration.java | 5 + .../integration/EnderscapeIntegration.java | 51 + .../FlamboyantRefabricatedIntegration.java | 52 + .../betterend/integration/Integrations.java | 56 + .../integration/NourishIntegration.java | 52 + .../betterend/integration/byg/BYGBlocks.java | 17 + .../integration/byg/BYGIntegration.java | 26 + .../integration/byg/biomes/BYGBiomes.java | 23 + .../byg/biomes/NightshadeRedwoods.java | 87 + .../byg/biomes/OldBulbisGardens.java | 120 + .../integration/byg/features/BYGFeatures.java | 66 + .../byg/features/BigEtherTreeFeature.java | 80 + .../NightshadeRedwoodTreeFeature.java | 200 ++ .../byg/features/OldBulbisTreeFeature.java | 214 ++ .../integration/rei/REIAlloyingCategory.java | 234 +- .../integration/rei/REIAlloyingDisplay.java | 2 +- .../rei/REIAlloyingFuelCategory.java | 214 +- .../rei/REIAlloyingFuelDisplay.java | 2 +- .../integration/rei/REIAnvilCategory.java | 242 +- .../integration/rei/REIAnvilDisplay.java | 4 +- .../integration/rei/REIBlastingDisplay.java | 2 +- .../integration/rei/REIContainer.java | 9 + .../integration/rei/REIInfusionCategory.java | 222 +- .../integration/rei/REIInfusionDisplay.java | 2 +- .../betterend/integration/rei/REIPlugin.java | 196 +- .../betterend/interfaces/BETargetChecker.java | 6 + .../betterend/interfaces/FallFlyingItem.java | 9 + .../betterx/betterend/interfaces/ISlime.java | 9 + .../interfaces/MobEffectApplier.java | 4 +- .../betterend/interfaces/MultiModelItem.java | 19 + .../betterend/interfaces/PottablePlant.java | 19 + .../betterend/interfaces/PottableTerrain.java | 7 + .../interfaces/TeleportingEntity.java | 11 + .../betterx/betterend/item/ArmoredElytra.java | 99 + .../betterend/item/CrystaliteArmor.java | 47 + .../betterend/item/CrystaliteBoots.java | 42 + .../betterend/item/CrystaliteChestplate.java | 40 + .../betterend/item/CrystaliteElytra.java | 85 + .../betterend/item/CrystaliteHelmet.java | 22 + .../betterend/item/CrystaliteLeggings.java | 22 + .../betterx/betterend/item/EnchantedItem.java | 37 + .../betterx/betterend/item/EndArmorItem.java | 62 + .../betterx/betterend/item/EndAttribute.java | 10 + .../betterx/betterend/item/EndBucketItem.java | 15 + .../betterend/item/EternalCrystalItem.java | 12 + .../betterx/betterend/item/GuideBookItem.java | 48 + .../item/material/EndArmorMaterial.java | 96 + .../item/material/EndToolMaterial.java | 74 + .../item/model/ArmoredElytraModel.java | 95 + .../item/model/CrystaliteArmorProvider.java | 92 + .../item/model/CrystaliteBootsModel.java | 83 + .../item/model/CrystaliteChestplateModel.java | 150 + .../item/model/CrystaliteHelmetModel.java | 73 + .../item/model/CrystaliteLeggingsModel.java | 84 + .../betterend/item/tool/EndHammerItem.java | 156 + .../betterend/item/tool/EndPickaxe.java | 22 + .../client/AbstractSoundInstanceAccessor.java | 23 +- .../mixin/client/ArmorStandRendererMixin.java | 23 +- .../mixin/client/BiomeColorsMixin.java | 62 + .../mixin/client/CapeLayerMixin.java | 36 + .../mixin/client/EndEffectsMixin.java | 27 + .../client/HumanoidMobRendererMixin.java | 32 + .../mixin/client/ItemStackMixin.java | 25 + .../mixin/client/LocalPlayerMixin.java | 47 + .../mixin/client/MinecraftClientMixin.java | 57 + .../mixin/client/ModelLoaderMixin.java | 29 + .../mixin/client/MusicTrackerMixin.java | 105 + .../mixin/client/PlayerRendererMixin.java | 25 +- .../mixin/common/BlockBehaviourMixin.java | 49 + .../mixin/common/ChorusFlowerBlockMixin.java | 100 + .../mixin/common/ChorusPlantBlockMixin.java | 76 + .../mixin/common/ChorusPlantFeatureMixin.java | 44 + .../mixin/common/CraftingMenuMixin.java | 57 +- .../mixin/common/EnchantmentMenuMixin.java | 147 + .../mixin/common/EndCityFeatureMixin.java | 33 + .../mixin/common/EndDragonFightMixin.java | 100 + .../mixin/common/EndPodiumFeatureMixin.java | 93 + .../betterend/mixin/common/EndSpikeMixin.java | 44 + .../betterend/mixin/common/EnderManMixin.java | 26 + .../betterend/mixin/common/EntityMixin.java | 110 + .../betterend/mixin/common/LevelMixin.java | 4 +- .../mixin/common/LivingEntityMixin.java | 288 ++ .../mixin/common/MappedRegistryMixin.java | 13 +- .../betterend/mixin/common/MonsterMixin.java | 37 + .../NoiseBasedChunkGeneratorAccessor.java | 7 +- .../mixin/common/NoiseChunkAccessor.java | 25 + .../mixin/common/NoiseChunkMixin.java | 79 + .../common/NoiseGeneratorSettingsMixin.java | 21 + .../common/NoiseInterpolatorAccessor.java | 11 +- .../mixin/common/PlayerAdvancementsMixin.java | 28 + .../betterend/mixin/common/PlayerMixin.java | 84 + .../mixin/common/ServerLevelMixin.java | 124 + .../mixin/common/ServerPlayerMixin.java | 182 ++ .../betterend/mixin/common/SlimeMixin.java | 31 + .../mixin/common/SpikeFeatureMixin.java | 186 ++ .../mixin/common/WorldGenRegionMixin.java | 27 +- .../betterend/noise/OpenSimplexNoise.java | 2528 ++++++++++++++++ .../betterend/particle/FireflyParticle.java | 96 + .../betterend/particle/InfusionParticle.java | 74 + .../particle/InfusionParticleType.java | 83 + .../particle/ParticleBlackSpore.java | 103 + .../betterend/particle/ParticleGeyser.java | 89 + .../particle/ParticleGlowingSphere.java | 92 + .../particle/ParticleJungleSpore.java | 83 + .../betterend/particle/ParticleSnowflake.java | 107 + .../betterend/particle/ParticleSulphur.java | 108 + .../particle/ParticleTenaneaPetal.java | 122 + .../particle/PaticlePortalSphere.java | 85 + .../particle/SmaragdantParticle.java | 103 + .../betterend/recipe/AlloyingRecipes.java | 53 + .../betterend/recipe/AnvilRecipes.java | 85 + .../betterend/recipe/CraftingRecipes.java | 484 +++ .../betterend/recipe/FurnaceRecipes.java | 45 + .../betterend/recipe/InfusionRecipes.java | 615 ++++ .../betterend/recipe/SmithingRecipes.java | 110 + .../recipe/builders/AlloyingRecipe.java | 298 ++ .../recipe/builders/InfusionRecipe.java | 297 ++ .../betterend/registry/EndAttributes.java | 26 + .../betterx/betterend/registry/EndBiomes.java | 160 + .../betterend/registry/EndBlockEntities.java | 53 + .../registry/EndBlockEntityRenders.java | 16 + .../betterx/betterend/registry/EndBlocks.java | 514 ++++ .../betterend/registry/EndEnchantments.java | 22 + .../betterend/registry/EndEntities.java | 151 + .../registry/EndEntitiesRenders.java | 67 + .../betterend/registry/EndFeatures.java | 591 ++++ .../betterx/betterend/registry/EndItems.java | 268 ++ .../betterend/registry/EndModelProviders.java | 18 + .../betterend/registry/EndParticles.java | 57 + .../betterend/registry/EndPortals.java | 162 + .../betterend/registry/EndScreens.java | 12 + .../betterx/betterend/registry/EndSounds.java | 49 + .../betterend/registry/EndStructures.java | 87 + .../betterx/betterend/registry/EndTags.java | 149 + .../betterend/rituals/EternalRitual.java | 773 +++++ .../betterend/rituals/InfusionRitual.java | 255 ++ .../betterx/betterend/tab/CreativeTabs.java | 36 + .../betterx/betterend/util/BlockFixer.java | 229 ++ .../betterend/util/BonemealPlants.java | 122 + .../betterx/betterend/util/GlobalState.java | 13 + .../org/betterx/betterend/util/LangUtil.java | 40 + .../betterx/betterend/util/LootTableUtil.java | 153 + .../betterend/util/StructureErode.java | 277 ++ .../betterend/world/biome/EndBiome.java | 182 ++ .../world/biome/air/BiomeIceStarfield.java | 34 + .../biome/cave/EmptyAuroraCaveBiome.java | 51 + .../world/biome/cave/EmptyEndCaveBiome.java | 45 + .../biome/cave/EmptySmaragdantCaveBiome.java | 52 + .../world/biome/cave/EndCaveBiome.java | 95 + .../world/biome/cave/JadeCaveBiome.java | 55 + .../world/biome/cave/LushAuroraCaveBiome.java | 80 + .../biome/cave/LushSmaragdantCaveBiome.java | 65 + .../world/biome/land/AmberLandBiome.java | 52 + .../biome/land/BlossomingSpiresBiome.java | 56 + .../world/biome/land/ChorusForestBiome.java | 59 + .../biome/land/CrystalMountainsBiome.java | 38 + .../biome/land/DragonGraveyardsBiome.java | 51 + .../world/biome/land/DryShrublandBiome.java | 45 + .../world/biome/land/DustWastelandsBiome.java | 56 + .../biome/land/FoggyMushroomlandBiome.java | 66 + .../biome/land/GlowingGrasslandsBiome.java | 56 + .../world/biome/land/LanternWoodsBiome.java | 56 + .../world/biome/land/MegalakeBiome.java | 59 + .../world/biome/land/MegalakeGroveBiome.java | 56 + .../world/biome/land/NeonOasisBiome.java | 82 + .../biome/land/PaintedMountainsBiome.java | 41 + .../world/biome/land/ShadowForestBiome.java | 60 + .../world/biome/land/SulphurSpringsBiome.java | 92 + .../world/biome/land/UmbraValleyBiome.java | 93 + .../world/biome/land/UmbrellaJungleBiome.java | 60 + .../world/features/BiomeIslandFeature.java | 73 + .../world/features/BlueVineFeature.java | 47 + .../world/features/BuildingListFeature.java | 68 + .../world/features/CavePumpkinFeature.java | 43 + .../world/features/CharniaFeature.java | 14 + .../world/features/CrashedShipFeature.java | 148 + .../world/features/DoublePlantFeature.java | 49 + .../world/features/EndLilyFeature.java | 25 + .../world/features/EndLotusFeature.java | 25 + .../world/features/EndLotusLeafFeature.java | 84 + .../world/features/FilaluxFeature.java | 47 + .../features/FullHeightScatterFeature.java | 63 + .../world/features/GlowPillarFeature.java | 34 + .../world/features/HydraluxFeature.java | 25 + .../features/InvertedScatterFeature.java | 63 + .../world/features/LanceleafFeature.java | 34 + .../world/features/MengerSpongeFeature.java | 42 + .../world/features/NeonCactusFeature.java | 30 + .../world/features/ScatterFeature.java | 92 + .../world/features/SilkMothNestFeature.java | 67 + .../SingleInvertedScatterFeature.java | 46 + .../world/features/SinglePlantFeature.java | 74 + .../world/features/SkyScatterFeature.java | 58 + .../features/UnderwaterPlantFeature.java | 40 + .../features/UnderwaterPlantScatter.java | 60 + .../betterend/world/features/VineFeature.java | 73 + .../world/features/WallPlantFeature.java | 45 + .../world/features/WallPlantOnLogFeature.java | 22 + .../world/features/WallScatterFeature.java | 71 + .../world/features/bushes/BushFeature.java | 99 + .../features/bushes/BushWithOuterFeature.java | 116 + .../bushes/LargeAmaranitaFeature.java | 55 + .../world/features/bushes/Lumecorn.java | 82 + .../features/bushes/TenaneaBushFeature.java | 137 + .../world/features/terrain/ArchFeature.java | 86 + .../terrain/BigAuroraCrystalFeature.java | 54 + .../features/terrain/DesertLakeFeature.java | 242 ++ .../features/terrain/EndLakeFeature.java | 238 ++ .../features/terrain/FallenPillarFeature.java | 67 + .../terrain/FloatingSpireFeature.java | 97 + .../world/features/terrain/GeyserFeature.java | 292 ++ .../features/terrain/IceStarFeature.java | 114 + .../terrain/ObsidianBoulderFeature.java | 76 + .../ObsidianPillarBasementFeature.java | 74 + .../features/terrain/OreLayerFeature.java | 76 + .../features/terrain/SingleBlockFeature.java | 41 + .../terrain/SmaragdantCrystalFeature.java | 63 + .../world/features/terrain/SpireFeature.java | 121 + .../features/terrain/StalactiteFeature.java | 84 + .../features/terrain/SulphurHillFeature.java | 96 + .../terrain/SulphuricCaveFeature.java | 222 ++ .../terrain/SulphuricLakeFeature.java | 211 ++ .../features/terrain/SurfaceVentFeature.java | 62 + .../features/terrain/ThinArchFeature.java | 83 + .../caves/CaveChunkPopulatorFeature.java | 149 + .../terrain/caves/EndCaveFeature.java | 270 ++ .../terrain/caves/RoundCaveFeature.java | 83 + .../terrain/caves/TunelCaveFeature.java | 250 ++ .../features/trees/DragonTreeFeature.java | 256 ++ .../trees/GiganticAmaranitaFeature.java | 379 +++ .../features/trees/HelixTreeFeature.java | 206 ++ .../features/trees/JellyshroomFeature.java | 128 + .../features/trees/LacugroveFeature.java | 223 ++ .../world/features/trees/LucerniaFeature.java | 234 ++ .../trees/MossyGlowshroomFeature.java | 173 ++ .../trees/PythadendronTreeFeature.java | 222 ++ .../world/features/trees/TenaneaFeature.java | 201 ++ .../features/trees/UmbrellaTreeFeature.java | 247 ++ .../betterend/world/generator/BiomeType.java | 5 + .../world/generator/GeneratorOptions.java | 153 + .../world/generator/IslandLayer.java | 192 ++ .../world/generator/LayerOptions.java | 55 + .../world/generator/TerrainBoolCache.java | 21 + .../world/generator/TerrainGenerator.java | 197 ++ .../features/EternalPortalStructure.java | 78 + .../features/FeatureBaseStructure.java | 93 + .../features/GiantIceStarStructure.java | 126 + .../GiantMossyGlowshroomStructure.java | 156 + .../features/MegaLakeSmallStructure.java | 51 + .../features/MegaLakeStructure.java | 54 + .../features/MountainStructure.java | 57 + .../features/PaintedMountainStructure.java | 72 + .../features/SDFStructureFeature.java | 43 + .../world/structures/piece/BasePiece.java | 29 + .../world/structures/piece/CavePiece.java | 114 + .../piece/CrystalMountainPiece.java | 184 ++ .../world/structures/piece/LakePiece.java | 283 ++ .../world/structures/piece/MountainPiece.java | 147 + .../world/structures/piece/NBTPiece.java | 112 + .../piece/PaintedMountainPiece.java | 118 + .../world/structures/piece/VoxelPiece.java | 53 + .../world/surface/SplitNoiseCondition.java | 39 + .../SulphuricSurfaceNoiseCondition.java | 47 + .../surface/UmbraSurfaceNoiseCondition.java | 52 + src/main/java/ru/betterend/BetterEnd.java | 87 - .../ru/betterend/api/BetterEndPlugin.java | 38 - .../ru/betterend/blocks/AeterniumAnvil.java | 25 - .../ru/betterend/blocks/AeterniumBlock.java | 28 - .../blocks/AmaranitaHymenophoreBlock.java | 20 - .../blocks/AncientEmeraldIceBlock.java | 93 - .../betterend/blocks/AuroraCrystalBlock.java | 130 - .../ru/betterend/blocks/BlueVineBlock.java | 23 - .../blocks/BlueVineLanternBlock.java | 51 - .../betterend/blocks/BlueVineSeedBlock.java | 81 - .../betterend/blocks/BoluxMushroomBlock.java | 53 - .../ru/betterend/blocks/BrimstoneBlock.java | 104 - .../ru/betterend/blocks/BubbleCoralBlock.java | 56 - .../ru/betterend/blocks/BulbVineBlock.java | 47 - .../blocks/BulbVineLanternBlock.java | 82 - .../blocks/BulbVineLanternColoredBlock.java | 38 - .../betterend/blocks/BulbVineSeedBlock.java | 49 - .../ru/betterend/blocks/CavePumpkinBlock.java | 68 - .../blocks/CavePumpkinVineBlock.java | 75 - .../ru/betterend/blocks/ChandelierBlock.java | 113 - .../ru/betterend/blocks/CharniaBlock.java | 16 - .../ru/betterend/blocks/ChorusGrassBlock.java | 16 - .../blocks/DenseEmeraldIceBlock.java | 38 - .../blocks/DragonTreeSaplingBlock.java | 25 - .../ru/betterend/blocks/EmeraldIceBlock.java | 96 - .../betterend/blocks/EndBlockProperties.java | 130 - .../ru/betterend/blocks/EndLilyBlock.java | 121 - .../ru/betterend/blocks/EndLilySeedBlock.java | 54 - .../betterend/blocks/EndLotusFlowerBlock.java | 59 - .../betterend/blocks/EndLotusLeafBlock.java | 80 - .../betterend/blocks/EndLotusSeedBlock.java | 140 - .../betterend/blocks/EndLotusStemBlock.java | 106 - .../java/ru/betterend/blocks/EndPedestal.java | 30 - .../ru/betterend/blocks/EndPortalBlock.java | 214 -- .../ru/betterend/blocks/EndStoneSmelter.java | 180 -- .../java/ru/betterend/blocks/EnderBlock.java | 28 - .../betterend/blocks/EndstoneDustBlock.java | 52 - .../ru/betterend/blocks/EternalPedestal.java | 139 - .../ru/betterend/blocks/FilaluxBlock.java | 10 - .../betterend/blocks/FilaluxLanternBlock.java | 15 - .../betterend/blocks/FilaluxWingsBlock.java | 49 - .../ru/betterend/blocks/FlamaeaBlock.java | 63 - .../ru/betterend/blocks/FlammalixBlock.java | 42 - .../ru/betterend/blocks/FlowerPotBlock.java | 447 --- .../blocks/GlowingHymenophoreBlock.java | 15 - .../ru/betterend/blocks/GlowingMossBlock.java | 30 - .../blocks/GlowingPillarLuminophorBlock.java | 53 - .../blocks/GlowingPillarRootsBlock.java | 35 - .../blocks/GlowingPillarSeedBlock.java | 83 - .../blocks/HelixTreeLeavesBlock.java | 82 - .../blocks/HelixTreeSaplingBlock.java | 25 - .../ru/betterend/blocks/HydraluxBlock.java | 98 - .../betterend/blocks/HydraluxPetalBlock.java | 33 - .../blocks/HydraluxPetalColoredBlock.java | 41 - .../blocks/HydraluxSaplingBlock.java | 73 - .../blocks/HydrothermalVentBlock.java | 149 - .../ru/betterend/blocks/InfusionPedestal.java | 98 - .../betterend/blocks/JellyshroomCapBlock.java | 104 - .../blocks/LacugroveSaplingBlock.java | 26 - .../ru/betterend/blocks/LanceleafBlock.java | 71 - .../betterend/blocks/LanceleafSeedBlock.java | 62 - .../betterend/blocks/LargeAmaranitaBlock.java | 79 - .../blocks/LucerniaSaplingBlock.java | 25 - .../ru/betterend/blocks/LumecornBlock.java | 107 - .../betterend/blocks/LumecornSeedBlock.java | 39 - .../betterend/blocks/MengerSpongeBlock.java | 127 - .../blocks/MengerSpongeWetBlock.java | 129 - .../ru/betterend/blocks/MissingTileBlock.java | 11 - .../blocks/MossyDragonBoneBlock.java | 70 - .../blocks/MossyGlowshroomCapBlock.java | 46 - .../blocks/MossyGlowshroomSaplingBlock.java | 26 - .../ru/betterend/blocks/MossyObsidian.java | 69 - .../ru/betterend/blocks/MurkweedBlock.java | 50 - .../ru/betterend/blocks/NeedlegrassBlock.java | 58 - .../ru/betterend/blocks/NeonCactusBlock.java | 11 - .../blocks/NeonCactusPlantBlock.java | 429 --- .../ru/betterend/blocks/PallidiumBlock.java | 66 - .../ru/betterend/blocks/PedestalVanilla.java | 33 - .../ru/betterend/blocks/PondAnemoneBlock.java | 57 - .../blocks/PythadendronSaplingBlock.java | 25 - .../betterend/blocks/RespawnObeliskBlock.java | 209 -- .../ru/betterend/blocks/RunedFlavolite.java | 52 - .../ru/betterend/blocks/ShadowBerryBlock.java | 24 - .../ru/betterend/blocks/ShadowGrassBlock.java | 48 - .../betterend/blocks/SilkMothHiveBlock.java | 126 - .../betterend/blocks/SilkMothNestBlock.java | 188 -- .../betterend/blocks/SmallAmaranitaBlock.java | 82 - .../blocks/SmallJellyshroomBlock.java | 121 - .../blocks/SmaragdantCrystalBlock.java | 18 - .../blocks/SmaragdantCrystalShardBlock.java | 106 - .../betterend/blocks/SulphurCrystalBlock.java | 123 - .../betterend/blocks/TenaneaFlowersBlock.java | 84 - .../betterend/blocks/TenaneaSaplingBlock.java | 25 - .../betterend/blocks/TerrainPlantBlock.java | 24 - .../blocks/TwistedUmbrellaMossBlock.java | 51 - .../blocks/TwistedUmbrellaMossTallBlock.java | 35 - .../betterend/blocks/UmbrellaMossBlock.java | 50 - .../blocks/UmbrellaMossTallBlock.java | 35 - .../blocks/UmbrellaTreeClusterBlock.java | 72 - .../blocks/UmbrellaTreeClusterEmptyBlock.java | 47 - .../blocks/UmbrellaTreeMembraneBlock.java | 89 - .../blocks/UmbrellaTreeSaplingBlock.java | 31 - .../blocks/VentBubbleColumnBlock.java | 169 -- .../betterend/blocks/basis/EndAnvilBlock.java | 22 - .../blocks/basis/EndLanternBlock.java | 137 - .../betterend/blocks/basis/EndPlantBlock.java | 55 - .../blocks/basis/EndPlantWithAgeBlock.java | 26 - .../blocks/basis/EndTerrainBlock.java | 26 - .../blocks/basis/EndTripleTerrain.java | 12 - .../blocks/basis/EndUnderwaterPlantBlock.java | 26 - .../basis/EndUnderwaterWallPlantBlock.java | 24 - .../blocks/basis/EndWallMushroom.java | 17 - .../blocks/basis/EndWallPlantBlock.java | 23 - .../ru/betterend/blocks/basis/FurBlock.java | 94 - .../betterend/blocks/basis/LitBaseBlock.java | 24 - .../blocks/basis/LitPillarBlock.java | 23 - .../betterend/blocks/basis/PedestalBlock.java | 460 --- .../blocks/basis/PottableCropBlock.java | 30 - .../blocks/basis/PottableFeatureSapling.java | 18 - .../blocks/basis/PottableLeavesBlock.java | 25 - .../blocks/basis/StoneLanternBlock.java | 59 - .../entities/BlockEntityHydrothermalVent.java | 81 - .../entities/EndStoneSmelterBlockEntity.java | 480 --- .../entities/EternalPedestalEntity.java | 53 - .../entities/InfusionPedestalEntity.java | 68 - .../blocks/entities/PedestalBlockEntity.java | 124 - .../ru/betterend/client/BetterEndClient.java | 83 - .../ru/betterend/client/ClientOptions.java | 50 - .../gui/EndStoneSmelterRecipeBookScreen.java | 108 - .../client/gui/EndStoneSmelterScreen.java | 151 - .../gui/EndStoneSmelterScreenHandler.java | 207 -- .../client/gui/slot/SmelterFuelSlot.java | 25 - .../client/gui/slot/SmelterOutputSlot.java | 48 - .../ru/betterend/client/models/Patterns.java | 152 - .../client/render/ArmoredElytraLayer.java | 60 - .../betterend/client/render/BeamRenderer.java | 182 -- .../client/render/BetterEndSkyRenderer.java | 385 --- .../client/render/EndCrystalRenderer.java | 78 - .../client/render/EternalCrystalRenderer.java | 130 - .../client/render/PedestalItemRenderer.java | 75 - .../complexmaterials/ColoredMaterial.java | 72 - .../CrystalSubblocksMaterial.java | 133 - .../EndWoodenComplexMaterial.java | 45 - .../complexmaterials/MetalMaterial.java | 497 --- .../complexmaterials/StoneMaterial.java | 197 -- .../java/ru/betterend/config/Configs.java | 36 - .../java/ru/betterend/effects/EndPotions.java | 31 - .../betterend/effects/EndStatusEffects.java | 20 - .../enchantment/EndVeilEnchantment.java | 17 - .../effects/status/EndVeilEffect.java | 16 - .../ru/betterend/entity/CubozoaEntity.java | 155 - .../ru/betterend/entity/DragonflyEntity.java | 218 -- .../ru/betterend/entity/EndFishEntity.java | 170 -- .../ru/betterend/entity/EndSlimeEntity.java | 433 --- .../betterend/entity/ShadowWalkerEntity.java | 153 - .../ru/betterend/entity/SilkMothEntity.java | 323 -- .../entity/model/CubozoaEntityModel.java | 89 - .../entity/model/DragonflyEntityModel.java | 131 - .../entity/model/EndFishEntityModel.java | 93 - .../entity/model/EndSlimeEntityModel.java | 148 - .../entity/model/SilkMothEntityModel.java | 170 -- .../entity/render/RendererEntityCubozoa.java | 64 - .../render/RendererEntityDragonfly.java | 31 - .../entity/render/RendererEntityEndFish.java | 63 - .../entity/render/RendererEntityEndSlime.java | 137 - .../render/RendererEntityShadowWalker.java | 23 - .../entity/render/SilkMothEntityRenderer.java | 22 - .../betterend/events/ItemTooltipCallback.java | 35 - .../events/PlayerAdvancementsCallback.java | 20 - .../integration/EndBiomeIntegration.java | 5 - .../integration/EnderscapeIntegration.java | 50 - .../FlamboyantRefabricatedIntegration.java | 51 - .../betterend/integration/Integrations.java | 54 - .../integration/NourishIntegration.java | 52 - .../betterend/integration/byg/BYGBlocks.java | 16 - .../integration/byg/BYGIntegration.java | 26 - .../integration/byg/biomes/BYGBiomes.java | 23 - .../byg/biomes/NightshadeRedwoods.java | 86 - .../byg/biomes/OldBulbisGardens.java | 119 - .../integration/byg/features/BYGFeatures.java | 65 - .../byg/features/BigEtherTreeFeature.java | 78 - .../NightshadeRedwoodTreeFeature.java | 199 -- .../byg/features/OldBulbisTreeFeature.java | 200 -- .../integration/rei/REIContainer.java | 9 - .../betterend/interfaces/BETargetChecker.java | 6 - .../betterend/interfaces/FallFlyingItem.java | 9 - .../java/ru/betterend/interfaces/ISlime.java | 9 - .../betterend/interfaces/MultiModelItem.java | 18 - .../betterend/interfaces/PottablePlant.java | 18 - .../betterend/interfaces/PottableTerrain.java | 7 - .../interfaces/TeleportingEntity.java | 11 - .../java/ru/betterend/item/ArmoredElytra.java | 96 - .../ru/betterend/item/CrystaliteArmor.java | 47 - .../ru/betterend/item/CrystaliteBoots.java | 42 - .../betterend/item/CrystaliteChestplate.java | 39 - .../ru/betterend/item/CrystaliteElytra.java | 83 - .../ru/betterend/item/CrystaliteHelmet.java | 21 - .../ru/betterend/item/CrystaliteLeggings.java | 21 - .../java/ru/betterend/item/EnchantedItem.java | 35 - .../java/ru/betterend/item/EndArmorItem.java | 61 - .../java/ru/betterend/item/EndAttribute.java | 10 - .../java/ru/betterend/item/EndBucketItem.java | 14 - .../ru/betterend/item/EternalCrystalItem.java | 11 - .../java/ru/betterend/item/GuideBookItem.java | 47 - .../item/material/EndArmorMaterial.java | 88 - .../item/material/EndToolMaterial.java | 68 - .../item/model/ArmoredElytraModel.java | 96 - .../item/model/CrystaliteArmorProvider.java | 81 - .../item/model/CrystaliteBootsModel.java | 84 - .../item/model/CrystaliteChestplateModel.java | 145 - .../item/model/CrystaliteHelmetModel.java | 73 - .../item/model/CrystaliteLeggingsModel.java | 85 - .../ru/betterend/item/tool/EndHammerItem.java | 156 - .../ru/betterend/item/tool/EndPickaxe.java | 21 - .../mixin/client/BiomeColorsMixin.java | 60 - .../mixin/client/CapeLayerMixin.java | 25 - .../mixin/client/EndEffectsMixin.java | 26 - .../client/HumanoidMobRendererMixin.java | 25 - .../mixin/client/ItemStackMixin.java | 22 - .../mixin/client/LocalPlayerMixin.java | 46 - .../mixin/client/MinecraftClientMixin.java | 57 - .../mixin/client/ModelLoaderMixin.java | 28 - .../mixin/client/MusicTrackerMixin.java | 106 - .../mixin/common/BlockBehaviourMixin.java | 46 - .../mixin/common/ChorusFlowerBlockMixin.java | 90 - .../mixin/common/ChorusPlantBlockMixin.java | 62 - .../mixin/common/ChorusPlantFeatureMixin.java | 43 - .../mixin/common/EnchantmentMenuMixin.java | 145 - .../mixin/common/EndCityFeatureMixin.java | 43 - .../mixin/common/EndDragonFightMixin.java | 98 - .../mixin/common/EndPodiumFeatureMixin.java | 91 - .../betterend/mixin/common/EndSpikeMixin.java | 43 - .../betterend/mixin/common/EnderManMixin.java | 25 - .../betterend/mixin/common/EntityMixin.java | 109 - .../mixin/common/LivingEntityMixin.java | 290 -- .../betterend/mixin/common/MonsterMixin.java | 32 - .../mixin/common/NoiseChunkAccessor.java | 24 - .../mixin/common/NoiseChunkMixin.java | 76 - .../common/NoiseGeneratorSettingsMixin.java | 20 - .../mixin/common/PlayerAdvancementsMixin.java | 27 - .../betterend/mixin/common/PlayerMixin.java | 79 - .../mixin/common/ServerLevelMixin.java | 123 - .../mixin/common/ServerPlayerMixin.java | 186 -- .../ru/betterend/mixin/common/SlimeMixin.java | 30 - .../mixin/common/SpikeFeatureMixin.java | 178 -- .../ru/betterend/noise/OpenSimplexNoise.java | 2671 ----------------- .../betterend/particle/FireflyParticle.java | 81 - .../betterend/particle/InfusionParticle.java | 63 - .../particle/InfusionParticleType.java | 78 - .../particle/ParticleBlackSpore.java | 92 - .../ru/betterend/particle/ParticleGeyser.java | 79 - .../particle/ParticleGlowingSphere.java | 76 - .../particle/ParticleJungleSpore.java | 70 - .../betterend/particle/ParticleSnowflake.java | 96 - .../betterend/particle/ParticleSulphur.java | 97 - .../particle/ParticleTenaneaPetal.java | 111 - .../particle/PaticlePortalSphere.java | 76 - .../particle/SmaragdantParticle.java | 92 - .../ru/betterend/recipe/AlloyingRecipes.java | 52 - .../ru/betterend/recipe/AnvilRecipes.java | 84 - .../ru/betterend/recipe/CraftingRecipes.java | 483 --- .../ru/betterend/recipe/FurnaceRecipes.java | 44 - .../ru/betterend/recipe/InfusionRecipes.java | 614 ---- .../ru/betterend/recipe/SmithingRecipes.java | 109 - .../recipe/builders/AlloyingRecipe.java | 290 -- .../recipe/builders/InfusionRecipe.java | 280 -- .../ru/betterend/registry/EndAttributes.java | 25 - .../java/ru/betterend/registry/EndBiomes.java | 183 -- .../betterend/registry/EndBlockEntities.java | 54 - .../registry/EndBlockEntityRenders.java | 15 - .../java/ru/betterend/registry/EndBlocks.java | 553 ---- .../betterend/registry/EndEnchantments.java | 20 - .../ru/betterend/registry/EndEntities.java | 140 - .../registry/EndEntitiesRenders.java | 75 - .../ru/betterend/registry/EndFeatures.java | 400 --- .../java/ru/betterend/registry/EndItems.java | 200 -- .../betterend/registry/EndModelProviders.java | 17 - .../ru/betterend/registry/EndParticles.java | 66 - .../ru/betterend/registry/EndPortals.java | 161 - .../ru/betterend/registry/EndScreens.java | 11 - .../java/ru/betterend/registry/EndSounds.java | 48 - .../ru/betterend/registry/EndStructures.java | 95 - .../java/ru/betterend/registry/EndTags.java | 152 - .../ru/betterend/rituals/EternalRitual.java | 779 ----- .../ru/betterend/rituals/InfusionRitual.java | 260 -- .../java/ru/betterend/tab/CreativeTabs.java | 34 - .../java/ru/betterend/util/BlockFixer.java | 233 -- .../ru/betterend/util/BonemealPlants.java | 121 - .../java/ru/betterend/util/GlobalState.java | 10 - src/main/java/ru/betterend/util/LangUtil.java | 40 - .../java/ru/betterend/util/LootTableUtil.java | 155 - .../ru/betterend/util/StructureErode.java | 278 -- .../ru/betterend/world/biome/EndBiome.java | 175 -- .../world/biome/air/BiomeIceStarfield.java | 33 - .../biome/cave/EmptyAuroraCaveBiome.java | 50 - .../world/biome/cave/EmptyEndCaveBiome.java | 44 - .../biome/cave/EmptySmaragdantCaveBiome.java | 51 - .../world/biome/cave/EndCaveBiome.java | 96 - .../world/biome/cave/JadeCaveBiome.java | 53 - .../world/biome/cave/LushAuroraCaveBiome.java | 79 - .../biome/cave/LushSmaragdantCaveBiome.java | 64 - .../world/biome/land/AmberLandBiome.java | 55 - .../biome/land/BlossomingSpiresBiome.java | 55 - .../world/biome/land/ChorusForestBiome.java | 58 - .../biome/land/CrystalMountainsBiome.java | 37 - .../biome/land/DragonGraveyardsBiome.java | 50 - .../world/biome/land/DryShrublandBiome.java | 44 - .../world/biome/land/DustWastelandsBiome.java | 55 - .../biome/land/FoggyMushroomlandBiome.java | 70 - .../biome/land/GlowingGrasslandsBiome.java | 55 - .../world/biome/land/LanternWoodsBiome.java | 55 - .../world/biome/land/MegalakeBiome.java | 62 - .../world/biome/land/MegalakeGroveBiome.java | 60 - .../world/biome/land/NeonOasisBiome.java | 81 - .../biome/land/PaintedMountainsBiome.java | 40 - .../world/biome/land/ShadowForestBiome.java | 59 - .../world/biome/land/SulphurSpringsBiome.java | 93 - .../world/biome/land/UmbraValleyBiome.java | 92 - .../world/biome/land/UmbrellaJungleBiome.java | 59 - .../world/features/BiomeIslandFeature.java | 73 - .../world/features/BlueVineFeature.java | 45 - .../world/features/BuildingListFeature.java | 63 - .../world/features/CavePumpkinFeature.java | 43 - .../world/features/CharniaFeature.java | 14 - .../world/features/CrashedShipFeature.java | 149 - .../world/features/DoublePlantFeature.java | 47 - .../world/features/EndLilyFeature.java | 26 - .../world/features/EndLotusFeature.java | 26 - .../world/features/EndLotusLeafFeature.java | 81 - .../world/features/FilaluxFeature.java | 48 - .../features/FullHeightScatterFeature.java | 60 - .../world/features/GlowPillarFeature.java | 31 - .../world/features/HydraluxFeature.java | 26 - .../features/InvertedScatterFeature.java | 60 - .../world/features/LanceleafFeature.java | 31 - .../world/features/MengerSpongeFeature.java | 42 - .../world/features/NeonCactusFeature.java | 31 - .../world/features/ScatterFeature.java | 93 - .../world/features/SilkMothNestFeature.java | 67 - .../SingleInvertedScatterFeature.java | 43 - .../world/features/SinglePlantFeature.java | 74 - .../world/features/SkyScatterFeature.java | 55 - .../features/UnderwaterPlantFeature.java | 38 - .../features/UnderwaterPlantScatter.java | 57 - .../betterend/world/features/VineFeature.java | 71 - .../world/features/WallPlantFeature.java | 48 - .../world/features/WallPlantOnLogFeature.java | 24 - .../world/features/WallScatterFeature.java | 72 - .../world/features/bushes/BushFeature.java | 101 - .../features/bushes/BushWithOuterFeature.java | 118 - .../bushes/LargeAmaranitaFeature.java | 56 - .../world/features/bushes/Lumecorn.java | 84 - .../features/bushes/TenaneaBushFeature.java | 139 - .../world/features/terrain/ArchFeature.java | 86 - .../terrain/BigAuroraCrystalFeature.java | 54 - .../features/terrain/DesertLakeFeature.java | 242 -- .../features/terrain/EndLakeFeature.java | 238 -- .../features/terrain/FallenPillarFeature.java | 67 - .../terrain/FloatingSpireFeature.java | 90 - .../world/features/terrain/GeyserFeature.java | 294 -- .../features/terrain/IceStarFeature.java | 117 - .../terrain/ObsidianBoulderFeature.java | 76 - .../ObsidianPillarBasementFeature.java | 74 - .../features/terrain/OreLayerFeature.java | 77 - .../features/terrain/SingleBlockFeature.java | 42 - .../terrain/SmaragdantCrystalFeature.java | 63 - .../world/features/terrain/SpireFeature.java | 115 - .../features/terrain/StalactiteFeature.java | 85 - .../features/terrain/SulphurHillFeature.java | 98 - .../terrain/SulphuricCaveFeature.java | 222 -- .../terrain/SulphuricLakeFeature.java | 212 -- .../features/terrain/SurfaceVentFeature.java | 62 - .../features/terrain/ThinArchFeature.java | 78 - .../caves/CaveChunkPopulatorFeature.java | 137 - .../terrain/caves/EndCaveFeature.java | 262 -- .../terrain/caves/RoundCaveFeature.java | 83 - .../terrain/caves/TunelCaveFeature.java | 238 -- .../features/trees/DragonTreeFeature.java | 252 -- .../trees/GiganticAmaranitaFeature.java | 380 --- .../features/trees/HelixTreeFeature.java | 198 -- .../features/trees/JellyshroomFeature.java | 133 - .../features/trees/LacugroveFeature.java | 219 -- .../world/features/trees/LucerniaFeature.java | 230 -- .../trees/MossyGlowshroomFeature.java | 184 -- .../trees/PythadendronTreeFeature.java | 214 -- .../world/features/trees/TenaneaFeature.java | 202 -- .../features/trees/UmbrellaTreeFeature.java | 246 -- .../betterend/world/generator/BiomeType.java | 5 - .../world/generator/GeneratorOptions.java | 152 - .../world/generator/IslandLayer.java | 192 -- .../world/generator/LayerOptions.java | 48 - .../world/generator/TerrainBoolCache.java | 21 - .../world/generator/TerrainGenerator.java | 200 -- .../features/EternalPortalStructure.java | 84 - .../features/FeatureBaseStructure.java | 79 - .../features/GiantIceStarStructure.java | 131 - .../GiantMossyGlowshroomStructure.java | 169 -- .../features/MegaLakeSmallStructure.java | 55 - .../features/MegaLakeStructure.java | 58 - .../features/MountainStructure.java | 61 - .../features/PaintedMountainStructure.java | 71 - .../features/SDFStructureFeature.java | 44 - .../world/structures/piece/BasePiece.java | 27 - .../world/structures/piece/CavePiece.java | 110 - .../piece/CrystalMountainPiece.java | 178 -- .../world/structures/piece/LakePiece.java | 269 -- .../world/structures/piece/MountainPiece.java | 142 - .../world/structures/piece/NBTPiece.java | 100 - .../piece/PaintedMountainPiece.java | 108 - .../world/structures/piece/VoxelPiece.java | 47 - .../world/surface/SplitNoiseCondition.java | 36 - .../SulphuricSurfaceNoiseCondition.java | 39 - .../surface/UmbraSurfaceNoiseCondition.java | 44 - .../resources/betterend.mixins.client.json | 2 +- .../resources/betterend.mixins.common.json | 2 +- src/main/resources/fabric.mod.json | 6 +- 854 files changed, 42775 insertions(+), 41811 deletions(-) create mode 100644 src/main/java/org/betterx/betterend/BetterEnd.java create mode 100644 src/main/java/org/betterx/betterend/api/BetterEndPlugin.java create mode 100644 src/main/java/org/betterx/betterend/blocks/AeterniumAnvil.java create mode 100644 src/main/java/org/betterx/betterend/blocks/AeterniumBlock.java rename src/main/java/{ru => org/betterx}/betterend/blocks/AmaranitaCapBlock.java (50%) create mode 100644 src/main/java/org/betterx/betterend/blocks/AmaranitaHymenophoreBlock.java rename src/main/java/{ru => org/betterx}/betterend/blocks/AmaranitaStemBlock.java (50%) rename src/main/java/{ru => org/betterx}/betterend/blocks/AmberBlock.java (51%) create mode 100644 src/main/java/org/betterx/betterend/blocks/AncientEmeraldIceBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/AuroraCrystalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BlueVineBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BlueVineLanternBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BlueVineSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BoluxMushroomBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BrimstoneBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BubbleCoralBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BulbVineBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BulbVineLanternBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BulbVineLanternColoredBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/BulbVineSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/CavePumpkinBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/CavePumpkinVineBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/ChandelierBlock.java rename src/main/java/{ru => org/betterx}/betterend/blocks/CharcoalBlock.java (50%) create mode 100644 src/main/java/org/betterx/betterend/blocks/CharniaBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/ChorusGrassBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/DenseEmeraldIceBlock.java rename src/main/java/{ru => org/betterx}/betterend/blocks/DenseSnowBlock.java (52%) create mode 100644 src/main/java/org/betterx/betterend/blocks/DragonTreeSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EmeraldIceBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndBlockProperties.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLilyBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLilySeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLotusFlowerBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLotusLeafBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLotusSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndLotusStemBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndPedestal.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndPortalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndStoneSmelter.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EnderBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EndstoneDustBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/EternalPedestal.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FilaluxBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FilaluxLanternBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FilaluxWingsBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FlamaeaBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FlammalixBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/FlowerPotBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/GlowingHymenophoreBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/GlowingMossBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/GlowingPillarLuminophorBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/GlowingPillarRootsBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/GlowingPillarSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HelixTreeLeavesBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HelixTreeSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HydraluxBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HydraluxPetalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HydraluxPetalColoredBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HydraluxSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/HydrothermalVentBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/InfusionPedestal.java create mode 100644 src/main/java/org/betterx/betterend/blocks/JellyshroomCapBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LacugroveSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LanceleafBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LanceleafSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LargeAmaranitaBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LucerniaSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LumecornBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/LumecornSeedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MengerSpongeBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MengerSpongeWetBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MissingTileBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MossyDragonBoneBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MossyGlowshroomCapBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MossyGlowshroomSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MossyObsidian.java create mode 100644 src/main/java/org/betterx/betterend/blocks/MurkweedBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/NeedlegrassBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/NeonCactusBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/NeonCactusPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/PallidiumBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/PedestalVanilla.java create mode 100644 src/main/java/org/betterx/betterend/blocks/PondAnemoneBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/PythadendronSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/RespawnObeliskBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/RunedFlavolite.java create mode 100644 src/main/java/org/betterx/betterend/blocks/ShadowBerryBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/ShadowGrassBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SilkMothHiveBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SilkMothNestBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SmallAmaranitaBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SmallJellyshroomBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalShardBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/SulphurCrystalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/TenaneaFlowersBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/TenaneaSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/TerrainPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossTallBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaMossBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaMossTallBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaTreeMembraneBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/UmbrellaTreeSaplingBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/VentBubbleColumnBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndAnvilBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndLanternBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndPlantWithAgeBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndTerrainBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndTripleTerrain.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndWallMushroom.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/EndWallPlantBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/FurBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/LitBaseBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/LitPillarBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/PedestalBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/PottableCropBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/PottableFeatureSapling.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/PottableLeavesBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/basis/StoneLanternBlock.java create mode 100644 src/main/java/org/betterx/betterend/blocks/entities/BlockEntityHydrothermalVent.java create mode 100644 src/main/java/org/betterx/betterend/blocks/entities/EndStoneSmelterBlockEntity.java create mode 100644 src/main/java/org/betterx/betterend/blocks/entities/EternalPedestalEntity.java create mode 100644 src/main/java/org/betterx/betterend/blocks/entities/InfusionPedestalEntity.java create mode 100644 src/main/java/org/betterx/betterend/blocks/entities/PedestalBlockEntity.java create mode 100644 src/main/java/org/betterx/betterend/client/BetterEndClient.java create mode 100644 src/main/java/org/betterx/betterend/client/ClientOptions.java create mode 100644 src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java create mode 100644 src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreen.java create mode 100644 src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreenHandler.java create mode 100644 src/main/java/org/betterx/betterend/client/gui/slot/SmelterFuelSlot.java create mode 100644 src/main/java/org/betterx/betterend/client/gui/slot/SmelterOutputSlot.java create mode 100644 src/main/java/org/betterx/betterend/client/models/Patterns.java create mode 100644 src/main/java/org/betterx/betterend/client/render/ArmoredElytraLayer.java create mode 100644 src/main/java/org/betterx/betterend/client/render/BeamRenderer.java create mode 100644 src/main/java/org/betterx/betterend/client/render/BetterEndSkyRenderer.java create mode 100644 src/main/java/org/betterx/betterend/client/render/EndCrystalRenderer.java create mode 100644 src/main/java/org/betterx/betterend/client/render/EternalCrystalRenderer.java create mode 100644 src/main/java/org/betterx/betterend/client/render/PedestalItemRenderer.java create mode 100644 src/main/java/org/betterx/betterend/complexmaterials/ColoredMaterial.java create mode 100644 src/main/java/org/betterx/betterend/complexmaterials/CrystalSubblocksMaterial.java create mode 100644 src/main/java/org/betterx/betterend/complexmaterials/EndWoodenComplexMaterial.java create mode 100644 src/main/java/org/betterx/betterend/complexmaterials/MetalMaterial.java create mode 100644 src/main/java/org/betterx/betterend/complexmaterials/StoneMaterial.java create mode 100644 src/main/java/org/betterx/betterend/config/Configs.java create mode 100644 src/main/java/org/betterx/betterend/effects/EndPotions.java create mode 100644 src/main/java/org/betterx/betterend/effects/EndStatusEffects.java create mode 100644 src/main/java/org/betterx/betterend/effects/enchantment/EndVeilEnchantment.java create mode 100644 src/main/java/org/betterx/betterend/effects/status/EndVeilEffect.java create mode 100644 src/main/java/org/betterx/betterend/entity/CubozoaEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/DragonflyEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/EndFishEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/ShadowWalkerEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/SilkMothEntity.java create mode 100644 src/main/java/org/betterx/betterend/entity/model/CubozoaEntityModel.java create mode 100644 src/main/java/org/betterx/betterend/entity/model/DragonflyEntityModel.java create mode 100644 src/main/java/org/betterx/betterend/entity/model/EndFishEntityModel.java create mode 100644 src/main/java/org/betterx/betterend/entity/model/EndSlimeEntityModel.java create mode 100644 src/main/java/org/betterx/betterend/entity/model/SilkMothEntityModel.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/RendererEntityCubozoa.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/RendererEntityDragonfly.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/RendererEntityEndFish.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/RendererEntityEndSlime.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/RendererEntityShadowWalker.java create mode 100644 src/main/java/org/betterx/betterend/entity/render/SilkMothEntityRenderer.java create mode 100644 src/main/java/org/betterx/betterend/events/ItemTooltipCallback.java create mode 100644 src/main/java/org/betterx/betterend/events/PlayerAdvancementsCallback.java create mode 100644 src/main/java/org/betterx/betterend/integration/EndBiomeIntegration.java create mode 100644 src/main/java/org/betterx/betterend/integration/EnderscapeIntegration.java create mode 100644 src/main/java/org/betterx/betterend/integration/FlamboyantRefabricatedIntegration.java create mode 100644 src/main/java/org/betterx/betterend/integration/Integrations.java create mode 100644 src/main/java/org/betterx/betterend/integration/NourishIntegration.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/BYGBlocks.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/BYGIntegration.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/biomes/BYGBiomes.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/biomes/NightshadeRedwoods.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/biomes/OldBulbisGardens.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/features/BYGFeatures.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/features/BigEtherTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/integration/byg/features/OldBulbisTreeFeature.java rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAlloyingCategory.java (96%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAlloyingDisplay.java (98%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAlloyingFuelCategory.java (96%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAlloyingFuelDisplay.java (95%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAnvilCategory.java (96%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIAnvilDisplay.java (94%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIBlastingDisplay.java (84%) create mode 100644 src/main/java/org/betterx/betterend/integration/rei/REIContainer.java rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIInfusionCategory.java (95%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIInfusionDisplay.java (97%) rename src/main/java/{ru => org/betterx}/betterend/integration/rei/REIPlugin.java (94%) create mode 100644 src/main/java/org/betterx/betterend/interfaces/BETargetChecker.java create mode 100644 src/main/java/org/betterx/betterend/interfaces/FallFlyingItem.java create mode 100644 src/main/java/org/betterx/betterend/interfaces/ISlime.java rename src/main/java/{ru => org/betterx}/betterend/interfaces/MobEffectApplier.java (51%) create mode 100644 src/main/java/org/betterx/betterend/interfaces/MultiModelItem.java create mode 100644 src/main/java/org/betterx/betterend/interfaces/PottablePlant.java create mode 100644 src/main/java/org/betterx/betterend/interfaces/PottableTerrain.java create mode 100644 src/main/java/org/betterx/betterend/interfaces/TeleportingEntity.java create mode 100644 src/main/java/org/betterx/betterend/item/ArmoredElytra.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteArmor.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteBoots.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteChestplate.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteElytra.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteHelmet.java create mode 100644 src/main/java/org/betterx/betterend/item/CrystaliteLeggings.java create mode 100644 src/main/java/org/betterx/betterend/item/EnchantedItem.java create mode 100644 src/main/java/org/betterx/betterend/item/EndArmorItem.java create mode 100644 src/main/java/org/betterx/betterend/item/EndAttribute.java create mode 100644 src/main/java/org/betterx/betterend/item/EndBucketItem.java create mode 100644 src/main/java/org/betterx/betterend/item/EternalCrystalItem.java create mode 100644 src/main/java/org/betterx/betterend/item/GuideBookItem.java create mode 100644 src/main/java/org/betterx/betterend/item/material/EndArmorMaterial.java create mode 100644 src/main/java/org/betterx/betterend/item/material/EndToolMaterial.java create mode 100644 src/main/java/org/betterx/betterend/item/model/ArmoredElytraModel.java create mode 100644 src/main/java/org/betterx/betterend/item/model/CrystaliteArmorProvider.java create mode 100644 src/main/java/org/betterx/betterend/item/model/CrystaliteBootsModel.java create mode 100644 src/main/java/org/betterx/betterend/item/model/CrystaliteChestplateModel.java create mode 100644 src/main/java/org/betterx/betterend/item/model/CrystaliteHelmetModel.java create mode 100644 src/main/java/org/betterx/betterend/item/model/CrystaliteLeggingsModel.java create mode 100644 src/main/java/org/betterx/betterend/item/tool/EndHammerItem.java create mode 100644 src/main/java/org/betterx/betterend/item/tool/EndPickaxe.java rename src/main/java/{ru => org/betterx}/betterend/mixin/client/AbstractSoundInstanceAccessor.java (70%) rename src/main/java/{ru => org/betterx}/betterend/mixin/client/ArmorStandRendererMixin.java (57%) create mode 100644 src/main/java/org/betterx/betterend/mixin/client/BiomeColorsMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/CapeLayerMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/EndEffectsMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/HumanoidMobRendererMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/ItemStackMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/LocalPlayerMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/MinecraftClientMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/ModelLoaderMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/client/MusicTrackerMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/client/PlayerRendererMixin.java (53%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/BlockBehaviourMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/ChorusFlowerBlockMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/ChorusPlantBlockMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/ChorusPlantFeatureMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/CraftingMenuMixin.java (55%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EnchantmentMenuMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EndCityFeatureMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EndDragonFightMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EndPodiumFeatureMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EndSpikeMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EnderManMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/EntityMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/LevelMixin.java (88%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/LivingEntityMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/MappedRegistryMixin.java (54%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/MonsterMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java (74%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/NoiseChunkAccessor.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/NoiseChunkMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/NoiseGeneratorSettingsMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/NoiseInterpolatorAccessor.java (60%) create mode 100644 src/main/java/org/betterx/betterend/mixin/common/PlayerAdvancementsMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/PlayerMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/ServerLevelMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/ServerPlayerMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/SlimeMixin.java create mode 100644 src/main/java/org/betterx/betterend/mixin/common/SpikeFeatureMixin.java rename src/main/java/{ru => org/betterx}/betterend/mixin/common/WorldGenRegionMixin.java (50%) create mode 100644 src/main/java/org/betterx/betterend/noise/OpenSimplexNoise.java create mode 100644 src/main/java/org/betterx/betterend/particle/FireflyParticle.java create mode 100644 src/main/java/org/betterx/betterend/particle/InfusionParticle.java create mode 100644 src/main/java/org/betterx/betterend/particle/InfusionParticleType.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleBlackSpore.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleGeyser.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleGlowingSphere.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleJungleSpore.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleSnowflake.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleSulphur.java create mode 100644 src/main/java/org/betterx/betterend/particle/ParticleTenaneaPetal.java create mode 100644 src/main/java/org/betterx/betterend/particle/PaticlePortalSphere.java create mode 100644 src/main/java/org/betterx/betterend/particle/SmaragdantParticle.java create mode 100644 src/main/java/org/betterx/betterend/recipe/AlloyingRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/AnvilRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/CraftingRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/FurnaceRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/InfusionRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/SmithingRecipes.java create mode 100644 src/main/java/org/betterx/betterend/recipe/builders/AlloyingRecipe.java create mode 100644 src/main/java/org/betterx/betterend/recipe/builders/InfusionRecipe.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndAttributes.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndBiomes.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndBlockEntities.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndBlockEntityRenders.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndBlocks.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndEnchantments.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndEntities.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndEntitiesRenders.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndFeatures.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndItems.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndModelProviders.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndParticles.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndPortals.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndScreens.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndSounds.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndStructures.java create mode 100644 src/main/java/org/betterx/betterend/registry/EndTags.java create mode 100644 src/main/java/org/betterx/betterend/rituals/EternalRitual.java create mode 100644 src/main/java/org/betterx/betterend/rituals/InfusionRitual.java create mode 100644 src/main/java/org/betterx/betterend/tab/CreativeTabs.java create mode 100644 src/main/java/org/betterx/betterend/util/BlockFixer.java create mode 100644 src/main/java/org/betterx/betterend/util/BonemealPlants.java create mode 100644 src/main/java/org/betterx/betterend/util/GlobalState.java create mode 100644 src/main/java/org/betterx/betterend/util/LangUtil.java create mode 100644 src/main/java/org/betterx/betterend/util/LootTableUtil.java create mode 100644 src/main/java/org/betterx/betterend/util/StructureErode.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/EndBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/air/BiomeIceStarfield.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/EmptyAuroraCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/EmptyEndCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/EndCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/JadeCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/LushAuroraCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/cave/LushSmaragdantCaveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/AmberLandBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/BlossomingSpiresBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/ChorusForestBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/CrystalMountainsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/DragonGraveyardsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/DryShrublandBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/DustWastelandsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/FoggyMushroomlandBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/GlowingGrasslandsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/LanternWoodsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/MegalakeBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/MegalakeGroveBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/NeonOasisBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/PaintedMountainsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/ShadowForestBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/SulphurSpringsBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/UmbraValleyBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/biome/land/UmbrellaJungleBiome.java create mode 100644 src/main/java/org/betterx/betterend/world/features/BiomeIslandFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/BlueVineFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/BuildingListFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/CavePumpkinFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/CharniaFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/CrashedShipFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/DoublePlantFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/EndLilyFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/EndLotusFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/EndLotusLeafFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/FilaluxFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/FullHeightScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/GlowPillarFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/HydraluxFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/InvertedScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/LanceleafFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/MengerSpongeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/NeonCactusFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/ScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/SilkMothNestFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/SingleInvertedScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/SinglePlantFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/SkyScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/UnderwaterPlantFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/UnderwaterPlantScatter.java create mode 100644 src/main/java/org/betterx/betterend/world/features/VineFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/WallPlantFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/WallPlantOnLogFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/WallScatterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/bushes/BushFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/bushes/BushWithOuterFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/bushes/LargeAmaranitaFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/bushes/Lumecorn.java create mode 100644 src/main/java/org/betterx/betterend/world/features/bushes/TenaneaBushFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/ArchFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/BigAuroraCrystalFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/DesertLakeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/EndLakeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/FallenPillarFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/FloatingSpireFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/GeyserFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/IceStarFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/ObsidianBoulderFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/ObsidianPillarBasementFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/OreLayerFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SingleBlockFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SmaragdantCrystalFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SpireFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/StalactiteFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SulphurHillFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SulphuricCaveFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SulphuricLakeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/SurfaceVentFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/ThinArchFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/caves/EndCaveFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/caves/RoundCaveFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/terrain/caves/TunelCaveFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/DragonTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/GiganticAmaranitaFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/HelixTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/JellyshroomFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/LacugroveFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/LucerniaFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/MossyGlowshroomFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/PythadendronTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/TenaneaFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/features/trees/UmbrellaTreeFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/BiomeType.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/GeneratorOptions.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/IslandLayer.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/LayerOptions.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/TerrainBoolCache.java create mode 100644 src/main/java/org/betterx/betterend/world/generator/TerrainGenerator.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/EternalPortalStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/FeatureBaseStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/GiantIceStarStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/GiantMossyGlowshroomStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/MegaLakeSmallStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/MegaLakeStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/MountainStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/PaintedMountainStructure.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/features/SDFStructureFeature.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/BasePiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/CavePiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/CrystalMountainPiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/LakePiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/MountainPiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/NBTPiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/PaintedMountainPiece.java create mode 100644 src/main/java/org/betterx/betterend/world/structures/piece/VoxelPiece.java create mode 100644 src/main/java/org/betterx/betterend/world/surface/SplitNoiseCondition.java create mode 100644 src/main/java/org/betterx/betterend/world/surface/SulphuricSurfaceNoiseCondition.java create mode 100644 src/main/java/org/betterx/betterend/world/surface/UmbraSurfaceNoiseCondition.java delete mode 100644 src/main/java/ru/betterend/BetterEnd.java delete mode 100644 src/main/java/ru/betterend/api/BetterEndPlugin.java delete mode 100644 src/main/java/ru/betterend/blocks/AeterniumAnvil.java delete mode 100644 src/main/java/ru/betterend/blocks/AeterniumBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/AmaranitaHymenophoreBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/AncientEmeraldIceBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/AuroraCrystalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BlueVineBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BlueVineLanternBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BlueVineSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BoluxMushroomBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BrimstoneBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BubbleCoralBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BulbVineBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BulbVineLanternBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BulbVineLanternColoredBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/BulbVineSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/CavePumpkinBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/CavePumpkinVineBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/ChandelierBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/CharniaBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/ChorusGrassBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/DenseEmeraldIceBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/DragonTreeSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EmeraldIceBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndBlockProperties.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLilyBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLilySeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLotusFlowerBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLotusLeafBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLotusSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndLotusStemBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndPedestal.java delete mode 100644 src/main/java/ru/betterend/blocks/EndPortalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndStoneSmelter.java delete mode 100644 src/main/java/ru/betterend/blocks/EnderBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EndstoneDustBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/EternalPedestal.java delete mode 100644 src/main/java/ru/betterend/blocks/FilaluxBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/FilaluxLanternBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/FilaluxWingsBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/FlamaeaBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/FlammalixBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/FlowerPotBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/GlowingHymenophoreBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/GlowingMossBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/GlowingPillarLuminophorBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/GlowingPillarRootsBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/GlowingPillarSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HelixTreeLeavesBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HelixTreeSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HydraluxBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HydraluxPetalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HydraluxPetalColoredBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HydraluxSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/HydrothermalVentBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/InfusionPedestal.java delete mode 100644 src/main/java/ru/betterend/blocks/JellyshroomCapBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LacugroveSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LanceleafBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LanceleafSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LargeAmaranitaBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LucerniaSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LumecornBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/LumecornSeedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MengerSpongeBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MengerSpongeWetBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MissingTileBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MossyDragonBoneBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MossyGlowshroomSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/MossyObsidian.java delete mode 100644 src/main/java/ru/betterend/blocks/MurkweedBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/NeedlegrassBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/NeonCactusBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/NeonCactusPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/PallidiumBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/PedestalVanilla.java delete mode 100644 src/main/java/ru/betterend/blocks/PondAnemoneBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/PythadendronSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/RespawnObeliskBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/RunedFlavolite.java delete mode 100644 src/main/java/ru/betterend/blocks/ShadowBerryBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/ShadowGrassBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SilkMothHiveBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SilkMothNestBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SmallAmaranitaBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SmallJellyshroomBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SmaragdantCrystalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SmaragdantCrystalShardBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/SulphurCrystalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/TenaneaFlowersBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/TenaneaSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/TerrainPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/TwistedUmbrellaMossBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/TwistedUmbrellaMossTallBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaMossBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaMossTallBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaTreeClusterBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaTreeMembraneBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/UmbrellaTreeSaplingBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/VentBubbleColumnBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndAnvilBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndLanternBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndPlantWithAgeBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndTerrainBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndTripleTerrain.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndUnderwaterPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndWallMushroom.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/EndWallPlantBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/FurBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/LitBaseBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/LitPillarBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/PedestalBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/PottableCropBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/PottableFeatureSapling.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/PottableLeavesBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/basis/StoneLanternBlock.java delete mode 100644 src/main/java/ru/betterend/blocks/entities/BlockEntityHydrothermalVent.java delete mode 100644 src/main/java/ru/betterend/blocks/entities/EndStoneSmelterBlockEntity.java delete mode 100644 src/main/java/ru/betterend/blocks/entities/EternalPedestalEntity.java delete mode 100644 src/main/java/ru/betterend/blocks/entities/InfusionPedestalEntity.java delete mode 100644 src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java delete mode 100644 src/main/java/ru/betterend/client/BetterEndClient.java delete mode 100644 src/main/java/ru/betterend/client/ClientOptions.java delete mode 100644 src/main/java/ru/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java delete mode 100644 src/main/java/ru/betterend/client/gui/EndStoneSmelterScreen.java delete mode 100644 src/main/java/ru/betterend/client/gui/EndStoneSmelterScreenHandler.java delete mode 100644 src/main/java/ru/betterend/client/gui/slot/SmelterFuelSlot.java delete mode 100644 src/main/java/ru/betterend/client/gui/slot/SmelterOutputSlot.java delete mode 100644 src/main/java/ru/betterend/client/models/Patterns.java delete mode 100644 src/main/java/ru/betterend/client/render/ArmoredElytraLayer.java delete mode 100644 src/main/java/ru/betterend/client/render/BeamRenderer.java delete mode 100644 src/main/java/ru/betterend/client/render/BetterEndSkyRenderer.java delete mode 100644 src/main/java/ru/betterend/client/render/EndCrystalRenderer.java delete mode 100644 src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java delete mode 100644 src/main/java/ru/betterend/client/render/PedestalItemRenderer.java delete mode 100644 src/main/java/ru/betterend/complexmaterials/ColoredMaterial.java delete mode 100644 src/main/java/ru/betterend/complexmaterials/CrystalSubblocksMaterial.java delete mode 100644 src/main/java/ru/betterend/complexmaterials/EndWoodenComplexMaterial.java delete mode 100644 src/main/java/ru/betterend/complexmaterials/MetalMaterial.java delete mode 100644 src/main/java/ru/betterend/complexmaterials/StoneMaterial.java delete mode 100644 src/main/java/ru/betterend/config/Configs.java delete mode 100644 src/main/java/ru/betterend/effects/EndPotions.java delete mode 100644 src/main/java/ru/betterend/effects/EndStatusEffects.java delete mode 100644 src/main/java/ru/betterend/effects/enchantment/EndVeilEnchantment.java delete mode 100644 src/main/java/ru/betterend/effects/status/EndVeilEffect.java delete mode 100644 src/main/java/ru/betterend/entity/CubozoaEntity.java delete mode 100644 src/main/java/ru/betterend/entity/DragonflyEntity.java delete mode 100644 src/main/java/ru/betterend/entity/EndFishEntity.java delete mode 100644 src/main/java/ru/betterend/entity/EndSlimeEntity.java delete mode 100644 src/main/java/ru/betterend/entity/ShadowWalkerEntity.java delete mode 100644 src/main/java/ru/betterend/entity/SilkMothEntity.java delete mode 100644 src/main/java/ru/betterend/entity/model/CubozoaEntityModel.java delete mode 100644 src/main/java/ru/betterend/entity/model/DragonflyEntityModel.java delete mode 100644 src/main/java/ru/betterend/entity/model/EndFishEntityModel.java delete mode 100644 src/main/java/ru/betterend/entity/model/EndSlimeEntityModel.java delete mode 100644 src/main/java/ru/betterend/entity/model/SilkMothEntityModel.java delete mode 100644 src/main/java/ru/betterend/entity/render/RendererEntityCubozoa.java delete mode 100644 src/main/java/ru/betterend/entity/render/RendererEntityDragonfly.java delete mode 100644 src/main/java/ru/betterend/entity/render/RendererEntityEndFish.java delete mode 100644 src/main/java/ru/betterend/entity/render/RendererEntityEndSlime.java delete mode 100644 src/main/java/ru/betterend/entity/render/RendererEntityShadowWalker.java delete mode 100644 src/main/java/ru/betterend/entity/render/SilkMothEntityRenderer.java delete mode 100644 src/main/java/ru/betterend/events/ItemTooltipCallback.java delete mode 100644 src/main/java/ru/betterend/events/PlayerAdvancementsCallback.java delete mode 100644 src/main/java/ru/betterend/integration/EndBiomeIntegration.java delete mode 100644 src/main/java/ru/betterend/integration/EnderscapeIntegration.java delete mode 100644 src/main/java/ru/betterend/integration/FlamboyantRefabricatedIntegration.java delete mode 100644 src/main/java/ru/betterend/integration/Integrations.java delete mode 100644 src/main/java/ru/betterend/integration/NourishIntegration.java delete mode 100644 src/main/java/ru/betterend/integration/byg/BYGBlocks.java delete mode 100644 src/main/java/ru/betterend/integration/byg/BYGIntegration.java delete mode 100644 src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java delete mode 100644 src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java delete mode 100644 src/main/java/ru/betterend/integration/byg/biomes/OldBulbisGardens.java delete mode 100644 src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java delete mode 100644 src/main/java/ru/betterend/integration/byg/features/BigEtherTreeFeature.java delete mode 100644 src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java delete mode 100644 src/main/java/ru/betterend/integration/byg/features/OldBulbisTreeFeature.java delete mode 100644 src/main/java/ru/betterend/integration/rei/REIContainer.java delete mode 100644 src/main/java/ru/betterend/interfaces/BETargetChecker.java delete mode 100644 src/main/java/ru/betterend/interfaces/FallFlyingItem.java delete mode 100644 src/main/java/ru/betterend/interfaces/ISlime.java delete mode 100644 src/main/java/ru/betterend/interfaces/MultiModelItem.java delete mode 100644 src/main/java/ru/betterend/interfaces/PottablePlant.java delete mode 100644 src/main/java/ru/betterend/interfaces/PottableTerrain.java delete mode 100644 src/main/java/ru/betterend/interfaces/TeleportingEntity.java delete mode 100644 src/main/java/ru/betterend/item/ArmoredElytra.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteArmor.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteBoots.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteChestplate.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteElytra.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteHelmet.java delete mode 100644 src/main/java/ru/betterend/item/CrystaliteLeggings.java delete mode 100644 src/main/java/ru/betterend/item/EnchantedItem.java delete mode 100644 src/main/java/ru/betterend/item/EndArmorItem.java delete mode 100644 src/main/java/ru/betterend/item/EndAttribute.java delete mode 100644 src/main/java/ru/betterend/item/EndBucketItem.java delete mode 100644 src/main/java/ru/betterend/item/EternalCrystalItem.java delete mode 100644 src/main/java/ru/betterend/item/GuideBookItem.java delete mode 100644 src/main/java/ru/betterend/item/material/EndArmorMaterial.java delete mode 100644 src/main/java/ru/betterend/item/material/EndToolMaterial.java delete mode 100644 src/main/java/ru/betterend/item/model/ArmoredElytraModel.java delete mode 100644 src/main/java/ru/betterend/item/model/CrystaliteArmorProvider.java delete mode 100644 src/main/java/ru/betterend/item/model/CrystaliteBootsModel.java delete mode 100644 src/main/java/ru/betterend/item/model/CrystaliteChestplateModel.java delete mode 100644 src/main/java/ru/betterend/item/model/CrystaliteHelmetModel.java delete mode 100644 src/main/java/ru/betterend/item/model/CrystaliteLeggingsModel.java delete mode 100644 src/main/java/ru/betterend/item/tool/EndHammerItem.java delete mode 100644 src/main/java/ru/betterend/item/tool/EndPickaxe.java delete mode 100644 src/main/java/ru/betterend/mixin/client/BiomeColorsMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/CapeLayerMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/EndEffectsMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/ItemStackMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/LocalPlayerMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/MinecraftClientMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/ModelLoaderMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/client/MusicTrackerMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/BlockBehaviourMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/ChorusFlowerBlockMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/ChorusPlantBlockMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/ChorusPlantFeatureMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EnchantmentMenuMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EndCityFeatureMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EndPodiumFeatureMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EnderManMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/EntityMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/LivingEntityMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/MonsterMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/NoiseChunkAccessor.java delete mode 100644 src/main/java/ru/betterend/mixin/common/NoiseChunkMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/NoiseGeneratorSettingsMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/PlayerAdvancementsMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/PlayerMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/ServerPlayerMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/SlimeMixin.java delete mode 100644 src/main/java/ru/betterend/mixin/common/SpikeFeatureMixin.java delete mode 100644 src/main/java/ru/betterend/noise/OpenSimplexNoise.java delete mode 100644 src/main/java/ru/betterend/particle/FireflyParticle.java delete mode 100644 src/main/java/ru/betterend/particle/InfusionParticle.java delete mode 100644 src/main/java/ru/betterend/particle/InfusionParticleType.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleBlackSpore.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleGeyser.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleGlowingSphere.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleJungleSpore.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleSnowflake.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleSulphur.java delete mode 100644 src/main/java/ru/betterend/particle/ParticleTenaneaPetal.java delete mode 100644 src/main/java/ru/betterend/particle/PaticlePortalSphere.java delete mode 100644 src/main/java/ru/betterend/particle/SmaragdantParticle.java delete mode 100644 src/main/java/ru/betterend/recipe/AlloyingRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/AnvilRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/CraftingRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/FurnaceRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/InfusionRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/SmithingRecipes.java delete mode 100644 src/main/java/ru/betterend/recipe/builders/AlloyingRecipe.java delete mode 100644 src/main/java/ru/betterend/recipe/builders/InfusionRecipe.java delete mode 100644 src/main/java/ru/betterend/registry/EndAttributes.java delete mode 100644 src/main/java/ru/betterend/registry/EndBiomes.java delete mode 100644 src/main/java/ru/betterend/registry/EndBlockEntities.java delete mode 100644 src/main/java/ru/betterend/registry/EndBlockEntityRenders.java delete mode 100644 src/main/java/ru/betterend/registry/EndBlocks.java delete mode 100644 src/main/java/ru/betterend/registry/EndEnchantments.java delete mode 100644 src/main/java/ru/betterend/registry/EndEntities.java delete mode 100644 src/main/java/ru/betterend/registry/EndEntitiesRenders.java delete mode 100644 src/main/java/ru/betterend/registry/EndFeatures.java delete mode 100644 src/main/java/ru/betterend/registry/EndItems.java delete mode 100644 src/main/java/ru/betterend/registry/EndModelProviders.java delete mode 100644 src/main/java/ru/betterend/registry/EndParticles.java delete mode 100644 src/main/java/ru/betterend/registry/EndPortals.java delete mode 100644 src/main/java/ru/betterend/registry/EndScreens.java delete mode 100644 src/main/java/ru/betterend/registry/EndSounds.java delete mode 100644 src/main/java/ru/betterend/registry/EndStructures.java delete mode 100644 src/main/java/ru/betterend/registry/EndTags.java delete mode 100644 src/main/java/ru/betterend/rituals/EternalRitual.java delete mode 100644 src/main/java/ru/betterend/rituals/InfusionRitual.java delete mode 100644 src/main/java/ru/betterend/tab/CreativeTabs.java delete mode 100644 src/main/java/ru/betterend/util/BlockFixer.java delete mode 100644 src/main/java/ru/betterend/util/BonemealPlants.java delete mode 100644 src/main/java/ru/betterend/util/GlobalState.java delete mode 100644 src/main/java/ru/betterend/util/LangUtil.java delete mode 100644 src/main/java/ru/betterend/util/LootTableUtil.java delete mode 100644 src/main/java/ru/betterend/util/StructureErode.java delete mode 100644 src/main/java/ru/betterend/world/biome/EndBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/air/BiomeIceStarfield.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/EmptyAuroraCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/EmptyEndCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/EndCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/JadeCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/LushAuroraCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/cave/LushSmaragdantCaveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/AmberLandBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/BlossomingSpiresBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/ChorusForestBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/CrystalMountainsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/DragonGraveyardsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/DryShrublandBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/DustWastelandsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/FoggyMushroomlandBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/GlowingGrasslandsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/LanternWoodsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/MegalakeBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/MegalakeGroveBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/NeonOasisBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/PaintedMountainsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/ShadowForestBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/SulphurSpringsBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/UmbraValleyBiome.java delete mode 100644 src/main/java/ru/betterend/world/biome/land/UmbrellaJungleBiome.java delete mode 100644 src/main/java/ru/betterend/world/features/BiomeIslandFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/BlueVineFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/BuildingListFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/CavePumpkinFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/CharniaFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/CrashedShipFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/DoublePlantFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/EndLilyFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/EndLotusFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/EndLotusLeafFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/FilaluxFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/FullHeightScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/GlowPillarFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/HydraluxFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/InvertedScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/LanceleafFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/MengerSpongeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/NeonCactusFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/ScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/SilkMothNestFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/SingleInvertedScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/SinglePlantFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/SkyScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/UnderwaterPlantFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/UnderwaterPlantScatter.java delete mode 100644 src/main/java/ru/betterend/world/features/VineFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/WallPlantFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/WallPlantOnLogFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/WallScatterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/bushes/BushFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/bushes/BushWithOuterFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/bushes/LargeAmaranitaFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/bushes/Lumecorn.java delete mode 100644 src/main/java/ru/betterend/world/features/bushes/TenaneaBushFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/ArchFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/BigAuroraCrystalFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/DesertLakeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/EndLakeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/FallenPillarFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/FloatingSpireFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/IceStarFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/ObsidianBoulderFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/ObsidianPillarBasementFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/OreLayerFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SingleBlockFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SmaragdantCrystalFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SpireFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/StalactiteFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SulphurHillFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SulphuricLakeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/SurfaceVentFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/ThinArchFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/caves/RoundCaveFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/DragonTreeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/HelixTreeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/JellyshroomFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/LacugroveFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/LucerniaFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/MossyGlowshroomFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/PythadendronTreeFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java delete mode 100644 src/main/java/ru/betterend/world/features/trees/UmbrellaTreeFeature.java delete mode 100644 src/main/java/ru/betterend/world/generator/BiomeType.java delete mode 100644 src/main/java/ru/betterend/world/generator/GeneratorOptions.java delete mode 100644 src/main/java/ru/betterend/world/generator/IslandLayer.java delete mode 100644 src/main/java/ru/betterend/world/generator/LayerOptions.java delete mode 100644 src/main/java/ru/betterend/world/generator/TerrainBoolCache.java delete mode 100644 src/main/java/ru/betterend/world/generator/TerrainGenerator.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/EternalPortalStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/FeatureBaseStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/GiantIceStarStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/GiantMossyGlowshroomStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/MegaLakeSmallStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/MegaLakeStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/MountainStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/PaintedMountainStructure.java delete mode 100644 src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/BasePiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/CavePiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/CrystalMountainPiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/LakePiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/MountainPiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/NBTPiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/PaintedMountainPiece.java delete mode 100644 src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java delete mode 100644 src/main/java/ru/betterend/world/surface/SplitNoiseCondition.java delete mode 100644 src/main/java/ru/betterend/world/surface/SulphuricSurfaceNoiseCondition.java delete mode 100644 src/main/java/ru/betterend/world/surface/UmbraSurfaceNoiseCondition.java diff --git a/src/main/java/org/betterx/betterend/BetterEnd.java b/src/main/java/org/betterx/betterend/BetterEnd.java new file mode 100644 index 00000000..edfadec5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/BetterEnd.java @@ -0,0 +1,82 @@ +package org.betterx.betterend; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.Biomes; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; + +import org.betterx.bclib.api.WorldDataAPI; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.util.Logger; +import org.betterx.betterend.api.BetterEndPlugin; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.effects.EndPotions; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.recipe.*; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.util.BonemealPlants; +import org.betterx.betterend.util.LootTableUtil; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.betterx.betterend.world.generator.TerrainGenerator; + +public class BetterEnd implements ModInitializer { + public static final String MOD_ID = "betterend"; + public static final Logger LOGGER = new Logger(MOD_ID); + public static final boolean RUNS_FALL_FLYING_LIB = FabricLoader.getInstance() + .getModContainer("fallflyinglib") + .isPresent(); + + @Override + public void onInitialize() { + WorldDataAPI.registerModCache(MOD_ID); + EndPortals.loadPortals(); + EndSounds.register(); + EndBlockEntities.register(); + EndFeatures.register(); + EndEntities.register(); + EndBiomes.register(); + EndTags.register(); + EndEnchantments.register(); + EndPotions.register(); + CraftingRecipes.register(); + FurnaceRecipes.register(); + AlloyingRecipes.register(); + AnvilRecipes.register(); + SmithingRecipes.register(); + InfusionRecipes.register(); + EndStructures.register(); + BonemealPlants.init(); + GeneratorOptions.init(); + LootTableUtil.init(); + FabricLoader.getInstance() + .getEntrypoints("betterend", BetterEndPlugin.class) + .forEach(BetterEndPlugin::register); + Integrations.init(); + Configs.saveConfigs(); + + if (GeneratorOptions.useNewGenerator()) { + org.betterx.bclib.world.generator.GeneratorOptions.setFarEndBiomes(GeneratorOptions.getIslandDistBlock()); + org.betterx.bclib.world.generator.GeneratorOptions.setEndLandFunction((pos) -> TerrainGenerator.isLand(pos.x, + pos.y)); + } + + BiomeAPI.registerEndBiomeModification((biomeID, biome) -> { + if (!biomeID.equals(Biomes.THE_VOID.location())) { + EndFeatures.addBiomeFeatures(biomeID, biome); + } + }); + + BiomeAPI.onFinishingEndBiomeTags((biomeID, biome) -> { + if (!biomeID.equals(Biomes.THE_VOID.location())) { + EndStructures.addBiomeStructures(biomeID, biome); + } + }); + + } + + public static ResourceLocation makeID(String path) { + return new ResourceLocation(MOD_ID, path); + } + +} diff --git a/src/main/java/org/betterx/betterend/api/BetterEndPlugin.java b/src/main/java/org/betterx/betterend/api/BetterEndPlugin.java new file mode 100644 index 00000000..9c361d3d --- /dev/null +++ b/src/main/java/org/betterx/betterend/api/BetterEndPlugin.java @@ -0,0 +1,38 @@ +package org.betterx.betterend.api; + +public interface BetterEndPlugin { + /** + * Alloying recipes registration. + * See AlloyingRecipe.Builder for details. + */ + default void registerAlloyingRecipes() { + } + + /** + * Smithing recipes registration. + * See AnvilSmithingRecipe.Builder for details. + */ + default void registerSmithingRecipes() { + } + + /** + * Additional biomes registration. + * See BiomeRegistry.registerBiome for details. + */ + default void registerEndBiomes() { + } + + /** + * Register other mod stuff, for example, EndITEM_HAMMERS. + */ + default void registerOthers() { + } + + + static void register(BetterEndPlugin plugin) { + plugin.registerAlloyingRecipes(); + plugin.registerSmithingRecipes(); + plugin.registerEndBiomes(); + plugin.registerOthers(); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/AeterniumAnvil.java b/src/main/java/org/betterx/betterend/blocks/AeterniumAnvil.java new file mode 100644 index 00000000..ed2b03bd --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/AeterniumAnvil.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; + +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; + +import org.betterx.bclib.items.BaseAnvilItem; +import org.betterx.betterend.blocks.basis.EndAnvilBlock; +import org.betterx.betterend.item.material.EndToolMaterial; +import org.betterx.betterend.registry.EndBlocks; + +public class AeterniumAnvil extends EndAnvilBlock { + public AeterniumAnvil() { + super(EndBlocks.AETERNIUM_BLOCK.defaultMaterialColor(), EndToolMaterial.AETERNIUM.getLevel()); + } + + @Override + public int getMaxDurability() { + return 8; + } + + @Override + public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { + return new BaseAnvilItem(this, settings.fireproof()); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/AeterniumBlock.java b/src/main/java/org/betterx/betterend/blocks/AeterniumBlock.java new file mode 100644 index 00000000..cb8a16e0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/AeterniumBlock.java @@ -0,0 +1,30 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.CustomItemProvider; + +public class AeterniumBlock extends BaseBlock implements CustomItemProvider { + public AeterniumBlock() { + super(FabricBlockSettings + .of(Material.METAL, MaterialColor.COLOR_GRAY) + .hardness(65F) + .resistance(1200F) + .requiresCorrectToolForDrops() + .sound(SoundType.NETHERITE_BLOCK) + ); + } + + @Override + public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { + return new BlockItem(this, settings.fireproof()); + } +} diff --git a/src/main/java/ru/betterend/blocks/AmaranitaCapBlock.java b/src/main/java/org/betterx/betterend/blocks/AmaranitaCapBlock.java similarity index 50% rename from src/main/java/ru/betterend/blocks/AmaranitaCapBlock.java rename to src/main/java/org/betterx/betterend/blocks/AmaranitaCapBlock.java index 734e855c..d199b3c3 100644 --- a/src/main/java/ru/betterend/blocks/AmaranitaCapBlock.java +++ b/src/main/java/org/betterx/betterend/blocks/AmaranitaCapBlock.java @@ -1,13 +1,15 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.tools.AddMineableAxe; - -public class AmaranitaCapBlock extends BaseBlock implements AddMineableAxe { - public AmaranitaCapBlock() { - super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); - } -} +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; + +public class AmaranitaCapBlock extends BaseBlock implements AddMineableAxe { + public AmaranitaCapBlock() { + super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/AmaranitaHymenophoreBlock.java b/src/main/java/org/betterx/betterend/blocks/AmaranitaHymenophoreBlock.java new file mode 100644 index 00000000..5a4e6caf --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/AmaranitaHymenophoreBlock.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; + +public class AmaranitaHymenophoreBlock extends BaseBlock implements RenderLayerProvider, AddMineableAxe { + public AmaranitaHymenophoreBlock() { + super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } +} diff --git a/src/main/java/ru/betterend/blocks/AmaranitaStemBlock.java b/src/main/java/org/betterx/betterend/blocks/AmaranitaStemBlock.java similarity index 50% rename from src/main/java/ru/betterend/blocks/AmaranitaStemBlock.java rename to src/main/java/org/betterx/betterend/blocks/AmaranitaStemBlock.java index f50684ba..91edbbf3 100644 --- a/src/main/java/ru/betterend/blocks/AmaranitaStemBlock.java +++ b/src/main/java/org/betterx/betterend/blocks/AmaranitaStemBlock.java @@ -1,12 +1,14 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseRotatedPillarBlock; - -public class AmaranitaStemBlock extends BaseRotatedPillarBlock { - public AmaranitaStemBlock() { - super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).mapColor(MaterialColor.COLOR_LIGHT_GREEN)); - } -} +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseRotatedPillarBlock; + +public class AmaranitaStemBlock extends BaseRotatedPillarBlock { + public AmaranitaStemBlock() { + super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).mapColor(MaterialColor.COLOR_LIGHT_GREEN)); + } +} diff --git a/src/main/java/ru/betterend/blocks/AmberBlock.java b/src/main/java/org/betterx/betterend/blocks/AmberBlock.java similarity index 51% rename from src/main/java/ru/betterend/blocks/AmberBlock.java rename to src/main/java/org/betterx/betterend/blocks/AmberBlock.java index 05773bdf..6734c3d2 100644 --- a/src/main/java/ru/betterend/blocks/AmberBlock.java +++ b/src/main/java/org/betterx/betterend/blocks/AmberBlock.java @@ -1,12 +1,14 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; - -public class AmberBlock extends BaseBlock { - public AmberBlock() { - super(FabricBlockSettings.copyOf(Blocks.DIAMOND_BLOCK).mapColor(MaterialColor.COLOR_YELLOW)); - } -} +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; + +public class AmberBlock extends BaseBlock { + public AmberBlock() { + super(FabricBlockSettings.copyOf(Blocks.DIAMOND_BLOCK).mapColor(MaterialColor.COLOR_YELLOW)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/AncientEmeraldIceBlock.java b/src/main/java/org/betterx/betterend/blocks/AncientEmeraldIceBlock.java new file mode 100644 index 00000000..f96e3037 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/AncientEmeraldIceBlock.java @@ -0,0 +1,89 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndParticles; + +import java.util.Collections; +import java.util.List; + +public class AncientEmeraldIceBlock extends BaseBlock { + public AncientEmeraldIceBlock() { + super(FabricBlockSettings.copyOf(Blocks.BLUE_ICE).randomTicks()); + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + Direction dir = BlocksHelper.randomDirection(random); + + if (random.nextBoolean()) { + int x = MHelper.randRange(-2, 2, random); + int y = MHelper.randRange(-2, 2, random); + int z = MHelper.randRange(-2, 2, random); + BlockPos p = pos.offset(x, y, z); + if (world.getBlockState(p).is(Blocks.WATER)) { + world.setBlockAndUpdate(p, EndBlocks.EMERALD_ICE.defaultBlockState()); + makeParticles(world, p, random); + } + } + + pos = pos.relative(dir); + state = world.getBlockState(pos); + if (state.is(Blocks.WATER)) { + world.setBlockAndUpdate(pos, EndBlocks.EMERALD_ICE.defaultBlockState()); + makeParticles(world, pos, random); + } else if (state.is(EndBlocks.EMERALD_ICE)) { + world.setBlockAndUpdate(pos, EndBlocks.DENSE_EMERALD_ICE.defaultBlockState()); + makeParticles(world, pos, random); + } + } + + private void makeParticles(ServerLevel world, BlockPos pos, RandomSource random) { + world.sendParticles( + EndParticles.SNOWFLAKE, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + 20, + 0.5, + 0.5, + 0.5, + 0 + ); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); + if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { + return Collections.singletonList(new ItemStack(this)); + } else { + return Collections.emptyList(); + } + } + + @Override + public void stepOn(Level level, BlockPos blockPos, BlockState blockState, Entity entity) { + super.stepOn(level, blockPos, blockState, entity); + entity.setIsInPowderSnow(true); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/AuroraCrystalBlock.java b/src/main/java/org/betterx/betterend/blocks/AuroraCrystalBlock.java new file mode 100644 index 00000000..7f2f0171 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/AuroraCrystalBlock.java @@ -0,0 +1,131 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.AbstractGlassBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineableHammer; +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndItems; + +import java.util.List; + +public class AuroraCrystalBlock extends AbstractGlassBlock implements RenderLayerProvider, CustomColorProvider, AddMineablePickaxe, AddMineableHammer { + public static final Vec3i[] COLORS; + private static final int MIN_DROP = 1; + private static final int MAX_DROP = 4; + + public AuroraCrystalBlock() { + super(FabricBlockSettings + .of(Material.GLASS) + .hardness(1F) + .resistance(1F) + .luminance(15) + .noOcclusion() + .isSuffocating((state, world, pos) -> false) + .sound(SoundType.GLASS)); + } + + @Override + @Deprecated + public VoxelShape getVisualShape(BlockState blockState, + BlockGetter blockGetter, + BlockPos blockPos, + CollisionContext collisionContext) { + return this.getCollisionShape(blockState, blockGetter, blockPos, collisionContext); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> { + if (pos == null) { + pos = BlockPos.ZERO; + } + + long i = (long) pos.getX() + (long) pos.getY() + (long) pos.getZ(); + double delta = i * 0.1; + int index = MHelper.floor(delta); + int index2 = (index + 1) & 3; + delta -= index; + index &= 3; + + Vec3i color1 = COLORS[index]; + Vec3i color2 = COLORS[index2]; + + int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); + int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); + int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); + + return ColorUtil.color(r, g, b); + }; + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> { + return ColorUtil.color(COLORS[3].getX(), COLORS[3].getY(), COLORS[3].getZ()); + }; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && tool.isCorrectToolForDrops(state)) { + int count = 0; + int enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool); + if (enchant > 0) { + return Lists.newArrayList(new ItemStack(this)); + } + enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool); + if (enchant > 0) { + int min = Mth.clamp(MIN_DROP + enchant, MIN_DROP, MAX_DROP); + int max = MAX_DROP + (enchant / Enchantments.BLOCK_FORTUNE.getMaxLevel()); + if (min == max) { + return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, max)); + } + count = MHelper.randRange(min, max, MHelper.RANDOM_SOURCE); + } else { + count = MHelper.randRange(MIN_DROP, MAX_DROP, MHelper.RANDOM_SOURCE); + } + return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, count)); + } + return Lists.newArrayList(); + } + + static { + COLORS = new Vec3i[]{ + new Vec3i(247, 77, 161), + new Vec3i(120, 184, 255), + new Vec3i(120, 255, 168), + new Vec3i(243, 58, 255) + }; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BlueVineBlock.java b/src/main/java/org/betterx/betterend/blocks/BlueVineBlock.java new file mode 100644 index 00000000..3094ba9b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BlueVineBlock.java @@ -0,0 +1,24 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.UpDownPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class BlueVineBlock extends UpDownPlantBlock { + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.getBlock() == EndBlocks.END_MOSS || state.getBlock() == EndBlocks.END_MYCELIUM; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BlueVineLanternBlock.java b/src/main/java/org/betterx/betterend/blocks/BlueVineLanternBlock.java new file mode 100644 index 00000000..c8dff07d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BlueVineLanternBlock.java @@ -0,0 +1,57 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; +import org.betterx.betterend.registry.EndBlocks; + +public class BlueVineLanternBlock extends BaseBlock implements AddMineableAxe { + public static final BooleanProperty NATURAL = BlockProperties.NATURAL; + + public BlueVineLanternBlock() { + super(FabricBlockSettings.of(Material.WOOD) + .luminance(15) + .sound(SoundType.WART_BLOCK)); + this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false)); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return !state.getValue(NATURAL) || world.getBlockState(pos.below()).getBlock() == EndBlocks.BLUE_VINE; + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { + return state; + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(NATURAL); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BlueVineSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/BlueVineSeedBlock.java new file mode 100644 index 00000000..7aec736d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BlueVineSeedBlock.java @@ -0,0 +1,81 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class BlueVineSeedBlock extends EndPlantWithAgeBlock { + public BlueVineSeedBlock() { + super(p -> p.offsetType(BlockBehaviour.OffsetType.NONE)); + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + int height = MHelper.randRange(2, 5, random); + int h = BlocksHelper.upRay(world, pos, height + 2); + if (h < height + 1) { + return; + } + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.BLUE_VINE.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM) + ); + for (int i = 1; i < height; i++) { + BlocksHelper.setWithoutUpdate( + world, + pos.above(i), + EndBlocks.BLUE_VINE.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE) + ); + } + BlocksHelper.setWithoutUpdate( + world, + pos.above(height), + EndBlocks.BLUE_VINE.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP) + ); + placeLantern(world, pos.above(height + 1)); + } + + private void placeLantern(WorldGenLevel world, BlockPos pos) { + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.BLUE_VINE_LANTERN.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true) + ); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos p = pos.relative(dir); + if (world.isEmptyBlock(p)) { + BlocksHelper.setWithoutUpdate( + world, + p, + EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, dir) + ); + } + } + if (world.isEmptyBlock(pos.above())) { + BlocksHelper.setWithoutUpdate( + world, + pos.above(), + EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, Direction.UP) + ); + } + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BoluxMushroomBlock.java b/src/main/java/org/betterx/betterend/blocks/BoluxMushroomBlock.java new file mode 100644 index 00000000..5eea70a5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BoluxMushroomBlock.java @@ -0,0 +1,53 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import com.google.common.collect.Lists; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class BoluxMushroomBlock extends EndPlantBlock { + private static final VoxelShape SHAPE = Block.box(1, 0, 1, 15, 9, 15); + + public BoluxMushroomBlock() { + super(10, p -> p.offsetType(BlockBehaviour.OffsetType.NONE)); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.RUTISCUS); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return Lists.newArrayList(new ItemStack(this)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BrimstoneBlock.java b/src/main/java/org/betterx/betterend/blocks/BrimstoneBlock.java new file mode 100644 index 00000000..963b4ffe --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BrimstoneBlock.java @@ -0,0 +1,106 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +import org.jetbrains.annotations.Nullable; + +public class BrimstoneBlock extends BaseBlock { + public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; + + public BrimstoneBlock() { + super(FabricBlockSettings.copyOf(Blocks.END_STONE).mapColor(MaterialColor.COLOR_BROWN).randomTicks()); + registerDefaultState(stateDefinition.any().setValue(ACTIVATED, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(ACTIVATED); + } + + @Override + public void setPlacedBy(Level world, + BlockPos pos, + BlockState state, + @Nullable LivingEntity placer, + ItemStack itemStack) { + if (world.isClientSide()) { + updateChunks((ClientLevel) world, pos); + } + } + + public void destroy(LevelAccessor world, BlockPos pos, BlockState state) { + if (world.isClientSide()) { + updateChunks((ClientLevel) world, pos); + } + } + + private void updateChunks(ClientLevel world, BlockPos pos) { + int y = pos.getY() >> 4; + int x1 = (pos.getX() - 2) >> 4; + int z1 = (pos.getZ() - 2) >> 4; + int x2 = (pos.getX() + 2) >> 4; + int z2 = (pos.getZ() + 2) >> 4; + for (int x = x1; x <= x2; x++) { + for (int z = z1; z <= z2; z++) { + world.setSectionDirtyWithNeighbors(x, y, z); + } + } + } + + @Override + @SuppressWarnings("deprecation") + public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + boolean deactivate = true; + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (world.getFluidState(pos.relative(dir)).getType().equals(Fluids.WATER)) { + deactivate = false; + break; + } + } + if (state.getValue(ACTIVATED)) { + if (deactivate) { + world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, false)); + } else if (state.getValue(ACTIVATED) && random.nextInt(16) == 0) { + Direction dir = BlocksHelper.randomDirection(random); + BlockPos side = pos.relative(dir); + BlockState sideState = world.getBlockState(side); + if (sideState.getBlock() instanceof SulphurCrystalBlock) { + if (sideState.getValue(SulphurCrystalBlock.AGE) < 2 && sideState.getValue(SulphurCrystalBlock.WATERLOGGED)) { + int age = sideState.getValue(SulphurCrystalBlock.AGE) + 1; + world.setBlockAndUpdate(side, sideState.setValue(SulphurCrystalBlock.AGE, age)); + } + } else if (sideState.getFluidState().getType() == Fluids.WATER) { + BlockState crystal = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() + .setValue(SulphurCrystalBlock.FACING, dir) + .setValue(SulphurCrystalBlock.WATERLOGGED, true) + .setValue(SulphurCrystalBlock.AGE, 0); + world.setBlockAndUpdate(side, crystal); + } + } + } else if (!deactivate && !state.getValue(ACTIVATED)) { + world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, true)); + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BubbleCoralBlock.java b/src/main/java/org/betterx/betterend/blocks/BubbleCoralBlock.java new file mode 100644 index 00000000..3b6f4813 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BubbleCoralBlock.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock; + +public class BubbleCoralBlock extends EndUnderwaterPlantBlock implements AddMineableShears { + + private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 14, 16); + + public BubbleCoralBlock() { + super(FabricBlockSettings.of(Material.WATER_PLANT) + .sound(SoundType.CORAL_BLOCK) + .noCollission() + .offsetType(BlockBehaviour.OffsetType.NONE)); + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + double x = pos.getX() + random.nextDouble(); + double y = pos.getY() + random.nextDouble() * 0.5F + 0.5F; + double z = pos.getZ() + random.nextDouble(); + world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0.0D, 0.0D, 0.0D); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BulbVineBlock.java b/src/main/java/org/betterx/betterend/blocks/BulbVineBlock.java new file mode 100644 index 00000000..b04f74c0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BulbVineBlock.java @@ -0,0 +1,48 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.List; + +public class BulbVineBlock extends BaseVineBlock { + public BulbVineBlock() { + super(15, true); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.getValue(SHAPE) == TripleShape.BOTTOM) { + return Lists.newArrayList(new ItemStack(EndItems.GLOWING_BULB)); + } else if (MHelper.RANDOM.nextInt(8) == 0) { + return Lists.newArrayList(new ItemStack(EndBlocks.BULB_VINE_SEED)); + } else { + return Lists.newArrayList(); + } + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + boolean canPlace = super.canSurvive(state, world, pos); + return (state.is(this) && state.getValue(SHAPE) == TripleShape.BOTTOM) + ? canPlace + : canPlace && world.getBlockState( + pos.below()).is(this); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BulbVineLanternBlock.java b/src/main/java/org/betterx/betterend/blocks/BulbVineLanternBlock.java new file mode 100644 index 00000000..5428a842 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BulbVineLanternBlock.java @@ -0,0 +1,86 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.BlockModelProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; +import org.betterx.betterend.blocks.basis.EndLanternBlock; +import org.betterx.betterend.client.models.Patterns; + +import java.util.Map; +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +public class BulbVineLanternBlock extends EndLanternBlock implements RenderLayerProvider, BlockModelProvider, AddMineablePickaxe { + private static final VoxelShape SHAPE_CEIL = Block.box(4, 4, 4, 12, 16, 12); + private static final VoxelShape SHAPE_FLOOR = Block.box(4, 0, 4, 12, 12, 12); + + public BulbVineLanternBlock() { + this(FabricBlockSettings.of(Material.METAL) + .hardness(1) + .resistance(1) + .mapColor(MaterialColor.COLOR_LIGHT_GRAY) + .luminance(15) + .requiresCorrectToolForDrops() + .sound(SoundType.LANTERN)); + } + + public BulbVineLanternBlock(Properties settings) { + super(settings); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + Map textures = Maps.newHashMap(); + textures.put("%glow%", getGlowTexture()); + textures.put("%metal%", getMetalTexture(resourceLocation)); + Optional pattern = blockState.getValue(IS_FLOOR) + ? Patterns.createJson( + Patterns.BLOCK_BULB_LANTERN_FLOOR, + textures + ) + : Patterns.createJson(Patterns.BLOCK_BULB_LANTERN_CEIL, textures); + return ModelsHelper.fromPattern(pattern); + } + + protected String getMetalTexture(ResourceLocation blockId) { + String name = blockId.getPath(); + name = name.substring(0, name.indexOf('_')); + return name + "_bulb_vine_lantern_metal"; + } + + protected String getGlowTexture() { + return "bulb_vine_lantern_bulb"; + } + +} diff --git a/src/main/java/org/betterx/betterend/blocks/BulbVineLanternColoredBlock.java b/src/main/java/org/betterx/betterend/blocks/BulbVineLanternColoredBlock.java new file mode 100644 index 00000000..28053efe --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BulbVineLanternColoredBlock.java @@ -0,0 +1,40 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.ColorUtil; + +public class BulbVineLanternColoredBlock extends BulbVineLanternBlock implements CustomColorProvider { + public BulbVineLanternColoredBlock(FabricBlockSettings settings) { + super(settings); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> getColor(); + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> getColor(); + } + + private int getColor() { + int color = BlocksHelper.getBlockColor(this); + int b = (color & 255); + int g = ((color >> 8) & 255); + int r = ((color >> 16) & 255); + float[] hsv = ColorUtil.RGBtoHSB(r, g, b, new float[3]); + return ColorUtil.HSBtoRGB(hsv[0], hsv[1], hsv[1] > 0.2 ? 1 : hsv[2]); + } + + @Override + protected String getGlowTexture() { + return "bulb_vine_lantern_overlay"; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/BulbVineSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/BulbVineSeedBlock.java new file mode 100644 index 00000000..19291d4f --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/BulbVineSeedBlock.java @@ -0,0 +1,49 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class BulbVineSeedBlock extends EndPlantWithAgeBlock { + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState up = world.getBlockState(pos.above()); + return up.is(CommonBlockTags.GEN_END_STONES) || up.is(BlockTags.LOGS) || up.is(BlockTags.LEAVES); + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + int h = BlocksHelper.downRay(world, pos, random.nextInt(24)) - 1; + if (h > 2) { + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) + ); + for (int i = 1; i < h; i++) { + BlocksHelper.setWithoutUpdate( + world, + pos.below(i), + EndBlocks.BULB_VINE.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) + ); + } + BlocksHelper.setWithoutUpdate( + world, + pos.below(h), + EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM) + ); + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/CavePumpkinBlock.java b/src/main/java/org/betterx/betterend/blocks/CavePumpkinBlock.java new file mode 100644 index 00000000..74d4e4fe --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/CavePumpkinBlock.java @@ -0,0 +1,72 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Collections; +import java.util.List; + +public class CavePumpkinBlock extends BaseBlockNotFull implements RenderLayerProvider { + public static final BooleanProperty SMALL = BlockProperties.SMALL; + private static final VoxelShape SHAPE_SMALL; + private static final VoxelShape SHAPE_BIG; + + public CavePumpkinBlock() { + super(FabricBlockSettings.copyOf(Blocks.PUMPKIN).luminance((state) -> state.getValue(SMALL) ? 10 : 15)); + registerDefaultState(defaultBlockState().setValue(SMALL, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SMALL); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { + return state.getValue(SMALL) ? SHAPE_SMALL : SHAPE_BIG; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return state.getValue(SMALL) + ? Collections.singletonList(new ItemStack(EndBlocks.CAVE_PUMPKIN_SEED)) + : Collections + .singletonList(new ItemStack(this)); + } + + static { + VoxelShape lantern = Block.box(1, 0, 1, 15, 13, 15); + VoxelShape cap = Block.box(0, 12, 0, 16, 15, 16); + VoxelShape top = Block.box(5, 15, 5, 11, 16, 11); + SHAPE_BIG = Shapes.or(lantern, cap, top); + + lantern = Block.box(5, 7, 5, 11, 13, 11); + cap = Block.box(4, 12, 4, 12, 15, 12); + top = Block.box(6, 15, 6, 10, 16, 10); + SHAPE_SMALL = Shapes.or(lantern, cap, top); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/CavePumpkinVineBlock.java b/src/main/java/org/betterx/betterend/blocks/CavePumpkinVineBlock.java new file mode 100644 index 00000000..66a8d1a1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/CavePumpkinVineBlock.java @@ -0,0 +1,79 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class CavePumpkinVineBlock extends EndPlantWithAgeBlock { + public CavePumpkinVineBlock() { + super(p -> p.offsetType(BlockBehaviour.OffsetType.NONE)); + } + + private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12); + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState down = world.getBlockState(pos.above()); + return isTerrain(down); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + int age = state.getValue(AGE); + BlockState down = world.getBlockState(pos.below()); + if (down.getMaterial() + .isReplaceable() || (down.is(EndBlocks.CAVE_PUMPKIN) && down.getValue(BlockProperties.SMALL))) { + if (age < 3) { + world.setBlockAndUpdate(pos, state.setValue(AGE, age + 1)); + } + if (age == 2) { + world.setBlockAndUpdate( + pos.below(), + EndBlocks.CAVE_PUMPKIN.defaultBlockState().setValue(BlockProperties.SMALL, true) + ); + } else if (age == 3) { + world.setBlockAndUpdate(pos.below(), EndBlocks.CAVE_PUMPKIN.defaultBlockState()); + } + } + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + state = super.updateShape(state, facing, neighborState, world, pos, neighborPos); + if (state.is(this) && state.getValue(BlockProperties.AGE) > 1) { + BlockState down = world.getBlockState(pos.below()); + if (!down.is(EndBlocks.CAVE_PUMPKIN)) { + state = state.setValue(BlockProperties.AGE, 1); + } + } + return state; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/ChandelierBlock.java b/src/main/java/org/betterx/betterend/blocks/ChandelierBlock.java new file mode 100644 index 00000000..525fc04f --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/ChandelierBlock.java @@ -0,0 +1,117 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.resources.model.BlockModelRotation; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.BlockModelProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.betterend.client.models.Patterns; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +public class ChandelierBlock extends BaseAttachedBlock implements RenderLayerProvider, BlockModelProvider { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + + public ChandelierBlock(Block source) { + super(FabricBlockSettings.copyOf(source) + .luminance(15) + .noCollission() + .noOcclusion() + .requiresCorrectToolForDrops()); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation blockId) { + return ModelsHelper.createItemModel(blockId); + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + Optional pattern; + switch (blockState.getValue(FACING)) { + case UP: + pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_FLOOR, resourceLocation.getPath()); + break; + case DOWN: + pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_CEIL, resourceLocation.getPath()); + break; + default: + pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_WALL, resourceLocation.getPath()); + } + return ModelsHelper.fromPattern(pattern); + } + + @Override + @Environment(EnvType.CLIENT) + public UnbakedModel getModelVariant(ResourceLocation stateId, + BlockState blockState, + Map modelCache) { + String state = "_wall"; + BlockModelRotation rotation = BlockModelRotation.X0_Y0; + switch (blockState.getValue(FACING)) { + case UP: + state = "_floor"; + break; + case DOWN: + state = "_ceil"; + break; + case EAST: + rotation = BlockModelRotation.X0_Y270; + break; + case NORTH: + rotation = BlockModelRotation.X0_Y180; + break; + case WEST: + rotation = BlockModelRotation.X0_Y90; + break; + default: + break; + } + ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath() + state); + registerBlockModel(stateId, modelId, blockState, modelCache); + return ModelsHelper.createMultiVariant(modelId, rotation.getRotation(), false); + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Block.box(5, 0, 5, 11, 13, 11)); + BOUNDING_SHAPES.put(Direction.DOWN, Block.box(5, 3, 5, 11, 16, 11)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); + } +} diff --git a/src/main/java/ru/betterend/blocks/CharcoalBlock.java b/src/main/java/org/betterx/betterend/blocks/CharcoalBlock.java similarity index 50% rename from src/main/java/ru/betterend/blocks/CharcoalBlock.java rename to src/main/java/org/betterx/betterend/blocks/CharcoalBlock.java index d9fa10a8..4534151f 100644 --- a/src/main/java/ru/betterend/blocks/CharcoalBlock.java +++ b/src/main/java/org/betterx/betterend/blocks/CharcoalBlock.java @@ -1,13 +1,15 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.fabricmc.fabric.api.registry.FuelRegistry; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.blocks.BaseBlock; - -public class CharcoalBlock extends BaseBlock { - public CharcoalBlock() { - super(FabricBlockSettings.copyOf(Blocks.COAL_BLOCK)); - FuelRegistry.INSTANCE.add(this, 16000); - } -} +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Blocks; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.fabricmc.fabric.api.registry.FuelRegistry; + +import org.betterx.bclib.blocks.BaseBlock; + +public class CharcoalBlock extends BaseBlock { + public CharcoalBlock() { + super(FabricBlockSettings.copyOf(Blocks.COAL_BLOCK)); + FuelRegistry.INSTANCE.add(this, 16000); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/CharniaBlock.java b/src/main/java/org/betterx/betterend/blocks/CharniaBlock.java new file mode 100644 index 00000000..021dff52 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/CharniaBlock.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; + +import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock; + +public class CharniaBlock extends EndUnderwaterPlantBlock { + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return canSupportCenter(world, pos.below(), Direction.UP) && world.getFluidState(pos).getType() == Fluids.WATER; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/ChorusGrassBlock.java b/src/main/java/org/betterx/betterend/blocks/ChorusGrassBlock.java new file mode 100644 index 00000000..8bede08e --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/ChorusGrassBlock.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class ChorusGrassBlock extends EndPlantBlock { + public ChorusGrassBlock() { + super(true); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.getBlock() == EndBlocks.CHORUS_NYLIUM; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/DenseEmeraldIceBlock.java b/src/main/java/org/betterx/betterend/blocks/DenseEmeraldIceBlock.java new file mode 100644 index 00000000..97c67ce1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/DenseEmeraldIceBlock.java @@ -0,0 +1,39 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; + +import java.util.Collections; +import java.util.List; + +public class DenseEmeraldIceBlock extends BaseBlock implements RenderLayerProvider { + public DenseEmeraldIceBlock() { + super(FabricBlockSettings.copyOf(Blocks.PACKED_ICE)); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); + if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { + return Collections.singletonList(new ItemStack(this)); + } else { + return Collections.emptyList(); + } + } +} diff --git a/src/main/java/ru/betterend/blocks/DenseSnowBlock.java b/src/main/java/org/betterx/betterend/blocks/DenseSnowBlock.java similarity index 52% rename from src/main/java/ru/betterend/blocks/DenseSnowBlock.java rename to src/main/java/org/betterx/betterend/blocks/DenseSnowBlock.java index 1371de16..54f78cc1 100644 --- a/src/main/java/ru/betterend/blocks/DenseSnowBlock.java +++ b/src/main/java/org/betterx/betterend/blocks/DenseSnowBlock.java @@ -1,12 +1,14 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; - -public class DenseSnowBlock extends BaseBlock { - public DenseSnowBlock() { - super(FabricBlockSettings.of(Material.SNOW).strength(0.2F).sound(SoundType.SNOW)); - } -} +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; + +public class DenseSnowBlock extends BaseBlock { + public DenseSnowBlock() { + super(FabricBlockSettings.of(Material.SNOW).strength(0.2F).sound(SoundType.SNOW)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/DragonTreeSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/DragonTreeSaplingBlock.java new file mode 100644 index 00000000..20f59b0b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/DragonTreeSaplingBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class DragonTreeSaplingBlock extends PottableFeatureSapling { + public DragonTreeSaplingBlock() { + super((state) -> EndFeatures.DRAGON_TREE.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.SHADOW_GRASS); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.SHADOW_GRASS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EmeraldIceBlock.java b/src/main/java/org/betterx/betterend/blocks/EmeraldIceBlock.java new file mode 100644 index 00000000..7b39c9c8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EmeraldIceBlock.java @@ -0,0 +1,100 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.HalfTransparentBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.BlockModelProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; + +import java.util.Collections; +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class EmeraldIceBlock extends HalfTransparentBlock implements RenderLayerProvider, BlockModelProvider { + public EmeraldIceBlock() { + super(FabricBlockSettings.copyOf(Blocks.ICE)); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + public void playerDestroy(Level world, + Player player, + BlockPos pos, + BlockState state, + @Nullable BlockEntity blockEntity, + ItemStack stack) { + super.playerDestroy(world, player, pos, state, blockEntity, stack); + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { + if (world.dimensionType().ultraWarm()) { + world.removeBlock(pos, false); + return; + } + + Material material = world.getBlockState(pos.below()).getMaterial(); + if (material.blocksMotion() || material.isLiquid()) { + world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState()); + } + } + + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (world.getBrightness(LightLayer.BLOCK, pos) > 11 - state.getLightBlock(world, pos)) { + this.melt(state, world, pos); + } + + } + + protected void melt(BlockState state, Level world, BlockPos pos) { + if (world.dimensionType().ultraWarm()) { + world.removeBlock(pos, false); + } else { + world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState()); + world.neighborChanged(pos, Blocks.WATER, pos); + } + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); + if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { + return Collections.singletonList(new ItemStack(this)); + } else { + return Collections.emptyList(); + } + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + return getBlockModel(resourceLocation, defaultBlockState()); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndBlockProperties.java b/src/main/java/org/betterx/betterend/blocks/EndBlockProperties.java new file mode 100644 index 00000000..12e6eeeb --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndBlockProperties.java @@ -0,0 +1,131 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.IntegerProperty; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.betterend.registry.EndPortals; + +public class EndBlockProperties extends BlockProperties { + public static final EnumProperty HYDRALUX_SHAPE = EnumProperty.create("shape", HydraluxShape.class); + public static final EnumProperty PEDESTAL_STATE = EnumProperty.create("state", PedestalState.class); + public static final EnumProperty CACTUS_BOTTOM = EnumProperty.create("bottom", CactusBottom.class); + + public static final IntegerProperty PORTAL = IntegerProperty.create("portal", 0, EndPortals.getCount()); + public static final IntegerProperty PLANT_ID = IntegerProperty.create("plant_id", 0, 63); + public static final IntegerProperty SOIL_ID = IntegerProperty.create("soil_id", 0, 16); + public static final IntegerProperty POT_LIGHT = IntegerProperty.create("pot_light", 0, 3); + public static final BooleanProperty HAS_ITEM = BooleanProperty.create("has_item"); + + public enum PedestalState implements StringRepresentable { + PEDESTAL_TOP("pedestal_top"), + COLUMN_TOP("column_top"), + BOTTOM("bottom"), + PILLAR("pillar"), + COLUMN("column"), + DEFAULT("default"); + + private final String name; + + PedestalState(String name) { + this.name = name; + } + + @Override + public String getSerializedName() { + return this.name; + } + + @Override + public String toString() { + return this.name; + } + } + + public enum HydraluxShape implements StringRepresentable { + FLOWER_BIG_BOTTOM("flower_big_bottom", true), + FLOWER_BIG_TOP("flower_big_top", true), + FLOWER_SMALL_BOTTOM("flower_small_bottom", true), + FLOWER_SMALL_TOP("flower_small_top", true), + VINE("vine", false), + ROOTS("roots", false); + + private final String name; + private final boolean glow; + + HydraluxShape(String name, boolean glow) { + this.name = name; + this.glow = glow; + } + + @Override + public String getSerializedName() { + return name; + } + + @Override + public String toString() { + return name; + } + + public boolean hasGlow() { + return glow; + } + } + + public enum LumecornShape implements StringRepresentable { + LIGHT_TOP("light_top", 15), + LIGHT_TOP_MIDDLE("light_top_middle", 15), + LIGHT_MIDDLE("light_middle", 15), + LIGHT_BOTTOM("light_bottom", 15), + MIDDLE("middle", 0), + BOTTOM_BIG("bottom_big", 0), + BOTTOM_SMALL("bottom_small", 0); + + private final String name; + private final int light; + + LumecornShape(String name, int light) { + this.name = name; + this.light = light; + } + + @Override + public String getSerializedName() { + return name; + } + + @Override + public String toString() { + return name; + } + + public int getLight() { + return light; + } + } + + public enum CactusBottom implements StringRepresentable { + EMPTY("empty"), + SAND("sand"), + MOSS("moss"); + + private final String name; + + CactusBottom(String name) { + this.name = name; + } + + @Override + public String getSerializedName() { + return name; + } + + @Override + public String toString() { + return name; + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLilyBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLilyBlock.java new file mode 100644 index 00000000..29b89ab2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLilyBlock.java @@ -0,0 +1,126 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.Collections; +import java.util.List; + +public class EndLilyBlock extends EndUnderwaterPlantBlock implements AddMineableShears { + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 16, 12); + private static final VoxelShape SHAPE_TOP = Block.box(2, 0, 2, 14, 6, 14); + + public EndLilyBlock() { + super(FabricBlockSettings.of(Material.WATER_PLANT) + .sound(SoundType.WET_GRASS) + .lightLevel((state) -> state.getValue(SHAPE) == TripleShape.TOP ? 13 : 0) + .noCollission()); + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return state.getValue(SHAPE) == TripleShape.TOP + ? Blocks.AIR.defaultBlockState() + : Blocks.WATER.defaultBlockState(); + } else { + return state; + } + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + Vec3 vec3d = state.getOffset(view, pos); + VoxelShape shape = state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM; + return shape.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(SHAPE) == TripleShape.TOP ? Fluids.EMPTY.defaultFluidState() : Fluids.WATER.getSource( + false); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + if (state.getValue(SHAPE) == TripleShape.TOP) { + return world.getBlockState(pos.below()).getBlock() == this; + } else if (state.getValue(SHAPE) == TripleShape.BOTTOM) { + return isTerrain(world.getBlockState(pos.below())); + } else { + BlockState up = world.getBlockState(pos.above()); + BlockState down = world.getBlockState(pos.below()); + return up.getBlock() == this && down.getBlock() == this; + } + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.getValue(SHAPE) == TripleShape.TOP) { + return Lists.newArrayList( + new ItemStack(EndItems.END_LILY_LEAF, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)), + new ItemStack(EndBlocks.END_LILY_SEED, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)) + ); + } + return Collections.emptyList(); + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + return new ItemStack(EndBlocks.END_LILY_SEED); + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLilySeedBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLilySeedBlock.java new file mode 100644 index 00000000..58489ad0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLilySeedBlock.java @@ -0,0 +1,53 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLilySeedBlock extends UnderwaterPlantWithAgeBlock { + @Override + public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { + if (canGrow(world, pos)) { + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.BOTTOM) + ); + BlockPos up = pos.above(); + while (world.getFluidState(up).isSource()) { + BlocksHelper.setWithoutUpdate( + world, + up, + EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.MIDDLE) + ); + up = up.above(); + } + BlocksHelper.setWithoutUpdate( + world, + up, + EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.TOP) + ); + } + } + + private boolean canGrow(WorldGenLevel world, BlockPos pos) { + BlockPos up = pos.above(); + while (world.getBlockState(up).getFluidState().getType().equals(Fluids.WATER.getSource())) { + up = up.above(); + } + return world.isEmptyBlock(up); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLotusFlowerBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLotusFlowerBlock.java new file mode 100644 index 00000000..1d7ce39f --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLotusFlowerBlock.java @@ -0,0 +1,65 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class EndLotusFlowerBlock extends EndPlantBlock { + private static final VoxelShape SHAPE_OUTLINE = Block.box(2, 0, 2, 14, 14, 14); + private static final VoxelShape SHAPE_COLLISION = Block.box(0, 0, 0, 16, 2, 16); + + public EndLotusFlowerBlock() { + //TODO: 1.19 Test if we can remove dynamic shape and offsetType + super(FabricBlockSettings.of(Material.PLANT) + .luminance(15) + .noOcclusion() + .dynamicShape() + .offsetType(BlockBehaviour.OffsetType.NONE)); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_LOTUS_STEM); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE_OUTLINE; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE_COLLISION; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + int count = MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE); + return Lists.newArrayList(new ItemStack(EndBlocks.END_LOTUS_SEED, count)); + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + return new ItemStack(EndBlocks.END_LOTUS_SEED); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLotusLeafBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLotusLeafBlock.java new file mode 100644 index 00000000..f47269d9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLotusLeafBlock.java @@ -0,0 +1,82 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +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.EnumProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.WaterFluid; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLotusLeafBlock extends BaseBlockNotFull implements RenderLayerProvider { + public static final EnumProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + private static final VoxelShape VSHAPE = Block.box(0, 0, 0, 16, 1, 16); + + public EndLotusLeafBlock() { + super(FabricBlockSettings.of(Material.PLANT).noOcclusion().sound(SoundType.WET_GRASS)); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState down = world.getBlockState(pos.below()); + return !down.getFluidState().isEmpty() && down.getFluidState().getType() instanceof WaterFluid; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(SHAPE, HORIZONTAL_FACING); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return VSHAPE; + } + + @Override + @SuppressWarnings("deprecation") + public BlockState rotate(BlockState state, Rotation rotation) { + return BlocksHelper.rotateHorizontal(state, rotation, HORIZONTAL_FACING); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirror) { + return BlocksHelper.mirrorHorizontal(state, mirror, HORIZONTAL_FACING); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + return new ItemStack(EndBlocks.END_LOTUS_SEED); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLotusSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLotusSeedBlock.java new file mode 100644 index 00000000..fbe13a77 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLotusSeedBlock.java @@ -0,0 +1,138 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLotusSeedBlock extends UnderwaterPlantWithAgeBlock { + @Override + public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { + if (canGrow(world, pos)) { + BlockState startLeaf = EndBlocks.END_LOTUS_STEM.defaultBlockState().setValue(EndLotusStemBlock.LEAF, true); + BlockState roots = EndBlocks.END_LOTUS_STEM.defaultBlockState() + .setValue(EndLotusStemBlock.SHAPE, TripleShape.BOTTOM) + .setValue(EndLotusStemBlock.WATERLOGGED, true); + BlockState stem = EndBlocks.END_LOTUS_STEM.defaultBlockState(); + BlockState flower = EndBlocks.END_LOTUS_FLOWER.defaultBlockState(); + + BlocksHelper.setWithoutUpdate(world, pos, roots); + MutableBlockPos bpos = new MutableBlockPos().set(pos); + bpos.setY(bpos.getY() + 1); + while (world.getFluidState(bpos).isSource()) { + BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.WATERLOGGED, true)); + bpos.setY(bpos.getY() + 1); + } + + int height = random.nextBoolean() ? 0 : random.nextBoolean() ? 1 : random.nextBoolean() ? 1 : -1; + TripleShape shape = (height == 0) ? TripleShape.TOP : TripleShape.MIDDLE; + Direction dir = BlocksHelper.randomHorizontal(random); + BlockPos leafCenter = bpos.immutable().relative(dir); + if (hasLeaf(world, leafCenter)) { + generateLeaf(world, leafCenter); + BlocksHelper.setWithoutUpdate( + world, + bpos, + startLeaf.setValue(EndLotusStemBlock.SHAPE, shape).setValue(EndLotusStemBlock.FACING, dir) + ); + } else { + BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, shape)); + } + + bpos.setY(bpos.getY() + 1); + for (int i = 1; i <= height; i++) { + if (!world.isEmptyBlock(bpos)) { + bpos.setY(bpos.getY() - 1); + BlocksHelper.setWithoutUpdate(world, bpos, flower); + bpos.setY(bpos.getY() - 1); + stem = world.getBlockState(bpos); + BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP)); + return; + } + BlocksHelper.setWithoutUpdate(world, bpos, stem); + bpos.setY(bpos.getY() + 1); + } + + if (!world.isEmptyBlock(bpos) || height < 0) { + bpos.setY(bpos.getY() - 1); + } + + BlocksHelper.setWithoutUpdate(world, bpos, flower); + bpos.setY(bpos.getY() - 1); + stem = world.getBlockState(bpos); + if (!stem.is(EndBlocks.END_LOTUS_STEM)) { + stem = EndBlocks.END_LOTUS_STEM.defaultBlockState(); + if (!world.getBlockState(bpos.north()).getFluidState().isEmpty()) { + stem = stem.setValue(EndLotusStemBlock.WATERLOGGED, true); + } + } + + if (world.getBlockState(bpos.relative(dir)).is(EndBlocks.END_LOTUS_LEAF)) { + stem = stem.setValue(EndLotusStemBlock.LEAF, true).setValue(EndLotusStemBlock.FACING, dir); + } + + BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP)); + } + } + + private boolean canGrow(WorldGenLevel world, BlockPos pos) { + MutableBlockPos bpos = new MutableBlockPos(); + bpos.set(pos); + while (world.getBlockState(bpos).getFluidState().getType().equals(Fluids.WATER.getSource())) { + bpos.setY(bpos.getY() + 1); + } + return world.isEmptyBlock(bpos) && world.isEmptyBlock(bpos.above()); + } + + private void generateLeaf(WorldGenLevel world, BlockPos pos) { + MutableBlockPos p = new MutableBlockPos(); + BlockState leaf = EndBlocks.END_LOTUS_LEAF.defaultBlockState(); + BlocksHelper.setWithoutUpdate(world, pos, leaf.setValue(EndLotusLeafBlock.SHAPE, TripleShape.BOTTOM)); + for (Direction move : BlocksHelper.HORIZONTAL) { + BlocksHelper.setWithoutUpdate( + world, + p.set(pos).move(move), + leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, move) + .setValue(EndLotusLeafBlock.SHAPE, TripleShape.MIDDLE) + ); + } + for (int i = 0; i < 4; i++) { + Direction d1 = BlocksHelper.HORIZONTAL[i]; + Direction d2 = BlocksHelper.HORIZONTAL[(i + 1) & 3]; + BlocksHelper.setWithoutUpdate( + world, + p.set(pos).move(d1).move(d2), + leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, d1) + .setValue(EndLotusLeafBlock.SHAPE, TripleShape.TOP) + ); + } + } + + private boolean hasLeaf(WorldGenLevel world, BlockPos pos) { + MutableBlockPos p = new MutableBlockPos(); + p.setY(pos.getY()); + int count = 0; + for (int x = -1; x < 2; x++) { + p.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + p.setZ(pos.getZ() + z); + if (world.isEmptyBlock(p) && !world.getFluidState(p.below()).isEmpty()) count++; + } + } + return count == 9; + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndLotusStemBlock.java b/src/main/java/org/betterx/betterend/blocks/EndLotusStemBlock.java new file mode 100644 index 00000000..c33c4bae --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndLotusStemBlock.java @@ -0,0 +1,109 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; + +import java.util.Map; + +public class EndLotusStemBlock extends BaseBlock implements SimpleWaterloggedBlock, RenderLayerProvider { + public static final EnumProperty FACING = BlockStateProperties.FACING; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final BooleanProperty LEAF = BooleanProperty.create("leaf"); + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + private static final Map SHAPES = Maps.newEnumMap(Axis.class); + + public EndLotusStemBlock() { + super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS)); + this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) + .setValue(SHAPE, TripleShape.MIDDLE) + .setValue(LEAF, false) + .setValue(FACING, Direction.UP)); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(LEAF) ? SHAPES.get(Axis.Y) : SHAPES.get(state.getValue(FACING).getAxis()); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(FACING, WATERLOGGED, SHAPE, LEAF); + } + + @Override + @SuppressWarnings("deprecation") + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + LevelAccessor worldAccess = ctx.getLevel(); + BlockPos blockPos = ctx.getClickedPos(); + return this.defaultBlockState() + .setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER) + .setValue(FACING, ctx.getClickedFace()); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState rotate(BlockState state, Rotation rotation) { + return BlocksHelper.rotateHorizontal(state, rotation, FACING); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirror) { + return BlocksHelper.mirrorHorizontal(state, mirror, FACING); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + if (state.getValue(WATERLOGGED)) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + return state; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + static { + SHAPES.put(Axis.X, Block.box(0, 6, 6, 16, 10, 10)); + SHAPES.put(Axis.Y, Block.box(6, 0, 6, 10, 16, 10)); + SHAPES.put(Axis.Z, Block.box(6, 6, 0, 10, 10, 16)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndPedestal.java b/src/main/java/org/betterx/betterend/blocks/EndPedestal.java new file mode 100644 index 00000000..cfe90af4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndPedestal.java @@ -0,0 +1,31 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; + +import com.google.common.collect.Maps; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.basis.PedestalBlock; + +import java.util.Map; + +public class EndPedestal extends PedestalBlock { + + public EndPedestal(Block parent) { + super(parent); + } + + @Override + protected Map createTexturesMap() { + ResourceLocation blockId = Registry.BLOCK.getKey(parent); + String name = blockId.getPath(); + Map textures = Maps.newHashMap(); + textures.put("%mod%", BetterEnd.MOD_ID); + textures.put("%top%", name + "_polished"); + textures.put("%base%", name + "_polished"); + textures.put("%pillar%", name + "_pillar_side"); + textures.put("%bottom%", name + "_polished"); + return textures; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndPortalBlock.java b/src/main/java/org/betterx/betterend/blocks/EndPortalBlock.java new file mode 100644 index 00000000..42414fdd --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndPortalBlock.java @@ -0,0 +1,218 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.NetherPortalBlock; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.dimension.DimensionType; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.betterend.interfaces.TeleportingEntity; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndPortals; +import org.betterx.betterend.rituals.EternalRitual; + +import java.util.Objects; +import java.util.Optional; + +public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProvider, CustomColorProvider { + public static final IntegerProperty PORTAL = EndBlockProperties.PORTAL; + + public EndPortalBlock() { + super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL) + .resistance(Blocks.BEDROCK.getExplosionResistance()) + .luminance(15)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(PORTAL); + } + + @Override + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + if (random.nextInt(100) == 0) { + world.playLocalSound( + pos.getX() + 0.5D, + pos.getY() + 0.5D, + pos.getZ() + 0.5D, + SoundEvents.PORTAL_AMBIENT, + SoundSource.BLOCKS, + 0.5F, + random.nextFloat() * 0.4F + 0.8F, + false + ); + } + + double x = pos.getX() + random.nextDouble(); + double y = pos.getY() + random.nextDouble(); + double z = pos.getZ() + random.nextDouble(); + int k = random.nextInt(2) * 2 - 1; + if (!world.getBlockState(pos.west()).is(this) && !world.getBlockState(pos.east()).is(this)) { + x = pos.getX() + 0.5D + 0.25D * k; + } else { + z = pos.getZ() + 0.5D + 0.25D * k; + } + + world.addParticle(EndParticles.PORTAL_SPHERE, x, y, z, 0, 0, 0); + } + + @Override + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + } + + @Override + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + return state; + } + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (world.isClientSide || !validate(entity)) return; + entity.setPortalCooldown(); + ServerLevel currentWorld = (ServerLevel) world; + MinecraftServer server = currentWorld.getServer(); + ServerLevel targetWorld = EndPortals.getWorld(server, state.getValue(PORTAL)); + boolean isInEnd = currentWorld.dimension().equals(Level.END); + ServerLevel destination = isInEnd ? targetWorld : server.getLevel(Level.END); + BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity); + if (exitPos == null) return; + if (entity instanceof ServerPlayer && ((ServerPlayer) entity).isCreative()) { + ((ServerPlayer) entity).teleportTo( + destination, + exitPos.getX() + 0.5, + exitPos.getY(), + exitPos.getZ() + 0.5, + entity.getYRot(), + entity.getXRot() + ); + } else { + ((TeleportingEntity) entity).be_setExitPos(exitPos); + Optional teleported = Optional.ofNullable(entity.changeDimension(destination)); + teleported.ifPresent(Entity::setPortalCooldown); + } + } + + private boolean validate(Entity entity) { + return !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && !entity.isOnPortalCooldown(); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + private BlockPos findExitPos(ServerLevel currentWorld, + ServerLevel targetWorld, + BlockPos currentPos, + Entity entity) { + if (targetWorld == null) return null; + Registry registry = targetWorld.registryAccess() + .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + ResourceLocation targetWorldId = targetWorld.dimension().location(); + ResourceLocation currentWorldId = currentWorld.dimension().location(); + double targetMultiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale(); + double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).coordinateScale(); + double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier; + MutableBlockPos basePos = currentPos.mutable() + .set(currentPos.getX() * multiplier, + currentPos.getY(), + currentPos.getZ() * multiplier + ); + MutableBlockPos checkPos = basePos.mutable(); + BlockState currentState = currentWorld.getBlockState(currentPos); + int radius = (EternalRitual.SEARCH_RADIUS >> 4) + 1; + checkPos = EternalRitual.findBlockPos( + targetWorld, + checkPos, + radius, + this, + state -> state.is(this) && state.getValue(PORTAL).equals(currentState.getValue(PORTAL)) + ); + if (checkPos != null) { + BlockState checkState = targetWorld.getBlockState(checkPos); + Axis axis = checkState.getValue(AXIS); + checkPos = findCenter(targetWorld, checkPos, axis); + Direction frontDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE).getClockWise(); + Direction entityDir = entity.getMotionDirection(); + if (entityDir.getAxis().isVertical()) { + entityDir = frontDir; + } + if (frontDir != entityDir && frontDir.getOpposite() != entityDir) { + entity.rotate(Rotation.CLOCKWISE_90); + entityDir = entityDir.getClockWise(); + } + return checkPos.relative(entityDir); + } + return null; + } + + private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis) { + return findCenter(world, pos, axis, 1); + } + + private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis, int step) { + if (step > 8) return pos; + BlockState right, left; + Direction rightDir, leftDir; + rightDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); + leftDir = rightDir.getOpposite(); + right = world.getBlockState(pos.relative(rightDir)); + left = world.getBlockState(pos.relative(leftDir)); + BlockState down = world.getBlockState(pos.below()); + if (down.is(this)) { + return findCenter(world, pos.move(Direction.DOWN), axis, step); + } else if (right.is(this) && left.is(this)) { + return pos; + } else if (right.is(this)) { + return findCenter(world, pos.move(rightDir), axis, ++step); + } else if (left.is(this)) { + return findCenter(world, pos.move(leftDir), axis, ++step); + } + return pos; + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> EndPortals.getColor(state.getValue(PORTAL)); + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> EndPortals.getColor(0); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndStoneSmelter.java b/src/main/java/org/betterx/betterend/blocks/EndStoneSmelter.java new file mode 100644 index 00000000..9f16fb20 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndStoneSmelter.java @@ -0,0 +1,182 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.*; +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.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.BlockHitResult; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BaseBlockWithEntity; +import org.betterx.betterend.blocks.entities.EndStoneSmelterBlockEntity; +import org.betterx.betterend.registry.EndBlockEntities; + +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class EndStoneSmelter extends BaseBlockWithEntity { + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final BooleanProperty LIT = BlockStateProperties.LIT; + public static final String ID = "end_stone_smelter"; + + public EndStoneSmelter() { + super(FabricBlockSettings.of(Material.STONE, MaterialColor.COLOR_GRAY) + .luminance(state -> state.getValue(LIT) ? 15 : 0) + .hardness(4F) + .resistance(100F) + .requiresCorrectToolForDrops() + .sound(SoundType.STONE)); + registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(LIT, false)); + } + + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level world, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (world.isClientSide) { + return InteractionResult.SUCCESS; + } else { + this.openScreen(world, pos, player); + return InteractionResult.CONSUME; + } + } + + private void openScreen(Level world, BlockPos pos, Player player) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof EndStoneSmelterBlockEntity) { + player.openMenu((EndStoneSmelterBlockEntity) blockEntity); + } + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite()); + } + + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return new EndStoneSmelterBlockEntity(blockPos, blockState); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + List drop = Lists.newArrayList(new ItemStack(this)); + BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); + if (blockEntity instanceof EndStoneSmelterBlockEntity) { + EndStoneSmelterBlockEntity smelterBlockEntity = (EndStoneSmelterBlockEntity) blockEntity; + for (int i = 0; i < smelterBlockEntity.getContainerSize(); i++) { + ItemStack item = smelterBlockEntity.getItem(i); + if (!item.isEmpty()) { + drop.add(item); + } + } + } + return drop; + } + + @Override + @SuppressWarnings("deprecation") + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } + + @Override + @SuppressWarnings("deprecation") + public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { + //TODO + return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(world.getBlockEntity(pos)); + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + @SuppressWarnings("deprecation") + public BlockState rotate(BlockState state, Rotation rotation) { + return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirror) { + return state.rotate(mirror.getRotation(state.getValue(FACING))); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(FACING, LIT); + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + if (state.getValue(LIT)) { + double x = pos.getX() + 0.5D; + double y = pos.getY(); + double z = pos.getZ() + 0.5D; + if (random.nextDouble() < 0.1D) { + world.playLocalSound( + x, + y, + z, + SoundEvents.BLASTFURNACE_FIRE_CRACKLE, + SoundSource.BLOCKS, + 1.0F, + 1.0F, + false + ); + } + + Direction direction = state.getValue(FACING); + Direction.Axis axis = direction.getAxis(); + double defOffset = random.nextDouble() * 0.6D - 0.3D; + double offX = axis == Direction.Axis.X ? direction.getStepX() * 0.52D : defOffset; + double offY = random.nextDouble() * 9.0D / 16.0D; + double offZ = axis == Direction.Axis.Z ? direction.getStepZ() * 0.52D : defOffset; + world.addParticle(ParticleTypes.SMOKE, x + offX, y + offY, z + offZ, 0.0D, 0.0D, 0.0D); + } + } + + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, + BlockState blockState, + BlockEntityType blockEntityType) { + return level.isClientSide() ? null : createTickerHelper( + blockEntityType, + EndBlockEntities.END_STONE_SMELTER, + EndStoneSmelterBlockEntity::tick + ); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EnderBlock.java b/src/main/java/org/betterx/betterend/blocks/EnderBlock.java new file mode 100644 index 00000000..7424e18d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EnderBlock.java @@ -0,0 +1,30 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; + +public class EnderBlock extends BaseBlock { + + public EnderBlock() { + super(FabricBlockSettings.of(Material.STONE, MaterialColor.WARPED_WART_BLOCK) + .hardness(5F) + .resistance(6F) + .requiresCorrectToolForDrops() + .sound(SoundType.STONE)); + } + + @Environment(EnvType.CLIENT) + public int getColor(BlockState state, BlockGetter world, BlockPos pos) { + return 0xFF005548; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EndstoneDustBlock.java b/src/main/java/org/betterx/betterend/blocks/EndstoneDustBlock.java new file mode 100644 index 00000000..ae00c8c4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EndstoneDustBlock.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.FallingBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.interfaces.TagProvider; +import org.betterx.bclib.interfaces.tools.AddMineableShovel; +import org.betterx.bclib.util.ColorUtil; + +import java.util.Collections; +import java.util.List; + +public class EndstoneDustBlock extends FallingBlock implements TagProvider, AddMineableShovel { + @Environment(EnvType.CLIENT) + private static final int COLOR = ColorUtil.color(226, 239, 168); + + public EndstoneDustBlock() { + super(FabricBlockSettings + .copyOf(Blocks.SAND) + .mapColor(Blocks.END_STONE.defaultMaterialColor()) + ); + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState state, LootContext.Builder builder) { + return Collections.singletonList(new ItemStack(this)); + } + + @Environment(EnvType.CLIENT) + public int getDustColor(BlockState state, BlockGetter world, BlockPos pos) { + return COLOR; + } + + @Override + public void addTags(List> blockTags, List> itemTags) { + blockTags.add(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/EternalPedestal.java b/src/main/java/org/betterx/betterend/blocks/EternalPedestal.java new file mode 100644 index 00000000..e0c1dbcc --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/EternalPedestal.java @@ -0,0 +1,142 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import com.google.common.collect.Lists; +import org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.blocks.entities.EternalPedestalEntity; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndPortals; +import org.betterx.betterend.rituals.EternalRitual; + +import java.util.List; + +public class EternalPedestal extends PedestalBlock { + public static final BooleanProperty ACTIVATED = EndBlockProperties.ACTIVE; + + public EternalPedestal() { + super(EndBlocks.FLAVOLITE_RUNED_ETERNAL); + this.registerDefaultState(defaultBlockState().setValue(ACTIVATED, false)); + } + + @Override + public void checkRitual(Level world, BlockPos pos) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof EternalPedestalEntity) { + EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity; + BlockState updatedState = world.getBlockState(pos); + if (pedestal.isEmpty()) { + if (pedestal.hasRitual()) { + EternalRitual ritual = pedestal.getRitual(); + if (ritual.isActive()) { + ResourceLocation targetWorld = ritual.getTargetWorldId(); + int portalId; + if (targetWorld != null) { + portalId = EndPortals.getPortalIdByWorld(targetWorld); + } else { + portalId = EndPortals.getPortalIdByWorld(EndPortals.OVERWORLD_ID); + } + ritual.disablePortal(portalId); + } + } + world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, false).setValue(HAS_LIGHT, false)); + } else { + ItemStack itemStack = pedestal.getItem(0); + ResourceLocation id = Registry.ITEM.getKey(itemStack.getItem()); + if (EndPortals.isAvailableItem(id)) { + world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, true).setValue(HAS_LIGHT, true)); + if (pedestal.hasRitual()) { + pedestal.getRitual().checkStructure(); + } else { + EternalRitual ritual = new EternalRitual(world, pos); + ritual.checkStructure(); + } + } + } + } + } + + @Override + @Deprecated + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + BlockState updated = super.updateShape(state, direction, newState, world, pos, posFrom); + if (!updated.is(this)) return updated; + if (!this.isPlaceable(updated)) { + return updated.setValue(ACTIVATED, false); + } + return updated; + } + + @Override + @Deprecated + public float getDestroyProgress(BlockState state, Player player, BlockGetter world, BlockPos pos) { + return 0.0F; + } + + @Override + public float getExplosionResistance() { + return Blocks.BEDROCK.getExplosionResistance(); + } + + @Override + public boolean dropFromExplosion(Explosion explosion) { + return false; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.is(this)) { + EndBlockProperties.PedestalState currentState = state.getValue(EndBlockProperties.PEDESTAL_STATE); + if (currentState.equals(EndBlockProperties.PedestalState.BOTTOM) || currentState.equals(EndBlockProperties.PedestalState.PILLAR)) { + return Lists.newArrayList(); + } + } + List drop = Lists.newArrayList(); + BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); + if (blockEntity instanceof EternalPedestalEntity) { + EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity; + if (!pedestal.isEmpty()) { + drop.add(pedestal.getItem(0)); + } + } + return drop; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + super.createBlockStateDefinition(stateManager); + stateManager.add(ACTIVATED); + } + + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return new EternalPedestalEntity(blockPos, blockState); + } + + @Override + public boolean hasUniqueEntity() { + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FilaluxBlock.java b/src/main/java/org/betterx/betterend/blocks/FilaluxBlock.java new file mode 100644 index 00000000..b69ff330 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FilaluxBlock.java @@ -0,0 +1,11 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.state.BlockBehaviour; + +import org.betterx.bclib.blocks.BaseVineBlock; + +public class FilaluxBlock extends BaseVineBlock { + public FilaluxBlock() { + super(15, true, p -> p.offsetType(BlockBehaviour.OffsetType.NONE)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FilaluxLanternBlock.java b/src/main/java/org/betterx/betterend/blocks/FilaluxLanternBlock.java new file mode 100644 index 00000000..ff329381 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FilaluxLanternBlock.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; + +public class FilaluxLanternBlock extends BaseBlock implements AddMineableAxe { + public FilaluxLanternBlock() { + super(FabricBlockSettings.of(Material.WOOD) + .luminance(15) + .sound(SoundType.WOOD)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FilaluxWingsBlock.java b/src/main/java/org/betterx/betterend/blocks/FilaluxWingsBlock.java new file mode 100644 index 00000000..fdf715f1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FilaluxWingsBlock.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineableShears; + +import java.util.EnumMap; + +public class FilaluxWingsBlock extends BaseAttachedBlock implements RenderLayerProvider, AddMineableShears { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + + public FilaluxWingsBlock() { + super(FabricBlockSettings.of(Material.PLANT) + .sound(SoundType.WET_GRASS) + .noCollission()); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.0, 0.0, 0.0, 1.0, 0.5, 1.0)); + BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.0, 0.5, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FlamaeaBlock.java b/src/main/java/org/betterx/betterend/blocks/FlamaeaBlock.java new file mode 100644 index 00000000..ab1064e7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FlamaeaBlock.java @@ -0,0 +1,64 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.PlaceOnWaterBlockItem; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.interfaces.CustomItemProvider; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.betterend.blocks.basis.EndPlantBlock; + +import java.util.List; + +public class FlamaeaBlock extends EndPlantBlock implements CustomItemProvider, AddMineableShears { + private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 1, 16); + + public FlamaeaBlock() { + //TODO: 1.19 Test if we can remove dynamic shape and offsetType + super(FabricBlockSettings.of(Material.PLANT) + .sound(SoundType.WET_GRASS) + .dynamicShape() + .offsetType(BlockBehaviour.OffsetType.NONE)); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(Blocks.WATER); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return Lists.newArrayList(new ItemStack(this)); + } + + @Override + public boolean canBePotted() { + return false; + } + + @Override + public BlockItem getCustomItem(ResourceLocation resourceLocation, FabricItemSettings fabricItemSettings) { + return new PlaceOnWaterBlockItem(this, fabricItemSettings); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FlammalixBlock.java b/src/main/java/org/betterx/betterend/blocks/FlammalixBlock.java new file mode 100644 index 00000000..016930c5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FlammalixBlock.java @@ -0,0 +1,44 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class FlammalixBlock extends EndPlantBlock { + private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14); + + public FlammalixBlock() { + super(false, 12, p -> p.offsetType(OffsetType.NONE)); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.PALLIDIUM_FULL) || + state.is(EndBlocks.PALLIDIUM_HEAVY) || + state.is(EndBlocks.PALLIDIUM_THIN) || + state.is(EndBlocks.PALLIDIUM_TINY); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + return ModelsHelper.createItemModel(resourceLocation); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/FlowerPotBlock.java b/src/main/java/org/betterx/betterend/blocks/FlowerPotBlock.java new file mode 100644 index 00000000..33b64933 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/FlowerPotBlock.java @@ -0,0 +1,453 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SaplingBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.storage.loot.LootContext.Builder; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.fabricmc.loader.api.FabricLoader; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.math.Transformation; +import com.mojang.math.Vector3f; +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.client.models.BasePatterns; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.client.models.ModelsHelper.MultiPartBuilder; +import org.betterx.bclib.client.models.PatternsHelper; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.PostInitable; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.JsonFactory; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.basis.PottableLeavesBlock; +import org.betterx.betterend.client.models.Patterns; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.interfaces.PottablePlant; +import org.betterx.betterend.interfaces.PottableTerrain; +import org.betterx.betterend.registry.EndBlocks; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class FlowerPotBlock extends BaseBlockNotFull implements RenderLayerProvider, PostInitable { + private static final IntegerProperty PLANT_ID = EndBlockProperties.PLANT_ID; + private static final IntegerProperty SOIL_ID = EndBlockProperties.SOIL_ID; + private static final IntegerProperty POT_LIGHT = EndBlockProperties.POT_LIGHT; + private static final VoxelShape SHAPE_EMPTY; + private static final VoxelShape SHAPE_FULL; + private static Block[] plants; + private static Block[] soils; + + public FlowerPotBlock(Block source) { + super(FabricBlockSettings.copyOf(source).luminance(state -> state.getValue(POT_LIGHT) * 5)); + this.registerDefaultState( + this.defaultBlockState() + .setValue(PLANT_ID, 0) + .setValue(SOIL_ID, 0) + .setValue(POT_LIGHT, 0) + ); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(PLANT_ID, SOIL_ID, POT_LIGHT); + } + + @Override + public List getDrops(BlockState state, Builder builder) { + List drop = Lists.newArrayList(new ItemStack(this)); + int id = state.getValue(SOIL_ID) - 1; + if (id >= 0 && id < soils.length && soils[id] != null) { + drop.add(new ItemStack(soils[id])); + } + id = state.getValue(PLANT_ID) - 1; + if (id >= 0 && id < plants.length && plants[id] != null) { + drop.add(new ItemStack(plants[id])); + } + return drop; + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + int plantID = state.getValue(PLANT_ID); + if (plantID < 1 || plantID > plants.length || plants[plantID - 1] == null) { + return state.getValue(POT_LIGHT) > 0 ? state.setValue(POT_LIGHT, 0) : state; + } + int light = plants[plantID - 1].defaultBlockState().getLightEmission() / 5; + if (state.getValue(POT_LIGHT) != light) { + state = state.setValue(POT_LIGHT, light); + } + return state; + } + + @Override + public void postInit() { + if (FlowerPotBlock.plants != null) { + return; + } + + Block[] plants = new Block[128]; + Block[] soils = new Block[16]; + + Map reservedPlantsIDs = Maps.newHashMap(); + Map reservedSoilIDs = Maps.newHashMap(); + + JsonObject obj = JsonFactory.getJsonObject(new File( + FabricLoader.getInstance().getConfigDir().toFile(), + BetterEnd.MOD_ID + "/blocks.json" + )); + if (obj.get("flower_pots") != null) { + JsonElement plantsObj = obj.get("flower_pots").getAsJsonObject().get("plants"); + JsonElement soilsObj = obj.get("flower_pots").getAsJsonObject().get("soils"); + if (plantsObj != null) { + plantsObj.getAsJsonObject().entrySet().forEach(entry -> { + String name = entry.getKey().substring(0, entry.getKey().indexOf(' ')); + reservedPlantsIDs.put(name, entry.getValue().getAsInt()); + }); + } + if (soilsObj != null) { + soilsObj.getAsJsonObject().entrySet().forEach(entry -> { + String name = entry.getKey().substring(0, entry.getKey().indexOf(' ')); + reservedSoilIDs.put(name, entry.getValue().getAsInt()); + }); + } + } + + EndBlocks.getModBlocks().forEach(block -> { + if (block instanceof PottablePlant && ((PottablePlant) block).canBePotted()) { + processBlock(plants, block, "flower_pots.plants", reservedPlantsIDs); + } else if (block instanceof PottableTerrain && ((PottableTerrain) block).canBePotted()) { + processBlock(soils, block, "flower_pots.soils", reservedSoilIDs); + } + }); + Configs.BLOCK_CONFIG.saveChanges(); + + FlowerPotBlock.plants = new Block[maxNotNull(plants) + 1]; + System.arraycopy(plants, 0, FlowerPotBlock.plants, 0, FlowerPotBlock.plants.length); + + FlowerPotBlock.soils = new Block[maxNotNull(soils) + 1]; + System.arraycopy(soils, 0, FlowerPotBlock.soils, 0, FlowerPotBlock.soils.length); + + if (PLANT_ID.getValue(Integer.toString(FlowerPotBlock.plants.length)).isEmpty()) { + throw new RuntimeException("There are too much plant ID values!"); + } + if (SOIL_ID.getValue(Integer.toString(FlowerPotBlock.soils.length)).isEmpty()) { + throw new RuntimeException("There are too much soil ID values!"); + } + } + + private int maxNotNull(Block[] array) { + int max = 0; + for (int i = 0; i < array.length; i++) { + if (array[i] != null) { + max = i; + } + } + return max; + } + + private void processBlock(Block[] target, Block block, String path, Map idMap) { + ResourceLocation location = Registry.BLOCK.getKey(block); + if (idMap.containsKey(location.getPath())) { + target[idMap.get(location.getPath())] = block; + } else { + for (int i = 0; i < target.length; i++) { + if (!idMap.containsValue(i)) { + target[i] = block; + idMap.put(location.getPath(), i); + Configs.BLOCK_CONFIG.getInt(path, location.getPath(), i); + break; + } + } + } + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.CONSUME; + } + ItemStack itemStack = player.getItemInHand(hand); + int soilID = state.getValue(SOIL_ID); + if (soilID == 0 || soilID > soils.length || soils[soilID - 1] == null) { + if (!(itemStack.getItem() instanceof BlockItem)) { + return InteractionResult.PASS; + } + Block block = ((BlockItem) itemStack.getItem()).getBlock(); + for (int i = 0; i < soils.length; i++) { + if (block == soils[i]) { + BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, i + 1)); + if (!player.isCreative()) { + itemStack.shrink(1); + } + level.playSound( + player, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + SoundEvents.SOUL_SOIL_PLACE, + SoundSource.BLOCKS, + 1, + 1 + ); + return InteractionResult.SUCCESS; + } + } + return InteractionResult.PASS; + } + + int plantID = state.getValue(PLANT_ID); + if (itemStack.isEmpty()) { + if (plantID > 0 && plantID <= plants.length && plants[plantID - 1] != null) { + BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, 0).setValue(POT_LIGHT, 0)); + player.addItem(new ItemStack(plants[plantID - 1])); + return InteractionResult.SUCCESS; + } + if (soilID > 0 && soilID <= soils.length && soils[soilID - 1] != null) { + BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, 0)); + player.addItem(new ItemStack(soils[soilID - 1])); + } + return InteractionResult.PASS; + } + if (!(itemStack.getItem() instanceof BlockItem)) { + return InteractionResult.PASS; + } + BlockItem item = (BlockItem) itemStack.getItem(); + for (int i = 0; i < plants.length; i++) { + if (item.getBlock() == plants[i]) { + if (!((PottablePlant) plants[i]).canPlantOn(soils[soilID - 1])) { + return InteractionResult.PASS; + } + int light = plants[i].defaultBlockState().getLightEmission() / 5; + BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, i + 1).setValue(POT_LIGHT, light)); + level.playSound( + player, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + SoundEvents.HOE_TILL, + SoundSource.BLOCKS, + 1, + 1 + ); + if (!player.isCreative()) { + itemStack.shrink(1); + } + return InteractionResult.SUCCESS; + } + } + return InteractionResult.PASS; + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation blockId) { + Optional pattern = PatternsHelper.createJson(Patterns.BLOCK_FLOWER_POT, blockId); + return ModelsHelper.fromPattern(pattern); + } + + @Override + @Environment(EnvType.CLIENT) + public UnbakedModel getModelVariant(ResourceLocation stateId, + BlockState blockState, + Map modelCache) { + MultiPartBuilder model = MultiPartBuilder.create(stateDefinition); + model.part(new ModelResourceLocation(stateId.getNamespace(), stateId.getPath(), "inventory")).add(); + Transformation offset = new Transformation(new Vector3f(0, 7.5F / 16F, 0), null, null, null); + + for (int i = 0; i < plants.length; i++) { + if (plants[i] == null) { + continue; + } + + final int compareID = i + 1; + ResourceLocation modelPath = Registry.BLOCK.getKey(plants[i]); + ResourceLocation objSource = new ResourceLocation( + modelPath.getNamespace(), + "models/block/" + modelPath.getPath() + "_potted.json" + ); + + if (Minecraft.getInstance().getResourceManager().getResource(objSource).isPresent()) { + objSource = new ResourceLocation(modelPath.getNamespace(), "block/" + modelPath.getPath() + "_potted"); + model.part(objSource) + .setTransformation(offset) + .setCondition(state -> state.getValue(PLANT_ID) == compareID) + .add(); + continue; + } else if (plants[i] instanceof SaplingBlock) { + ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); + modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); + Map textures = Maps.newHashMap(); + textures.put("%modid%", loc.getNamespace()); + textures.put("%texture%", loc.getPath()); + Optional pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures); + UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); + modelCache.put(modelPath, unbakedModel); + model.part(modelPath) + .setTransformation(offset) + .setCondition(state -> state.getValue(PLANT_ID) == compareID) + .add(); + continue; + } else if (plants[i] instanceof PottableLeavesBlock) { + ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); + modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); + Map textures = Maps.newHashMap(); + textures.put("%leaves%", loc.getPath().contains("lucernia") ? loc.getPath() + "_1" : loc.getPath()); + textures.put("%stem%", loc.getPath().replace("_leaves", "_log_side")); + Optional pattern = Patterns.createJson(Patterns.BLOCK_POTTED_LEAVES, textures); + UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); + modelCache.put(modelPath, unbakedModel); + model.part(modelPath) + .setTransformation(offset) + .setCondition(state -> state.getValue(PLANT_ID) == compareID) + .add(); + continue; + } + + objSource = new ResourceLocation(modelPath.getNamespace(), "blockstates/" + modelPath.getPath() + ".json"); + JsonObject obj = JsonFactory.getJsonObject(objSource); + if (obj != null) { + JsonElement variants = obj.get("variants"); + JsonElement list = null; + String path = null; + + if (variants == null) { + continue; + } + + if (variants.isJsonArray()) { + list = variants.getAsJsonArray().get(0); + } else if (variants.isJsonObject()) { + list = variants.getAsJsonObject().get(((PottablePlant) plants[i]).getPottedState()); + } + + if (list == null) { + BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants"); + continue; + } + + if (list.isJsonArray()) { + path = list.getAsJsonArray().get(0).getAsJsonObject().get("model").getAsString(); + } else { + path = list.getAsJsonObject().get("model").getAsString(); + } + + if (path == null) { + BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants"); + continue; + } + + model.part(new ResourceLocation(path)) + .setTransformation(offset) + .setCondition(state -> state.getValue(PLANT_ID) == compareID) + .add(); + } else { + ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); + modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); + Map textures = Maps.newHashMap(); + textures.put("%modid%", loc.getNamespace()); + textures.put("%texture%", loc.getPath()); + Optional pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures); + UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); + modelCache.put(modelPath, unbakedModel); + model.part(modelPath) + .setTransformation(offset) + .setCondition(state -> state.getValue(PLANT_ID) == compareID) + .add(); + } + } + + for (int i = 0; i < soils.length; i++) { + if (soils[i] == null) { + continue; + } + + ResourceLocation soilLoc = BetterEnd.makeID("flower_pot_soil_" + i); + if (!modelCache.containsKey(soilLoc)) { + String texture = Registry.BLOCK.getKey(soils[i]).getPath() + "_top"; + if (texture.contains("rutiscus")) { + texture += "_1"; + } + Optional pattern = Patterns.createJson(Patterns.BLOCK_FLOWER_POT_SOIL, texture); + UnbakedModel soil = ModelsHelper.fromPattern(pattern); + modelCache.put(soilLoc, soil); + } + final int compareID = i + 1; + model.part(soilLoc).setCondition(state -> state.getValue(SOIL_ID) == compareID).add(); + } + + UnbakedModel result = model.build(); + modelCache.put(stateId, result); + return result; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + int id = state.getValue(PLANT_ID); + return id > 0 && id <= plants.length ? SHAPE_FULL : SHAPE_EMPTY; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE_EMPTY; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + static { + SHAPE_EMPTY = Shapes.or(Block.box(4, 1, 4, 12, 8, 12), Block.box(5, 0, 5, 11, 1, 11)); + SHAPE_FULL = Shapes.or(SHAPE_EMPTY, Block.box(3, 8, 3, 13, 16, 13)); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/blocks/GlowingHymenophoreBlock.java b/src/main/java/org/betterx/betterend/blocks/GlowingHymenophoreBlock.java new file mode 100644 index 00000000..2b672e22 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/GlowingHymenophoreBlock.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; + +public class GlowingHymenophoreBlock extends BaseBlock implements AddMineableAxe { + public GlowingHymenophoreBlock() { + super(FabricBlockSettings.of(Material.WOOD) + .luminance(15) + .sound(SoundType.WART_BLOCK)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/GlowingMossBlock.java b/src/main/java/org/betterx/betterend/blocks/GlowingMossBlock.java new file mode 100644 index 00000000..6f09ae66 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/GlowingMossBlock.java @@ -0,0 +1,32 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class GlowingMossBlock extends EndPlantBlock { + public GlowingMossBlock(int light) { + super(light); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.getBlock() == EndBlocks.END_MOSS || state.getBlock() == EndBlocks.END_MYCELIUM; + } + + @Environment(EnvType.CLIENT) + public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { + return true; + } + + @Environment(EnvType.CLIENT) + public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { + return 1F; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/blocks/GlowingPillarLuminophorBlock.java b/src/main/java/org/betterx/betterend/blocks/GlowingPillarLuminophorBlock.java new file mode 100644 index 00000000..705af9ed --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/GlowingPillarLuminophorBlock.java @@ -0,0 +1,59 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.betterend.registry.EndBlocks; + +public class GlowingPillarLuminophorBlock extends BaseBlock implements AddMineableShears { + public static final BooleanProperty NATURAL = EndBlockProperties.NATURAL; + + public GlowingPillarLuminophorBlock() { + super(FabricBlockSettings.of(Material.LEAVES) + .mapColor(MaterialColor.COLOR_ORANGE) + .strength(0.2F) + .luminance(15) + .sound(SoundType.GRASS)); + this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false)); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return !state.getValue(NATURAL) || world.getBlockState(pos.below()).is(EndBlocks.GLOWING_PILLAR_ROOTS); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { + return state; + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(NATURAL); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/GlowingPillarRootsBlock.java b/src/main/java/org/betterx/betterend/blocks/GlowingPillarRootsBlock.java new file mode 100644 index 00000000..2ae1f2b8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/GlowingPillarRootsBlock.java @@ -0,0 +1,37 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.blocks.UpDownPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class GlowingPillarRootsBlock extends UpDownPlantBlock { + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.AMBER_MOSS); + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + return new ItemStack(EndBlocks.GLOWING_PILLAR_SEED); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/GlowingPillarSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/GlowingPillarSeedBlock.java new file mode 100644 index 00000000..f88f51f7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/GlowingPillarSeedBlock.java @@ -0,0 +1,82 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class GlowingPillarSeedBlock extends EndPlantWithAgeBlock implements AddMineableShears { + + public GlowingPillarSeedBlock() { + super(FabricBlockSettings.of(Material.PLANT) + .sound(SoundType.GRASS) + .lightLevel(state -> state.getValue(AGE) * 3 + 3) + .randomTicks() + .noCollission() + .offsetType(OffsetType.NONE)); + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + int height = MHelper.randRange(1, 2, random); + int h = BlocksHelper.upRay(world, pos, height + 2); + if (h < height) { + return; + } + + MutableBlockPos mut = new MutableBlockPos().set(pos); + BlockState roots = EndBlocks.GLOWING_PILLAR_ROOTS.defaultBlockState(); + if (height < 2) { + BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE)); + } else { + BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM)); + mut.move(Direction.UP); + BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP)); + } + mut.move(Direction.UP); + BlocksHelper.setWithUpdate( + world, + mut, + EndBlocks.GLOWING_PILLAR_LUMINOPHOR.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true) + ); + for (Direction dir : BlocksHelper.DIRECTIONS) { + pos = mut.relative(dir); + if (world.isEmptyBlock(pos)) { + BlocksHelper.setWithUpdate( + world, + pos, + EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState().setValue(BlockStateProperties.FACING, dir) + ); + } + } + mut.move(Direction.UP); + if (world.isEmptyBlock(mut)) { + BlocksHelper.setWithUpdate( + world, + mut, + EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState() + .setValue(BlockStateProperties.FACING, Direction.UP) + ); + } + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.AMBER_MOSS); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HelixTreeLeavesBlock.java b/src/main/java/org/betterx/betterend/blocks/HelixTreeLeavesBlock.java new file mode 100644 index 00000000..d5f9a81b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HelixTreeLeavesBlock.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.NamedBlockTags; +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BaseLeavesBlock; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class HelixTreeLeavesBlock extends BaseBlock implements CustomColorProvider, AddMineableShears { + public static final IntegerProperty COLOR = EndBlockProperties.COLOR; + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); + + public HelixTreeLeavesBlock() { + super(FabricBlockSettings + .of(Material.LEAVES) + .mapColor(MaterialColor.COLOR_ORANGE) + .sound(SoundType.WART_BLOCK) + .sound(SoundType.GRASS) + .strength(0.2F) + ); + + TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(COLOR); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> { + return ColorUtil.color(237, getGreen(state.getValue(COLOR)), 20); + }; + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> { + return ColorUtil.color(237, getGreen(4), 20); + }; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + double px = ctx.getClickedPos().getX() * 0.1; + double py = ctx.getClickedPos().getY() * 0.1; + double pz = ctx.getClickedPos().getZ() * 0.1; + return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); + } + + private int getGreen(int color) { + float delta = color / 7F; + return (int) Mth.lerp(delta, 80, 158); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return BaseLeavesBlock.getLeaveDrops(this, EndBlocks.HELIX_TREE_SAPLING, builder, 16, 32); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HelixTreeSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/HelixTreeSaplingBlock.java new file mode 100644 index 00000000..ea3a7930 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HelixTreeSaplingBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class HelixTreeSaplingBlock extends PottableFeatureSapling { + public HelixTreeSaplingBlock() { + super((state) -> EndFeatures.HELIX_TREE.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.AMBER_MOSS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HydraluxBlock.java b/src/main/java/org/betterx/betterend/blocks/HydraluxBlock.java new file mode 100644 index 00000000..f5763f92 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HydraluxBlock.java @@ -0,0 +1,97 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.UnderwaterPlantBlock; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.EndBlockProperties.HydraluxShape; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.Collections; +import java.util.List; + +public class HydraluxBlock extends UnderwaterPlantBlock implements AddMineableShears { + + public static final EnumProperty SHAPE = EndBlockProperties.HYDRALUX_SHAPE; + + public HydraluxBlock() { + super(FabricBlockSettings.of(Material.WATER_PLANT) + .sound(SoundType.WET_GRASS) + .lightLevel((state) -> state.getValue(SHAPE).hasGlow() ? 15 : 0) + .noCollission()); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState down = world.getBlockState(pos.below()); + HydraluxShape shape = state.getValue(SHAPE); + if (shape == HydraluxShape.FLOWER_BIG_TOP || shape == HydraluxShape.FLOWER_SMALL_TOP) { + return down.is(this); + } else if (shape == HydraluxShape.ROOTS) { + return down.is(EndBlocks.SULPHURIC_ROCK.stone) && world.getBlockState(pos.above()).is(this); + } else { + return down.is(this) && world.getBlockState(pos.above()).is(this); + } + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + return new ItemStack(EndBlocks.HYDRALUX_SAPLING); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + HydraluxShape shape = state.getValue(SHAPE); + if (shape == HydraluxShape.FLOWER_BIG_BOTTOM || shape == HydraluxShape.FLOWER_SMALL_BOTTOM) { + return Lists.newArrayList(new ItemStack(EndItems.HYDRALUX_PETAL, + MHelper.randRange(1, 4, MHelper.RANDOM_SOURCE))); + } else if (shape == HydraluxShape.ROOTS) { + return Lists.newArrayList(new ItemStack( + EndBlocks.HYDRALUX_SAPLING, + MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE) + )); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HydraluxPetalBlock.java b/src/main/java/org/betterx/betterend/blocks/HydraluxPetalBlock.java new file mode 100644 index 00000000..fbf90ef2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HydraluxPetalBlock.java @@ -0,0 +1,35 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; + +public class HydraluxPetalBlock extends BaseBlock implements AddMineableAxe { + public HydraluxPetalBlock() { + this( + FabricBlockSettings + .of(Material.PLANT) + .hardness(1) + .resistance(1) + .mapColor(MaterialColor.PODZOL) + .sound(SoundType.WART_BLOCK) + ); + } + + public HydraluxPetalBlock(Properties settings) { + super(settings); + } + + @Override + public void fallOn(Level level, BlockState blockState, BlockPos blockPos, Entity entity, float f) { + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HydraluxPetalColoredBlock.java b/src/main/java/org/betterx/betterend/blocks/HydraluxPetalColoredBlock.java new file mode 100644 index 00000000..fb278391 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HydraluxPetalColoredBlock.java @@ -0,0 +1,43 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.client.models.Patterns; + +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +public class HydraluxPetalColoredBlock extends HydraluxPetalBlock implements CustomColorProvider { + public HydraluxPetalColoredBlock(FabricBlockSettings settings) { + super(settings); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> BlocksHelper.getBlockColor(this); + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> BlocksHelper.getBlockColor(this); + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + String path = "betterend:block/block_petal_colored"; + Optional pattern = Patterns.createJson(Patterns.BLOCK_PETAL_COLORED, path, path); + return ModelsHelper.fromPattern(pattern); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HydraluxSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/HydraluxSaplingBlock.java new file mode 100644 index 00000000..0e082ab0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HydraluxSaplingBlock.java @@ -0,0 +1,75 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class HydraluxSaplingBlock extends UnderwaterPlantWithAgeBlock { + + @Override + public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { + int h = MHelper.randRange(4, 8, random); + MutableBlockPos mut = new MutableBlockPos().set(pos); + + for (int i = 1; i < h; i++) { + mut.setY(pos.getY() + i); + if (!world.getBlockState(mut).is(Blocks.WATER)) { + return; + } + } + + mut.setY(pos.getY()); + BlockState state = EndBlocks.HYDRALUX.defaultBlockState(); + BlocksHelper.setWithoutUpdate( + world, + pos, + state.setValue(EndBlockProperties.HYDRALUX_SHAPE, EndBlockProperties.HydraluxShape.ROOTS) + ); + for (int i = 1; i < h - 2; i++) { + mut.setY(pos.getY() + i); + BlocksHelper.setWithoutUpdate( + world, + mut, + state.setValue(EndBlockProperties.HYDRALUX_SHAPE, EndBlockProperties.HydraluxShape.VINE) + ); + } + + mut.setY(mut.getY() + 1); + boolean big = random.nextBoolean(); + BlocksHelper.setWithoutUpdate( + world, + mut, + state.setValue( + EndBlockProperties.HYDRALUX_SHAPE, + big + ? EndBlockProperties.HydraluxShape.FLOWER_BIG_BOTTOM + : EndBlockProperties.HydraluxShape.FLOWER_SMALL_BOTTOM + ) + ); + + mut.setY(mut.getY() + 1); + BlocksHelper.setWithoutUpdate( + world, + mut, + state.setValue( + EndBlockProperties.HYDRALUX_SHAPE, + big + ? EndBlockProperties.HydraluxShape.FLOWER_BIG_TOP + : EndBlockProperties.HydraluxShape.FLOWER_SMALL_TOP + ) + ); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.SULPHURIC_ROCK.stone); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/HydrothermalVentBlock.java b/src/main/java/org/betterx/betterend/blocks/HydrothermalVentBlock.java new file mode 100644 index 00000000..39ba6857 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/HydrothermalVentBlock.java @@ -0,0 +1,155 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.*; +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.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +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.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.entities.BlockEntityHydrothermalVent; +import org.betterx.betterend.registry.EndBlocks; + +import org.jetbrains.annotations.Nullable; + +@SuppressWarnings("deprecation") +public class HydrothermalVentBlock extends BaseBlockNotFull implements EntityBlock, LiquidBlockContainer, SimpleWaterloggedBlock, AddMineablePickaxe { + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; + private static final VoxelShape SHAPE = Block.box(1, 1, 1, 15, 16, 15); + + public HydrothermalVentBlock() { + super(FabricBlockSettings.of(Material.STONE) + .sound(SoundType.STONE) + .noCollission() + .requiresCorrectToolForDrops()); + this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, true).setValue(ACTIVATED, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(WATERLOGGED, ACTIVATED); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + @Override + public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { + return false; + } + + @Override + public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { + return false; + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + state = world.getBlockState(pos.below()); + return state.is(EndBlocks.SULPHURIC_ROCK.stone); + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return Blocks.WATER.defaultBlockState(); + } else if (state.getValue(WATERLOGGED) && facing == Direction.UP && neighborState.is(Blocks.WATER)) { + world.scheduleTick(pos, this, 20); + } + return state; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + LevelAccessor worldAccess = ctx.getLevel(); + BlockPos blockPos = ctx.getClickedPos(); + return this.defaultBlockState() + .setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new BlockEntityHydrothermalVent(pos, state); + } + + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + BlockPos up = pos.above(); + if (world.getBlockState(up).is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate(world, up, EndBlocks.VENT_BUBBLE_COLUMN); + world.scheduleTick(up, EndBlocks.VENT_BUBBLE_COLUMN, 5); + } + } + + @Override + public void setPlacedBy(Level world, + BlockPos pos, + BlockState state, + @Nullable LivingEntity placer, + ItemStack itemStack) { + if (world instanceof ServerLevel && state.getValue(WATERLOGGED) && world.getBlockState(pos.above()) + .is(Blocks.WATER)) { + tick(state, (ServerLevel) world, pos, world.random); + } + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + super.animateTick(state, world, pos, random); + if (!state.getValue(ACTIVATED) && random.nextBoolean()) { + double x = pos.getX() + random.nextDouble(); + double y = pos.getY() + 0.9 + random.nextDouble() * 0.3; + double z = pos.getZ() + random.nextDouble(); + world.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, 0, 0, 0); + } + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, + BlockState blockState, + BlockEntityType blockEntityType) { + return BlockEntityHydrothermalVent::tick; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/InfusionPedestal.java b/src/main/java/org/betterx/betterend/blocks/InfusionPedestal.java new file mode 100644 index 00000000..9f3e90b0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/InfusionPedestal.java @@ -0,0 +1,101 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +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.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.blocks.entities.InfusionPedestalEntity; +import org.betterx.betterend.rituals.InfusionRitual; + +import org.jetbrains.annotations.Nullable; + +@SuppressWarnings("deprecation") +public class InfusionPedestal extends PedestalBlock { + private static final VoxelShape SHAPE_DEFAULT; + private static final VoxelShape SHAPE_PEDESTAL_TOP; + + public InfusionPedestal() { + super(Blocks.OBSIDIAN); + this.height = 1.08F; + } + + @Override + public void checkRitual(Level world, BlockPos pos) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof InfusionPedestalEntity) { + InfusionPedestalEntity pedestal = (InfusionPedestalEntity) blockEntity; + if (pedestal.hasRitual()) { + InfusionRitual ritual = pedestal.getRitual(); + if (!ritual.isValid()) { + ritual.configure(); + } + pedestal.getRitual().checkRecipe(); + } else { + InfusionRitual ritual = new InfusionRitual(pedestal, world, pos); + pedestal.linkRitual(ritual); + ritual.checkRecipe(); + } + } + } + + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return new InfusionPedestalEntity(blockPos, blockState); + } + + @Override + public boolean hasUniqueEntity() { + return true; + } + + @Override + @Deprecated + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { + if (state.is(this)) { + switch (state.getValue(STATE)) { + case PEDESTAL_TOP: { + return SHAPE_PEDESTAL_TOP; + } + case DEFAULT: { + return SHAPE_DEFAULT; + } + default: { + return super.getShape(state, world, pos, context); + } + } + } + return super.getShape(state, world, pos, context); + } + + @Override + @Nullable + public BlockEntityTicker getTicker(Level level, + BlockState blockState, + BlockEntityType blockEntityType) { + return InfusionPedestalEntity::tickEnity; + } + + static { + VoxelShape basinUp = Block.box(2, 3, 2, 14, 4, 14); + VoxelShape basinDown = Block.box(0, 0, 0, 16, 3, 16); + VoxelShape pedestalTop = Block.box(1, 9, 1, 15, 11, 15); + VoxelShape pedestalDefault = Block.box(1, 13, 1, 15, 15, 15); + VoxelShape pillar = Block.box(3, 0, 3, 13, 9, 13); + VoxelShape pillarDefault = Block.box(3, 4, 3, 13, 13, 13); + VoxelShape eyeDefault = Block.box(4, 15, 4, 12, 16, 12); + VoxelShape eyeTop = Block.box(4, 11, 4, 12, 12, 12); + VoxelShape basin = Shapes.or(basinDown, basinUp); + SHAPE_DEFAULT = Shapes.or(basin, pillarDefault, pedestalDefault, eyeDefault); + SHAPE_PEDESTAL_TOP = Shapes.or(pillar, pedestalTop, eyeTop); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/JellyshroomCapBlock.java b/src/main/java/org/betterx/betterend/blocks/JellyshroomCapBlock.java new file mode 100644 index 00000000..2270e83c --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/JellyshroomCapBlock.java @@ -0,0 +1,106 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.Vec3i; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SlimeBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.BlockModelProvider; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.client.models.Patterns; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.List; +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +public class JellyshroomCapBlock extends SlimeBlock implements RenderLayerProvider, BlockModelProvider, CustomColorProvider { + public static final IntegerProperty COLOR = EndBlockProperties.COLOR; + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); + private final Vec3i colorStart; + private final Vec3i colorEnd; + private final int coloritem; + + public JellyshroomCapBlock(int r1, int g1, int b1, int r2, int g2, int b2) { + super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK)); + colorStart = new Vec3i(r1, g1, b1); + colorEnd = new Vec3i(r2, g2, b2); + coloritem = ColorUtil.color((r1 + r2) >> 1, (g1 + g2) >> 1, (b1 + b2) >> 1); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + double px = ctx.getClickedPos().getX() * 0.1; + double py = ctx.getClickedPos().getY() * 0.1; + double pz = ctx.getClickedPos().getZ() * 0.1; + return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(COLOR); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState state, LootContext.Builder builder) { + return Lists.newArrayList(new ItemStack(this)); + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + return getBlockModel(resourceLocation, defaultBlockState()); + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + Optional pattern = Patterns.createJson(Patterns.BLOCK_COLORED, "jellyshroom_cap"); + return ModelsHelper.fromPattern(pattern); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> { + float delta = (float) state.getValue(COLOR) / 7F; + int r = Mth.floor(Mth.lerp(delta, colorStart.getX() / 255F, colorEnd.getX() / 255F) * 255F); + int g = Mth.floor(Mth.lerp(delta, colorStart.getY() / 255F, colorEnd.getY() / 255F) * 255F); + int b = Mth.floor(Mth.lerp(delta, colorStart.getZ() / 255F, colorEnd.getZ() / 255F) * 255F); + return ColorUtil.color(r, g, b); + }; + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> { + return coloritem; + }; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LacugroveSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/LacugroveSaplingBlock.java new file mode 100644 index 00000000..372e6c0a --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LacugroveSaplingBlock.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class LacugroveSaplingBlock extends PottableFeatureSapling { + public LacugroveSaplingBlock() { + super((state) -> EndFeatures.LACUGROVE.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below()) + .is(EndBlocks.ENDSTONE_DUST); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.END_MOSS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LanceleafBlock.java b/src/main/java/org/betterx/betterend/blocks/LanceleafBlock.java new file mode 100644 index 00000000..ad67168a --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LanceleafBlock.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.storage.loot.LootContext; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.PentaShape; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Collections; +import java.util.List; + +public class LanceleafBlock extends EndPlantBlock { + + public static final EnumProperty SHAPE = BlockProperties.PENTA_SHAPE; + public static final IntegerProperty ROTATION = BlockProperties.ROTATION; + + public LanceleafBlock() { + super(); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE, ROTATION); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + PentaShape shape = state.getValue(SHAPE); + if (shape == PentaShape.TOP) { + return world.getBlockState(pos.below()).is(this); + } else if (shape == PentaShape.BOTTOM) { + return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS) && world.getBlockState(pos.above()) + .is(this); + } else { + return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); + } + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { + return state; + } + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.getValue(SHAPE) == PentaShape.BOTTOM) { + return Collections.singletonList(new ItemStack(EndBlocks.LANCELEAF_SEED)); + } + return MHelper.RANDOM.nextBoolean() ? Collections.emptyList() : Collections.singletonList(new ItemStack( + EndBlocks.LANCELEAF_SEED)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LanceleafSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/LanceleafSeedBlock.java new file mode 100644 index 00000000..11ed64af --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LanceleafSeedBlock.java @@ -0,0 +1,61 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.PentaShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class LanceleafSeedBlock extends EndPlantWithAgeBlock { + public LanceleafSeedBlock() { + super(p -> p.offsetType(OffsetType.NONE)); + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + int height = MHelper.randRange(4, 6, random); + int h = BlocksHelper.upRay(world, pos, height + 2); + if (h < height + 1) { + return; + } + int rotation = random.nextInt(4); + MutableBlockPos mut = new MutableBlockPos().set(pos); + BlockState plant = EndBlocks.LANCELEAF.defaultBlockState().setValue(BlockProperties.ROTATION, rotation); + BlocksHelper.setWithoutUpdate(world, mut, plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.BOTTOM)); + BlocksHelper.setWithoutUpdate( + world, + mut.move(Direction.UP), + plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_BOTTOM) + ); + for (int i = 2; i < height - 2; i++) { + BlocksHelper.setWithoutUpdate( + world, + mut.move(Direction.UP), + plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.MIDDLE) + ); + } + BlocksHelper.setWithoutUpdate( + world, + mut.move(Direction.UP), + plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_TOP) + ); + BlocksHelper.setWithoutUpdate( + world, + mut.move(Direction.UP), + plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.TOP) + ); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.AMBER_MOSS); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LargeAmaranitaBlock.java b/src/main/java/org/betterx/betterend/blocks/LargeAmaranitaBlock.java new file mode 100644 index 00000000..a1313bdc --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LargeAmaranitaBlock.java @@ -0,0 +1,77 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class LargeAmaranitaBlock extends EndPlantBlock implements AddMineableShears { + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 14, 12); + private static final VoxelShape SHAPE_TOP = Shapes.or(Block.box(1, 3, 1, 15, 16, 15), SHAPE_BOTTOM); + + public LargeAmaranitaBlock() { + //TODO: 1.19 Test if we can remove dynamic shape and offsetType + super(FabricBlockSettings.of(Material.PLANT) + + .sound(SoundType.GRASS) + .lightLevel((state) -> (state.getValue(SHAPE) == TripleShape.TOP) ? 15 : 0) + .dynamicShape() + .offsetType(OffsetType.NONE)); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM; + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.SANGNUM) || state.is(EndBlocks.MOSSY_OBSIDIAN) || state.is(EndBlocks.MOSSY_DRAGON_BONE); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + TripleShape shape = state.getValue(SHAPE); + if (shape == TripleShape.BOTTOM) { + return isTerrain(world.getBlockState(pos.below())) && world.getBlockState(pos.above()).is(this); + } else if (shape == TripleShape.TOP) { + return world.getBlockState(pos.below()).is(this); + } else { + return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); + } + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LucerniaSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/LucerniaSaplingBlock.java new file mode 100644 index 00000000..6c6f4901 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LucerniaSaplingBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class LucerniaSaplingBlock extends PottableFeatureSapling { + public LucerniaSaplingBlock() { + super((state) -> EndFeatures.LUCERNIA.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.RUTISCUS); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.RUTISCUS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LumecornBlock.java b/src/main/java/org/betterx/betterend/blocks/LumecornBlock.java new file mode 100644 index 00000000..a478937c --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LumecornBlock.java @@ -0,0 +1,113 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineableAxe; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.Collections; +import java.util.List; + +@SuppressWarnings("deprecation") +public class LumecornBlock extends BaseBlockNotFull implements RenderLayerProvider, AddMineableAxe { + public static final EnumProperty SHAPE = EnumProperty.create("shape", + EndBlockProperties.LumecornShape.class); + private static final VoxelShape SHAPE_BOTTOM = Block.box(6, 0, 6, 10, 16, 10); + private static final VoxelShape SHAPE_TOP = Block.box(6, 0, 6, 10, 8, 10); + + public LumecornBlock() { + super(FabricBlockSettings.of(Material.WOOD) + .hardness(0.5F) + .luminance(state -> state.getValue(SHAPE).getLight())); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(SHAPE) == EndBlockProperties.LumecornShape.LIGHT_TOP ? SHAPE_TOP : SHAPE_BOTTOM; + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + EndBlockProperties.LumecornShape shape = state.getValue(SHAPE); + if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL) { + return world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES); + } else if (shape == EndBlockProperties.LumecornShape.LIGHT_TOP) { + return world.getBlockState(pos.below()).is(this); + } else { + return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); + } + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!canSurvive(state, world, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { + return state; + } + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + EndBlockProperties.LumecornShape shape = state.getValue(SHAPE); + if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL || shape == EndBlockProperties.LumecornShape.MIDDLE) { + return Collections.singletonList(new ItemStack( + EndBlocks.LUMECORN_SEED, + MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE) + )); + } + return MHelper.RANDOM.nextBoolean() + ? Collections.singletonList(new ItemStack(EndItems.LUMECORN_ROD)) + : Collections + .emptyList(); + } + + @Override + @Environment(EnvType.CLIENT) + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + EndBlockProperties.LumecornShape shape = state.getValue(SHAPE); + if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL || shape == EndBlockProperties.LumecornShape.MIDDLE) { + return new ItemStack(EndBlocks.LUMECORN_SEED); + } + return new ItemStack(EndItems.LUMECORN_ROD); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/LumecornSeedBlock.java b/src/main/java/org/betterx/betterend/blocks/LumecornSeedBlock.java new file mode 100644 index 00000000..1e6d00bc --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/LumecornSeedBlock.java @@ -0,0 +1,38 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +import java.util.Optional; + +public class LumecornSeedBlock extends EndPlantWithAgeBlock { + + public LumecornSeedBlock() { + super(p -> p.offsetType(OffsetType.NONE)); + } + + @Override + public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { + ((Feature) (EndFeatures.LUMECORN.getFeature())).place(new FeaturePlaceContext<>( + Optional.empty(), + world, + null, + random, + pos, + null)); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MengerSpongeBlock.java b/src/main/java/org/betterx/betterend/blocks/MengerSpongeBlock.java new file mode 100644 index 00000000..cfc29cbe --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MengerSpongeBlock.java @@ -0,0 +1,136 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Tuple; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.BucketPickup; +import net.minecraft.world.level.block.LiquidBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Queue; + +@SuppressWarnings("deprecation") +public class MengerSpongeBlock extends BaseBlockNotFull implements RenderLayerProvider { + private static final VoxelShape SHAPE; + + public MengerSpongeBlock() { + super(FabricBlockSettings.copyOf(Blocks.SPONGE).noOcclusion()); + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (absorbWater(world, pos)) { + world.setBlockAndUpdate(pos, EndBlocks.MENGER_SPONGE_WET.defaultBlockState()); + } + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (absorbWater(world, pos)) { + return EndBlocks.MENGER_SPONGE_WET.defaultBlockState(); + } + return state; + } + + private boolean absorbWater(LevelAccessor world, BlockPos pos) { + Queue> queue = Lists.newLinkedList(); + queue.add(new Tuple<>(pos, 0)); + int i = 0; + + while (!queue.isEmpty()) { + Tuple pair = queue.poll(); + BlockPos blockPos = pair.getA(); + int j = pair.getB(); + + for (Direction direction : Direction.values()) { + BlockPos blockPos2 = blockPos.relative(direction); + BlockState blockState = world.getBlockState(blockPos2); + FluidState fluidState = world.getFluidState(blockPos2); + Material material = blockState.getMaterial(); + if (fluidState.is(FluidTags.WATER)) { + if (blockState.getBlock() instanceof BucketPickup && !((BucketPickup) blockState.getBlock()).pickupBlock( + world, + blockPos2, + blockState + ) + .isEmpty()) { + ++i; + if (j < 6) { + queue.add(new Tuple<>(blockPos2, j + 1)); + } + } else if (blockState.getBlock() instanceof LiquidBlock) { + world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3); + ++i; + if (j < 6) { + queue.add(new Tuple<>(blockPos2, j + 1)); + } + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + BlockEntity blockEntity = blockState.hasBlockEntity() ? world.getBlockEntity(blockPos2) : null; + dropResources(blockState, world, blockPos2, blockEntity); + world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3); + ++i; + if (j < 6) { + queue.add(new Tuple<>(blockPos2, j + 1)); + } + } + } + } + + if (i > 64) { + break; + } + } + + return i > 0; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public VoxelShape getShape(BlockState blockState, + BlockGetter blockGetter, + BlockPos blockPos, + CollisionContext collisionContext) { + return SHAPE; + } + + static { + SHAPE = Shapes.or( + Shapes.or(box(0, 0, 0, 16, 6, 6), box(0, 0, 10, 16, 6, 16), + Shapes.or(box(0, 10, 0, 16, 16, 6), box(0, 10, 10, 16, 16, 16)), + + Shapes.or(box(0, 0, 0, 6, 6, 16), box(10, 0, 0, 16, 6, 16)), + Shapes.or(box(0, 10, 0, 6, 16, 16), box(10, 10, 0, 16, 16, 16)), + + Shapes.or(box(0, 0, 0, 6, 16, 6), box(10, 0, 0, 16, 16, 6)), + Shapes.or(box(0, 0, 10, 6, 16, 16), box(10, 0, 10, 16, 16, 16)) + )); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MengerSpongeWetBlock.java b/src/main/java/org/betterx/betterend/blocks/MengerSpongeWetBlock.java new file mode 100644 index 00000000..6fa9deab --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MengerSpongeWetBlock.java @@ -0,0 +1,128 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +@SuppressWarnings("deprecation") +public class MengerSpongeWetBlock extends BaseBlockNotFull implements RenderLayerProvider { + public MengerSpongeWetBlock() { + super(FabricBlockSettings.copyOf(Blocks.WET_SPONGE).noOcclusion()); + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (world.dimensionType().ultraWarm()) { + world.setBlock(pos, EndBlocks.MENGER_SPONGE.defaultBlockState(), 3); + world.levelEvent(2009, pos, 0); + world.playSound( + null, + pos, + SoundEvents.FIRE_EXTINGUISH, + SoundSource.BLOCKS, + 1.0F, + (1.0F + world.getRandom().nextFloat() * 0.2F) * 0.7F + ); + } + } + + @Override + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + Direction direction = Direction.getRandom(random); + if (direction != Direction.UP) { + BlockPos blockPos = pos.relative(direction); + BlockState blockState = world.getBlockState(blockPos); + if (!state.canOcclude() || !blockState.isFaceSturdy(world, blockPos, direction.getOpposite())) { + double x = pos.getX(); + double y = pos.getY(); + double z = pos.getZ(); + if (direction == Direction.DOWN) { + y -= 0.05; + x += random.nextDouble(); + z += random.nextDouble(); + } else { + y += random.nextDouble() * 0.8; + if (direction.getAxis() == Direction.Axis.X) { + z += random.nextDouble(); + if (direction == Direction.EAST) { + ++x; + } else { + x += 0.05; + } + } else { + x += random.nextDouble(); + if (direction == Direction.SOUTH) { + ++z; + } else { + z += 0.05; + } + } + } + + world.addParticle(ParticleTypes.DRIPPING_WATER, x, y, z, 0, 0, 0); + } + } + } + + @Override + public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { + BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); + if (!world.isClientSide()) { + world.levelEvent(2001, pos, getId(state)); + } + if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && (player == null || !player.isCreative())) { + ItemEntity drop = new ItemEntity( + world, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + new ItemStack(this) + ); + world.addFreshEntity(drop); + } + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public FluidState getFluidState(BlockState state) { + return Fluids.WATER.getSource(false); + } + + @Override + public VoxelShape getShape(BlockState blockState, + BlockGetter blockGetter, + BlockPos blockPos, + CollisionContext collisionContext) { + return EndBlocks.MENGER_SPONGE.getShape(blockState, blockGetter, blockPos, collisionContext); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MissingTileBlock.java b/src/main/java/org/betterx/betterend/blocks/MissingTileBlock.java new file mode 100644 index 00000000..11fb2b08 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MissingTileBlock.java @@ -0,0 +1,13 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Blocks; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; + +public class MissingTileBlock extends BaseBlock { + public MissingTileBlock() { + super(FabricBlockSettings.copyOf(Blocks.END_STONE)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MossyDragonBoneBlock.java b/src/main/java/org/betterx/betterend/blocks/MossyDragonBoneBlock.java new file mode 100644 index 00000000..fe69a79d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MossyDragonBoneBlock.java @@ -0,0 +1,69 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SnowLayerBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.lighting.LayerLightEngine; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseRotatedPillarBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Collections; +import java.util.List; + +@SuppressWarnings("deprecation") +public class MossyDragonBoneBlock extends BaseRotatedPillarBlock { + public MossyDragonBoneBlock() { + super(FabricBlockSettings.copyOf(Blocks.BONE_BLOCK).hardness(0.5F).randomTicks()); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { + return Collections.singletonList(new ItemStack(this)); + } + return Collections.singletonList(new ItemStack(EndBlocks.DRAGON_BONE_BLOCK)); + } + + @Override + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) { + world.setBlockAndUpdate(pos, Blocks.BONE_BLOCK.defaultBlockState().setValue(AXIS, state.getValue(AXIS))); + } + } + + @Override + public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) { + BlockPos blockPos = pos.above(); + BlockState blockState = worldView.getBlockState(blockPos); + if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) { + return true; + } else if (blockState.getFluidState().getAmount() == 8) { + return false; + } else { + int i = LayerLightEngine.getLightBlockInto( + worldView, + state, + pos, + blockState, + blockPos, + Direction.UP, + blockState.getLightBlock(worldView, blockPos) + ); + return i < 5; + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomCapBlock.java b/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomCapBlock.java new file mode 100644 index 00000000..521ab65b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomCapBlock.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.NamedMineableTags; +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.interfaces.TagProvider; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class MossyGlowshroomCapBlock extends BaseBlock implements TagProvider { + public static final BooleanProperty TRANSITION = EndBlockProperties.TRANSITION; + + public MossyGlowshroomCapBlock() { + super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); + this.registerDefaultState(this.stateDefinition.any().setValue(TRANSITION, false)); + } + + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return this.defaultBlockState() + .setValue( + TRANSITION, + EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(ctx.getLevel() + .getBlockState(ctx.getClickedPos().below())) + ); + } + + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(TRANSITION); + } + + @Override + public void addTags(List> blockTags, List> itemTags) { + blockTags.add(NamedMineableTags.AXE); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomSaplingBlock.java new file mode 100644 index 00000000..4262ccf0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MossyGlowshroomSaplingBlock.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class MossyGlowshroomSaplingBlock extends PottableFeatureSapling { + public MossyGlowshroomSaplingBlock() { + super(7, (state) -> EndFeatures.MOSSY_GLOWSHROOM.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below()) + .is(EndBlocks.END_MYCELIUM); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.END_MOSS || block == EndBlocks.END_MYCELIUM; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MossyObsidian.java b/src/main/java/org/betterx/betterend/blocks/MossyObsidian.java new file mode 100644 index 00000000..5c8f2d17 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MossyObsidian.java @@ -0,0 +1,68 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SnowLayerBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.lighting.LayerLightEngine; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; + +import java.util.Collections; +import java.util.List; + +public class MossyObsidian extends BaseBlock { + public MossyObsidian() { + super(FabricBlockSettings.copyOf(Blocks.OBSIDIAN).hardness(3).randomTicks()); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { + return Collections.singletonList(new ItemStack(this)); + } + return Collections.singletonList(new ItemStack(Blocks.OBSIDIAN)); + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) { + world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState()); + } + } + + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) { + BlockPos blockPos = pos.above(); + BlockState blockState = worldView.getBlockState(blockPos); + if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) { + return true; + } else if (blockState.getFluidState().getAmount() == 8) { + return false; + } else { + int i = LayerLightEngine.getLightBlockInto( + worldView, + state, + pos, + blockState, + blockPos, + Direction.UP, + blockState.getLightBlock(worldView, blockPos) + ); + return i < 5; + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/MurkweedBlock.java b/src/main/java/org/betterx/betterend/blocks/MurkweedBlock.java new file mode 100644 index 00000000..c9e4caeb --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/MurkweedBlock.java @@ -0,0 +1,50 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.RandomSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.PathComputationType; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class MurkweedBlock extends EndPlantBlock { + @Override + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + double x = pos.getX() + random.nextDouble(); + double y = pos.getY() + random.nextDouble() * 0.5 + 0.5; + double z = pos.getZ() + random.nextDouble(); + double v = random.nextDouble() * 0.1; + world.addParticle(ParticleTypes.ENTITY_EFFECT, x, y, z, v, v, v); + } + + @Override + @SuppressWarnings("deprecation") + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (entity instanceof LivingEntity && !((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS)) { + ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 50)); + } + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.SHADOW_GRASS); + } + + @Override + @SuppressWarnings("deprecation") + public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/NeedlegrassBlock.java b/src/main/java/org/betterx/betterend/blocks/NeedlegrassBlock.java new file mode 100644 index 00000000..c4b07728 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/NeedlegrassBlock.java @@ -0,0 +1,58 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import com.google.common.collect.Lists; +import org.betterx.bclib.items.tool.BaseShearsItem; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class NeedlegrassBlock extends EndPlantBlock { + @Override + @SuppressWarnings("deprecation") + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + if (entity instanceof LivingEntity) { + entity.hurt(DamageSource.CACTUS, 0.1F); + } + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( + Enchantments.SILK_TOUCH, + tool + ) > 0) { + return Lists.newArrayList(new ItemStack(this)); + } else { + return Lists.newArrayList(new ItemStack(Items.STICK, MHelper.randRange(0, 2, MHelper.RANDOM_SOURCE))); + } + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.SHADOW_GRASS); + } + + @Override + @SuppressWarnings("deprecation") + public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/NeonCactusBlock.java b/src/main/java/org/betterx/betterend/blocks/NeonCactusBlock.java new file mode 100644 index 00000000..aac7588c --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/NeonCactusBlock.java @@ -0,0 +1,13 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Blocks; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.betterend.blocks.basis.LitPillarBlock; + +public class NeonCactusBlock extends LitPillarBlock { + public NeonCactusBlock() { + super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/NeonCactusPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/NeonCactusPlantBlock.java new file mode 100644 index 00000000..eabfd6ea --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/NeonCactusPlantBlock.java @@ -0,0 +1,429 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.*; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.EndBlockProperties.CactusBottom; +import org.betterx.betterend.interfaces.PottablePlant; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.EnumMap; +import java.util.List; + +@SuppressWarnings("deprecation") +public class NeonCactusPlantBlock extends BaseBlockNotFull implements SimpleWaterloggedBlock, RenderLayerProvider, PottablePlant { + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + public static final EnumProperty CACTUS_BOTTOM = EndBlockProperties.CACTUS_BOTTOM; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final DirectionProperty FACING = BlockStateProperties.FACING; + + private static final EnumMap BIG_SHAPES_OPEN = Maps.newEnumMap(Direction.class); + private static final EnumMap MEDIUM_SHAPES_OPEN = Maps.newEnumMap(Direction.class); + private static final EnumMap SMALL_SHAPES_OPEN = Maps.newEnumMap(Direction.class); + private static final EnumMap BIG_SHAPES = Maps.newEnumMap(Axis.class); + private static final EnumMap MEDIUM_SHAPES = Maps.newEnumMap(Axis.class); + private static final EnumMap SMALL_SHAPES = Maps.newEnumMap(Axis.class); + private static final int MAX_LENGTH = 12; + + public NeonCactusPlantBlock() { + super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15).randomTicks()); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) + .setValue(FACING, Direction.UP) + .setValue(SHAPE, TripleShape.TOP)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE, CACTUS_BOTTOM, WATERLOGGED, FACING); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + LevelAccessor world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + Direction dir = ctx.getClickedFace(); + BlockState down = world.getBlockState(pos.relative(dir.getOpposite())); + BlockState state = this.defaultBlockState() + .setValue(WATERLOGGED, world.getFluidState(pos).getType() == Fluids.WATER) + .setValue(FACING, ctx.getClickedFace()); + if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); + } else if (down.is(EndBlocks.END_MOSS)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); + } else { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); + } + return state; + } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + return BlocksHelper.rotateHorizontal(state, rotation, FACING); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + return BlocksHelper.mirrorHorizontal(state, mirror, FACING); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + world.scheduleTick(pos, this, 2); + if (state.getValue(WATERLOGGED)) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + Direction dir = state.getValue(FACING); + BlockState downState = world.getBlockState(pos.relative(dir.getOpposite())); + if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); + } else if (downState.is(EndBlocks.END_MOSS)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); + } else { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); + } + return state; + } + + @Override + public void tick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource random) { + if (!blockState.canSurvive(serverLevel, blockPos)) { + serverLevel.destroyBlock(blockPos, true, null, 1); + } + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + TripleShape shape = state.getValue(SHAPE); + Direction dir = state.getValue(FACING); + BlockState next = view.getBlockState(pos.relative(dir)); + if (next.is(this)) { + Axis axis = dir.getAxis(); + if (shape == TripleShape.BOTTOM) { + return BIG_SHAPES.get(axis); + } + return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES.get(axis) : SMALL_SHAPES.get(axis); + } else { + if (shape == TripleShape.BOTTOM) { + return BIG_SHAPES_OPEN.get(dir); + } + return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES_OPEN.get(dir) : SMALL_SHAPES_OPEN.get(dir); + } + } + + @Override + public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { + Direction dir = state.getValue(FACING); + BlockPos supportPos = pos.relative(dir.getOpposite()); + BlockState support = level.getBlockState(supportPos); + return support.is(this) || support.isFaceSturdy(level, supportPos, dir); + } + + @Override + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (!this.canSurvive(state, world, pos) || random.nextInt(8) > 0) { + return; + } + Direction dir = state.getValue(FACING); + if (!world.isEmptyBlock(pos.relative(dir))) { + return; + } + int length = getLength(state, world, pos, MAX_LENGTH); + if (length < 0 || length > MAX_LENGTH - 1) { + return; + } + if (dir.getAxis().isHorizontal()) { + int horizontal = getHorizontal(state, world, pos, 2); + if (horizontal > random.nextInt(2)) { + dir = Direction.UP; + if (!world.getBlockState(pos.above()).isAir()) { + return; + } + } + } else if (length > 1 && world.getBlockState(pos.relative(dir.getOpposite())).is(this)) { + Direction side = getSideDirection(world, pos, state, dir, random); + BlockPos sidePos = pos.relative(side); + if (world.isEmptyBlock(sidePos)) { + BlockState placement = state.setValue(SHAPE, TripleShape.TOP) + .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) + .setValue(WATERLOGGED, false) + .setValue(FACING, side); + BlocksHelper.setWithoutUpdate(world, sidePos, placement); + } + } + BlockState placement = state.setValue(SHAPE, TripleShape.TOP) + .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) + .setValue(WATERLOGGED, false) + .setValue(FACING, dir); + BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement); + mutateStem(placement, world, pos, MAX_LENGTH); + } + + public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random) { + growPlant(world, pos, random, MHelper.randRange(MAX_LENGTH >> 1, MAX_LENGTH, random)); + } + + public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random, int iterations) { + BlockState state = defaultBlockState(); + BlockState downState = world.getBlockState(pos.below()); + if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); + } else if (downState.is(EndBlocks.END_MOSS)) { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); + } else { + state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); + } + BlocksHelper.setWithoutUpdate(world, pos, state); + List ends = Lists.newArrayList(pos.mutable()); + for (int i = 0; i < iterations; i++) { + int count = ends.size(); + for (int n = 0; n < count; n++) { + if (!growIteration(world, ends.get(n), random, ends, i)) { + ends.remove(n); + count--; + n--; + } + } + } + } + + private boolean growIteration(WorldGenLevel world, + MutableBlockPos pos, + RandomSource random, + List ends, + int length) { + BlockState state = world.getBlockState(pos); + if (!state.is(this)) { + return false; + } + Direction dir = state.getValue(FACING); + if (!world.isEmptyBlock(pos.relative(dir))) { + return false; + } + if (dir.getAxis().isHorizontal()) { + int horizontal = getHorizontal(state, world, pos, 2); + if (horizontal > random.nextInt(2)) { + dir = Direction.UP; + if (!world.getBlockState(pos.above()).isAir()) { + return false; + } + } + } else if (length > 1 && world.getBlockState(pos.below()).is(this)) { + Direction side = getSideDirection(world, pos, state, dir, random); + BlockPos sidePos = pos.relative(side); + if (world.isEmptyBlock(sidePos)) { + BlockState placement = state.setValue(SHAPE, TripleShape.TOP) + .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) + .setValue(WATERLOGGED, false) + .setValue(FACING, side); + BlocksHelper.setWithoutUpdate(world, sidePos, placement); + ends.add(sidePos.mutable()); + } + } + BlockState placement = state.setValue(SHAPE, TripleShape.TOP) + .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) + .setValue(WATERLOGGED, false) + .setValue(FACING, dir); + BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement); + mutateStem(placement, world, pos, MAX_LENGTH); + pos.move(dir); + return true; + } + + private Direction getSideDirection(WorldGenLevel world, + BlockPos pos, + BlockState iterState, + Direction dir, + RandomSource random) { + MutableBlockPos iterPos = pos.mutable(); + Direction startDir = dir; + Direction lastDir = null; + while (iterState.is(this) && startDir.getAxis().isVertical()) { + startDir = iterState.getValue(FACING); + if (lastDir == null) { + for (Direction side : BlocksHelper.HORIZONTAL) { + BlockState sideState = world.getBlockState(iterPos.relative(side)); + if (sideState.is(this)) { + Direction sideDir = sideState.getValue(FACING); + if (sideDir != side) { + continue; + } + lastDir = sideDir; + } + } + } + iterPos.move(dir); + iterState = world.getBlockState(iterPos); + } + + Direction side = lastDir == null ? BlocksHelper.randomHorizontal(random) : lastDir.getClockWise(); + if (side.getOpposite() == startDir) { + side = side.getOpposite(); + } + return side; + } + + @Override + public boolean isPathfindable(BlockState blockState, + BlockGetter blockGetter, + BlockPos blockPos, + PathComputationType pathComputationType) { + return false; + } + + @Override + public void entityInside(BlockState blockState, Level level, BlockPos blockPos, Entity entity) { + entity.hurt(DamageSource.CACTUS, 1.0F); + } + + private int getLength(BlockState state, ServerLevel world, BlockPos pos, int max) { + int length = 0; + Direction dir = state.getValue(FACING).getOpposite(); + MutableBlockPos mut = new MutableBlockPos().set(pos); + for (int i = 0; i < max; i++) { + mut.move(dir); + state = world.getBlockState(mut); + if (!state.is(this)) { + if (!state.is(CommonBlockTags.END_STONES)) { + length = -1; + } + break; + } + dir = state.getValue(FACING).getOpposite(); + length++; + } + return length; + } + + private int getHorizontal(BlockState state, WorldGenLevel world, BlockPos pos, int max) { + int count = 0; + Direction dir = state.getValue(FACING).getOpposite(); + MutableBlockPos mut = new MutableBlockPos().set(pos); + for (int i = 0; i < max; i++) { + mut.move(dir); + state = world.getBlockState(mut); + if (!state.is(this)) { + break; + } + dir = state.getValue(FACING).getOpposite(); + if (dir.getStepY() != 0) { + break; + } + count++; + } + return count; + } + + private void mutateStem(BlockState state, WorldGenLevel world, BlockPos pos, int max) { + Direction dir = state.getValue(FACING).getOpposite(); + MutableBlockPos mut = new MutableBlockPos().set(pos); + for (int i = 0; i < max; i++) { + mut.move(dir); + state = world.getBlockState(mut); + if (!state.is(this)) { + return; + } + int size = (i + 2) * 3 / max; + int src = state.getValue(SHAPE).getIndex(); + dir = state.getValue(FACING).getOpposite(); + if (src < size) { + TripleShape shape = TripleShape.fromIndex(size); + BlocksHelper.setWithoutUpdate(world, mut, state.setValue(SHAPE, shape)); + } + } + } + + static { + BIG_SHAPES.put(Axis.X, Block.box(0, 2, 2, 16, 14, 14)); + BIG_SHAPES.put(Axis.Y, Block.box(2, 0, 2, 14, 16, 14)); + BIG_SHAPES.put(Axis.Z, Block.box(2, 2, 0, 14, 14, 16)); + + MEDIUM_SHAPES.put(Axis.X, Block.box(0, 3, 3, 16, 13, 13)); + MEDIUM_SHAPES.put(Axis.Y, Block.box(3, 0, 3, 13, 16, 13)); + MEDIUM_SHAPES.put(Axis.Z, Block.box(3, 3, 0, 13, 13, 16)); + + SMALL_SHAPES.put(Axis.X, Block.box(0, 4, 4, 16, 12, 12)); + SMALL_SHAPES.put(Axis.Y, Block.box(4, 0, 4, 12, 16, 12)); + SMALL_SHAPES.put(Axis.Z, Block.box(4, 4, 0, 12, 12, 16)); + + BIG_SHAPES_OPEN.put(Direction.UP, Block.box(2, 0, 2, 14, 14, 14)); + BIG_SHAPES_OPEN.put(Direction.DOWN, Block.box(2, 2, 2, 14, 16, 14)); + BIG_SHAPES_OPEN.put(Direction.NORTH, Block.box(2, 2, 2, 14, 14, 16)); + BIG_SHAPES_OPEN.put(Direction.SOUTH, Block.box(2, 2, 0, 14, 14, 14)); + BIG_SHAPES_OPEN.put(Direction.WEST, Block.box(2, 2, 2, 16, 14, 14)); + BIG_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 2, 2, 14, 14, 14)); + + MEDIUM_SHAPES_OPEN.put(Direction.UP, Block.box(3, 0, 3, 13, 13, 13)); + MEDIUM_SHAPES_OPEN.put(Direction.DOWN, Block.box(3, 3, 3, 13, 16, 13)); + MEDIUM_SHAPES_OPEN.put(Direction.NORTH, Block.box(3, 3, 3, 13, 13, 16)); + MEDIUM_SHAPES_OPEN.put(Direction.SOUTH, Block.box(3, 3, 0, 13, 13, 13)); + MEDIUM_SHAPES_OPEN.put(Direction.WEST, Block.box(3, 3, 3, 16, 13, 13)); + MEDIUM_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 3, 3, 13, 13, 13)); + + SMALL_SHAPES_OPEN.put(Direction.UP, Block.box(4, 0, 4, 12, 12, 12)); + SMALL_SHAPES_OPEN.put(Direction.DOWN, Block.box(4, 4, 4, 12, 16, 12)); + SMALL_SHAPES_OPEN.put(Direction.NORTH, Block.box(4, 4, 4, 12, 12, 16)); + SMALL_SHAPES_OPEN.put(Direction.SOUTH, Block.box(4, 4, 0, 12, 12, 12)); + SMALL_SHAPES_OPEN.put(Direction.WEST, Block.box(4, 4, 4, 16, 12, 12)); + SMALL_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 4, 4, 12, 12, 12)); + } + + @Override + public boolean canPlantOn(Block block) { + return true; + } + + @Override + @Environment(EnvType.CLIENT) + public String getPottedState() { + return "bottom=moss,shape=top,facing=up"; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/PallidiumBlock.java b/src/main/java/org/betterx/betterend/blocks/PallidiumBlock.java new file mode 100644 index 00000000..67edb1c5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/PallidiumBlock.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.phys.BlockHitResult; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndTerrainBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Map; + +public class PallidiumBlock extends EndTerrainBlock { + private final Block nextLevel; + + public PallidiumBlock(String thickness, Block nextLevel) { + super(MaterialColor.COLOR_LIGHT_GRAY); + this.nextLevel = nextLevel; + } + + public boolean canBePotted() { + return this == EndBlocks.PALLIDIUM_FULL; + } + + @Override + public Block getBaseBlock() { + return EndBlocks.UMBRALITH.stone; + } + + @Override + public InteractionResult use(BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (nextLevel == null) { + return InteractionResult.PASS; + } else if (level.isClientSide) { + return InteractionResult.PASS; + } + + ItemStack itemStack = player.getItemInHand(hand); + if (itemStack.is(Items.BONE_MEAL)) { + BlocksHelper.setWithUpdate(level, pos, nextLevel); + if (!player.isCreative()) { + itemStack.shrink(1); + } + return InteractionResult.SUCCESS; + } + return InteractionResult.PASS; + } + + @Override + @Environment(EnvType.CLIENT) + public UnbakedModel getModelVariant(ResourceLocation stateId, + BlockState blockState, + Map modelCache) { + return this.getBlockModel(stateId, blockState); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/PedestalVanilla.java b/src/main/java/org/betterx/betterend/blocks/PedestalVanilla.java new file mode 100644 index 00000000..44dd28ae --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/PedestalVanilla.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; + +import org.betterx.betterend.blocks.basis.PedestalBlock; + +import java.util.HashMap; +import java.util.Map; + +public class PedestalVanilla extends PedestalBlock { + + public PedestalVanilla(Block parent) { + super(parent); + } + + @Override + protected Map createTexturesMap() { + ResourceLocation blockId = Registry.BLOCK.getKey(parent); + String name = blockId.getPath().replace("_block", ""); + return new HashMap() { + private static final long serialVersionUID = 1L; + + { + put("%mod%", blockId.getNamespace()); + put("%top%", "polished_" + name); + put("%base%", "polished_" + name); + put("%pillar%", name + "_pillar"); + put("%bottom%", "polished_" + name); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/PondAnemoneBlock.java b/src/main/java/org/betterx/betterend/blocks/PondAnemoneBlock.java new file mode 100644 index 00000000..cc5547ca --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/PondAnemoneBlock.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock; + +public class PondAnemoneBlock extends EndUnderwaterPlantBlock implements AddMineableShears { + private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14); + + public PondAnemoneBlock() { + super(FabricBlockSettings.of(Material.WATER_PLANT) + + .luminance(13) + .sound(SoundType.CORAL_BLOCK) + .noCollission() + .offsetType(OffsetType.NONE)); + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + double x = pos.getX() + random.nextDouble(); + double y = pos.getY() + random.nextDouble() * 0.5F + 0.5F; + double z = pos.getZ() + random.nextDouble(); + world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0.0D, 0.0D, 0.0D); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/PythadendronSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/PythadendronSaplingBlock.java new file mode 100644 index 00000000..0140db8d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/PythadendronSaplingBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class PythadendronSaplingBlock extends PottableFeatureSapling { + public PythadendronSaplingBlock() { + super((state) -> EndFeatures.PYTHADENDRON_TREE.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.CHORUS_NYLIUM); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.CHORUS_NYLIUM; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/RespawnObeliskBlock.java b/src/main/java/org/betterx/betterend/blocks/RespawnObeliskBlock.java new file mode 100644 index 00000000..cd9e0f0c --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/RespawnObeliskBlock.java @@ -0,0 +1,214 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.betterend.particle.InfusionParticleType; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class RespawnObeliskBlock extends BaseBlock implements CustomColorProvider, RenderLayerProvider { + private static final VoxelShape VOXEL_SHAPE_BOTTOM = Block.box(1, 0, 1, 15, 16, 15); + private static final VoxelShape VOXEL_SHAPE_MIDDLE_TOP = Block.box(2, 0, 2, 14, 16, 14); + + public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; + + public RespawnObeliskBlock() { + super(FabricBlockSettings.copyOf(Blocks.END_STONE).luminance((state) -> { + return (state.getValue(SHAPE) == TripleShape.BOTTOM) ? 0 : 15; + })); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return (state.getValue(SHAPE) == TripleShape.BOTTOM) ? VOXEL_SHAPE_BOTTOM : VOXEL_SHAPE_MIDDLE_TOP; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(SHAPE); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + for (int i = 0; i < 3; i++) { + if (!world.getBlockState(pos.above(i)).getMaterial().isReplaceable()) { + return false; + } + } + return true; + } + + @Override + public void setPlacedBy(Level world, + BlockPos pos, + BlockState state, + @Nullable LivingEntity placer, + ItemStack itemStack) { + state = this.defaultBlockState(); + BlocksHelper.setWithUpdate(world, pos, state.setValue(SHAPE, TripleShape.BOTTOM)); + BlocksHelper.setWithUpdate(world, pos.above(), state.setValue(SHAPE, TripleShape.MIDDLE)); + BlocksHelper.setWithUpdate(world, pos.above(2), state.setValue(SHAPE, TripleShape.TOP)); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + TripleShape shape = state.getValue(SHAPE); + if (shape == TripleShape.BOTTOM) { + if (world.getBlockState(pos.above()).is(this)) { + return state; + } else { + return Blocks.AIR.defaultBlockState(); + } + } else if (shape == TripleShape.MIDDLE) { + if (world.getBlockState(pos.above()).is(this) && world.getBlockState(pos.below()).is(this)) { + return state; + } else { + return Blocks.AIR.defaultBlockState(); + } + } else { + if (world.getBlockState(pos.below()).is(this)) { + return state; + } else { + return Blocks.AIR.defaultBlockState(); + } + } + } + + @Override + public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { + if (player.isCreative()) { + TripleShape shape = state.getValue(SHAPE); + if (shape == TripleShape.MIDDLE) { + BlocksHelper.setWithUpdate(world, pos.below(), Blocks.AIR); + } else if (shape == TripleShape.TOP) { + BlocksHelper.setWithUpdate(world, pos.below(2), Blocks.AIR); + } + } + super.playerWillDestroy(world, pos, state, player); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.getValue(SHAPE) == TripleShape.BOTTOM) { + return Lists.newArrayList(new ItemStack(this)); + } else { + return Lists.newArrayList(); + } + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + public BlockColor getProvider() { + return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getProvider(); + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> { + return ColorUtil.color(255, 255, 255); + }; + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level world, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + ItemStack itemStack = player.getItemInHand(hand); + boolean canActivate = itemStack.getItem() == EndItems.AMBER_GEM && itemStack.getCount() > 5; + if (hand != InteractionHand.MAIN_HAND || !canActivate) { + if (!world.isClientSide && !(itemStack.getItem() instanceof BlockItem) && !player.isCreative()) { + ServerPlayer serverPlayerEntity = (ServerPlayer) player; + serverPlayerEntity.displayClientMessage( + Component.translatable("message.betterend.fail_spawn"), + true + ); + } + return InteractionResult.FAIL; + } else if (!world.isClientSide) { + ServerPlayer serverPlayerEntity = (ServerPlayer) player; + serverPlayerEntity.setRespawnPosition(world.dimension(), pos, 0.0F, false, false); + serverPlayerEntity.displayClientMessage(Component.translatable("message.betterend.set_spawn"), true); + double px = pos.getX() + 0.5; + double py = pos.getY() + 0.5; + double pz = pos.getZ() + 0.5; + InfusionParticleType particle = new InfusionParticleType(new ItemStack(EndItems.AMBER_GEM)); + if (world instanceof ServerLevel) { + double py1 = py; + double py2 = py - 0.2; + if (state.getValue(SHAPE) == TripleShape.BOTTOM) { + py1 += 1; + py2 += 2; + } else if (state.getValue(SHAPE) == TripleShape.MIDDLE) { + py1 += 0; + py2 += 1; + } else { + py1 -= 2; + } + ((ServerLevel) world).sendParticles(particle, px, py1, pz, 20, 0.14, 0.5, 0.14, 0.1); + ((ServerLevel) world).sendParticles(particle, px, py2, pz, 20, 0.14, 0.3, 0.14, 0.1); + } + world.playSound(null, px, py, py, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1F, 1F); + if (!player.isCreative()) { + itemStack.shrink(6); + } + } + return player.isCreative() ? InteractionResult.PASS : InteractionResult.sidedSuccess(world.isClientSide); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/RunedFlavolite.java b/src/main/java/org/betterx/betterend/blocks/RunedFlavolite.java new file mode 100644 index 00000000..7cceeb4e --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/RunedFlavolite.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class RunedFlavolite extends BaseBlock { + public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; + + public RunedFlavolite(boolean unbreakable) { + super(FabricBlockSettings.copyOf(EndBlocks.FLAVOLITE.polished) + .strength( + unbreakable ? -1 : 1, + unbreakable + ? Blocks.BEDROCK.getExplosionResistance() + : Blocks.OBSIDIAN.getExplosionResistance() + ) + .luminance(state -> { + return state.getValue(ACTIVATED) ? 8 : 0; + })); + this.registerDefaultState(stateDefinition.any().setValue(ACTIVATED, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(ACTIVATED); + } + + @Override + public boolean dropFromExplosion(Explosion explosion) { + return !BlocksHelper.isInvulnerableUnsafe(this.defaultBlockState()); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + if (BlocksHelper.isInvulnerableUnsafe(this.defaultBlockState())) { + return Lists.newArrayList(); + } + return super.getDrops(state, builder); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/ShadowBerryBlock.java b/src/main/java/org/betterx/betterend/blocks/ShadowBerryBlock.java new file mode 100644 index 00000000..6b95695a --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/ShadowBerryBlock.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import org.betterx.betterend.blocks.basis.PottableCropBlock; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class ShadowBerryBlock extends PottableCropBlock { + private static final VoxelShape SHAPE = Block.box(1, 0, 1, 15, 8, 15); + + public ShadowBerryBlock() { + super(EndItems.SHADOW_BERRY_RAW, EndBlocks.SHADOW_GRASS); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return SHAPE; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/ShadowGrassBlock.java b/src/main/java/org/betterx/betterend/blocks/ShadowGrassBlock.java new file mode 100644 index 00000000..287b438c --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/ShadowGrassBlock.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.interfaces.TagProvider; +import org.betterx.betterend.blocks.basis.EndTerrainBlock; +import org.betterx.betterend.registry.EndParticles; + +import java.util.List; + +public class ShadowGrassBlock extends EndTerrainBlock implements TagProvider { + public ShadowGrassBlock() { + super(MaterialColor.COLOR_BLACK); + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + super.animateTick(state, world, pos, random); + if (random.nextInt(32) == 0) { + world.addParticle( + EndParticles.BLACK_SPORE, + (double) pos.getX() + random.nextDouble(), + (double) pos.getY() + 1.1D, + (double) pos.getZ() + random.nextDouble(), + 0.0D, + 0.0D, + 0.0D + ); + } + } + + @Override + public void addTags(List> blockTags, List> itemTags) { + blockTags.add(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SilkMothHiveBlock.java b/src/main/java/org/betterx/betterend/blocks/SilkMothHiveBlock.java new file mode 100644 index 00000000..54eb72df --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SilkMothHiveBlock.java @@ -0,0 +1,131 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +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.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +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.IntegerProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.items.tool.BaseShearsItem; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.entity.SilkMothEntity; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndItems; + +public class SilkMothHiveBlock extends BaseBlock { + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final IntegerProperty FULLNESS = EndBlockProperties.FULLNESS; + + public SilkMothHiveBlock() { + super(FabricBlockSettings.of(Material.WOOD) + .hardness(0.5F) + .resistance(0.1F) + .sound(SoundType.WOOL) + .noOcclusion() + .randomTicks()); + this.registerDefaultState(defaultBlockState().setValue(FULLNESS, 0)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(FACING, FULLNESS); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + Direction dir = ctx.getHorizontalDirection().getOpposite(); + return this.defaultBlockState().setValue(FACING, dir); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState rotate(BlockState state, Rotation rotation) { + return BlocksHelper.rotateHorizontal(state, rotation, FACING); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirror) { + return BlocksHelper.mirrorHorizontal(state, mirror, FACING); + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + Direction dir = state.getValue(FACING); + BlockPos spawn = pos.relative(dir); + if (!world.getBlockState(spawn).isAir()) { + return; + } + int count = world.getEntities(EndEntities.SILK_MOTH, new AABB(pos).inflate(16), (entity) -> { + return true; + }).size(); + if (count > 6) { + return; + } + SilkMothEntity moth = new SilkMothEntity(EndEntities.SILK_MOTH, world); + moth.moveTo(spawn.getX() + 0.5, spawn.getY() + 0.5, spawn.getZ() + 0.5, dir.toYRot(), 0); + moth.setDeltaMovement(new Vec3(dir.getStepX() * 0.4, 0, dir.getStepZ() * 0.4)); + moth.setHive(world, pos); + world.addFreshEntity(moth); + world.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1, 1); + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level world, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (hand == InteractionHand.MAIN_HAND) { + ItemStack stack = player.getMainHandItem(); + if (BaseShearsItem.isShear(stack) && state.getValue(FULLNESS) == 3) { + BlocksHelper.setWithUpdate(world, pos, state.setValue(FULLNESS, 0)); + Direction dir = state.getValue(FACING); + double px = pos.getX() + dir.getStepX() + 0.5; + double py = pos.getY() + dir.getStepY() + 0.5; + double pz = pos.getZ() + dir.getStepZ() + 0.5; + ItemStack drop = new ItemStack(EndItems.SILK_FIBER, MHelper.randRange(8, 16, world.getRandom())); + ItemEntity entity = new ItemEntity(world, px, py, pz, drop); + world.addFreshEntity(entity); + if (world.getRandom().nextInt(4) == 0) { + drop = new ItemStack(EndItems.SILK_MOTH_MATRIX); + entity = new ItemEntity(world, px, py, pz, drop); + world.addFreshEntity(entity); + } + if (!player.isCreative()) { + stack.setDamageValue(stack.getDamageValue() + 1); + } + return InteractionResult.SUCCESS; + } + } + return InteractionResult.FAIL; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SilkMothNestBlock.java b/src/main/java/org/betterx/betterend/blocks/SilkMothNestBlock.java new file mode 100644 index 00000000..25b4b83b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SilkMothNestBlock.java @@ -0,0 +1,194 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +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.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.items.tool.BaseShearsItem; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.entity.SilkMothEntity; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndItems; + +import java.util.Collections; +import java.util.List; + +public class SilkMothNestBlock extends BaseBlock implements RenderLayerProvider { + public static final BooleanProperty ACTIVE = EndBlockProperties.ACTIVE; + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final IntegerProperty FULLNESS = EndBlockProperties.FULLNESS; + private static final VoxelShape TOP = box(6, 0, 6, 10, 16, 10); + private static final VoxelShape BOTTOM = box(0, 0, 0, 16, 16, 16); + + public SilkMothNestBlock() { + super(FabricBlockSettings.of(Material.WOOL) + .hardness(0.5F) + .resistance(0.1F) + .sound(SoundType.WOOL) + .noOcclusion() + .randomTicks()); + this.registerDefaultState(defaultBlockState().setValue(ACTIVE, true).setValue(FULLNESS, 0)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(ACTIVE, FACING, FULLNESS); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(ACTIVE) ? BOTTOM : TOP; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + Direction dir = ctx.getHorizontalDirection().getOpposite(); + return this.defaultBlockState().setValue(FACING, dir); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + if (!state.getValue(ACTIVE)) { + if (canSupportCenter(world, pos.above(), Direction.DOWN) || world.getBlockState(pos.above()) + .is(BlockTags.LEAVES)) { + return state; + } else { + return Blocks.AIR.defaultBlockState(); + } + } + return state; + } + + @Override + @SuppressWarnings("deprecation") + public BlockState rotate(BlockState state, Rotation rotation) { + return BlocksHelper.rotateHorizontal(state, rotation, FACING); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirror) { + return BlocksHelper.mirrorHorizontal(state, mirror, FACING); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return state.getValue(ACTIVE) ? Collections.singletonList(new ItemStack(this)) : Collections.emptyList(); + } + + @Override + public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { + if (!state.getValue(ACTIVE) && player.isCreative()) { + BlocksHelper.setWithUpdate(world, pos.below(), Blocks.AIR); + } + BlockState up = world.getBlockState(pos.above()); + if (up.is(this) && !up.getValue(ACTIVE)) { + BlocksHelper.setWithUpdate(world, pos.above(), Blocks.AIR); + } + super.playerWillDestroy(world, pos, state, player); + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (!state.getValue(ACTIVE)) { + return; + } + if (random.nextBoolean()) { + return; + } + Direction dir = state.getValue(FACING); + BlockPos spawn = pos.relative(dir); + if (!world.getBlockState(spawn).isAir()) { + return; + } + int count = world.getEntities(EndEntities.SILK_MOTH, new AABB(pos).inflate(16), (entity) -> { + return true; + }).size(); + if (count > 6) { + return; + } + SilkMothEntity moth = new SilkMothEntity(EndEntities.SILK_MOTH, world); + moth.moveTo(spawn.getX() + 0.5, spawn.getY() + 0.5, spawn.getZ() + 0.5, dir.toYRot(), 0); + moth.setDeltaMovement(new Vec3(dir.getStepX() * 0.4, 0, dir.getStepZ() * 0.4)); + moth.setHive(world, pos); + world.addFreshEntity(moth); + world.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1, 1); + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level world, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (hand == InteractionHand.MAIN_HAND) { + ItemStack stack = player.getMainHandItem(); + if (BaseShearsItem.isShear(stack) && state.getValue(ACTIVE) && state.getValue(FULLNESS) == 3) { + BlocksHelper.setWithUpdate(world, pos, state.setValue(FULLNESS, 0)); + Direction dir = state.getValue(FACING); + double px = pos.getX() + dir.getStepX() + 0.5; + double py = pos.getY() + dir.getStepY() + 0.5; + double pz = pos.getZ() + dir.getStepZ() + 0.5; + ItemStack drop = new ItemStack(EndItems.SILK_FIBER, MHelper.randRange(1, 4, world.getRandom())); + ItemEntity entity = new ItemEntity(world, px, py, pz, drop); + world.addFreshEntity(entity); + drop = new ItemStack(EndItems.SILK_MOTH_MATRIX, MHelper.randRange(1, 3, world.getRandom())); + entity = new ItemEntity(world, px, py, pz, drop); + world.addFreshEntity(entity); + if (!player.isCreative()) { + stack.setDamageValue(stack.getDamageValue() + 1); + } + return InteractionResult.SUCCESS; + } + } + return InteractionResult.FAIL; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SmallAmaranitaBlock.java b/src/main/java/org/betterx/betterend/blocks/SmallAmaranitaBlock.java new file mode 100644 index 00000000..385fea09 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SmallAmaranitaBlock.java @@ -0,0 +1,90 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +import java.util.Optional; + +public class SmallAmaranitaBlock extends EndPlantBlock { + private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 10, 12); + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.SANGNUM) || state.is(EndBlocks.MOSSY_OBSIDIAN) || state.is(EndBlocks.MOSSY_DRAGON_BONE); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + BlockPos bigPos = growBig(world, pos); + if (bigPos != null) { + if (EndFeatures.GIGANTIC_AMARANITA.getFeature() + .place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, bigPos, null))) { + replaceMushroom(world, bigPos); + replaceMushroom(world, bigPos.south()); + replaceMushroom(world, bigPos.east()); + replaceMushroom(world, bigPos.south().east()); + } + return; + } + EndFeatures.LARGE_AMARANITA.getFeature().place(new FeaturePlaceContext<>( + Optional.empty(), + world, + null, + random, + pos, + null)); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + Vec3 vec3d = state.getOffset(view, pos); + return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); + } + + private BlockPos growBig(ServerLevel world, BlockPos pos) { + for (int x = -1; x < 2; x++) { + for (int z = -1; z < 2; z++) { + BlockPos p = pos.offset(x, 0, z); + if (checkFrame(world, p)) { + return p; + } + } + } + return null; + } + + private boolean checkFrame(ServerLevel world, BlockPos pos) { + return world.getBlockState(pos).is(this) && world.getBlockState(pos.south()).is(this) && world.getBlockState(pos + .east()) + .is(this) && world.getBlockState( + pos.south().east()).is(this); + } + + private void replaceMushroom(ServerLevel world, BlockPos pos) { + if (world.getBlockState(pos).is(this)) { + BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); + } + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return random.nextInt(8) == 0; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SmallJellyshroomBlock.java b/src/main/java/org/betterx/betterend/blocks/SmallJellyshroomBlock.java new file mode 100644 index 00000000..3a230c88 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SmallJellyshroomBlock.java @@ -0,0 +1,128 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.BonemealableBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.items.tool.BaseShearsItem; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.interfaces.PottablePlant; +import org.betterx.betterend.registry.EndFeatures; + +import java.util.EnumMap; +import java.util.List; +import java.util.Optional; + +public class SmallJellyshroomBlock extends BaseAttachedBlock implements RenderLayerProvider, BonemealableBlock, PottablePlant { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + + public SmallJellyshroomBlock() { + super(FabricBlockSettings.of(Material.PLANT).sound(SoundType.NETHER_WART).noCollission()); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( + Enchantments.SILK_TOUCH, + tool + ) > 0) { + return Lists.newArrayList(new ItemStack(this)); + } else { + return Lists.newArrayList(); + } + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos blockPos = pos.relative(direction.getOpposite()); + BlockState support = world.getBlockState(blockPos); + return canSupportCenter(world, blockPos, direction) && support.canOcclude() && support.getLightEmission() == 0; + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Block.box(3, 0, 3, 13, 16, 13)); + BOUNDING_SHAPES.put(Direction.DOWN, Block.box(3, 0, 3, 13, 16, 13)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return state.getValue(FACING) == Direction.UP && world.getBlockState(pos.below()) + .is(CommonBlockTags.END_STONES); + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return random.nextInt(16) == 0; + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); + EndFeatures.JELLYSHROOM.getFeature().place(new FeaturePlaceContext<>( + Optional.empty(), + world, + null, + random, + pos, + null)); + } + + @Override + public boolean canPlantOn(Block block) { + return true; + } + + @Override + @Environment(EnvType.CLIENT) + public String getPottedState() { + return "facing=up"; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalBlock.java b/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalBlock.java new file mode 100644 index 00000000..5b2f540f --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalBlock.java @@ -0,0 +1,20 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; +import org.betterx.betterend.blocks.basis.LitPillarBlock; + +public class SmaragdantCrystalBlock extends LitPillarBlock implements AddMineablePickaxe { + public SmaragdantCrystalBlock() { + super(FabricBlockSettings.of(Material.GLASS) + .luminance(15) + .hardness(1F) + .resistance(1F) + .noOcclusion() + .sound(SoundType.AMETHYST)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalShardBlock.java b/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalShardBlock.java new file mode 100644 index 00000000..9b40862d --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SmaragdantCrystalShardBlock.java @@ -0,0 +1,104 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.LiquidBlockContainer; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.material.*; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; + +import java.util.EnumMap; + +@SuppressWarnings("deprecation") +public class SmaragdantCrystalShardBlock extends BaseAttachedBlock implements AddMineablePickaxe, RenderLayerProvider, SimpleWaterloggedBlock, LiquidBlockContainer { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + + public SmaragdantCrystalShardBlock() { + super(FabricBlockSettings.of(Material.STONE) + .materialColor(MaterialColor.COLOR_GREEN) + .luminance(15) + .sound(SoundType.AMETHYST_CLUSTER) + .requiresCorrectToolForDrops() + .noCollission()); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + super.createBlockStateDefinition(stateManager); + stateManager.add(WATERLOGGED); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { + return !state.getValue(WATERLOGGED); + } + + @Override + public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { + return !state.getValue(WATERLOGGED); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + BlockState state = super.getStateForPlacement(ctx); + if (state != null) { + LevelReader worldView = ctx.getLevel(); + BlockPos blockPos = ctx.getClickedPos(); + boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; + return state.setValue(WATERLOGGED, water); + } + return null; + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos blockPos = pos.relative(direction.getOpposite()); + return world.getBlockState(blockPos).isFaceSturdy(world, blockPos, direction); + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.125, 0.0, 0.125, 0.875F, 0.875F, 0.875F)); + BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.125, 0.125, 0.125, 0.875F, 1.0, 0.875F)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.125, 0.125, 0.125, 0.875F, 0.875F, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.125, 0.125, 0.0, 0.875F, 0.875F, 0.875F)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.125, 0.125, 0.125, 1.0, 0.875F, 0.875F)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.125, 0.125, 0.875F, 0.875F, 0.875F)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/SulphurCrystalBlock.java b/src/main/java/org/betterx/betterend/blocks/SulphurCrystalBlock.java new file mode 100644 index 00000000..9e018849 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/SulphurCrystalBlock.java @@ -0,0 +1,121 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.LiquidBlockContainer; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.material.*; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineablePickaxe; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; + +@SuppressWarnings("deprecation") +public class SulphurCrystalBlock extends BaseAttachedBlock implements AddMineablePickaxe, RenderLayerProvider, SimpleWaterloggedBlock, LiquidBlockContainer { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + public static final IntegerProperty AGE = IntegerProperty.create("age", 0, 2); + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + + public SulphurCrystalBlock() { + super(FabricBlockSettings.of(Material.STONE) + .materialColor(MaterialColor.COLOR_YELLOW) + .sound(SoundType.GLASS) + .requiresCorrectToolForDrops() + .noCollission()); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + super.createBlockStateDefinition(stateManager); + stateManager.add(AGE, WATERLOGGED); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + return state.getValue(AGE) < 2 ? Collections.emptyList() : Lists.newArrayList(new ItemStack( + EndItems.CRYSTALLINE_SULPHUR, + MHelper.randRange(1, 3, MHelper.RANDOM_SOURCE) + )); + } + + @Override + public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { + return !state.getValue(WATERLOGGED); + } + + @Override + public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { + return !state.getValue(WATERLOGGED); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + BlockState state = super.getStateForPlacement(ctx); + if (state != null) { + LevelReader worldView = ctx.getLevel(); + BlockPos blockPos = ctx.getClickedPos(); + boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; + return state.setValue(WATERLOGGED, water); + } + return null; + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos blockPos = pos.relative(direction.getOpposite()); + return world.getBlockState(blockPos).is(EndBlocks.BRIMSTONE); + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.125, 0.0, 0.125, 0.875F, 0.5, 0.875F)); + BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.125, 0.5, 0.125, 0.875F, 1.0, 0.875F)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.125, 0.125, 0.5, 0.875F, 0.875F, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.125, 0.125, 0.0, 0.875F, 0.875F, 0.5)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.125, 0.125, 1.0, 0.875F, 0.875F)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.125, 0.125, 0.5, 0.875F, 0.875F)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/TenaneaFlowersBlock.java b/src/main/java/org/betterx/betterend/blocks/TenaneaFlowersBlock.java new file mode 100644 index 00000000..278b8599 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/TenaneaFlowersBlock.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndParticles; + +public class TenaneaFlowersBlock extends BaseVineBlock implements CustomColorProvider { + public static final Vec3i[] COLORS; + + public TenaneaFlowersBlock() { + super(15); + } + + @Override + public BlockColor getProvider() { + return (state, world, pos, tintIndex) -> { + if (pos == null) { + pos = BlockPos.ZERO; + } + long i = (MHelper.getRandom(pos.getX(), pos.getZ()) & 63) + pos.getY(); + double delta = i * 0.1; + int index = MHelper.floor(delta); + int index2 = (index + 1) & 3; + delta -= index; + index &= 3; + + Vec3i color1 = COLORS[index]; + Vec3i color2 = COLORS[index2]; + + int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); + int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); + int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); + float[] hsb = ColorUtil.RGBtoHSB(r, g, b, new float[3]); + + return ColorUtil.HSBtoRGB(hsb[0], MHelper.max(0.5F, hsb[1]), hsb[2]); + }; + } + + @Override + public ItemColor getItemProvider() { + return (stack, tintIndex) -> ColorUtil.color(255, 255, 255); + } + + @Override + public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { + return false; + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + super.animateTick(state, world, pos, random); + if (random.nextInt(32) == 0) { + double x = (double) pos.getX() + random.nextGaussian() + 0.5; + double z = (double) pos.getZ() + random.nextGaussian() + 0.5; + double y = (double) pos.getY() + random.nextDouble(); + world.addParticle(EndParticles.TENANEA_PETAL, x, y, z, 0, 0, 0); + } + } + + static { + COLORS = new Vec3i[]{ + new Vec3i(250, 111, 222), + new Vec3i(167, 89, 255), + new Vec3i(120, 207, 239), + new Vec3i(255, 87, 182) + }; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/TenaneaSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/TenaneaSaplingBlock.java new file mode 100644 index 00000000..d06ea355 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/TenaneaSaplingBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class TenaneaSaplingBlock extends PottableFeatureSapling { + public TenaneaSaplingBlock() { + super((state) -> EndFeatures.TENANEA.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.PINK_MOSS); + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.PINK_MOSS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/TerrainPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/TerrainPlantBlock.java new file mode 100644 index 00000000..1e6b646e --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/TerrainPlantBlock.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.blocks.basis.EndPlantBlock; + +public class TerrainPlantBlock extends EndPlantBlock { + private final Block[] ground; + + public TerrainPlantBlock(Block... ground) { + super(true); + this.ground = ground; + } + + @Override + protected boolean isTerrain(BlockState state) { + for (Block block : ground) { + if (state.is(block)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossBlock.java b/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossBlock.java new file mode 100644 index 00000000..4fb3f1c7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossBlock.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class TwistedUmbrellaMossBlock extends EndPlantBlock { + public TwistedUmbrellaMossBlock() { + super(11); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); + } + + @Environment(EnvType.CLIENT) + public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { + return true; + } + + @Environment(EnvType.CLIENT) + public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { + return 1F; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return world.isEmptyBlock(pos.above()); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + int rot = world.random.nextInt(4); + BlockState bs = EndBlocks.TWISTED_UMBRELLA_MOSS_TALL.defaultBlockState() + .setValue(BaseDoublePlantBlock.ROTATION, rot); + BlocksHelper.setWithoutUpdate(world, pos, bs); + BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(BaseDoublePlantBlock.TOP, true)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossTallBlock.java b/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossTallBlock.java new file mode 100644 index 00000000..ea36bf2a --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/TwistedUmbrellaMossTallBlock.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class TwistedUmbrellaMossTallBlock extends BaseDoublePlantBlock { + public TwistedUmbrellaMossTallBlock() { + super(12); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + ItemEntity item = new ItemEntity( + world, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + new ItemStack(EndBlocks.TWISTED_UMBRELLA_MOSS) + ); + world.addFreshEntity(item); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaMossBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaMossBlock.java new file mode 100644 index 00000000..084f3486 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaMossBlock.java @@ -0,0 +1,50 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class UmbrellaMossBlock extends EndPlantBlock { + public UmbrellaMossBlock() { + super(11); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); + } + + @Environment(EnvType.CLIENT) + public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { + return true; + } + + @Environment(EnvType.CLIENT) + public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { + return 1F; + } + + @Override + public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { + return world.isEmptyBlock(pos.above()); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + int rot = world.random.nextInt(4); + BlockState bs = EndBlocks.UMBRELLA_MOSS_TALL.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); + BlocksHelper.setWithoutUpdate(world, pos, bs); + BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(BaseDoublePlantBlock.TOP, true)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaMossTallBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaMossTallBlock.java new file mode 100644 index 00000000..9242acee --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaMossTallBlock.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class UmbrellaMossTallBlock extends BaseDoublePlantBlock { + public UmbrellaMossTallBlock() { + super(12); + } + + @Override + public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { + ItemEntity item = new ItemEntity( + world, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + new ItemStack(EndBlocks.UMBRELLA_MOSS) + ); + world.addFreshEntity(item); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterBlock.java new file mode 100644 index 00000000..c7df32f9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterBlock.java @@ -0,0 +1,79 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.phys.BlockHitResult; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class UmbrellaTreeClusterBlock extends BaseBlock { + public static final BooleanProperty NATURAL = BlockProperties.NATURAL; + + public UmbrellaTreeClusterBlock() { + super(FabricBlockSettings + .copyOf(Blocks.NETHER_WART_BLOCK) + .mapColor(MaterialColor.COLOR_PURPLE) + .luminance(15) + ); + registerDefaultState(stateDefinition.any().setValue(NATURAL, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(NATURAL); + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level world, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + ItemStack stack = player.getMainHandItem(); + if (stack.getItem() == Items.GLASS_BOTTLE) { + if (!player.isCreative()) { + stack.shrink(1); + } + stack = new ItemStack(EndItems.UMBRELLA_CLUSTER_JUICE); + player.addItem(stack); + world.playLocalSound( + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + SoundEvents.BOTTLE_FILL, + SoundSource.BLOCKS, + 1, + 1, + false + ); + BlocksHelper.setWithUpdate( + world, + pos, + EndBlocks.UMBRELLA_TREE_CLUSTER_EMPTY.defaultBlockState().setValue(NATURAL, state.getValue(NATURAL)) + ); + return InteractionResult.SUCCESS; + } + return InteractionResult.FAIL; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java new file mode 100644 index 00000000..ce2470e7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class UmbrellaTreeClusterEmptyBlock extends BaseBlock { + public static final BooleanProperty NATURAL = EndBlockProperties.NATURAL; + + public UmbrellaTreeClusterEmptyBlock() { + super(FabricBlockSettings + .copyOf(Blocks.NETHER_WART_BLOCK) + .mapColor(MaterialColor.COLOR_PURPLE) + .randomTicks() + ); + registerDefaultState(stateDefinition.any().setValue(NATURAL, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(NATURAL); + } + + @Override + @SuppressWarnings("deprecation") + public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + if (state.getValue(NATURAL) && random.nextInt(16) == 0) { + BlocksHelper.setWithUpdate( + world, + pos, + EndBlocks.UMBRELLA_TREE_CLUSTER.defaultBlockState().setValue(UmbrellaTreeClusterBlock.NATURAL, true) + ); + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeMembraneBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeMembraneBlock.java new file mode 100644 index 00000000..a74083b7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeMembraneBlock.java @@ -0,0 +1,91 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SlimeBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.storage.loot.LootContext; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.BlockModelProvider; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Collections; +import java.util.List; + +public class UmbrellaTreeMembraneBlock extends SlimeBlock implements RenderLayerProvider, BlockModelProvider { + public static final IntegerProperty COLOR = EndBlockProperties.COLOR; + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); + + public UmbrellaTreeMembraneBlock() { + super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + double px = ctx.getClickedPos().getX() * 0.1; + double py = ctx.getClickedPos().getY() * 0.1; + double pz = ctx.getClickedPos().getZ() * 0.1; + return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(COLOR); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState state, LootContext.Builder builder) { + if (state.getValue(COLOR) > 0) { + return Lists.newArrayList(new ItemStack(this)); + } else { + return MHelper.RANDOM.nextInt(4) == 0 + ? Lists.newArrayList(new ItemStack(EndBlocks.UMBRELLA_TREE_SAPLING)) + : Collections + .emptyList(); + } + } + + @Override + public boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) { + return state.getValue(COLOR) > 0; + } + + @Environment(EnvType.CLIENT) + public boolean skipRendering(BlockState state, BlockState stateFrom, Direction direction) { + if (state.getValue(COLOR) > 0) { + return super.skipRendering(state, stateFrom, direction); + } else { + return false; + } + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + return getBlockModel(resourceLocation, defaultBlockState()); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeSaplingBlock.java b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeSaplingBlock.java new file mode 100644 index 00000000..1c4a56bb --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/UmbrellaTreeSaplingBlock.java @@ -0,0 +1,32 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.betterend.blocks.basis.PottableFeatureSapling; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; + +public class UmbrellaTreeSaplingBlock extends PottableFeatureSapling { + public UmbrellaTreeSaplingBlock() { + super((state) -> EndFeatures.UMBRELLA_TREE.getFeature()); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + return world.getBlockState(pos.below()).is(EndBlocks.JUNGLE_MOSS); + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.TRANSLUCENT; + } + + @Override + public boolean canPlantOn(Block block) { + return block == EndBlocks.JUNGLE_MOSS; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/VentBubbleColumnBlock.java b/src/main/java/org/betterx/betterend/blocks/VentBubbleColumnBlock.java new file mode 100644 index 00000000..b4667433 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/VentBubbleColumnBlock.java @@ -0,0 +1,169 @@ +package org.betterx.betterend.blocks; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +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.level.material.Material; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Optional; + +public class VentBubbleColumnBlock extends Block implements BucketPickup, LiquidBlockContainer { + public VentBubbleColumnBlock() { + super(FabricBlockSettings.of(Material.BUBBLE_COLUMN).nonOpaque().noCollision().noLootTable()); + } + + @Override + public ItemStack pickupBlock(LevelAccessor world, BlockPos pos, BlockState state) { + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + return new ItemStack(Items.WATER_BUCKET); + } + + @Override + @SuppressWarnings("deprecation") + public RenderShape getRenderShape(BlockState state) { + return RenderShape.INVISIBLE; + } + + @Override + @SuppressWarnings("deprecation") + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState blockState = world.getBlockState(pos.below()); + return blockState.is(this) || blockState.is(EndBlocks.HYDROTHERMAL_VENT); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + if (!state.canSurvive(world, pos)) { + return Blocks.WATER.defaultBlockState(); + } else { + BlockPos up = pos.above(); + if (world.getBlockState(up).is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate(world, up, this); + world.scheduleTick(up, this, 5); + } + } + return state; + } + + @Environment(EnvType.CLIENT) + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + if (random.nextInt(4) == 0) { + double px = pos.getX() + random.nextDouble(); + double py = pos.getY() + random.nextDouble(); + double pz = pos.getZ() + random.nextDouble(); + world.addAlwaysVisibleParticle(ParticleTypes.BUBBLE_COLUMN_UP, px, py, pz, 0, 0.04, 0); + } + if (random.nextInt(200) == 0) { + world.playLocalSound( + pos.getX(), + pos.getY(), + pos.getZ(), + SoundEvents.BUBBLE_COLUMN_UPWARDS_AMBIENT, + SoundSource.BLOCKS, + 0.2F + random.nextFloat() * 0.2F, + 0.9F + random.nextFloat() * 0.15F, + false + ); + } + } + + @Environment(EnvType.CLIENT) + @SuppressWarnings("deprecation") + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + BlockState blockState = world.getBlockState(pos.above()); + if (blockState.isAir()) { + entity.onAboveBubbleCol(false); + if (!world.isClientSide) { + ServerLevel serverWorld = (ServerLevel) world; + + for (int i = 0; i < 2; ++i) { + serverWorld.sendParticles( + ParticleTypes.SPLASH, + (double) pos.getX() + world.random.nextDouble(), + pos.getY() + 1, + (double) pos.getZ() + world.random.nextDouble(), + 1, + 0.0D, + 0.0D, + 0.0D, + 1.0D + ); + serverWorld.sendParticles( + ParticleTypes.BUBBLE, + (double) pos.getX() + world.random.nextDouble(), + pos.getY() + 1, + (double) pos.getZ() + world.random.nextDouble(), + 1, + 0.0D, + 0.01D, + 0.0D, + 0.2D + ); + } + } + } else { + entity.onInsideBubbleColumn(false); + } + } + + @Override + public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { + return false; + } + + @Override + public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { + return false; + } + + @Override + @SuppressWarnings("deprecation") + public FluidState getFluidState(BlockState state) { + return Fluids.WATER.getSource(false); + } + + + @Override + public Optional getPickupSound() { + return Fluids.WATER.getPickupSound(); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndAnvilBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndAnvilBlock.java new file mode 100644 index 00000000..175d7176 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndAnvilBlock.java @@ -0,0 +1,23 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.material.MaterialColor; + +import org.betterx.bclib.blocks.LeveledAnvilBlock; +import org.betterx.betterend.complexmaterials.MetalMaterial; + +public class EndAnvilBlock extends LeveledAnvilBlock { + protected MetalMaterial metalMaterial; + + public EndAnvilBlock(MaterialColor color, int level) { + super(color, level); + } + + public EndAnvilBlock(MetalMaterial metalMaterial, MaterialColor color, int level) { + super(color, level); + this.metalMaterial = metalMaterial; + } + + public int getCraftingLevel() { + return level; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndLanternBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndLanternBlock.java new file mode 100644 index 00000000..85a2007e --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndLanternBlock.java @@ -0,0 +1,136 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LiquidBlockContainer; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.state.BlockState; +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.BooleanProperty; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.client.models.ModelsHelper; + +import java.util.Map; + +@SuppressWarnings("deprecation") +public class EndLanternBlock extends BaseBlockNotFull implements SimpleWaterloggedBlock, LiquidBlockContainer { + public static final BooleanProperty IS_FLOOR = BlockProperties.IS_FLOOR; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + + public EndLanternBlock(Block source) { + this(FabricBlockSettings.copyOf(source).luminance(15).noOcclusion()); + } + + public EndLanternBlock(Properties settings) { + super(settings.noOcclusion()); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(IS_FLOOR, WATERLOGGED); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + LevelReader worldView = ctx.getLevel(); + BlockPos blockPos = ctx.getClickedPos(); + Direction dir = ctx.getClickedFace(); + boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; + if (dir != Direction.DOWN && dir != Direction.UP) { + if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { + return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); + } else if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { + return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); + } else { + return null; + } + } else if (dir == Direction.DOWN) { + if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { + return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); + } else if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { + return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); + } else { + return null; + } + } else { + if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { + return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); + } else if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { + return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); + } else { + return null; + } + } + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + if (state.getValue(IS_FLOOR)) { + return canSupportCenter(world, pos.below(), Direction.UP); + } else { + return canSupportCenter(world, pos.above(), Direction.DOWN); + } + } + + @Override + public BlockState updateShape(BlockState state, + Direction facing, + BlockState neighborState, + LevelAccessor world, + BlockPos pos, + BlockPos neighborPos) { + Boolean water = state.getValue(WATERLOGGED); + if (water) { + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + if (!canSurvive(state, world, pos)) { + return water ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); + } else { + return state; + } + } + + @Override + public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { + return false; + } + + @Override + public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { + return false; + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + @Environment(EnvType.CLIENT) + public UnbakedModel getModelVariant(ResourceLocation stateId, + BlockState blockState, + Map modelCache) { + String floor = blockState.getValue(IS_FLOOR) ? "_floor" : ""; + ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath() + floor); + registerBlockModel(stateId, modelId, blockState, modelCache); + return ModelsHelper.createBlockSimple(modelId); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndPlantBlock.java new file mode 100644 index 00000000..26226995 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndPlantBlock.java @@ -0,0 +1,59 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BasePlantBlock; +import org.betterx.betterend.interfaces.PottablePlant; + +import java.util.function.Function; + +public class EndPlantBlock extends BasePlantBlock implements PottablePlant { + public EndPlantBlock() { + this(false, p -> p); + } + + public EndPlantBlock(int light) { + this(light, p -> p); + } + + public EndPlantBlock(int light, Function propMod) { + this(false, light, propMod); + } + + public EndPlantBlock(boolean replaceable) { + super(replaceable); + } + + public EndPlantBlock(boolean replaceable, Function propMod) { + super(replaceable, propMod); + } + + public EndPlantBlock(boolean replaceable, int light) { + this(replaceable, light, p -> p); + } + + public EndPlantBlock(boolean replaceable, int light, Function propMod) { + super(replaceable, light, propMod); + } + + public EndPlantBlock(Properties settings) { + super(settings); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } + + @Override + public boolean canPlantOn(Block block) { + return isTerrain(block.defaultBlockState()); + } + + @Override + public boolean canBePotted() { + return getStateDefinition().getProperties().isEmpty(); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndPlantWithAgeBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndPlantWithAgeBlock.java new file mode 100644 index 00000000..7ab1aa1f --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndPlantWithAgeBlock.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BasePlantWithAgeBlock; + +import java.util.function.Function; + +public abstract class EndPlantWithAgeBlock extends BasePlantWithAgeBlock { + + public EndPlantWithAgeBlock() { + } + + public EndPlantWithAgeBlock(Function propMod) { + super(propMod); + } + + public EndPlantWithAgeBlock(Properties settings) { + super(settings); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndTerrainBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndTerrainBlock.java new file mode 100644 index 00000000..94dc94e9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndTerrainBlock.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseTerrainBlock; +import org.betterx.bclib.interfaces.TagProvider; +import org.betterx.betterend.interfaces.PottableTerrain; + +import java.util.List; + +public class EndTerrainBlock extends BaseTerrainBlock implements PottableTerrain, TagProvider { + public EndTerrainBlock(MaterialColor color) { + super(Blocks.END_STONE, color); + } + + @Override + public void addTags(List> blockTags, List> itemTags) { + blockTags.add(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndTripleTerrain.java b/src/main/java/org/betterx/betterend/blocks/basis/EndTripleTerrain.java new file mode 100644 index 00000000..80897d4a --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndTripleTerrain.java @@ -0,0 +1,13 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import org.betterx.bclib.blocks.TripleTerrainBlock; +import org.betterx.betterend.interfaces.PottableTerrain; + +public class EndTripleTerrain extends TripleTerrainBlock implements PottableTerrain { + public EndTripleTerrain(MaterialColor color) { + super(Blocks.END_STONE, color); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterPlantBlock.java new file mode 100644 index 00000000..b1f167ee --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterPlantBlock.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.UnderwaterPlantBlock; + +import java.util.function.Function; + +public class EndUnderwaterPlantBlock extends UnderwaterPlantBlock { + + public EndUnderwaterPlantBlock() { + } + + public EndUnderwaterPlantBlock(int light, Function propMod) { + super(light, propMod); + } + + public EndUnderwaterPlantBlock(Properties settings) { + super(settings); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java new file mode 100644 index 00000000..b0427bfc --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseUnderwaterWallPlantBlock; + +public class EndUnderwaterWallPlantBlock extends BaseUnderwaterWallPlantBlock { + + public EndUnderwaterWallPlantBlock() { + } + + public EndUnderwaterWallPlantBlock(int light) { + super(light); + } + + public EndUnderwaterWallPlantBlock(Properties settings) { + super(settings); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndWallMushroom.java b/src/main/java/org/betterx/betterend/blocks/basis/EndWallMushroom.java new file mode 100644 index 00000000..96abea79 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndWallMushroom.java @@ -0,0 +1,18 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.WallMushroomBlock; + +public class EndWallMushroom extends WallMushroomBlock { + + public EndWallMushroom(int light) { + super(light); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/EndWallPlantBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/EndWallPlantBlock.java new file mode 100644 index 00000000..2419fb47 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/EndWallPlantBlock.java @@ -0,0 +1,24 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BaseWallPlantBlock; + +public class EndWallPlantBlock extends BaseWallPlantBlock { + public EndWallPlantBlock() { + } + + public EndWallPlantBlock(int light) { + super(light); + } + + public EndWallPlantBlock(Properties settings) { + super(settings); + } + + @Override + protected boolean isTerrain(BlockState state) { + return state.is(CommonBlockTags.END_STONES); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/FurBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/FurBlock.java new file mode 100644 index 00000000..86b4c5f9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/FurBlock.java @@ -0,0 +1,94 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.api.tag.NamedBlockTags; +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.client.render.BCLRenderLayer; +import org.betterx.bclib.interfaces.RenderLayerProvider; +import org.betterx.bclib.interfaces.tools.AddMineableShears; +import org.betterx.bclib.items.tool.BaseShearsItem; +import org.betterx.bclib.util.MHelper; + +import java.util.EnumMap; +import java.util.List; + +public class FurBlock extends BaseAttachedBlock implements RenderLayerProvider, AddMineableShears { + private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); + private final ItemLike drop; + private final int dropChance; + + public FurBlock(ItemLike drop, int light, int dropChance, boolean wet) { + super(FabricBlockSettings.of(Material.REPLACEABLE_PLANT) + .luminance(light) + .sound(wet ? SoundType.WET_GRASS : SoundType.GRASS) + .noCollission()); + this.drop = drop; + this.dropChance = dropChance; + TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); + } + + public FurBlock(ItemLike drop, int dropChance) { + super(FabricBlockSettings.of(Material.REPLACEABLE_PLANT) + + .sound(SoundType.GRASS) + .noCollission()); + this.drop = drop; + this.dropChance = dropChance; + TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return BOUNDING_SHAPES.get(state.getValue(FACING)); + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( + Enchantments.SILK_TOUCH, + tool + ) > 0) { + return Lists.newArrayList(new ItemStack(this)); + } else if (dropChance < 1 || MHelper.RANDOM.nextInt(dropChance) == 0) { + return Lists.newArrayList(new ItemStack(drop)); + } else { + return Lists.newArrayList(); + } + } + + @Override + public BCLRenderLayer getRenderLayer() { + return BCLRenderLayer.CUTOUT; + } + + static { + BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.0, 0.0, 0.0, 1.0, 0.5, 1.0)); + BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.0, 0.5, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); + BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); + BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/LitBaseBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/LitBaseBlock.java new file mode 100644 index 00000000..b5c53f11 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/LitBaseBlock.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BaseBlock; + +import org.jetbrains.annotations.Nullable; + +public class LitBaseBlock extends BaseBlock { + private static final String PATTERN = "{\"parent\":\"betterend:block/cube_noshade\",\"textures\":{\"texture\":\"betterend:block/name\"}}"; + + public LitBaseBlock(Properties settings) { + super(settings); + } + + @Nullable + @Override + @Environment(EnvType.CLIENT) + public BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + return BlockModel.fromString(PATTERN.replace("name", resourceLocation.getPath())); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/LitPillarBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/LitPillarBlock.java new file mode 100644 index 00000000..b0092cee --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/LitPillarBlock.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.resources.ResourceLocation; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.blocks.BaseRotatedPillarBlock; + +import java.util.Optional; + +public class LitPillarBlock extends BaseRotatedPillarBlock { + private static final String PATTERN = "{\"parent\":\"betterend:block/pillar_noshade\",\"textures\":{\"end\":\"betterend:block/name_top\",\"side\":\"betterend:block/name_side\"}}"; + + public LitPillarBlock(Properties settings) { + super(settings); + } + + @Override + @Environment(EnvType.CLIENT) + protected Optional createBlockPattern(ResourceLocation blockId) { + String name = blockId.getPath(); + return Optional.of(PATTERN.replace("name", name)); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/PedestalBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/PedestalBlock.java new file mode 100644 index 00000000..cf5cd9d8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/PedestalBlock.java @@ -0,0 +1,462 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +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.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.blocks.BaseBlockNotFull; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.betterend.blocks.EndBlockProperties; +import org.betterx.betterend.blocks.EndBlockProperties.PedestalState; +import org.betterx.betterend.blocks.InfusionPedestal; +import org.betterx.betterend.blocks.entities.InfusionPedestalEntity; +import org.betterx.betterend.blocks.entities.PedestalBlockEntity; +import org.betterx.betterend.client.models.Patterns; +import org.betterx.betterend.rituals.InfusionRitual; + +import java.awt.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.ToIntFunction; +import org.jetbrains.annotations.Nullable; + +public class PedestalBlock extends BaseBlockNotFull implements EntityBlock { + public final static EnumProperty STATE = EndBlockProperties.PEDESTAL_STATE; + public static final BooleanProperty HAS_ITEM = EndBlockProperties.HAS_ITEM; + public static final BooleanProperty HAS_LIGHT = BlockProperties.HAS_LIGHT; + + private static final VoxelShape SHAPE_DEFAULT; + private static final VoxelShape SHAPE_COLUMN; + private static final VoxelShape SHAPE_PILLAR; + private static final VoxelShape SHAPE_PEDESTAL_TOP; + private static final VoxelShape SHAPE_COLUMN_TOP; + private static final VoxelShape SHAPE_BOTTOM; + + protected final Block parent; + protected float height = 1.0F; + + public PedestalBlock(Block parent) { + super(FabricBlockSettings.copyOf(parent).luminance(getLuminance(parent.defaultBlockState()))); + this.registerDefaultState( + stateDefinition + .any() + .setValue(STATE, PedestalState.DEFAULT) + .setValue(HAS_ITEM, false) + .setValue(HAS_LIGHT, false) + ); + this.parent = parent; + } + + private static ToIntFunction getLuminance(BlockState parent) { + final int light = parent.getLightEmission(); + if (light > 0) { + return state -> light; + } + return state -> state.getValue(HAS_LIGHT) ? 12 : 0; + } + + public float getHeight(BlockState state) { + if (state.getBlock() instanceof PedestalBlock && state.getValue(STATE) == PedestalState.PEDESTAL_TOP) { + return this.height - 0.2F; + } + return this.height; + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit) { + if (!state.is(this) || !isPlaceable(state)) { + return InteractionResult.PASS; + } + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof PedestalBlockEntity) { + PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; + if (pedestal.isEmpty()) { + ItemStack itemStack = player.getItemInHand(hand); + if (itemStack.isEmpty()) return InteractionResult.CONSUME; + pedestal.setItem(0, itemStack); + level.blockEntityChanged(pos); + checkRitual(level, pos); + return InteractionResult.sidedSuccess(level.isClientSide()); + } else { + ItemStack itemStack = pedestal.getItem(0); + if (player.addItem(itemStack)) { + pedestal.removeItemNoUpdate(0); + level.blockEntityChanged(pos); + checkRitual(level, pos); + return InteractionResult.sidedSuccess(level.isClientSide()); + } + return InteractionResult.FAIL; + } + } + return InteractionResult.PASS; + } + + @Override + public void destroy(LevelAccessor levelAccessor, BlockPos blockPos, BlockState blockState) { + MutableBlockPos posMutable = new MutableBlockPos(); + for (Point point : InfusionRitual.getMap()) { + posMutable.set(blockPos).move(point.x, 0, point.y); + BlockState state = levelAccessor.getBlockState(posMutable); + if (state.getBlock() instanceof InfusionPedestal) { + BlockEntity blockEntity = levelAccessor.getBlockEntity(posMutable); + if (blockEntity instanceof InfusionPedestalEntity) { + InfusionPedestalEntity pedestal = (InfusionPedestalEntity) blockEntity; + if (pedestal.hasRitual()) { + pedestal.getRitual().setDirty(); + } + } + break; + } + } + } + + public void checkRitual(Level world, BlockPos pos) { + MutableBlockPos posMutable = new MutableBlockPos(); + for (Point point : InfusionRitual.getMap()) { + posMutable.set(pos).move(point.x, 0, point.y); + BlockState state = world.getBlockState(posMutable); + if (state.getBlock() instanceof InfusionPedestal) { + ((InfusionPedestal) state.getBlock()).checkRitual(world, posMutable); + break; + } + } + } + + @Override + @Nullable + public BlockState getStateForPlacement(BlockPlaceContext context) { + Level world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + BlockState upState = world.getBlockState(pos.above()); + BlockState downState = world.getBlockState(pos.below()); + boolean upSideSolid = upState.isFaceSturdy(world, pos.above(), Direction.DOWN) || upState.is(BlockTags.WALLS); + boolean hasPedestalOver = upState.getBlock() instanceof PedestalBlock; + boolean hasPedestalUnder = downState.getBlock() instanceof PedestalBlock; + if (!hasPedestalOver && hasPedestalUnder && upSideSolid) { + return defaultBlockState().setValue(STATE, PedestalState.COLUMN_TOP); + } else if (!hasPedestalOver && !hasPedestalUnder && upSideSolid) { + return defaultBlockState().setValue(STATE, PedestalState.COLUMN); + } else if (hasPedestalUnder && hasPedestalOver) { + return defaultBlockState().setValue(STATE, PedestalState.PILLAR); + } else if (hasPedestalUnder) { + return defaultBlockState().setValue(STATE, PedestalState.PEDESTAL_TOP); + } else if (hasPedestalOver) { + return defaultBlockState().setValue(STATE, PedestalState.BOTTOM); + } + return defaultBlockState(); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + BlockState updated = getUpdatedState(state, direction, newState, world, pos, posFrom); + if (!updated.is(this)) return updated; + if (!isPlaceable(updated)) { + moveStoredStack(world, updated, pos); + } + return updated; + } + + private BlockState getUpdatedState(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom) { + if (!state.is(this)) return state.updateShape(direction, newState, world, pos, posFrom); + if (direction != Direction.UP && direction != Direction.DOWN) return state; + BlockState upState = world.getBlockState(pos.above()); + BlockState downState = world.getBlockState(pos.below()); + boolean upSideSolid = upState.isFaceSturdy(world, pos.above(), Direction.DOWN) || upState.is(BlockTags.WALLS); + boolean hasPedestalOver = upState.getBlock() instanceof PedestalBlock; + boolean hasPedestalUnder = downState.getBlock() instanceof PedestalBlock; + if (direction == Direction.UP) { + upSideSolid = newState.isFaceSturdy(world, posFrom, Direction.DOWN) || newState.is(BlockTags.WALLS); + hasPedestalOver = newState.getBlock() instanceof PedestalBlock; + } else { + hasPedestalUnder = newState.getBlock() instanceof PedestalBlock; + } + BlockState updatedState; + if (!hasPedestalOver && hasPedestalUnder && upSideSolid) { + updatedState = state.setValue(STATE, PedestalState.COLUMN_TOP); + } else if (!hasPedestalOver && !hasPedestalUnder && upSideSolid) { + updatedState = state.setValue(STATE, PedestalState.COLUMN); + } else if (hasPedestalUnder && hasPedestalOver) { + updatedState = state.setValue(STATE, PedestalState.PILLAR); + } else if (hasPedestalUnder) { + updatedState = state.setValue(STATE, PedestalState.PEDESTAL_TOP); + } else if (hasPedestalOver) { + updatedState = state.setValue(STATE, PedestalState.BOTTOM); + } else { + updatedState = state.setValue(STATE, PedestalState.DEFAULT); + } + if (!isPlaceable(updatedState)) { + updatedState = updatedState.setValue(HAS_ITEM, false).setValue(HAS_LIGHT, false); + } + return updatedState; + } + + @Override + public List getDrops(BlockState state, LootContext.Builder builder) { + List drop = Lists.newArrayList(super.getDrops(state, builder)); + if (state.is(this)) { + if (isPlaceable(state)) { + BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); + if (blockEntity instanceof PedestalBlockEntity) { + PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; + if (!pedestal.isEmpty()) { + drop.add(pedestal.getItem(0)); + } + } + } else { + return drop; + } + } + return drop; + } + + private void moveStoredStack(LevelAccessor world, BlockState state, BlockPos pos) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof PedestalBlockEntity && state.is(this)) { + PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; + ItemStack stack = pedestal.removeItemNoUpdate(0); + if (!stack.isEmpty()) { + moveStoredStack(blockEntity, world, stack, pos.above()); + } + } + } + + private void moveStoredStack(BlockEntity blockEntity, LevelAccessor world, ItemStack stack, BlockPos pos) { + BlockState state = world.getBlockState(pos); + if (!state.is(this)) { + dropStoredStack(blockEntity, stack, pos); + } else if (state.getValue(STATE).equals(PedestalState.PILLAR)) { + moveStoredStack(blockEntity, world, stack, pos.above()); + } else if (!isPlaceable(state)) { + dropStoredStack(blockEntity, stack, pos); + } else if (blockEntity instanceof PedestalBlockEntity) { + PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; + if (pedestal.isEmpty()) { + pedestal.setItem(0, stack); + } else { + dropStoredStack(blockEntity, stack, pos); + } + } else { + dropStoredStack(blockEntity, stack, pos); + } + } + + private void dropStoredStack(BlockEntity blockEntity, ItemStack stack, BlockPos pos) { + if (blockEntity != null && blockEntity.getLevel() != null) { + Level world = blockEntity.getLevel(); + Block.popResource(world, getDropPos(world, pos), stack); + } + } + + private BlockPos getDropPos(LevelAccessor world, BlockPos pos) { + BlockPos dropPos; + if (world.getBlockState(pos).isAir()) { + return pos; + } + if (world.getBlockState(pos.above()).isAir()) { + return pos.above(); + } + for (int i = 2; i < Direction.values().length; i++) { + dropPos = pos.relative(Direction.from3DDataValue(i)); + if (world.getBlockState(dropPos).isAir()) { + return dropPos.immutable(); + } + } + return getDropPos(world, pos.above()); + } + + public boolean isPlaceable(BlockState state) { + if (!state.is(this)) return false; + PedestalState currentState = state.getValue(STATE); + return currentState == PedestalState.DEFAULT || currentState == PedestalState.PEDESTAL_TOP; + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { + if (state.is(this)) { + switch (state.getValue(STATE)) { + case BOTTOM: { + return SHAPE_BOTTOM; + } + case PEDESTAL_TOP: { + return SHAPE_PEDESTAL_TOP; + } + case COLUMN_TOP: { + return SHAPE_COLUMN_TOP; + } + case PILLAR: { + return SHAPE_PILLAR; + } + case COLUMN: { + return SHAPE_COLUMN; + } + default: { + return SHAPE_DEFAULT; + } + } + } + return super.getShape(state, world, pos, context); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { + stateManager.add(STATE, HAS_ITEM, HAS_LIGHT); + } + + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return new PedestalBlockEntity(blockPos, blockState); + } + + public boolean hasUniqueEntity() { + return false; + } + + @Override + @SuppressWarnings("deprecation") + public boolean hasAnalogOutputSignal(BlockState state) { + return state.getBlock() instanceof PedestalBlock; + } + + @Override + @SuppressWarnings("deprecation") + public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { + return state.getValue(HAS_ITEM) ? 15 : 0; + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation blockId) { + return getBlockModel(blockId, defaultBlockState()); + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + Map textures = createTexturesMap(); + PedestalState state = blockState.getValue(STATE); + Optional pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_DEFAULT, textures); + switch (state) { + case COLUMN_TOP: + pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_COLUMN_TOP, textures); + break; + case COLUMN: + pattern = Patterns.createJson(Patterns.BLOKC_PEDESTAL_COLUMN, textures); + break; + case PEDESTAL_TOP: + pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_TOP, textures); + break; + case BOTTOM: + pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_BOTTOM, textures); + break; + case PILLAR: + pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_PILLAR, textures); + break; + default: + break; + } + return ModelsHelper.fromPattern(pattern); + } + + @Override + @Environment(EnvType.CLIENT) + public UnbakedModel getModelVariant(ResourceLocation stateId, + BlockState blockState, + Map modelCache) { + PedestalState state = blockState.getValue(STATE); + ResourceLocation modelId = new ResourceLocation( + stateId.getNamespace(), + "block/" + stateId.getPath() + "_" + state + ); + registerBlockModel(stateId, modelId, blockState, modelCache); + return ModelsHelper.createBlockSimple(modelId); + } + + protected Map createTexturesMap() { + ResourceLocation blockId = Registry.BLOCK.getKey(parent); + String name = blockId.getPath(); + Map textures = Maps.newHashMap(); + textures.put("%mod%", blockId.getNamespace()); + textures.put("%top%", name + "_top"); + textures.put("%base%", name + "_base"); + textures.put("%pillar%", name + "_pillar"); + textures.put("%bottom%", name + "_bottom"); + return textures; + } + + static { + VoxelShape basinUp = Block.box(2, 3, 2, 14, 4, 14); + VoxelShape basinDown = Block.box(0, 0, 0, 16, 3, 16); + VoxelShape columnTopUp = Block.box(1, 14, 1, 15, 16, 15); + VoxelShape columnTopDown = Block.box(2, 13, 2, 14, 14, 14); + VoxelShape pedestalTop = Block.box(1, 8, 1, 15, 10, 15); + VoxelShape pedestalDefault = Block.box(1, 12, 1, 15, 14, 15); + VoxelShape pillar = Block.box(3, 0, 3, 13, 8, 13); + VoxelShape pillarDefault = Block.box(3, 0, 3, 13, 12, 13); + VoxelShape columnTop = Shapes.or(columnTopDown, columnTopUp); + VoxelShape basin = Shapes.or(basinDown, basinUp); + SHAPE_PILLAR = Block.box(3, 0, 3, 13, 16, 13); + SHAPE_DEFAULT = Shapes.or(basin, pillarDefault, pedestalDefault); + SHAPE_PEDESTAL_TOP = Shapes.or(pillar, pedestalTop); + SHAPE_COLUMN_TOP = Shapes.or(SHAPE_PILLAR, columnTop); + SHAPE_COLUMN = Shapes.or(basin, SHAPE_PILLAR, columnTop); + SHAPE_BOTTOM = Shapes.or(basin, SHAPE_PILLAR); + } + + /*@Override + @Nullable + public BlockEntityTicker getTicker(Level level, BlockState blockState, BlockEntityType blockEntityType) { + return level.isClientSide() ? PedestalBlockEntity::tick : null; + }*/ +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/PottableCropBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/PottableCropBlock.java new file mode 100644 index 00000000..583f7595 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/PottableCropBlock.java @@ -0,0 +1,31 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; + +import org.betterx.bclib.blocks.BaseCropBlock; +import org.betterx.betterend.interfaces.PottablePlant; + +public class PottableCropBlock extends BaseCropBlock implements PottablePlant { + private final Block[] terrain; + + public PottableCropBlock(Item drop, Block... terrain) { + super(drop, terrain); + this.terrain = terrain; + } + + @Override + public boolean canPlantOn(Block block) { + for (Block ter : terrain) { + if (block == ter) { + return true; + } + } + return false; + } + + @Override + public String getPottedState() { + return "age=3"; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/PottableFeatureSapling.java b/src/main/java/org/betterx/betterend/blocks/basis/PottableFeatureSapling.java new file mode 100644 index 00000000..44114215 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/PottableFeatureSapling.java @@ -0,0 +1,19 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.Feature; + +import org.betterx.bclib.blocks.FeatureSaplingBlock; +import org.betterx.betterend.interfaces.PottablePlant; + +import java.util.function.Function; + +public abstract class PottableFeatureSapling extends FeatureSaplingBlock implements PottablePlant { + public PottableFeatureSapling(Function> featureSupplier) { + super(featureSupplier); + } + + public PottableFeatureSapling(int light, Function> featureSupplier) { + super(light, featureSupplier); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/PottableLeavesBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/PottableLeavesBlock.java new file mode 100644 index 00000000..4bd9e782 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/PottableLeavesBlock.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.material.MaterialColor; + +import org.betterx.bclib.blocks.BaseLeavesBlock; +import org.betterx.betterend.interfaces.PottablePlant; + +public class PottableLeavesBlock extends BaseLeavesBlock implements PottablePlant { + + public PottableLeavesBlock(Block sapling, MaterialColor color) { + super(sapling, color); + } + + public PottableLeavesBlock(Block sapling, MaterialColor color, int light) { + super(sapling, color, light); + } + + @Override + public boolean canPlantOn(Block block) { + if (sapling instanceof PottablePlant) { + return ((PottablePlant) sapling).canPlantOn(block); + } + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/basis/StoneLanternBlock.java b/src/main/java/org/betterx/betterend/blocks/basis/StoneLanternBlock.java new file mode 100644 index 00000000..1140f3b5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/basis/StoneLanternBlock.java @@ -0,0 +1,63 @@ +package org.betterx.betterend.blocks.basis; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.betterend.client.models.Patterns; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +public class StoneLanternBlock extends EndLanternBlock implements CustomColorProvider { + private static final VoxelShape SHAPE_CEIL = box(3, 1, 3, 13, 16, 13); + private static final VoxelShape SHAPE_FLOOR = box(3, 0, 3, 13, 15, 13); + + public StoneLanternBlock(Block source) { + super(FabricBlockSettings.copyOf(source).luminance(15)); + } + + @Override + public BlockColor getProvider() { + return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getProvider(); + } + + @Override + public ItemColor getItemProvider() { + return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getItemProvider(); + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { + return state.getValue(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL; + } + + @Override + @Environment(EnvType.CLIENT) + public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { + String blockName = resourceLocation.getPath(); + Optional pattern = blockState.getValue(IS_FLOOR) + ? Patterns.createJson( + Patterns.BLOCK_STONE_LANTERN_FLOOR, + blockName, + blockName + ) + : Patterns.createJson(Patterns.BLOCK_STONE_LANTERN_CEIL, blockName, blockName); + return ModelsHelper.fromPattern(pattern); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/entities/BlockEntityHydrothermalVent.java b/src/main/java/org/betterx/betterend/blocks/entities/BlockEntityHydrothermalVent.java new file mode 100644 index 00000000..31421dc9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/entities/BlockEntityHydrothermalVent.java @@ -0,0 +1,91 @@ +package org.betterx.betterend.blocks.entities; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import org.betterx.betterend.blocks.HydrothermalVentBlock; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.registry.EndBlockEntities; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.util.GlobalState; + +import java.util.List; + +public class BlockEntityHydrothermalVent extends BlockEntity { + private final static Vec3 POSITIVE_Y = new Vec3(0.0f, 1.0f, 0.0f); + + public BlockEntityHydrothermalVent(BlockPos blockPos, BlockState blockState) { + super(EndBlockEntities.HYDROTHERMAL_VENT, blockPos, blockState); + } + + public static void tick(Level level, + BlockPos worldPosition, + BlockState state, + T uncastedEntity) { + if (level != null && uncastedEntity instanceof BlockEntityHydrothermalVent && state.is(EndBlocks.HYDROTHERMAL_VENT)) { + BlockEntityHydrothermalVent blockEntity = (BlockEntityHydrothermalVent) uncastedEntity; + if (level.isClientSide()) { + clientTick(level, worldPosition, state, blockEntity); + } + //else { + serverTick(level, worldPosition, state, blockEntity); + //} + } + } + + private static void clientTick(Level level, + BlockPos worldPosition, + BlockState state, + BlockEntityHydrothermalVent blockEntity) { + boolean active = state.getValue(HydrothermalVentBlock.ACTIVATED); + if (active && level.random.nextInt(20) == 0 && state.getValue(HydrothermalVentBlock.WATERLOGGED)) { + double x = worldPosition.getX() + level.random.nextDouble(); + double y = worldPosition.getY() + 0.9 + level.random.nextDouble() * 0.3; + double z = worldPosition.getZ() + level.random.nextDouble(); + level.addParticle(EndParticles.GEYSER_PARTICLE, x, y, z, 0, 0, 0); + } + } + + private static void serverTick(Level level, + BlockPos worldPosition, + BlockState state, + BlockEntityHydrothermalVent blockEntity) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + boolean active = state.getValue(HydrothermalVentBlock.ACTIVATED); + POS.set(worldPosition).move(Direction.UP); + int height = active ? 85 : 25; + AABB box = new AABB(POS.offset(-1, 0, -1), POS.offset(1, height, 1)); + List entities = level.getEntitiesOfClass(LivingEntity.class, box); + if (entities.size() > 0) { + while (POS.getY() < box.maxY) { + BlockState blockState = level.getBlockState(POS); + if (blockState.isSolidRender(level, POS)) break; + if (blockState.isAir()) { + double mult = active ? 3.0 : 5.0; + float force = (float) ((1.0 - (POS.getY() / box.maxY)) / mult); + entities.stream() + .filter(entity -> (int) entity.getY() == POS.getY() && blockEntity.hasElytra(entity) && entity + .isFallFlying()) + .forEach(entity -> entity.moveRelative(force, POSITIVE_Y)); + } + POS.move(Direction.UP); + } + } + } + + private boolean hasElytra(LivingEntity entity) { + Item item = entity.getItemBySlot(EquipmentSlot.CHEST).getItem(); + return item instanceof ElytraItem || item instanceof FallFlyingItem; + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/entities/EndStoneSmelterBlockEntity.java b/src/main/java/org/betterx/betterend/blocks/entities/EndStoneSmelterBlockEntity.java new file mode 100644 index 00000000..5bb22858 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/entities/EndStoneSmelterBlockEntity.java @@ -0,0 +1,476 @@ +package org.betterx.betterend.blocks.entities; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.WorldlyContainer; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.StackedContents; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.RecipeHolder; +import net.minecraft.world.inventory.StackedContentsCompatible; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.BlastingRecipe; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +import net.fabricmc.fabric.api.registry.FuelRegistry; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndStoneSmelter; +import org.betterx.betterend.client.gui.EndStoneSmelterScreenHandler; +import org.betterx.betterend.recipe.builders.AlloyingRecipe; +import org.betterx.betterend.registry.EndBlockEntities; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class EndStoneSmelterBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeHolder, StackedContentsCompatible { + + private static final int[] TOP_SLOTS = new int[]{0, 1}; + private static final int[] BOTTOM_SLOTS = new int[]{2, 3}; + private static final int[] SIDE_SLOTS = new int[]{1, 2}; + private static final Map AVAILABLE_FUELS = Maps.newHashMap(); + + private final Object2IntOpenHashMap recipesUsed; + protected NonNullList inventory; + protected final ContainerData propertyDelegate; + private Recipe lastRecipe; + private int smeltTimeTotal; + private int smeltTime; + private int burnTime; + private int fuelTime; + + public EndStoneSmelterBlockEntity(BlockPos blockPos, BlockState blockState) { + super(EndBlockEntities.END_STONE_SMELTER, blockPos, blockState); + this.inventory = NonNullList.withSize(4, ItemStack.EMPTY); + this.recipesUsed = new Object2IntOpenHashMap<>(); + this.propertyDelegate = new ContainerData() { + public int get(int index) { + switch (index) { + case 0: + return EndStoneSmelterBlockEntity.this.burnTime; + case 1: + return EndStoneSmelterBlockEntity.this.fuelTime; + case 2: + return EndStoneSmelterBlockEntity.this.smeltTime; + case 3: + return EndStoneSmelterBlockEntity.this.smeltTimeTotal; + default: + return 0; + } + } + + public void set(int index, int value) { + switch (index) { + case 0: + EndStoneSmelterBlockEntity.this.burnTime = value; + break; + case 1: + EndStoneSmelterBlockEntity.this.fuelTime = value; + break; + case 2: + EndStoneSmelterBlockEntity.this.smeltTime = value; + break; + case 3: + EndStoneSmelterBlockEntity.this.smeltTimeTotal = value; + } + } + + public int getCount() { + return 4; + } + }; + } + + private boolean isBurning() { + return burnTime > 0; + } + + @Override + public int getContainerSize() { + return inventory.size(); + } + + @Override + public boolean isEmpty() { + Iterator iterator = inventory.iterator(); + ItemStack itemStack; + do { + if (!iterator.hasNext()) { + return true; + } + itemStack = iterator.next(); + } while (itemStack.isEmpty()); + + return false; + } + + @Override + public ItemStack getItem(int slot) { + return inventory.get(slot); + } + + @Override + public ItemStack removeItem(int slot, int amount) { + return ContainerHelper.removeItem(inventory, slot, amount); + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + return ContainerHelper.takeItem(inventory, slot); + } + + @Override + public void setItem(int slot, ItemStack stack) { + ItemStack itemStack = inventory.get(slot); + boolean stackValid = !stack.isEmpty() && stack.sameItem(itemStack) && ItemStack.tagMatches(stack, itemStack); + inventory.set(slot, stack); + if (stack.getCount() > getMaxStackSize()) { + stack.setCount(getMaxStackSize()); + } + if ((slot == 0 || slot == 1) && !stackValid) { + smeltTimeTotal = getSmeltTime(); + smeltTime = 0; + setChanged(); + } + } + + protected int getSmeltTime() { + if (level == null) return 200; + int smeltTime = level.getRecipeManager() + .getRecipeFor(AlloyingRecipe.TYPE, this, level) + .map(AlloyingRecipe::getSmeltTime) + .orElse(0); + if (smeltTime == 0) { + smeltTime = level.getRecipeManager() + .getRecipeFor(RecipeType.BLASTING, this, level) + .map(BlastingRecipe::getCookingTime) + .orElse(200); + smeltTime /= 1.5; + } + return smeltTime; + } + + public void dropExperience(Player player) { + if (level == null) return; + List> list = Lists.newArrayList(); + for (Entry entry : recipesUsed.object2IntEntrySet()) { + level.getRecipeManager().byKey(entry.getKey()).ifPresent((recipe) -> { + list.add(recipe); + if (recipe instanceof AlloyingRecipe) { + AlloyingRecipe alloying = (AlloyingRecipe) recipe; + dropExperience(player.level, player.position(), entry.getIntValue(), alloying.getExperience()); + } else { + BlastingRecipe blasting = (BlastingRecipe) recipe; + dropExperience(player.level, player.position(), entry.getIntValue(), blasting.getExperience()); + } + }); + } + player.awardRecipes(list); + recipesUsed.clear(); + } + + private void dropExperience(Level world, Vec3 vec3d, int count, float amount) { + int expTotal = Mth.floor(count * amount); + float g = Mth.frac(count * amount); + if (g != 0.0F && Math.random() < g) { + expTotal++; + } + + while (expTotal > 0) { + int expVal = ExperienceOrb.getExperienceValue(expTotal); + expTotal -= expVal; + world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, expVal)); + } + } + + @Override + public boolean stillValid(Player player) { + if (level != null && level.getBlockEntity(worldPosition) != this) { + return false; + } + return player.distanceToSqr( + worldPosition.getX() + 0.5D, + worldPosition.getY() + 0.5D, + worldPosition.getZ() + 0.5D + ) <= 64.0D; + } + + @Override + public void clearContent() { + inventory.clear(); + } + + @Override + protected Component getDefaultName() { + return Component.translatable(String.format("block.%s.%s", BetterEnd.MOD_ID, EndStoneSmelter.ID)); + } + + @Override + protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) { + return new EndStoneSmelterScreenHandler(syncId, playerInventory, this, propertyDelegate); + } + + public static void tick(Level tickLevel, + BlockPos tickPos, + BlockState tickState, + EndStoneSmelterBlockEntity blockEntity) { + if (tickLevel == null) return; + + boolean initialBurning = blockEntity.isBurning(); + if (initialBurning) { + blockEntity.burnTime--; + } + + boolean burning = initialBurning; + if (!tickLevel.isClientSide) { + ItemStack fuel = blockEntity.inventory.get(2); + if (!burning && (fuel.isEmpty() || blockEntity.inventory.get(0).isEmpty() && blockEntity.inventory.get(1) + .isEmpty())) { + if (blockEntity.smeltTime > 0) { + blockEntity.smeltTime = Mth.clamp(blockEntity.smeltTime - 2, 0, blockEntity.smeltTimeTotal); + } + } else { + Recipe recipe = tickLevel.getRecipeManager() + .getRecipeFor(AlloyingRecipe.TYPE, blockEntity, tickLevel) + .orElse(null); + if (recipe == null) { + recipe = tickLevel.getRecipeManager() + .getRecipeFor(RecipeType.BLASTING, blockEntity, tickLevel) + .orElse(null); + } + boolean accepted = blockEntity.canAcceptRecipeOutput(recipe); + if (!burning && accepted) { + blockEntity.burnTime = blockEntity.getFuelTime(fuel); + blockEntity.fuelTime = blockEntity.burnTime; + burning = blockEntity.isBurning(); + if (burning) { + if (!fuel.isEmpty()) { + Item item = fuel.getItem(); + fuel.shrink(1); + if (fuel.isEmpty()) { + Item remainFuel = item.getCraftingRemainingItem(); + blockEntity.inventory.set( + 2, + remainFuel == null ? ItemStack.EMPTY : new ItemStack(remainFuel) + ); + } + } + blockEntity.setChanged(); + } + } + + if (burning && accepted) { + blockEntity.smeltTime++; + if (blockEntity.smeltTime == blockEntity.smeltTimeTotal) { + blockEntity.smeltTime = 0; + blockEntity.smeltTimeTotal = blockEntity.getSmeltTime(); + blockEntity.craftRecipe(recipe); + blockEntity.setChanged(); + } + } else { + blockEntity.smeltTime = 0; + } + } + burning = blockEntity.isBurning(); + if (initialBurning != burning) { + tickLevel.setBlock(tickPos, tickState.setValue(EndStoneSmelter.LIT, burning), 3); + blockEntity.setChanged(); + } + } + } + + protected boolean canAcceptRecipeOutput(Recipe recipe) { + if (recipe == null) return false; + boolean validInput; + if (recipe instanceof AlloyingRecipe) { + validInput = !inventory.get(0).isEmpty() && !inventory.get(1).isEmpty(); + } else { + validInput = !inventory.get(0).isEmpty() || !inventory.get(1).isEmpty(); + } + if (validInput) { + ItemStack result = recipe.getResultItem(); + if (result.isEmpty()) { + return false; + } + ItemStack output = this.inventory.get(3); + int outCount = output.getCount(); + int total = outCount + result.getCount(); + if (output.isEmpty()) { + return true; + } + if (!output.sameItem(result)) { + return false; + } + if (outCount < getMaxStackSize() && outCount < output.getMaxStackSize()) { + return getMaxStackSize() >= total; + } + return output.getCount() < result.getMaxStackSize(); + } + return false; + } + + private void craftRecipe(Recipe recipe) { + if (recipe == null || !canAcceptRecipeOutput(recipe)) return; + + ItemStack result = recipe.getResultItem(); + ItemStack output = inventory.get(3); + if (output.isEmpty()) { + inventory.set(3, result.copy()); + } else if (output.getItem() == result.getItem()) { + output.grow(result.getCount()); + } + + assert this.level != null; + if (!this.level.isClientSide) { + setRecipeUsed(recipe); + } + + if (recipe instanceof AlloyingRecipe) { + inventory.get(0).shrink(1); + inventory.get(1).shrink(1); + } else { + if (!inventory.get(0).isEmpty()) { + inventory.get(0).shrink(1); + } else { + inventory.get(1).shrink(1); + } + } + } + + @Override + public void fillStackedContents(StackedContents finder) { + for (ItemStack itemStack : this.inventory) { + finder.accountStack(itemStack); + } + } + + @Override + public void setRecipeUsed(Recipe recipe) { + if (recipe != null) { + ResourceLocation recipeId = recipe.getId(); + recipesUsed.addTo(recipeId, 1); + lastRecipe = recipe; + } + } + + @Override + public Recipe getRecipeUsed() { + return this.lastRecipe; + } + + @Override + public int[] getSlotsForFace(Direction side) { + if (side == Direction.DOWN) { + return BOTTOM_SLOTS; + } + return side == Direction.UP ? TOP_SLOTS : SIDE_SLOTS; + } + + @Override + public boolean canPlaceItemThroughFace(int slot, ItemStack stack, Direction dir) { + return this.canPlaceItem(slot, stack); + } + + @Override + public boolean canTakeItemThroughFace(int slot, ItemStack stack, Direction dir) { + if (dir == Direction.DOWN && slot == 2) { + return stack.getItem() == Items.BUCKET; + } + return true; + } + + protected int getFuelTime(ItemStack fuel) { + if (fuel.isEmpty()) { + return 0; + } + Item item = fuel.getItem(); + return AVAILABLE_FUELS.getOrDefault(item, getFabricFuel(fuel)); + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + inventory = NonNullList.withSize(getContainerSize(), ItemStack.EMPTY); + ContainerHelper.loadAllItems(tag, inventory); + burnTime = tag.getShort("BurnTime"); + fuelTime = tag.getShort("FuelTime"); + smeltTime = tag.getShort("SmeltTime"); + smeltTimeTotal = tag.getShort("SmeltTimeTotal"); + CompoundTag compoundTag = tag.getCompound("RecipesUsed"); + for (String id : compoundTag.getAllKeys()) { + recipesUsed.put(new ResourceLocation(id), compoundTag.getInt(id)); + } + } + + @Override + public void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + + tag.putShort("BurnTime", (short) burnTime); + tag.putShort("FuelTime", (short) fuelTime); + tag.putShort("SmeltTime", (short) smeltTime); + tag.putShort("SmeltTimeTotal", (short) smeltTimeTotal); + ContainerHelper.saveAllItems(tag, inventory); + CompoundTag usedRecipes = new CompoundTag(); + recipesUsed.forEach((identifier, integer) -> usedRecipes.putInt(identifier.toString(), integer)); + tag.put("RecipesUsed", usedRecipes); + } + + public boolean canPlaceItem(int slot, ItemStack stack) { + if (slot == 3) { + return false; + } else if (slot != 2) { + return true; + } + ItemStack itemStack = this.inventory.get(2); + return canUseAsFuel(stack) || stack.getItem() == Items.BUCKET && itemStack.getItem() != Items.BUCKET; + } + + public static boolean canUseAsFuel(ItemStack stack) { + return AVAILABLE_FUELS.containsKey(stack.getItem()) || getFabricFuel(stack) > 2000; + } + + public static void registerFuel(ItemLike fuel, int time) { + AVAILABLE_FUELS.put(fuel.asItem(), time); + } + + public static Map availableFuels() { + return AVAILABLE_FUELS; + } + + private static int getFabricFuel(ItemStack stack) { + Integer ticks = FuelRegistry.INSTANCE.get(stack.getItem()); + return ticks == null ? 0 : ticks; + } + + static { + AbstractFurnaceBlockEntity.getFuel().forEach((item, time) -> { + if (time >= 2000) { + registerFuel(item, time); + } + }); + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/entities/EternalPedestalEntity.java b/src/main/java/org/betterx/betterend/blocks/entities/EternalPedestalEntity.java new file mode 100644 index 00000000..9f7d5aa0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/entities/EternalPedestalEntity.java @@ -0,0 +1,54 @@ +package org.betterx.betterend.blocks.entities; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.registry.EndBlockEntities; +import org.betterx.betterend.rituals.EternalRitual; + +public class EternalPedestalEntity extends PedestalBlockEntity { + private EternalRitual linkedRitual; + + public EternalPedestalEntity(BlockPos blockPos, BlockState blockState) { + super(EndBlockEntities.ETERNAL_PEDESTAL, blockPos, blockState); + } + + public boolean hasRitual() { + return linkedRitual != null; + } + + public void linkRitual(EternalRitual ritual) { + this.linkedRitual = ritual; + } + + public EternalRitual getRitual() { + return linkedRitual; + } + + @Override + public void setLevel(Level level) { + super.setLevel(level); + if (hasRitual()) { + linkedRitual.setWorld(level); + } + } + + @Override + public void saveAdditional(CompoundTag tag) { + if (hasRitual()) { + tag.put("ritual", linkedRitual.toTag(new CompoundTag())); + } + super.saveAdditional(tag); + } + + @Override + protected void fromTag(CompoundTag tag) { + super.fromTag(tag); + if (tag.contains("ritual")) { + linkedRitual = new EternalRitual(level); + linkedRitual.fromTag(tag.getCompound("ritual")); + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/entities/InfusionPedestalEntity.java b/src/main/java/org/betterx/betterend/blocks/entities/InfusionPedestalEntity.java new file mode 100644 index 00000000..8a77bf9b --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/entities/InfusionPedestalEntity.java @@ -0,0 +1,71 @@ +package org.betterx.betterend.blocks.entities; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.betterend.registry.EndBlockEntities; +import org.betterx.betterend.rituals.InfusionRitual; + +public class InfusionPedestalEntity extends PedestalBlockEntity { + + private InfusionRitual linkedRitual; + + public InfusionPedestalEntity(BlockPos blockPos, BlockState blockState) { + super(EndBlockEntities.INFUSION_PEDESTAL, blockPos, blockState); + } + + @Override + public void setLevel(Level world) { + super.setLevel(world); + if (hasRitual()) { + linkedRitual.setLocation(world, this.getBlockPos()); + } else { + linkRitual(new InfusionRitual(this, world, this.getBlockPos())); + } + } + + public void linkRitual(InfusionRitual ritual) { + linkedRitual = ritual; + } + + public InfusionRitual getRitual() { + return linkedRitual; + } + + public boolean hasRitual() { + return linkedRitual != null; + } + + @Override + public void saveAdditional(CompoundTag tag) { + if (hasRitual()) { + tag.put("ritual", linkedRitual.toTag(new CompoundTag())); + } + super.saveAdditional(tag); + } + + @Override + protected void fromTag(CompoundTag tag) { + super.fromTag(tag); + if (tag.contains("ritual")) { + linkedRitual = new InfusionRitual(this, level, worldPosition); + linkedRitual.fromTag(tag.getCompound("ritual")); + } + } + + public static void tickEnity(Level level, + BlockPos blockPos, + BlockState blockState, + T uncastedEntity) { + if (uncastedEntity instanceof InfusionPedestalEntity) { + InfusionPedestalEntity blockEntity = (InfusionPedestalEntity) uncastedEntity; + if (blockEntity.hasRitual()) { + blockEntity.linkedRitual.tick(); + } + //PedestalBlockEntity.tick(level, blockPos, blockState, blockEntity); + } + } +} diff --git a/src/main/java/org/betterx/betterend/blocks/entities/PedestalBlockEntity.java b/src/main/java/org/betterx/betterend/blocks/entities/PedestalBlockEntity.java new file mode 100644 index 00000000..33a17bff --- /dev/null +++ b/src/main/java/org/betterx/betterend/blocks/entities/PedestalBlockEntity.java @@ -0,0 +1,125 @@ +package org.betterx.betterend.blocks.entities; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +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 org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.registry.EndBlockEntities; +import org.betterx.betterend.registry.EndItems; + +public class PedestalBlockEntity extends BlockEntity implements Container { + private ItemStack activeItem = ItemStack.EMPTY; + + public PedestalBlockEntity(BlockPos blockPos, BlockState blockState) { + this(EndBlockEntities.PEDESTAL, blockPos, blockState); + } + + public PedestalBlockEntity(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState) { + super(blockEntityType, blockPos, blockState); + } + + protected void toTag(CompoundTag tag) { + if (activeItem != ItemStack.EMPTY) { + tag.put("active_item", activeItem.save(new CompoundTag())); + } + } + + protected void fromTag(CompoundTag tag) { + if (tag.contains("active_item")) { + CompoundTag itemTag = tag.getCompound("active_item"); + activeItem = ItemStack.of(itemTag); + } + } + + @Override + public int getContainerSize() { + return 1; + } + + @Override + public boolean isEmpty() { + return activeItem.isEmpty(); + } + + @Override + public ItemStack getItem(int slot) { + return activeItem; + } + + @Override + public ItemStack removeItem(int slot, int amount) { + return removeItemNoUpdate(slot); + } + + @Override + public boolean canPlaceItem(int slot, ItemStack stack) { + return isEmpty(); + } + + @Override + public void clearContent() { + activeItem = ItemStack.EMPTY; + setChanged(); + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + ItemStack stored = activeItem; + clearContent(); + return stored; + } + + @Override + public void setItem(int slot, ItemStack stack) { + activeItem = stack.split(1); + setChanged(); + } + + @Override + public void setChanged() { + if (level != null && !level.isClientSide()) { + BlockState state = level.getBlockState(worldPosition); + if (state.getBlock() instanceof PedestalBlock) { + state = state.setValue(PedestalBlock.HAS_ITEM, !isEmpty()); + state = state.setValue(PedestalBlock.HAS_LIGHT, activeItem.getItem() == EndItems.ETERNAL_CRYSTAL); + } + level.setBlockAndUpdate(worldPosition, state); + level.blockEntityChanged(worldPosition); + } + super.setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return true; + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + fromTag(tag); + } + + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + toTag(tag); + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } +} diff --git a/src/main/java/org/betterx/betterend/client/BetterEndClient.java b/src/main/java/org/betterx/betterend/client/BetterEndClient.java new file mode 100644 index 00000000..2255cbf9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/BetterEndClient.java @@ -0,0 +1,79 @@ +package org.betterx.betterend.client; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.DimensionRenderingRegistry; + +import org.betterx.bclib.BCLib; +import org.betterx.bclib.util.TranslationHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.client.render.BetterEndSkyRenderer; +import org.betterx.betterend.events.ItemTooltipCallback; +import org.betterx.betterend.interfaces.MultiModelItem; +import org.betterx.betterend.item.CrystaliteArmor; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.generator.GeneratorOptions; + +public class BetterEndClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + EndBlockEntityRenders.register(); + EndScreens.register(); + EndParticles.register(); + EndEntitiesRenders.register(); + EndModelProviders.register(); + MultiModelItem.register(); + ClientOptions.init(); + registerTooltips(); + + if (BCLib.isDevEnvironment()) { + TranslationHelper.printMissingEnNames(BetterEnd.MOD_ID); + TranslationHelper.printMissingNames(BetterEnd.MOD_ID, "ru_ru"); + } + + ResourceLocation checkFlowerId = new ResourceLocation("item/chorus_flower"); + ResourceLocation checkPlantId = new ResourceLocation("item/chorus_plant"); + ResourceLocation toLoadFlowerId = new ResourceLocation("betterend", "item/custom_chorus_flower"); + ResourceLocation toLoadPlantId = new ResourceLocation("betterend", "item/custom_chorus_plant"); + ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> (resourceId, context) -> { + if (GeneratorOptions.changeChorusPlant()) { + if (resourceId.equals(checkFlowerId)) { + return context.loadModel(toLoadFlowerId); + } else if (resourceId.equals(checkPlantId)) { + return context.loadModel(toLoadPlantId); + } + } + return null; + }); + + if (ClientOptions.isCustomSky()) { + DimensionRenderingRegistry.registerSkyRenderer(Level.END, new BetterEndSkyRenderer()); + } + } + + public static void registerTooltips() { + ItemTooltipCallback.EVENT.register((player, stack, context, lines) -> { + if (stack.getItem() instanceof CrystaliteArmor) { + boolean hasSet = false; + if (player != null) { + hasSet = CrystaliteArmor.hasFullSet(player); + } + MutableComponent setDesc = Component.translatable("tooltip.armor.crystalite_set"); + + setDesc.setStyle(Style.EMPTY.applyFormats( + hasSet ? ChatFormatting.BLUE : ChatFormatting.DARK_GRAY, + ChatFormatting.ITALIC + )); + lines.add(Component.empty()); + lines.add(setDesc); + } + }); + } +} diff --git a/src/main/java/org/betterx/betterend/client/ClientOptions.java b/src/main/java/org/betterx/betterend/client/ClientOptions.java new file mode 100644 index 00000000..3443883f --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/ClientOptions.java @@ -0,0 +1,50 @@ +package org.betterx.betterend.client; + +import org.betterx.betterend.config.Configs; + +public class ClientOptions { + private static boolean customSky; + private static boolean useFogDensity; + private static boolean blendBiomeMusic; + private static boolean sulfurWaterColor; + + public static void init() { + customSky = Configs.CLENT_CONFIG.getBooleanRoot("customSky", true); + useFogDensity = Configs.CLENT_CONFIG.getBooleanRoot("useFogDensity", true); + blendBiomeMusic = Configs.CLENT_CONFIG.getBooleanRoot("blendBiomeMusic", true); + sulfurWaterColor = Configs.CLENT_CONFIG.getBooleanRoot("sulfurWaterColor", true); + Configs.CLENT_CONFIG.saveChanges(); + } + + public static boolean isCustomSky() { + return customSky; + } + + public static void setCustomSky(boolean customSky) { + ClientOptions.customSky = customSky; + } + + public static boolean useFogDensity() { + return useFogDensity; + } + + public static void setUseFogDensity(boolean useFogDensity) { + ClientOptions.useFogDensity = useFogDensity; + } + + public static boolean blendBiomeMusic() { + return blendBiomeMusic; + } + + public static void setBlendBiomeMusic(boolean blendBiomeMusic) { + ClientOptions.blendBiomeMusic = blendBiomeMusic; + } + + public static boolean useSulfurWaterColor() { + return sulfurWaterColor; + } + + public static void setSulfurWaterColor(boolean sulfurWaterColor) { + ClientOptions.sulfurWaterColor = sulfurWaterColor; + } +} diff --git a/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java new file mode 100644 index 00000000..7b7eef0b --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java @@ -0,0 +1,110 @@ +package org.betterx.betterend.client.gui; + +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.recipebook.BlastingRecipeBookComponent; +import net.minecraft.core.NonNullList; +import net.minecraft.world.inventory.Slot; +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.Recipe; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import org.betterx.betterend.blocks.entities.EndStoneSmelterBlockEntity; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +@Environment(EnvType.CLIENT) +public class EndStoneSmelterRecipeBookScreen extends BlastingRecipeBookComponent { + private Iterator fuelIterator; + private Set fuels; + private Slot fuelSlot; + private Item currentItem; + private float frameTime; + + @Override + protected Set getFuelItems() { + return EndStoneSmelterBlockEntity.availableFuels().keySet(); + } + + @Override + public void slotClicked(Slot slot) { + super.slotClicked(slot); + if (slot != null && slot.index < this.menu.getSize()) { + this.fuelSlot = null; + } + } + + @Override + public void setupGhostRecipe(Recipe recipe, List slots) { + this.ghostRecipe.clear(); + ItemStack result = recipe.getResultItem(); + this.ghostRecipe.setRecipe(recipe); + this.ghostRecipe.addIngredient(Ingredient.of(result), (slots.get(3)).x, (slots.get(3)).y); + NonNullList inputs = recipe.getIngredients(); + Iterator iterator = inputs.iterator(); + for (int i = 0; i < 2; i++) { + if (!iterator.hasNext()) { + return; + } + Ingredient ingredient = iterator.next(); + if (!ingredient.isEmpty()) { + Slot slot = slots.get(i); + this.ghostRecipe.addIngredient(ingredient, slot.x, slot.y); + } + } + this.fuelSlot = slots.get(2); + if (this.fuels == null) { + this.fuels = this.getFuelItems(); + } + + this.fuelIterator = this.fuels.iterator(); + this.currentItem = null; + } + + @Override + public void renderGhostRecipe(PoseStack matrices, int x, int y, boolean bl, float f) { + this.ghostRecipe.render(matrices, minecraft, x, y, bl, f); + if (fuelSlot != null) { + if (!Screen.hasControlDown()) { + this.frameTime += f; + } + + int slotX = this.fuelSlot.x + x; + int slotY = this.fuelSlot.y + y; + GuiComponent.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822018048); + //TODO: test k=0 + this.minecraft.getItemRenderer() + .renderAndDecorateItem(minecraft.player, + this.getFuel().getDefaultInstance(), + slotX, + slotY, + 0 + ); + RenderSystem.depthFunc(516); + GuiComponent.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822083583); + RenderSystem.depthFunc(515); + } + } + + private Item getFuel() { + if (this.currentItem == null || this.frameTime > 30.0F) { + this.frameTime = 0.0F; + if (this.fuelIterator == null || !this.fuelIterator.hasNext()) { + if (this.fuels == null) { + this.fuels = this.getFuelItems(); + } + this.fuelIterator = this.fuels.iterator(); + } + this.currentItem = this.fuelIterator.next(); + } + return this.currentItem; + } +} diff --git a/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreen.java b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreen.java new file mode 100644 index 00000000..8156619d --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreen.java @@ -0,0 +1,151 @@ +package org.betterx.betterend.client.gui; + +import net.minecraft.client.gui.components.ImageButton; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; +import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.Slot; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import org.betterx.betterend.BetterEnd; + +@Environment(EnvType.CLIENT) +public class EndStoneSmelterScreen extends AbstractContainerScreen implements RecipeUpdateListener { + + private final static ResourceLocation RECIPE_BUTTON_TEXTURE = new ResourceLocation("textures/gui/recipe_button.png"); + private final static ResourceLocation BACKGROUND_TEXTURE = BetterEnd.makeID("textures/gui/smelter_gui.png"); + + public final EndStoneSmelterRecipeBookScreen recipeBook; + private boolean narrow; + + public EndStoneSmelterScreen(EndStoneSmelterScreenHandler handler, Inventory inventory, Component title) { + super(handler, inventory, title); + recipeBook = new EndStoneSmelterRecipeBookScreen(); + } + + public void init() { + super.init(); + //TODO: test in 1.17 + narrow = width < 379; + recipeBook.init(width, height, minecraft, narrow, menu); + leftPos = recipeBook.updateScreenPosition(width, imageWidth); + addRenderableWidget(new ImageButton( + leftPos + 20, + height / 2 - 49, + 20, + 18, + 0, + 0, + 19, + RECIPE_BUTTON_TEXTURE, + (buttonWidget) -> { + recipeBook.initVisuals(); + recipeBook.toggleVisibility(); + leftPos = recipeBook.updateScreenPosition(width, imageWidth); + ((ImageButton) buttonWidget).setPosition(leftPos + 20, height / 2 - 49); + } + )); + titleLabelX = (imageWidth - font.width(title)) / 2; + } + + @Override + public void containerTick() { + super.containerTick(); + recipeBook.tick(); + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + renderBackground(matrices); + if (recipeBook.isVisible() && narrow) { + renderBg(matrices, delta, mouseX, mouseY); + recipeBook.render(matrices, mouseX, mouseY, delta); + } else { + recipeBook.render(matrices, mouseX, mouseY, delta); + super.render(matrices, mouseX, mouseY, delta); + recipeBook.renderGhostRecipe(matrices, leftPos, topPos, true, delta); + } + renderTooltip(matrices, mouseX, mouseY); + recipeBook.renderTooltip(matrices, leftPos, topPos, mouseX, mouseY); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) { + return true; + } else { + return narrow && recipeBook.isVisible() || super.mouseClicked(mouseX, mouseY, button); + } + } + + @Override + protected void slotClicked(Slot slot, int invSlot, int clickData, ClickType actionType) { + super.slotClicked(slot, invSlot, clickData, actionType); + this.recipeBook.slotClicked(slot); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + return !recipeBook.keyPressed(keyCode, scanCode, modifiers) && super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + protected boolean hasClickedOutside(double mouseX, double mouseY, int left, int top, int button) { + boolean isMouseOut = mouseX < left || mouseY < top || mouseX >= (left + imageWidth) || mouseY >= (top + imageHeight); + return this.recipeBook.hasClickedOutside( + mouseX, + mouseY, + leftPos, + topPos, + imageWidth, + imageHeight, + button + ) && isMouseOut; + } + + @Override + public boolean charTyped(char chr, int keyCode) { + return recipeBook.charTyped(chr, keyCode) || super.charTyped(chr, keyCode); + } + + @Override + public void recipesUpdated() { + recipeBook.recipesUpdated(); + } + + @Override + public RecipeBookComponent getRecipeBookComponent() { + return recipeBook; + } + + @Override + protected void renderBg(PoseStack matrices, float delta, int mouseX, int mouseY) { + if (minecraft == null) return; + //TODO: verify + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, BACKGROUND_TEXTURE); + //minecraft.getTextureManager().bind(BACKGROUND_TEXTURE); + blit(matrices, leftPos, topPos, 0, 0, imageWidth, imageHeight); + int progress; + if (menu.isBurning()) { + progress = menu.getFuelProgress(); + blit(matrices, leftPos + 56, topPos + 36 + 12 - progress, 176, 12 - progress, 14, progress + 1); + } + progress = menu.getSmeltProgress(); + blit(matrices, leftPos + 92, topPos + 34, 176, 14, progress + 1, 16); + } + + @Override + public void removed() { + recipeBook.removed(); + super.removed(); + } +} diff --git a/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreenHandler.java b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreenHandler.java new file mode 100644 index 00000000..5e0024f0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/gui/EndStoneSmelterScreenHandler.java @@ -0,0 +1,200 @@ +package org.betterx.betterend.client.gui; + +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.StackedContents; +import net.minecraft.world.inventory.*; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; + +import org.anti_ad.mc.ipn.api.IPNIgnore; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndStoneSmelter; +import org.betterx.betterend.blocks.entities.EndStoneSmelterBlockEntity; +import org.betterx.betterend.client.gui.slot.SmelterFuelSlot; +import org.betterx.betterend.client.gui.slot.SmelterOutputSlot; +import org.betterx.betterend.recipe.builders.AlloyingRecipe; + +@IPNIgnore +public class EndStoneSmelterScreenHandler extends RecipeBookMenu { + + public final static MenuType HANDLER_TYPE = ScreenHandlerRegistry.registerSimple( + BetterEnd.makeID(EndStoneSmelter.ID), + EndStoneSmelterScreenHandler::new + ); + + private final Container inventory; + private final ContainerData propertyDelegate; + protected final Level world; + + public EndStoneSmelterScreenHandler(int syncId, Inventory playerInventory) { + this(syncId, playerInventory, new SimpleContainer(4), new SimpleContainerData(4)); + } + + public EndStoneSmelterScreenHandler(int syncId, + Inventory playerInventory, + Container inventory, + ContainerData propertyDelegate) { + super(HANDLER_TYPE, syncId); + this.inventory = inventory; + this.propertyDelegate = propertyDelegate; + this.world = playerInventory.player.level; + + addDataSlots(propertyDelegate); + addSlot(new Slot(inventory, 0, 45, 17)); + addSlot(new Slot(inventory, 1, 67, 17)); + addSlot(new SmelterFuelSlot(this, inventory, 2, 56, 53)); + addSlot(new SmelterOutputSlot(playerInventory.player, inventory, 3, 129, 35)); + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 9; ++j) { + addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); + } + } + for (int i = 0; i < 9; ++i) { + addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + } + + @Override + public MenuType getType() { + return HANDLER_TYPE; + } + + @Override + public void fillCraftSlotsStackedContents(StackedContents finder) { + if (inventory instanceof StackedContentsCompatible) { + ((StackedContentsCompatible) inventory).fillStackedContents(finder); + } + } + + @Override + public void clearCraftingContent() { + inventory.clearContent(); + } + + @Override + public boolean recipeMatches(Recipe recipe) { + return recipe.matches(inventory, world); + } + + @Override + public int getResultSlotIndex() { + return 3; + } + + @Override + public int getGridWidth() { + return 2; + } + + @Override + public int getGridHeight() { + return 1; + } + + @Override + public int getSize() { + return 4; + } + + @Override + public RecipeBookType getRecipeBookType() { + return RecipeBookType.BLAST_FURNACE; + } + + @Override + public boolean shouldMoveToInventory(int i) { + return i != this.getResultSlotIndex(); + } + + @Override + public boolean stillValid(Player player) { + return inventory.stillValid(player); + } + + protected boolean isSmeltable(ItemStack itemStack) { + return world.getRecipeManager() + .getRecipeFor(AlloyingRecipe.TYPE, new SimpleContainer(itemStack), world) + .isPresent(); + } + + public boolean isFuel(ItemStack itemStack) { + return EndStoneSmelterBlockEntity.canUseAsFuel(itemStack); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + Slot slot = slots.get(index); + if (slot == null || !slot.hasItem()) return ItemStack.EMPTY; + + ItemStack slotStack = slot.getItem(); + ItemStack itemStack = slotStack.copy(); + if (index == 3) { + if (!moveItemStackTo(slotStack, 4, 40, true)) { + return ItemStack.EMPTY; + } + slot.onQuickCraft(slotStack, itemStack); + } else if (index != 2 && index != 1 && index != 0) { + if (isSmeltable(slotStack)) { + if (!moveItemStackTo(slotStack, 0, 2, false)) { + return ItemStack.EMPTY; + } + } else if (isFuel(slotStack)) { + if (!moveItemStackTo(slotStack, 2, 3, false)) { + return ItemStack.EMPTY; + } + } else if (index < 31) { + if (!moveItemStackTo(slotStack, 31, 40, false)) { + return ItemStack.EMPTY; + } + } else if (index < 40 && !moveItemStackTo(slotStack, 4, 31, false)) { + return ItemStack.EMPTY; + } + } else if (!moveItemStackTo(slotStack, 4, 40, false)) { + return ItemStack.EMPTY; + } + + if (slotStack.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + if (slotStack.getCount() == itemStack.getCount()) { + return ItemStack.EMPTY; + } + + slot.onTake(player, slotStack); + + return itemStack; + } + + @Environment(EnvType.CLIENT) + public int getSmeltProgress() { + int time = propertyDelegate.get(2); + int timeTotal = propertyDelegate.get(3); + return timeTotal != 0 && time != 0 ? time * 24 / timeTotal : 0; + } + + @Environment(EnvType.CLIENT) + public int getFuelProgress() { + int fuelTime = propertyDelegate.get(1); + if (fuelTime == 0) { + fuelTime = 200; + } + return propertyDelegate.get(0) * 13 / fuelTime; + } + + @Environment(EnvType.CLIENT) + public boolean isBurning() { + return propertyDelegate.get(0) > 0; + } +} diff --git a/src/main/java/org/betterx/betterend/client/gui/slot/SmelterFuelSlot.java b/src/main/java/org/betterx/betterend/client/gui/slot/SmelterFuelSlot.java new file mode 100644 index 00000000..448c6d31 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/gui/slot/SmelterFuelSlot.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.client.gui.slot; + +import net.minecraft.world.Container; +import net.minecraft.world.inventory.FurnaceFuelSlot; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +import org.betterx.betterend.client.gui.EndStoneSmelterScreenHandler; + +public class SmelterFuelSlot extends Slot { + + private final EndStoneSmelterScreenHandler handler; + + public SmelterFuelSlot(EndStoneSmelterScreenHandler handler, Container inventory, int index, int x, int y) { + super(inventory, index, x, y); + this.handler = handler; + } + + public boolean mayPlace(ItemStack stack) { + return this.handler.isFuel(stack) || FurnaceFuelSlot.isBucket(stack); + } + + public int getMaxStackSize(ItemStack stack) { + return FurnaceFuelSlot.isBucket(stack) ? 1 : super.getMaxStackSize(stack); + } +} diff --git a/src/main/java/org/betterx/betterend/client/gui/slot/SmelterOutputSlot.java b/src/main/java/org/betterx/betterend/client/gui/slot/SmelterOutputSlot.java new file mode 100644 index 00000000..95036b03 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/gui/slot/SmelterOutputSlot.java @@ -0,0 +1,49 @@ +package org.betterx.betterend.client.gui.slot; + +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +import org.betterx.betterend.blocks.entities.EndStoneSmelterBlockEntity; + +public class SmelterOutputSlot extends Slot { + + private final Player player; + private int amount; + + public SmelterOutputSlot(Player player, Container inventory, int index, int x, int y) { + super(inventory, index, x, y); + this.player = player; + } + + public boolean mayPlace(ItemStack stack) { + return false; + } + + public ItemStack remove(int amount) { + if (this.hasItem()) { + this.amount += Math.min(amount, this.getItem().getCount()); + } + + return super.remove(amount); + } + + public void onTake(Player player, ItemStack stack) { + this.checkTakeAchievements(stack); + super.onTake(player, stack); + } + + protected void onQuickCraft(ItemStack stack, int amount) { + this.amount += amount; + this.checkTakeAchievements(stack); + } + + protected void checkTakeAchievements(ItemStack stack) { + stack.onCraftedBy(this.player.level, this.player, this.amount); + if (!this.player.level.isClientSide && this.container instanceof EndStoneSmelterBlockEntity) { + ((EndStoneSmelterBlockEntity) this.container).dropExperience(player); + } + this.amount = 0; + } +} diff --git a/src/main/java/org/betterx/betterend/client/models/Patterns.java b/src/main/java/org/betterx/betterend/client/models/Patterns.java new file mode 100644 index 00000000..85b80946 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/models/Patterns.java @@ -0,0 +1,150 @@ +package org.betterx.betterend.client.models; + +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; + +import com.google.common.collect.Maps; +import org.betterx.betterend.BetterEnd; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.stream.Collectors; + +public class Patterns { + //Block Models + public final static ResourceLocation BLOCK_EMPTY = BetterEnd.makeID("patterns/block/empty.json"); + public final static ResourceLocation BLOCK_BASE = BetterEnd.makeID("patterns/block/block.json"); + public final static ResourceLocation BLOCK_SIDED = BetterEnd.makeID("patterns/block/block_sided.json"); + public final static ResourceLocation BLOCK_BOTTOM_TOP = BetterEnd.makeID("patterns/block/block_bottom_top.json"); + public final static ResourceLocation BLOCK_SLAB = BetterEnd.makeID("patterns/block/slab.json"); + public final static ResourceLocation BLOCK_STAIR = BetterEnd.makeID("patterns/block/stairs.json"); + public final static ResourceLocation BLOCK_STAIR_INNER = BetterEnd.makeID("patterns/block/inner_stairs.json"); + public final static ResourceLocation BLOCK_STAIR_OUTER = BetterEnd.makeID("patterns/block/outer_stairs.json"); + public final static ResourceLocation BLOCK_WALL_POST = BetterEnd.makeID("patterns/block/wall_post.json"); + public final static ResourceLocation BLOCK_WALL_SIDE = BetterEnd.makeID("patterns/block/wall_side.json"); + public final static ResourceLocation BLOCK_WALL_SIDE_TALL = BetterEnd.makeID("patterns/block/wall_side_tall.json"); + public final static ResourceLocation BLOCK_FENCE_POST = BetterEnd.makeID("patterns/block/fence_post.json"); + public final static ResourceLocation BLOCK_FENCE_SIDE = BetterEnd.makeID("patterns/block/fence_side.json"); + public final static ResourceLocation BLOCK_BUTTON = BetterEnd.makeID("patterns/block/button.json"); + public final static ResourceLocation BLOCK_BUTTON_PRESSED = BetterEnd.makeID("patterns/block/button_pressed.json"); + public final static ResourceLocation BLOCK_PILLAR = BetterEnd.makeID("patterns/block/pillar.json"); + public final static ResourceLocation BLOCK_PLATE_UP = BetterEnd.makeID("patterns/block/pressure_plate_up.json"); + public final static ResourceLocation BLOCK_PLATE_DOWN = BetterEnd.makeID("patterns/block/pressure_plate_down.json"); + public final static ResourceLocation BLOCK_DOOR_TOP = BetterEnd.makeID("patterns/block/door_top.json"); + public final static ResourceLocation BLOCK_DOOR_TOP_HINGE = BetterEnd.makeID("patterns/block/door_top_hinge.json"); + public final static ResourceLocation BLOCK_DOOR_BOTTOM = BetterEnd.makeID("patterns/block/door_bottom.json"); + public final static ResourceLocation BLOCK_DOOR_BOTTOM_HINGE = BetterEnd.makeID( + "patterns/block/door_bottom_hinge.json"); + public final static ResourceLocation BLOCK_CROSS = BetterEnd.makeID("patterns/block/cross.json"); + public final static ResourceLocation BLOCK_CROSS_SHADED = BetterEnd.makeID("patterns/block/cross_shaded.json"); + public final static ResourceLocation BLOCK_GATE_CLOSED = BetterEnd.makeID("patterns/block/fence_gate_closed.json"); + public final static ResourceLocation BLOCK_GATE_CLOSED_WALL = BetterEnd.makeID( + "patterns/block/wall_gate_closed.json"); + public final static ResourceLocation BLOCK_GATE_OPEN = BetterEnd.makeID("patterns/block/fence_gate_open.json"); + public final static ResourceLocation BLOCK_GATE_OPEN_WALL = BetterEnd.makeID("patterns/block/wall_gate_open.json"); + public final static ResourceLocation BLOCK_TRAPDOOR = BetterEnd.makeID("patterns/block/trapdoor.json"); + public final static ResourceLocation BLOCK_LADDER = BetterEnd.makeID("patterns/block/ladder.json"); + public final static ResourceLocation BLOCK_BARREL_OPEN = BetterEnd.makeID("patterns/block/barrel_open.json"); + public final static ResourceLocation BLOCK_PEDESTAL_DEFAULT = BetterEnd.makeID( + "patterns/block/pedestal_default.json"); + public final static ResourceLocation BLOKC_PEDESTAL_COLUMN = BetterEnd.makeID("patterns/block/pedestal_column.json"); + public final static ResourceLocation BLOCK_PEDESTAL_COLUMN_TOP = BetterEnd.makeID( + "patterns/block/pedestal_column_top.json"); + public final static ResourceLocation BLOCK_PEDESTAL_TOP = BetterEnd.makeID("patterns/block/pedestal_top.json"); + public final static ResourceLocation BLOCK_PEDESTAL_BOTTOM = BetterEnd.makeID("patterns/block/pedestal_bottom.json"); + public final static ResourceLocation BLOCK_PEDESTAL_PILLAR = BetterEnd.makeID("patterns/block/pedestal_pillar.json"); + public final static ResourceLocation BLOCK_BOOKSHELF = BetterEnd.makeID("patterns/block/bookshelf.json"); + public final static ResourceLocation BLOCK_STONE_LANTERN_CEIL = BetterEnd.makeID( + "patterns/block/stone_lantern_ceil.json"); + public final static ResourceLocation BLOCK_STONE_LANTERN_FLOOR = BetterEnd.makeID( + "patterns/block/stone_lantern_floor.json"); + public final static ResourceLocation BLOCK_BULB_LANTERN_FLOOR = BetterEnd.makeID( + "patterns/block/bulb_lantern_floor.json"); + public final static ResourceLocation BLOCK_BULB_LANTERN_CEIL = BetterEnd.makeID( + "patterns/block/bulb_lantern_ceil.json"); + public final static ResourceLocation BLOCK_PETAL_COLORED = BetterEnd.makeID("models/block/block_petal_colored.json"); + public final static ResourceLocation BLOCK_COMPOSTER = BetterEnd.makeID("patterns/block/composter.json"); + public final static ResourceLocation BLOCK_COLORED = BetterEnd.makeID("patterns/block/block_colored.json"); + public final static ResourceLocation BLOCK_BARS_POST = BetterEnd.makeID("patterns/block/bars_post.json"); + public final static ResourceLocation BLOCK_BARS_SIDE = BetterEnd.makeID("patterns/block/bars_side.json"); + public final static ResourceLocation BLOCK_ANVIL = BetterEnd.makeID("patterns/block/anvil.json"); + public final static ResourceLocation BLOCK_CHAIN = BetterEnd.makeID("patterns/block/chain.json"); + public final static ResourceLocation BLOCK_CHANDELIER_FLOOR = BetterEnd.makeID( + "patterns/block/chandelier_floor.json"); + public final static ResourceLocation BLOCK_CHANDELIER_WALL = BetterEnd.makeID("patterns/block/chandelier_wall.json"); + public final static ResourceLocation BLOCK_CHANDELIER_CEIL = BetterEnd.makeID("patterns/block/chandelier_ceil.json"); + public final static ResourceLocation BLOCK_FURNACE = BetterEnd.makeID("patterns/block/furnace.json"); + public final static ResourceLocation BLOCK_FURNACE_LIT = BetterEnd.makeID("patterns/block/furnace_glow.json"); + public final static ResourceLocation BLOCK_TOP_SIDE_BOTTOM = BetterEnd.makeID("patterns/block/top_side_bottom.json"); + public final static ResourceLocation BLOCK_PATH = BetterEnd.makeID("patterns/block/path.json"); + public final static ResourceLocation BLOCK_FLOWER_POT = BetterEnd.makeID("patterns/block/flower_pot.json"); + public final static ResourceLocation BLOCK_FLOWER_POT_SOIL = BetterEnd.makeID("patterns/block/flower_pot_soil.json"); + public final static ResourceLocation BLOCK_POTTED_LEAVES = BetterEnd.makeID("patterns/block/potted_leaves.json"); + + //Item Models + public final static ResourceLocation ITEM_WALL = BetterEnd.makeID("patterns/item/pattern_wall.json"); + public final static ResourceLocation ITEM_FENCE = BetterEnd.makeID("patterns/item/pattern_fence.json"); + public final static ResourceLocation ITEM_BUTTON = BetterEnd.makeID("patterns/item/pattern_button.json"); + public final static ResourceLocation ITEM_CHEST = BetterEnd.makeID("patterns/item/pattern_chest.json"); + public final static ResourceLocation ITEM_BLOCK = BetterEnd.makeID("patterns/item/pattern_block_item.json"); + public final static ResourceLocation ITEM_GENERATED = BetterEnd.makeID("patterns/item/pattern_item_generated.json"); + public final static ResourceLocation ITEM_HANDHELD = BetterEnd.makeID("patterns/item/pattern_item_handheld.json"); + public final static ResourceLocation ITEM_SPAWN_EGG = BetterEnd.makeID("patterns/item/pattern_item_spawn_egg.json"); + + public static Optional createItemGenerated(String name) { + return createJson(ITEM_GENERATED, name); + } + + public static Optional createBlockSimple(String name) { + return Patterns.createJson(Patterns.BLOCK_BASE, name, name); + } + + public static Optional createBlockPillar(String name) { + return Patterns.createJson(Patterns.BLOCK_PILLAR, name, name); + } + + public static String createJson(Reader data, String parent, String block) { + try (BufferedReader buffer = new BufferedReader(data)) { + return buffer.lines().collect(Collectors.joining()).replace("%parent%", parent).replace("%block%", block); + } catch (Exception ex) { + return null; + } + } + + public static Optional createJson(ResourceLocation patternId, String parent, String block) { + ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); + try (InputStream input = resourceManager.getResource(patternId).get().open()) { + return Optional.ofNullable(createJson(new InputStreamReader(input, StandardCharsets.UTF_8), parent, block)); + } catch (Exception ex) { + return Optional.empty(); + } + } + + public static Optional createJson(ResourceLocation patternId, String texture) { + Map textures = Maps.newHashMap(); + textures.put("%texture%", texture); + return createJson(patternId, textures); + } + + public static Optional createJson(ResourceLocation patternId, Map textures) { + ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); + try (InputStream input = resourceManager.getResource(patternId).get().open()) { + String json = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() + .collect(Collectors.joining()); + for (Entry texture : textures.entrySet()) { + json = json.replace(texture.getKey(), texture.getValue()); + } + return Optional.of(json); + } catch (Exception ex) { + return Optional.empty(); + } + } + +} diff --git a/src/main/java/org/betterx/betterend/client/render/ArmoredElytraLayer.java b/src/main/java/org/betterx/betterend/client/render/ArmoredElytraLayer.java new file mode 100644 index 00000000..9aeca007 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/ArmoredElytraLayer.java @@ -0,0 +1,69 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.ElytraLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.PlayerModelPart; +import net.minecraft.world.item.ItemStack; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.item.model.ArmoredElytraModel; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class ArmoredElytraLayer> extends ElytraLayer { + private final ArmoredElytraModel elytraModel; + + public ArmoredElytraLayer(RenderLayerParent renderLayerParent, EntityModelSet entityModelSet) { + super(renderLayerParent, entityModelSet); + elytraModel = new ArmoredElytraModel<>(entityModelSet.bakeLayer(EndEntitiesRenders.ARMORED_ELYTRA)); + } + + public void render(PoseStack poseStack, + MultiBufferSource multiBufferSource, + int i, + T livingEntity, + float f, + float g, + float h, + float j, + float k, + float l) { + ItemStack itemStack = livingEntity.getItemBySlot(EquipmentSlot.CHEST); + if (itemStack.getItem() instanceof FallFlyingItem) { + ResourceLocation wingsTexture = ((FallFlyingItem) itemStack.getItem()).getModelTexture(); + if (livingEntity instanceof AbstractClientPlayer) { + AbstractClientPlayer abstractClientPlayer = (AbstractClientPlayer) livingEntity; + if (abstractClientPlayer.isElytraLoaded() && abstractClientPlayer.getElytraTextureLocation() != null) { + wingsTexture = abstractClientPlayer.getElytraTextureLocation(); + } else if (abstractClientPlayer.isCapeLoaded() && abstractClientPlayer.getCloakTextureLocation() != null && abstractClientPlayer + .isModelPartShown(PlayerModelPart.CAPE)) { + wingsTexture = abstractClientPlayer.getCloakTextureLocation(); + } + } + + poseStack.pushPose(); + poseStack.translate(0.0D, 0.0D, 0.125D); + getParentModel().copyPropertiesTo(elytraModel); + elytraModel.setupAnim(livingEntity, f, g, j, k, l); + VertexConsumer vertexConsumer = ItemRenderer.getArmorFoilBuffer( + multiBufferSource, + RenderType.armorCutoutNoCull(wingsTexture), + false, + itemStack.hasFoil() + ); + elytraModel.renderToBuffer(poseStack, vertexConsumer, i, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); + poseStack.popPose(); + } + } +} diff --git a/src/main/java/org/betterx/betterend/client/render/BeamRenderer.java b/src/main/java/org/betterx/betterend/client/render/BeamRenderer.java new file mode 100644 index 00000000..97c0d344 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/BeamRenderer.java @@ -0,0 +1,238 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; + +public class BeamRenderer { + private static final ResourceLocation BEAM_TEXTURE = new ResourceLocation("textures/entity/end_gateway_beam.png"); + + public static void renderLightBeam(PoseStack matrices, + MultiBufferSource vertexConsumers, + int age, + float tick, + int minY, + int maxY, + float[] colors, + float alpha, + float beamIn, + float beamOut) { + float red = colors[0]; + float green = colors[1]; + float blue = colors[2]; + + int maxBY = minY + maxY; + float delta = maxY < 0 ? tick : -tick; + float fractDelta = Mth.frac(delta * 0.2F - (float) Mth.floor(delta * 0.1F)); + float xIn = -beamIn; + float minV = Mth.clamp(fractDelta - 1.0F, 0.0F, 1.0F); + float maxV = (float) maxY * (0.5F / beamIn) + minV; + float rotation = (age + tick) / 25.0F + 6.0F; + + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderType.beaconBeam(BEAM_TEXTURE, true)); + + matrices.pushPose(); + matrices.mulPose(Vector3f.YP.rotation(-rotation)); + renderBeam( + matrices, + vertexConsumer, + red, + green, + blue, + alpha, + minY, + maxBY, + beamIn, + 0.0F, + 0.0F, + beamIn, + 0.0F, + xIn, + xIn, + 0.0F, + 0.0F, + 1.0F, + minV, + maxV + ); + + float xOut = -beamOut; + maxV = (float) maxY + minV; + renderBeam( + matrices, + vertexConsumer, + red, + green, + blue, + alpha, + minY, + maxBY, + xOut, + xOut, + beamOut, + xOut, + xOut, + beamOut, + beamOut, + beamOut, + 0.0F, + 1.0F, + minV, + maxV + ); + matrices.popPose(); + } + + private static void renderBeam(PoseStack matrices, + VertexConsumer vertexConsumer, + float red, + float green, + float blue, + float alpha, + int minY, + int maxY, + float x1, + float d1, + float x2, + float d2, + float x3, + float d3, + float x4, + float d4, + float minU, + float maxU, + float minV, + float maxV) { + PoseStack.Pose entry = matrices.last(); + Matrix4f matrix4f = entry.pose(); + Matrix3f matrix3f = entry.normal(); + renderBeam( + matrix4f, + matrix3f, + vertexConsumer, + red, + green, + blue, + alpha, + maxY, + minY, + x1, + d1, + x2, + d2, + minU, + maxU, + minV, + maxV + ); + renderBeam( + matrix4f, + matrix3f, + vertexConsumer, + red, + green, + blue, + alpha, + maxY, + minY, + x4, + d4, + x3, + d3, + minU, + maxU, + minV, + maxV + ); + renderBeam( + matrix4f, + matrix3f, + vertexConsumer, + red, + green, + blue, + alpha, + maxY, + minY, + x2, + d2, + x4, + d4, + minU, + maxU, + minV, + maxV + ); + renderBeam( + matrix4f, + matrix3f, + vertexConsumer, + red, + green, + blue, + alpha, + maxY, + minY, + x3, + d3, + x1, + d1, + minU, + maxU, + minV, + maxV + ); + } + + private static void renderBeam(Matrix4f matrix4f, + Matrix3f matrix3f, + VertexConsumer vertexConsumer, + float red, + float green, + float blue, + float alpha, + int minY, + int maxY, + float minX, + float minD, + float maxX, + float maxD, + float minU, + float maxU, + float minV, + float maxV) { + addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, maxX, minY, maxD, maxU, minV); + addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, maxX, maxY, maxD, maxU, maxV); + addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, minX, maxY, minD, minU, maxV); + addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, minX, minY, minD, minU, minV); + } + + private static void addVertex(Matrix4f matrix4f, + Matrix3f matrix3f, + VertexConsumer vertexConsumer, + float red, + float green, + float blue, + float alpha, + float x, + float y, + float d, + float u, + float v) { + vertexConsumer.vertex(matrix4f, x, y, d) + .color(red, green, blue, alpha) + .uv(u, v) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(15728880) + .normal(matrix3f, 0.0F, 1.0F, 0.0F) + .endVertex(); + } +} diff --git a/src/main/java/org/betterx/betterend/client/render/BetterEndSkyRenderer.java b/src/main/java/org/betterx/betterend/client/render/BetterEndSkyRenderer.java new file mode 100644 index 00000000..fa3509eb --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/BetterEndSkyRenderer.java @@ -0,0 +1,425 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.renderer.FogRenderer; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.LegacyRandomSource; + +import net.fabricmc.fabric.api.client.rendering.v1.DimensionRenderingRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; +import com.mojang.math.Vector3f; +import org.betterx.bclib.util.BackgroundInfo; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; + +public class BetterEndSkyRenderer implements DimensionRenderingRegistry.SkyRenderer { + @FunctionalInterface + interface BufferFunction { + void make(BufferBuilder bufferBuilder, double minSize, double maxSize, int count, long seed); + } + + private static final ResourceLocation NEBULA_1 = BetterEnd.makeID("textures/sky/nebula_2.png"); + private static final ResourceLocation NEBULA_2 = BetterEnd.makeID("textures/sky/nebula_3.png"); + private static final ResourceLocation HORIZON = BetterEnd.makeID("textures/sky/nebula_1.png"); + private static final ResourceLocation STARS = BetterEnd.makeID("textures/sky/stars.png"); + private static final ResourceLocation FOG = BetterEnd.makeID("textures/sky/fog.png"); + + private VertexBuffer nebula1; + private VertexBuffer nebula2; + private VertexBuffer horizon; + private VertexBuffer stars1; + private VertexBuffer stars2; + private VertexBuffer stars3; + private VertexBuffer stars4; + private VertexBuffer fog; + private Vector3f axis1; + private Vector3f axis2; + private Vector3f axis3; + private Vector3f axis4; + + private boolean initialised; + + private void initialise() { + if (!initialised) { + initStars(); + RandomSource random = new LegacyRandomSource(131); + axis1 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); + axis2 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); + axis3 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); + axis4 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); + axis1.normalize(); + axis2.normalize(); + axis3.normalize(); + axis4.normalize(); + initialised = true; + } + } + + @Override + public void render(WorldRenderContext context) { + if (context.world() == null || context.matrixStack() == null) { + return; + } + + initialise(); + + Matrix4f projectionMatrix = context.projectionMatrix(); + PoseStack matrices = context.matrixStack(); + + float time = ((context.world().getDayTime() + context.tickDelta()) % 360000) * 0.000017453292F; + float time2 = time * 2; + float time3 = time * 3; + + FogRenderer.levelFogColor(); + RenderSystem.depthMask(false); + RenderSystem.enableTexture(); + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + + float blindA = 1F - BackgroundInfo.blindness; + float blind02 = blindA * 0.2F; + float blind06 = blindA * 0.6F; + + if (blindA > 0) { + matrices.pushPose(); + matrices.mulPose(new Quaternion(0, time, 0, false)); + RenderSystem.setShaderTexture(0, HORIZON); + renderBuffer(matrices, + projectionMatrix, + horizon, + DefaultVertexFormat.POSITION_TEX, + 0.77F, + 0.31F, + 0.73F, + 0.7F * blindA); + matrices.popPose(); + + matrices.pushPose(); + matrices.mulPose(new Quaternion(0, -time, 0, false)); + RenderSystem.setShaderTexture(0, NEBULA_1); + renderBuffer(matrices, + projectionMatrix, + nebula1, + DefaultVertexFormat.POSITION_TEX, + 0.77F, + 0.31F, + 0.73F, + blind02); + matrices.popPose(); + + matrices.pushPose(); + matrices.mulPose(new Quaternion(0, time2, 0, false)); + RenderSystem.setShaderTexture(0, NEBULA_2); + renderBuffer(matrices, + projectionMatrix, + nebula2, + DefaultVertexFormat.POSITION_TEX, + 0.77F, + 0.31F, + 0.73F, + blind02); + matrices.popPose(); + + RenderSystem.setShaderTexture(0, STARS); + + matrices.pushPose(); + matrices.mulPose(axis3.rotation(time)); + renderBuffer(matrices, + projectionMatrix, + stars3, + DefaultVertexFormat.POSITION_TEX, + 0.77F, + 0.31F, + 0.73F, + blind06); + matrices.popPose(); + + matrices.pushPose(); + matrices.mulPose(axis4.rotation(time2)); + renderBuffer(matrices, projectionMatrix, stars4, DefaultVertexFormat.POSITION_TEX, 1F, 1F, 1F, blind06); + matrices.popPose(); + } + + float a = (BackgroundInfo.fogDensity - 1F); + if (a > 0) { + if (a > 1) a = 1; + RenderSystem.setShaderTexture(0, FOG); + renderBuffer( + matrices, + projectionMatrix, + fog, + DefaultVertexFormat.POSITION_TEX, + BackgroundInfo.fogColorRed, + BackgroundInfo.fogColorGreen, + BackgroundInfo.fogColorBlue, + a); + } + + RenderSystem.disableTexture(); + + if (blindA > 0) { + matrices.pushPose(); + matrices.mulPose(axis1.rotation(time3)); + renderBuffer(matrices, projectionMatrix, stars1, DefaultVertexFormat.POSITION, 1, 1, 1, blind06); + matrices.popPose(); + + matrices.pushPose(); + matrices.mulPose(axis2.rotation(time2)); + renderBuffer(matrices, + projectionMatrix, + stars2, + DefaultVertexFormat.POSITION, + 0.95F, + 0.64F, + 0.93F, + blind06); + matrices.popPose(); + } + + RenderSystem.enableTexture(); + RenderSystem.depthMask(true); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableBlend(); + } + + private void renderBuffer(PoseStack matrices, + Matrix4f matrix4f, + VertexBuffer buffer, + VertexFormat format, + float r, + float g, + float b, + float a) { + RenderSystem.setShaderColor(r, g, b, a); + buffer.bind(); + if (format == DefaultVertexFormat.POSITION) { + buffer.drawWithShader(matrices.last().pose(), matrix4f, GameRenderer.getPositionShader()); + } else { + buffer.drawWithShader(matrices.last().pose(), matrix4f, GameRenderer.getPositionTexShader()); + } + VertexBuffer.unbind(); + } + + private void initStars() { + BufferBuilder buffer = Tesselator.getInstance().getBuilder(); + stars1 = buildBuffer(buffer, stars1, 0.1, 0.30, 3500, 41315, this::makeStars); + stars2 = buildBuffer(buffer, stars2, 0.1, 0.35, 2000, 35151, this::makeStars); + stars3 = buildBuffer(buffer, stars3, 0.4, 1.2, 1000, 61354, this::makeUVStars); + stars4 = buildBuffer(buffer, stars4, 0.4, 1.2, 1000, 61355, this::makeUVStars); + nebula1 = buildBuffer(buffer, nebula1, 40, 60, 30, 11515, this::makeFarFog); + nebula2 = buildBuffer(buffer, nebula2, 40, 60, 10, 14151, this::makeFarFog); + horizon = buildBufferHorizon(buffer, horizon); + fog = buildBufferFog(buffer, fog); + } + + private VertexBuffer buildBuffer(BufferBuilder bufferBuilder, + VertexBuffer buffer, + double minSize, + double maxSize, + int count, + long seed, + BufferFunction fkt) { + if (buffer != null) { + buffer.close(); + } + + buffer = new VertexBuffer(); + fkt.make(bufferBuilder, minSize, maxSize, count, seed); + BufferBuilder.RenderedBuffer renderedBuffer = bufferBuilder.end(); + buffer.bind(); + buffer.upload(renderedBuffer); + + return buffer; + } + + + private VertexBuffer buildBufferHorizon(BufferBuilder bufferBuilder, VertexBuffer buffer) { + return buildBuffer( + bufferBuilder, buffer, 0, 0, 0, 0, + (_builder, _minSize, _maxSize, _count, _seed) -> makeCylinder(_builder, 16, 50, 100)); + + } + + private VertexBuffer buildBufferFog(BufferBuilder bufferBuilder, VertexBuffer buffer) { + return buildBuffer( + bufferBuilder, buffer, 0, 0, 0, 0, + (_builder, _minSize, _maxSize, _count, _seed) -> makeCylinder(_builder, 16, 50, 70)); + } + + private void makeStars(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { + RandomSource random = new LegacyRandomSource(seed); + RenderSystem.setShader(GameRenderer::getPositionShader); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); + + for (int i = 0; i < count; ++i) { + double posX = random.nextDouble() * 2.0 - 1.0; + double posY = random.nextDouble() * 2.0 - 1.0; + double posZ = random.nextDouble() * 2.0 - 1.0; + double size = MHelper.randRange(minSize, maxSize, random); + double length = posX * posX + posY * posY + posZ * posZ; + + if (length < 1.0 && length > 0.001) { + length = 1.0 / Math.sqrt(length); + posX *= length; + posY *= length; + posZ *= length; + + double px = posX * 100.0; + double py = posY * 100.0; + double pz = posZ * 100.0; + + double angle = Math.atan2(posX, posZ); + double sin1 = Math.sin(angle); + double cos1 = Math.cos(angle); + angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); + double sin2 = Math.sin(angle); + double cos2 = Math.cos(angle); + angle = random.nextDouble() * Math.PI * 2.0; + double sin3 = Math.sin(angle); + double cos3 = Math.cos(angle); + + for (int index = 0; index < 4; ++index) { + double x = (double) ((index & 2) - 1) * size; + double y = (double) ((index + 1 & 2) - 1) * size; + double aa = x * cos3 - y * sin3; + double ab = y * cos3 + x * sin3; + double dy = aa * sin2 + 0.0 * cos2; + double ae = 0.0 * sin2 - aa * cos2; + double dx = ae * sin1 - ab * cos1; + double dz = ab * sin1 + ae * cos1; + buffer.vertex(px + dx, py + dy, pz + dz).endVertex(); + } + } + } + } + + private void makeUVStars(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { + RandomSource random = new LegacyRandomSource(seed); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); + + for (int i = 0; i < count; ++i) { + double posX = random.nextDouble() * 2.0 - 1.0; + double posY = random.nextDouble() * 2.0 - 1.0; + double posZ = random.nextDouble() * 2.0 - 1.0; + double size = MHelper.randRange(minSize, maxSize, random); + double length = posX * posX + posY * posY + posZ * posZ; + + if (length < 1.0 && length > 0.001) { + length = 1.0 / Math.sqrt(length); + posX *= length; + posY *= length; + posZ *= length; + + double px = posX * 100.0; + double py = posY * 100.0; + double pz = posZ * 100.0; + + double angle = Math.atan2(posX, posZ); + double sin1 = Math.sin(angle); + double cos1 = Math.cos(angle); + angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); + double sin2 = Math.sin(angle); + double cos2 = Math.cos(angle); + angle = random.nextDouble() * Math.PI * 2.0; + double sin3 = Math.sin(angle); + double cos3 = Math.cos(angle); + + float minV = random.nextInt(4) / 4F; + for (int index = 0; index < 4; ++index) { + double x = (double) ((index & 2) - 1) * size; + double y = (double) ((index + 1 & 2) - 1) * size; + double aa = x * cos3 - y * sin3; + double ab = y * cos3 + x * sin3; + double dy = aa * sin2 + 0.0 * cos2; + double ae = 0.0 * sin2 - aa * cos2; + double dx = ae * sin1 - ab * cos1; + double dz = ab * sin1 + ae * cos1; + float texU = (index >> 1) & 1; + float texV = (((index + 1) >> 1) & 1) / 4F + minV; + buffer.vertex(px + dx, py + dy, pz + dz).uv(texU, texV).endVertex(); + } + } + } + } + + private void makeFarFog(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { + RandomSource random = new LegacyRandomSource(seed); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); + + for (int i = 0; i < count; ++i) { + double posX = random.nextDouble() * 2.0 - 1.0; + double posY = random.nextDouble() - 0.5; + double posZ = random.nextDouble() * 2.0 - 1.0; + double size = MHelper.randRange(minSize, maxSize, random); + double length = posX * posX + posY * posY + posZ * posZ; + double distance = 2.0; + + if (length < 1.0 && length > 0.001) { + length = distance / Math.sqrt(length); + size *= distance; + posX *= length; + posY *= length; + posZ *= length; + + double px = posX * 100.0; + double py = posY * 100.0; + double pz = posZ * 100.0; + + double angle = Math.atan2(posX, posZ); + double sin1 = Math.sin(angle); + double cos1 = Math.cos(angle); + angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); + double sin2 = Math.sin(angle); + double cos2 = Math.cos(angle); + angle = random.nextDouble() * Math.PI * 2.0; + double sin3 = Math.sin(angle); + double cos3 = Math.cos(angle); + + for (int index = 0; index < 4; ++index) { + double x = (double) ((index & 2) - 1) * size; + double y = (double) ((index + 1 & 2) - 1) * size; + double aa = x * cos3 - y * sin3; + double ab = y * cos3 + x * sin3; + double dy = aa * sin2 + 0.0 * cos2; + double ae = 0.0 * sin2 - aa * cos2; + double dx = ae * sin1 - ab * cos1; + double dz = ab * sin1 + ae * cos1; + float texU = (index >> 1) & 1; + float texV = ((index + 1) >> 1) & 1; + buffer.vertex(px + dx, py + dy, pz + dz).uv(texU, texV).endVertex(); + } + } + } + } + + private void makeCylinder(BufferBuilder buffer, int segments, double height, double radius) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); + for (int i = 0; i < segments; i++) { + double a1 = (double) i * Math.PI * 2.0 / (double) segments; + double a2 = (double) (i + 1) * Math.PI * 2.0 / (double) segments; + double px1 = Math.sin(a1) * radius; + double pz1 = Math.cos(a1) * radius; + double px2 = Math.sin(a2) * radius; + double pz2 = Math.cos(a2) * radius; + + float u0 = (float) i / (float) segments; + float u1 = (float) (i + 1) / (float) segments; + + buffer.vertex(px1, -height, pz1).uv(u0, 0).endVertex(); + buffer.vertex(px1, height, pz1).uv(u0, 1).endVertex(); + buffer.vertex(px2, height, pz2).uv(u1, 1).endVertex(); + buffer.vertex(px2, -height, pz2).uv(u1, 0).endVertex(); + } + } +} diff --git a/src/main/java/org/betterx/betterend/client/render/EndCrystalRenderer.java b/src/main/java/org/betterx/betterend/client/render/EndCrystalRenderer.java new file mode 100644 index 00000000..a38b5e1d --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/EndCrystalRenderer.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +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.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Quaternion; +import com.mojang.math.Vector3f; + +public class EndCrystalRenderer { + private static final ResourceLocation CRYSTAL_TEXTURE = new ResourceLocation( + "textures/entity/end_crystal/end_crystal.png"); + private static final ResourceLocation CRYSTAL_BEAM_TEXTURE = new ResourceLocation( + "textures/entity/end_crystal/end_crystal_beam.png"); + private static final RenderType END_CRYSTAL; + private static final ModelPart CORE; + private static final ModelPart FRAME; + private static final int AGE_CYCLE = 240; + private static final float SINE_45_DEGREES; + + public static void render(int age, + int maxAge, + float tickDelta, + PoseStack matrices, + MultiBufferSource vertexConsumerProvider, + int light) { + float k = (float) AGE_CYCLE / maxAge; + float rotation = (age * k + tickDelta) * 3.0F; + VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(END_CRYSTAL); + matrices.pushPose(); + matrices.scale(0.8F, 0.8F, 0.8F); + matrices.translate(0.0D, -0.5D, 0.0D); + matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); + matrices.translate(0.0D, 0.8F, 0.0D); + matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); + FRAME.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); + matrices.scale(0.875F, 0.875F, 0.875F); + matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); + matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); + FRAME.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); + matrices.scale(0.875F, 0.875F, 0.875F); + matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); + matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); + CORE.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); + matrices.popPose(); + } + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + modelPartData.addOrReplaceChild( + "FRAME", + CubeListBuilder.create().texOffs(0, 0).addBox(-4.0f, -4.0f, -4.0f, 8.0f, 8.0f, 8.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + "CORE", + CubeListBuilder.create().texOffs(32, 0).addBox(-4.0f, -4.0f, -4.0f, 8.0f, 8.0f, 8.0f), + PartPose.ZERO + ); + + return LayerDefinition.create(modelData, 64, 32); + } + + static { + END_CRYSTAL = RenderType.entityCutoutNoCull(CRYSTAL_TEXTURE); + RenderType.entitySmoothCutout(CRYSTAL_BEAM_TEXTURE); + SINE_45_DEGREES = (float) Math.sin(0.7853981633974483D); + + ModelPart root = getTexturedModelData().bakeRoot(); + FRAME = root.getChild("FRAME"); + CORE = root.getChild("CORE"); + } +} diff --git a/src/main/java/org/betterx/betterend/client/render/EternalCrystalRenderer.java b/src/main/java/org/betterx/betterend/client/render/EternalCrystalRenderer.java new file mode 100644 index 00000000..6d6e3a14 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/EternalCrystalRenderer.java @@ -0,0 +1,135 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +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.renderer.texture.OverlayTexture; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.AuroraCrystalBlock; + +// TODO make crystals bright +public class EternalCrystalRenderer { + private static final RenderType RENDER_LAYER; + private static final ModelPart[] SHARDS; + private static final ModelPart CORE; + + public static void render(int age, + float tickDelta, + PoseStack matrices, + MultiBufferSource vertexConsumerProvider, + int light) { + VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RENDER_LAYER); + float[] colors = colors(age); + float rotation = (age + tickDelta) / 25.0F + 6.0F; + matrices.pushPose(); + matrices.scale(0.6F, 0.6F, 0.6F); + matrices.mulPose(Vector3f.YP.rotation(rotation)); + CORE.render( + matrices, + vertexConsumer, + light, + OverlayTexture.NO_OVERLAY, + colors[0], + colors[1], + colors[2], + colors[3] + ); + + for (int i = 0; i < 4; i++) { + matrices.pushPose(); + float offset = Mth.sin(rotation * 2 + i) * 0.15F; + matrices.translate(0, offset, 0); + SHARDS[i].render( + matrices, + vertexConsumer, + light, + OverlayTexture.NO_OVERLAY, + colors[0], + colors[1], + colors[2], + colors[3] + ); + matrices.popPose(); + } + + matrices.popPose(); + } + + public static float[] colors(int age) { + double delta = age * 0.01; + int index = MHelper.floor(delta); + int index2 = (index + 1) & 3; + delta -= index; + index &= 3; + + Vec3i color1 = AuroraCrystalBlock.COLORS[index]; + Vec3i color2 = AuroraCrystalBlock.COLORS[index2]; + + int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); + int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); + int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); + + return ColorUtil.toFloatArray(ColorUtil.color(r, g, b)); + } + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + modelPartData.addOrReplaceChild( + "SHARDS_0", + CubeListBuilder.create().texOffs(2, 4).addBox(-5.0f, 1.0f, -3.0f, 2.0f, 8.0f, 2.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + "SHARDS_1", + CubeListBuilder.create().texOffs(2, 4).addBox(3.0f, -1.0f, -1.0f, 2.0f, 8.0f, 2.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + "SHARDS_2", + CubeListBuilder.create().texOffs(2, 4).addBox(-1.0f, 0.0f, -5.0f, 2.0f, 4.0f, 2.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + "SHARDS_3", + CubeListBuilder.create().texOffs(2, 4).addBox(0.0f, 3.0f, 4.0f, 2.0f, 6.0f, 2.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + "CORE", + CubeListBuilder.create().texOffs(0, 0).addBox(-2.0f, -2.0f, -2.0f, 4.0f, 12.0f, 4.0f), + PartPose.ZERO + ); + + return LayerDefinition.create(modelData, 16, 16); + } + + static { + RENDER_LAYER = RenderType.itemEntityTranslucentCull(BetterEnd.makeID("textures/entity/eternal_crystal.png")); + SHARDS = new ModelPart[4]; + + ModelPart root = getTexturedModelData().bakeRoot(); + SHARDS[0] = root.getChild("SHARDS_0"); + SHARDS[1] = root.getChild("SHARDS_1"); + SHARDS[2] = root.getChild("SHARDS_2"); + SHARDS[3] = root.getChild("SHARDS_3"); + CORE = root.getChild("CORE"); + } +} diff --git a/src/main/java/org/betterx/betterend/client/render/PedestalItemRenderer.java b/src/main/java/org/betterx/betterend/client/render/PedestalItemRenderer.java new file mode 100644 index 00000000..190b1fc1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/client/render/PedestalItemRenderer.java @@ -0,0 +1,96 @@ +package org.betterx.betterend.client.render; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.util.Mth; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Vector3f; +import org.betterx.betterend.blocks.EternalPedestal; +import org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.blocks.entities.PedestalBlockEntity; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +@Environment(EnvType.CLIENT) +public class PedestalItemRenderer implements BlockEntityRenderer { + public PedestalItemRenderer(BlockEntityRendererProvider.Context ctx) { + super(); + } + + @Override + public void render(T blockEntity, + float tickDelta, + PoseStack matrices, + MultiBufferSource vertexConsumers, + int light, + int overlay) { + Level world = blockEntity.getLevel(); + if (world == null || blockEntity.isEmpty()) return; + + BlockState state = world.getBlockState(blockEntity.getBlockPos()); + if (!(state.getBlock() instanceof PedestalBlock)) return; + + ItemStack activeItem = blockEntity.getItem(0); + + matrices.pushPose(); + Minecraft minecraft = Minecraft.getInstance(); + BakedModel model = minecraft.getItemRenderer().getModel(activeItem, world, null, 0); + Vector3f translate = model.getTransforms().ground.translation; + PedestalBlock pedestal = (PedestalBlock) state.getBlock(); + matrices.translate(translate.x() + 0.5, translate.y() + pedestal.getHeight(state), translate.z() + 0.5); + if (activeItem.getItem() instanceof BlockItem) { + matrices.scale(1.5F, 1.5F, 1.5F); + } else { + matrices.scale(1.25F, 1.25F, 1.25F); + } + int age = (int) (minecraft.level.getGameTime() % 314); + if (state.is(EndBlocks.ETERNAL_PEDESTAL) && state.getValue(EternalPedestal.ACTIVATED)) { + float[] colors = EternalCrystalRenderer.colors(age); + int y = blockEntity.getBlockPos().getY(); + + BeamRenderer.renderLightBeam(matrices, + vertexConsumers, + age, + tickDelta, + -y, + 1024 - y, + colors, + 0.25F, + 0.13F, + 0.16F); + float altitude = Mth.sin((age + tickDelta) / 10.0F) * 0.1F + 0.1F; + matrices.translate(0.0D, altitude, 0.0D); + } + if (activeItem.getItem() == Items.END_CRYSTAL) { + EndCrystalRenderer.render(age, 314, tickDelta, matrices, vertexConsumers, light); + } else if (activeItem.getItem() == EndItems.ETERNAL_CRYSTAL) { + EternalCrystalRenderer.render(age, tickDelta, matrices, vertexConsumers, light); + } else { + float rotation = (age + tickDelta) / 25.0F + 6.0F; + matrices.mulPose(Vector3f.YP.rotation(rotation)); + minecraft.getItemRenderer() + .render(activeItem, + ItemTransforms.TransformType.GROUND, + false, + matrices, + vertexConsumers, + light, + overlay, + model); + } + matrices.popPose(); + } +} diff --git a/src/main/java/org/betterx/betterend/complexmaterials/ColoredMaterial.java b/src/main/java/org/betterx/betterend/complexmaterials/ColoredMaterial.java new file mode 100644 index 00000000..7d880856 --- /dev/null +++ b/src/main/java/org/betterx/betterend/complexmaterials/ColoredMaterial.java @@ -0,0 +1,77 @@ +package org.betterx.betterend.complexmaterials; + +import net.minecraft.core.Registry; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.DyeItem; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import com.google.common.collect.Maps; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Map; +import java.util.function.Function; + +public class ColoredMaterial { + private static final Map DYES = Maps.newHashMap(); + private static final Map COLORS = Maps.newHashMap(); + private final Map colors = Maps.newHashMap(); + + public ColoredMaterial(Function constructor, Block source, boolean craftEight) { + this(constructor, source, COLORS, DYES, craftEight); + } + + public ColoredMaterial(Function constructor, + Block source, + Map colors, + Map dyes, + boolean craftEight) { + String id = Registry.BLOCK.getKey(source).getPath(); + colors.forEach((color, name) -> { + String blockName = id + "_" + name; + Block block = constructor.apply(FabricBlockSettings.copyOf(source).mapColor(MaterialColor.COLOR_BLACK)); + EndBlocks.registerBlock(blockName, block); + if (craftEight) { + GridRecipe.make(BetterEnd.MOD_ID, blockName, block) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(8) + .setShape("###", "#D#", "###") + .addMaterial('#', source) + .addMaterial('D', dyes.get(color)) + .build(); + } else { + GridRecipe.make(BetterEnd.MOD_ID, blockName, block) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#D") + .addMaterial('#', source) + .addMaterial('D', dyes.get(color)) + .build(); + } + this.colors.put(color, block); + BlocksHelper.addBlockColor(block, color); + }); + } + + public Block getByColor(DyeColor color) { + return colors.get(color.getMaterialColor().col); + } + + public Block getByColor(int color) { + return colors.get(color); + } + + static { + for (DyeColor color : DyeColor.values()) { + int colorRGB = color.getMaterialColor().col; + COLORS.put(colorRGB, color.getName()); + DYES.put(colorRGB, DyeItem.byColor(color)); + } + } +} diff --git a/src/main/java/org/betterx/betterend/complexmaterials/CrystalSubblocksMaterial.java b/src/main/java/org/betterx/betterend/complexmaterials/CrystalSubblocksMaterial.java new file mode 100644 index 00000000..edf5b1c7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/complexmaterials/CrystalSubblocksMaterial.java @@ -0,0 +1,135 @@ +package org.betterx.betterend.complexmaterials; + +import net.minecraft.world.level.block.Block; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.NamedBlockTags; +import org.betterx.bclib.api.tag.NamedItemTags; +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.blocks.BaseSlabBlock; +import org.betterx.bclib.blocks.BaseStairsBlock; +import org.betterx.bclib.blocks.BaseWallBlock; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndPedestal; +import org.betterx.betterend.blocks.basis.LitBaseBlock; +import org.betterx.betterend.blocks.basis.LitPillarBlock; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.recipe.CraftingRecipes; +import org.betterx.betterend.registry.EndBlocks; + +public class CrystalSubblocksMaterial { + public final Block polished; + public final Block tiles; + public final Block pillar; + public final Block stairs; + public final Block slab; + public final Block wall; + public final Block pedestal; + public final Block bricks; + public final Block brick_stairs; + public final Block brick_slab; + public final Block brick_wall; + + public CrystalSubblocksMaterial(String name, Block source) { + FabricBlockSettings material = FabricBlockSettings.copyOf(source); + polished = EndBlocks.registerBlock(name + "_polished", new LitBaseBlock(material)); + tiles = EndBlocks.registerBlock(name + "_tiles", new LitBaseBlock(material)); + pillar = EndBlocks.registerBlock(name + "_pillar", new LitPillarBlock(material)); + stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(source)); + slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(source)); + wall = EndBlocks.registerBlock(name + "_wall", new BaseWallBlock(source)); + pedestal = EndBlocks.registerBlock(name + "_pedestal", new EndPedestal(source)); + bricks = EndBlocks.registerBlock(name + "_bricks", new LitBaseBlock(material)); + brick_stairs = EndBlocks.registerBlock(name + "_bricks_stairs", new BaseStairsBlock(bricks)); + brick_slab = EndBlocks.registerBlock(name + "_bricks_slab", new BaseSlabBlock(bricks)); + brick_wall = EndBlocks.registerBlock(name + "_bricks_wall", new BaseWallBlock(bricks)); + + // Recipes // + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks", bricks) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', source) + .setGroup("end_bricks") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_polished", polished) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', bricks) + .setGroup("end_tile") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_tiles", tiles) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', polished) + .setGroup("end_small_tile") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_pillar", pillar) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("#", "#") + .addMaterial('#', slab) + .setGroup("end_pillar") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("# ", "## ", "###") + .addMaterial('#', source) + .setGroup("end_stone_stairs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###") + .addMaterial('#', source) + .setGroup("end_stone_slabs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_stairs", brick_stairs) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("# ", "## ", "###") + .addMaterial('#', bricks) + .setGroup("end_stone_stairs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_slab", brick_slab) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###") + .addMaterial('#', bricks) + .setGroup("end_stone_slabs") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_wall", wall) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###", "###") + .addMaterial('#', source) + .setGroup("end_wall") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_wall", brick_wall) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###", "###") + .addMaterial('#', bricks) + .setGroup("end_wall") + .build(); + + CraftingRecipes.registerPedestal(name + "_pedestal", pedestal, slab, pillar); + + // Item Tags // + TagAPI.addItemTag(NamedItemTags.SLABS, slab, brick_slab); + TagAPI.addItemTag(NamedItemTags.STONE_BRICKS, bricks); + TagAPI.addItemTag(NamedItemTags.STONE_CRAFTING_MATERIALS, source); + TagAPI.addItemTag(NamedItemTags.STONE_TOOL_MATERIALS, source); + + // Block Tags // + TagAPI.addBlockTag(NamedBlockTags.STONE_BRICKS, bricks); + TagAPI.addBlockTag(NamedBlockTags.WALLS, wall, brick_wall); + TagAPI.addBlockTag(NamedBlockTags.SLABS, slab, brick_slab); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/complexmaterials/EndWoodenComplexMaterial.java b/src/main/java/org/betterx/betterend/complexmaterials/EndWoodenComplexMaterial.java new file mode 100644 index 00000000..a73e5416 --- /dev/null +++ b/src/main/java/org/betterx/betterend/complexmaterials/EndWoodenComplexMaterial.java @@ -0,0 +1,48 @@ +package org.betterx.betterend.complexmaterials; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.MaterialColor; + +import org.betterx.bclib.complexmaterials.WoodenComplexMaterial; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class EndWoodenComplexMaterial extends WoodenComplexMaterial { + private Block bark; + private Block log; + + public EndWoodenComplexMaterial(String name, MaterialColor woodColor, MaterialColor planksColor) { + super(BetterEnd.MOD_ID, name, name, woodColor, planksColor); + } + + public EndWoodenComplexMaterial init() { + return (EndWoodenComplexMaterial) super.init(EndBlocks.getBlockRegistry(), + EndItems.getItemRegistry(), + Configs.RECIPE_CONFIG); + } + + public boolean isTreeLog(Block block) { + return block == getLog() || block == getBark(); + } + + public boolean isTreeLog(BlockState state) { + return isTreeLog(state.getBlock()); + } + + public Block getLog() { + if (log == null) { + log = getBlock("log"); + } + return log; + } + + public Block getBark() { + if (bark == null) { + bark = getBlock("bark"); + } + return bark; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/complexmaterials/MetalMaterial.java b/src/main/java/org/betterx/betterend/complexmaterials/MetalMaterial.java new file mode 100644 index 00000000..664ebda1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/complexmaterials/MetalMaterial.java @@ -0,0 +1,508 @@ +package org.betterx.betterend.complexmaterials; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Item.Properties; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.Tier; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.api.tag.NamedBlockTags; +import org.betterx.bclib.api.tag.NamedItemTags; +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.blocks.*; +import org.betterx.bclib.items.ModelProviderItem; +import org.betterx.bclib.items.tool.BaseAxeItem; +import org.betterx.bclib.items.tool.BaseHoeItem; +import org.betterx.bclib.items.tool.BaseShovelItem; +import org.betterx.bclib.items.tool.BaseSwordItem; +import org.betterx.bclib.recipes.AnvilRecipe; +import org.betterx.bclib.recipes.FurnaceRecipe; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.bclib.recipes.SmithingTableRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.BulbVineLanternBlock; +import org.betterx.betterend.blocks.BulbVineLanternColoredBlock; +import org.betterx.betterend.blocks.ChandelierBlock; +import org.betterx.betterend.blocks.basis.EndAnvilBlock; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.item.EndArmorItem; +import org.betterx.betterend.item.tool.EndHammerItem; +import org.betterx.betterend.item.tool.EndPickaxe; +import org.betterx.betterend.recipe.builders.AlloyingRecipe; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class MetalMaterial { + public final Block ore; + public final Block block; + public final Block tile; + public final Block bars; + public final Block pressurePlate; + public final Block door; + public final Block trapdoor; + public final Block chain; + public final Block stairs; + public final Block slab; + + public final Block chandelier; + public final Block bulb_lantern; + public final ColoredMaterial bulb_lantern_colored; + + public final Block anvilBlock; + + public final Item rawOre; + public final Item nugget; + public final Item ingot; + + public final Item shovelHead; + public final Item pickaxeHead; + public final Item axeHead; + public final Item hoeHead; + public final Item swordBlade; + public final Item swordHandle; + + public final Item shovel; + public final Item sword; + public final Item pickaxe; + public final Item axe; + public final Item hoe; + public final Item hammer; + + public final Item forgedPlate; + public final Item helmet; + public final Item chestplate; + public final Item leggings; + public final Item boots; + + public final TagKey alloyingOre; + + public static MetalMaterial makeNormal(String name, MaterialColor color, Tier material, ArmorMaterial armor) { + return new MetalMaterial( + name, + true, + FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).mapColor(color), + EndItems.makeEndItemSettings(), + material, + armor + ); + } + + public static MetalMaterial makeNormal(String name, + MaterialColor color, + float hardness, + float resistance, + Tier material, + ArmorMaterial armor) { + return new MetalMaterial( + name, + true, + FabricBlockSettings.copyOf(Blocks.IRON_BLOCK) + .mapColor(color) + .hardness(hardness) + .resistance(resistance), + EndItems.makeEndItemSettings(), + material, + armor + ); + } + + public static MetalMaterial makeOreless(String name, MaterialColor color, Tier material, ArmorMaterial armor) { + return new MetalMaterial( + name, + false, + FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).mapColor(color), + EndItems.makeEndItemSettings(), + material, + armor + ); + } + + public static MetalMaterial makeOreless(String name, + MaterialColor color, + float hardness, + float resistance, + Tier material, + ArmorMaterial armor) { + return new MetalMaterial( + name, + false, + FabricBlockSettings.copyOf(Blocks.IRON_BLOCK) + .mapColor(color) + .hardness(hardness) + .resistance(resistance), + EndItems.makeEndItemSettings(), + material, + armor + ); + } + + private MetalMaterial(String name, + boolean hasOre, + FabricBlockSettings settings, + Properties itemSettings, + Tier material, + ArmorMaterial armor) { + BlockBehaviour.Properties lanternProperties = FabricBlockSettings.copyOf(settings) + .hardness(1) + .resistance(1) + .luminance(15) + .sound(SoundType.LANTERN); + final int level = material.getLevel(); + + rawOre = hasOre ? EndItems.registerEndItem(name + "_raw", new ModelProviderItem(itemSettings)) : null; + ore = hasOre ? EndBlocks.registerBlock(name + "_ore", new BaseOreBlock(() -> rawOre, 1, 3, 1)) : null; + alloyingOre = hasOre ? TagAPI.makeItemTag(BetterEnd.MOD_ID, name + "_alloying") : null; + if (hasOre) { + TagAPI.addItemTag(alloyingOre, ore, rawOre); + } + + block = EndBlocks.registerBlock(name + "_block", new BaseBlock(settings)); + tile = EndBlocks.registerBlock(name + "_tile", new BaseBlock(settings)); + stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(tile)); + slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(tile)); + door = EndBlocks.registerBlock(name + "_door", new BaseDoorBlock(block)); + trapdoor = EndBlocks.registerBlock(name + "_trapdoor", new BaseTrapdoorBlock(block)); + bars = EndBlocks.registerBlock(name + "_bars", new BaseMetalBarsBlock(block)); + chain = EndBlocks.registerBlock(name + "_chain", new BaseChainBlock(block.defaultMaterialColor())); + pressurePlate = EndBlocks.registerBlock(name + "_plate", new WoodenPressurePlateBlock(block)); + + chandelier = EndBlocks.registerBlock(name + "_chandelier", new ChandelierBlock(block)); + bulb_lantern = EndBlocks.registerBlock(name + "_bulb_lantern", new BulbVineLanternBlock(lanternProperties)); + bulb_lantern_colored = new ColoredMaterial(BulbVineLanternColoredBlock::new, bulb_lantern, false); + + nugget = EndItems.registerEndItem(name + "_nugget", new ModelProviderItem(itemSettings)); + ingot = EndItems.registerEndItem(name + "_ingot", new ModelProviderItem(itemSettings)); + + shovelHead = EndItems.registerEndItem(name + "_shovel_head"); + pickaxeHead = EndItems.registerEndItem(name + "_pickaxe_head"); + axeHead = EndItems.registerEndItem(name + "_axe_head"); + hoeHead = EndItems.registerEndItem(name + "_hoe_head"); + swordBlade = EndItems.registerEndItem(name + "_sword_blade"); + swordHandle = EndItems.registerEndItem(name + "_sword_handle"); + + shovel = EndItems.registerEndTool(name + "_shovel", new BaseShovelItem(material, 1.5F, -3.0F, itemSettings)); + sword = EndItems.registerEndTool(name + "_sword", new BaseSwordItem(material, 3, -2.4F, itemSettings)); + pickaxe = EndItems.registerEndTool(name + "_pickaxe", new EndPickaxe(material, 1, -2.8F, itemSettings)); + axe = EndItems.registerEndTool(name + "_axe", new BaseAxeItem(material, 6.0F, -3.0F, itemSettings)); + hoe = EndItems.registerEndTool(name + "_hoe", new BaseHoeItem(material, -3, 0.0F, itemSettings)); + hammer = EndItems.registerEndTool( + name + "_hammer", + new EndHammerItem(material, 5.0F, -3.2F, 0.3D, itemSettings) + ); + + forgedPlate = EndItems.registerEndItem(name + "_forged_plate"); + helmet = EndItems.registerEndItem(name + "_helmet", new EndArmorItem(armor, EquipmentSlot.HEAD, itemSettings)); + chestplate = EndItems.registerEndItem( + name + "_chestplate", + new EndArmorItem(armor, EquipmentSlot.CHEST, itemSettings) + ); + leggings = EndItems.registerEndItem( + name + "_leggings", + new EndArmorItem(armor, EquipmentSlot.LEGS, itemSettings) + ); + boots = EndItems.registerEndItem(name + "_boots", new EndArmorItem(armor, EquipmentSlot.FEET, itemSettings)); + + anvilBlock = EndBlocks.registerBlock( + name + "_anvil", + new EndAnvilBlock(this, block.defaultMaterialColor(), level) + ); + + if (hasOre) { + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_ingot_furnace_ore", ore, ingot) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_ingot") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_ingot_furnace_raw", rawOre, ingot) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_ingot") + .buildWithBlasting(); + AlloyingRecipe.Builder.create(name + "_ingot_alloy") + .setInput(alloyingOre, alloyingOre) + .setOutput(ingot, 3) + .setExpiriense(2.1F) + .build(); + } + + // Basic recipes + GridRecipe.make(BetterEnd.MOD_ID, name + "_ingot_from_nuggets", ingot) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "###", "###") + .addMaterial('#', nugget) + .setGroup("end_metal_ingots_nug") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_nuggets_from_ingot", nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(9) + .setList("#") + .addMaterial('#', ingot) + .setGroup("end_metal_nuggets_ing") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_block", block) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "###", "###") + .addMaterial('#', ingot) + .setGroup("end_metal_blocks") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_ingot_from_block", ingot) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(9) + .setList("#") + .addMaterial('#', block) + .setGroup("end_metal_ingots") + .build(); + + // Block recipes + GridRecipe.make(BetterEnd.MOD_ID, name + "_tile", tile) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', block) + .setGroup("end_metal_tiles") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bars", bars) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(16) + .setShape("###", "###") + .addMaterial('#', ingot) + .setGroup("end_metal_bars") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_pressure_plate", pressurePlate) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##") + .addMaterial('#', ingot) + .setGroup("end_metal_plates") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_door", door) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(3) + .setShape("##", "##", "##") + .addMaterial('#', ingot) + .setGroup("end_metal_doors") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_trapdoor", trapdoor) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', ingot) + .setGroup("end_metal_trapdoors") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("# ", "## ", "###") + .addMaterial('#', block, tile) + .setGroup("end_metal_stairs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###") + .addMaterial('#', block, tile) + .setGroup("end_metal_slabs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_chain", chain) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("N", "#", "N") + .addMaterial('#', ingot) + .addMaterial('N', nugget) + .setGroup("end_metal_chain") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_anvil", anvilBlock) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", " I ", "III") + .addMaterial('#', block, tile) + .addMaterial('I', ingot) + .setGroup("end_metal_anvil") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bulb_lantern", bulb_lantern) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("C", "I", "#") + .addMaterial('C', chain) + .addMaterial('I', ingot) + .addMaterial('#', EndItems.GLOWING_BULB) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_chandelier", chandelier) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("I#I", " # ") + .addMaterial('#', ingot) + .addMaterial('I', EndItems.LUMECORN_ROD) + .setGroup("end_metal_chandelier") + .build(); + + // Tools & armor into nuggets + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_axe_nugget", axe, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_hoe_nugget", hoe, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_pickaxe_nugget", pickaxe, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_sword_nugget", sword, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_hammer_nugget", hammer, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_helmet_nugget", helmet, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_chestplate_nugget", chestplate, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_leggings_nugget", leggings, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_boots_nugget", boots, nugget) + .checkConfig(Configs.RECIPE_CONFIG) + .setGroup("end_nugget") + .buildWithBlasting(); + + // Tool parts from ingots + AnvilRecipe.create(name + "_shovel_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setOutput(shovelHead) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + AnvilRecipe.create(name + "_pickaxe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setInputCount(3) + .setOutput(pickaxeHead) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + AnvilRecipe.create(name + "_axe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setInputCount(3) + .setOutput(axeHead) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + AnvilRecipe.create(name + "_hoe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setInputCount(2) + .setOutput(hoeHead) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + AnvilRecipe.create(name + "_sword_blade") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setOutput(swordBlade) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + AnvilRecipe.create(name + "_forged_plate") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(ingot) + .setOutput(forgedPlate) + .setAnvilLevel(level) + .setToolLevel(level) + .setDamage(level) + .build(); + + // Tools from parts + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_hammer") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(hammer) + .setBase(block) + .setAddition(Items.STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_axe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(axe) + .setBase(axeHead) + .setAddition(Items.STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_pickaxe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(pickaxe) + .setBase(pickaxeHead) + .setAddition(Items.STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_hoe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(hoe) + .setBase(hoeHead) + .setAddition(Items.STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_sword_handle") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(swordHandle) + .setBase(ingot) + .setAddition(Items.STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_sword") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(sword) + .setBase(swordBlade) + .setAddition(swordHandle) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_shovel") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(shovel) + .setBase(shovelHead) + .setAddition(Items.STICK) + .build(); + + // Armor crafting + GridRecipe.make(BetterEnd.MOD_ID, name + "_helmet", helmet) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "# #") + .addMaterial('#', forgedPlate) + .setGroup("end_metal_helmets") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_chestplate", chestplate) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("# #", "###", "###") + .addMaterial('#', forgedPlate) + .setGroup("end_metal_chestplates") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_leggings", leggings) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "# #", "# #") + .addMaterial('#', forgedPlate) + .setGroup("end_metal_leggings") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_boots", boots) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("# #", "# #") + .addMaterial('#', forgedPlate) + .setGroup("end_metal_boots") + .build(); + + TagAPI.addBlockTag(NamedBlockTags.ANVIL, anvilBlock); + TagAPI.addBlockTag(NamedBlockTags.BEACON_BASE_BLOCKS, block); + TagAPI.addItemTag(NamedItemTags.BEACON_PAYMENT_ITEMS, ingot); + TagAPI.addBlockTag(CommonBlockTags.DRAGON_IMMUNE, ore, bars); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/complexmaterials/StoneMaterial.java b/src/main/java/org/betterx/betterend/complexmaterials/StoneMaterial.java new file mode 100644 index 00000000..2c6ea05f --- /dev/null +++ b/src/main/java/org/betterx/betterend/complexmaterials/StoneMaterial.java @@ -0,0 +1,191 @@ +package org.betterx.betterend.complexmaterials; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; + +import org.betterx.bclib.api.tag.*; +import org.betterx.bclib.blocks.*; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndPedestal; +import org.betterx.betterend.blocks.FlowerPotBlock; +import org.betterx.betterend.blocks.basis.StoneLanternBlock; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.recipe.CraftingRecipes; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class StoneMaterial { + public final Block stone; + + public final Block polished; + public final Block tiles; + public final Block pillar; + public final Block stairs; + public final Block slab; + public final Block wall; + public final Block button; + public final Block pressurePlate; + public final Block pedestal; + public final Block lantern; + + public final Block bricks; + public final Block brickStairs; + public final Block brickSlab; + public final Block brickWall; + public final Block furnace; + public final Block flowerPot; + + public StoneMaterial(String name, MaterialColor color) { + FabricBlockSettings material = FabricBlockSettings.copyOf(Blocks.END_STONE).mapColor(color); + + stone = EndBlocks.registerBlock(name, new BaseBlock(material)); + polished = EndBlocks.registerBlock(name + "_polished", new BaseBlock(material)); + tiles = EndBlocks.registerBlock(name + "_tiles", new BaseBlock(material)); + pillar = EndBlocks.registerBlock(name + "_pillar", new BaseRotatedPillarBlock(material)); + stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(stone)); + slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(stone)); + wall = EndBlocks.registerBlock(name + "_wall", new BaseWallBlock(stone)); + button = EndBlocks.registerBlock(name + "_button", new BaseStoneButtonBlock(stone)); + pressurePlate = EndBlocks.registerBlock(name + "_plate", new StonePressurePlateBlock(stone)); + pedestal = EndBlocks.registerBlock(name + "_pedestal", new EndPedestal(stone)); + lantern = EndBlocks.registerBlock(name + "_lantern", new StoneLanternBlock(stone)); + + bricks = EndBlocks.registerBlock(name + "_bricks", new BaseBlock(material)); + brickStairs = EndBlocks.registerBlock(name + "_bricks_stairs", new BaseStairsBlock(bricks)); + brickSlab = EndBlocks.registerBlock(name + "_bricks_slab", new BaseSlabBlock(bricks)); + brickWall = EndBlocks.registerBlock(name + "_bricks_wall", new BaseWallBlock(bricks)); + furnace = EndBlocks.registerBlock(name + "_furnace", new BaseFurnaceBlock(bricks)); + flowerPot = EndBlocks.registerBlock(name + "_flower_pot", new FlowerPotBlock(bricks)); + + // Recipes // + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks", bricks) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', stone) + .setGroup("end_bricks") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_polished", polished) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', bricks) + .setGroup("end_tile") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_tiles", tiles) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("##", "##") + .addMaterial('#', polished) + .setGroup("end_small_tile") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_pillar", pillar) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("#", "#") + .addMaterial('#', slab) + .setGroup("end_pillar") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("# ", "## ", "###") + .addMaterial('#', stone) + .setGroup("end_stone_stairs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###") + .addMaterial('#', stone) + .setGroup("end_stone_slabs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_stairs", brickStairs) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("# ", "## ", "###") + .addMaterial('#', bricks) + .setGroup("end_stone_stairs") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_slab", brickSlab) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###") + .addMaterial('#', bricks) + .setGroup("end_stone_slabs") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_wall", wall) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###", "###") + .addMaterial('#', stone) + .setGroup("end_wall") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_wall", brickWall) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("###", "###") + .addMaterial('#', bricks) + .setGroup("end_wall") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, name + "_button", button) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', stone) + .setGroup("end_stone_buttons") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_pressure_plate", pressurePlate) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##") + .addMaterial('#', stone) + .setGroup("end_stone_plates") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_lantern", lantern) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("S", "#", "S") + .addMaterial('#', EndItems.CRYSTAL_SHARDS) + .addMaterial('S', slab, brickSlab) + .setGroup("end_stone_lanterns") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_furnace", furnace) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "# #", "###") + .addMaterial('#', stone) + .setGroup("end_stone_ITEM_FURNACES") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, name + "_flower_pot", flowerPot) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(3) + .setShape("# #", " # ") + .addMaterial('#', bricks) + .setGroup("end_pots") + .build(); + + CraftingRecipes.registerPedestal(name + "_pedestal", pedestal, slab, pillar); + + // Item Tags // + TagAPI.addItemTag(NamedItemTags.SLABS, slab, brickSlab); + TagAPI.addItemTag(NamedItemTags.STONE_BRICKS, bricks); + TagAPI.addItemTag(NamedItemTags.STONE_CRAFTING_MATERIALS, stone); + TagAPI.addItemTag(NamedItemTags.STONE_TOOL_MATERIALS, stone); + TagAPI.addItemTag(CommonItemTags.FURNACES, furnace); + + // Block Tags // + TagAPI.addBlockTag(NamedBlockTags.STONE_BRICKS, bricks); + TagAPI.addBlockTag(NamedBlockTags.WALLS, wall, brickWall); + TagAPI.addBlockTag(NamedBlockTags.SLABS, slab, brickSlab); + TagAPI.addBlockTags(pressurePlate, NamedBlockTags.PRESSURE_PLATES, NamedBlockTags.STONE_PRESSURE_PLATES); + TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); + + TagAPI.addBlockTag(CommonBlockTags.DRAGON_IMMUNE, stone, stairs, slab, wall); + + TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); + TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/config/Configs.java b/src/main/java/org/betterx/betterend/config/Configs.java new file mode 100644 index 00000000..9a33a2db --- /dev/null +++ b/src/main/java/org/betterx/betterend/config/Configs.java @@ -0,0 +1,37 @@ +package org.betterx.betterend.config; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.BCLib; +import org.betterx.bclib.config.EntryConfig; +import org.betterx.bclib.config.IdConfig; +import org.betterx.bclib.config.PathConfig; +import org.betterx.betterend.BetterEnd; + +public class Configs { + public static final PathConfig ENTITY_CONFIG = new PathConfig(BetterEnd.MOD_ID, "entities"); + public static final PathConfig BLOCK_CONFIG = new PathConfig(BetterEnd.MOD_ID, "blocks"); + public static final PathConfig ITEM_CONFIG = new PathConfig(BetterEnd.MOD_ID, "items"); + public static final IdConfig BIOME_CONFIG = new EntryConfig(BetterEnd.MOD_ID, "biomes"); + public static final PathConfig GENERATOR_CONFIG = new PathConfig(BetterEnd.MOD_ID, "generator", false); + public static final PathConfig RECIPE_CONFIG = new PathConfig(BetterEnd.MOD_ID, "recipes"); + public static final PathConfig ENCHANTMENT_CONFIG = new PathConfig(BetterEnd.MOD_ID, "enchantments"); + + @Environment(value = EnvType.CLIENT) + public static final PathConfig CLENT_CONFIG = new PathConfig(BetterEnd.MOD_ID, "client", false); + + public static void saveConfigs() { + ENTITY_CONFIG.saveChanges(); + BLOCK_CONFIG.saveChanges(); + BIOME_CONFIG.saveChanges(); + ITEM_CONFIG.saveChanges(); + GENERATOR_CONFIG.saveChanges(); + RECIPE_CONFIG.saveChanges(); + ENCHANTMENT_CONFIG.saveChanges(); + + if (BCLib.isClient()) { + CLENT_CONFIG.saveChanges(); + } + } +} diff --git a/src/main/java/org/betterx/betterend/effects/EndPotions.java b/src/main/java/org/betterx/betterend/effects/EndPotions.java new file mode 100644 index 00000000..8c672155 --- /dev/null +++ b/src/main/java/org/betterx/betterend/effects/EndPotions.java @@ -0,0 +1,32 @@ +package org.betterx.betterend.effects; + +import net.minecraft.core.Registry; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.Potions; + +import org.betterx.bclib.mixin.common.PotionBrewingAccessor; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class EndPotions { + public final static Potion END_VEIL = registerPotion("end_veil", EndStatusEffects.END_VEIL, 3600); + public final static Potion LONG_END_VEIL = registerPotion("long_end_veil", EndStatusEffects.END_VEIL, 9600); + + public static Potion registerPotion(String name, MobEffect effect, int duration) { + return registerPotion(name, new Potion(name, new MobEffectInstance(effect, duration))); + } + + public static Potion registerPotion(String name, Potion potion) { + return Registry.register(Registry.POTION, BetterEnd.makeID(name), potion); + } + + public static void register() { + PotionBrewingAccessor.callAddMix(Potions.AWKWARD, EndItems.ENDER_DUST, END_VEIL); + PotionBrewingAccessor.callAddMix(END_VEIL, Items.REDSTONE, LONG_END_VEIL); + PotionBrewingAccessor.callAddMix(Potions.AWKWARD, EndBlocks.MURKWEED.asItem(), Potions.NIGHT_VISION); + } +} diff --git a/src/main/java/org/betterx/betterend/effects/EndStatusEffects.java b/src/main/java/org/betterx/betterend/effects/EndStatusEffects.java new file mode 100644 index 00000000..58439f90 --- /dev/null +++ b/src/main/java/org/betterx/betterend/effects/EndStatusEffects.java @@ -0,0 +1,36 @@ +package org.betterx.betterend.effects; + +import net.minecraft.core.Registry; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.effects.status.EndVeilEffect; + +public class EndStatusEffects { + public final static MobEffectInstance CRYSTALITE_HEALTH_REGEN = new MobEffectInstance(MobEffects.REGENERATION, + 80, + 0, + true, + false, + true); + public final static MobEffectInstance CRYSTALITE_DIG_SPEED = new MobEffectInstance(MobEffects.DIG_SPEED, + 80, + 0, + true, + false, + true); + public final static MobEffectInstance CRYSTALITE_MOVE_SPEED = new MobEffectInstance(MobEffects.MOVEMENT_SPEED, + 80, + 0, + true, + false, + true); + + public final static MobEffect END_VEIL = registerEffect("end_veil", new EndVeilEffect()); + + public static MobEffect registerEffect(String name, E effect) { + return Registry.register(Registry.MOB_EFFECT, BetterEnd.makeID(name), effect); + } +} diff --git a/src/main/java/org/betterx/betterend/effects/enchantment/EndVeilEnchantment.java b/src/main/java/org/betterx/betterend/effects/enchantment/EndVeilEnchantment.java new file mode 100644 index 00000000..6c554b46 --- /dev/null +++ b/src/main/java/org/betterx/betterend/effects/enchantment/EndVeilEnchantment.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.effects.enchantment; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentCategory; + +public class EndVeilEnchantment extends Enchantment { + + public EndVeilEnchantment() { + super(Enchantment.Rarity.VERY_RARE, EnchantmentCategory.ARMOR_HEAD, new EquipmentSlot[]{EquipmentSlot.HEAD}); + } + + @Override + public boolean isDiscoverable() { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/effects/status/EndVeilEffect.java b/src/main/java/org/betterx/betterend/effects/status/EndVeilEffect.java new file mode 100644 index 00000000..3ac183aa --- /dev/null +++ b/src/main/java/org/betterx/betterend/effects/status/EndVeilEffect.java @@ -0,0 +1,16 @@ +package org.betterx.betterend.effects.status; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; + +public class EndVeilEffect extends MobEffect { + + public EndVeilEffect() { + super(MobEffectCategory.BENEFICIAL, 0x0D554A); + } + + @Override + public boolean isDurationEffectTick(int duration, int amplifier) { + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/entity/CubozoaEntity.java b/src/main/java/org/betterx/betterend/entity/CubozoaEntity.java new file mode 100644 index 00000000..8bfad56c --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/CubozoaEntity.java @@ -0,0 +1,155 @@ +package org.betterx.betterend.entity; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundGameEventPacket; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.AbstractSchoolingFish; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerLevelAccessor; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndItems; + +public class CubozoaEntity extends AbstractSchoolingFish { + public static final int VARIANTS = 2; + private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( + CubozoaEntity.class, + EntityDataSerializers.BYTE + ); + private static final EntityDataAccessor SCALE = SynchedEntityData.defineId( + CubozoaEntity.class, + EntityDataSerializers.BYTE + ); + + public CubozoaEntity(EntityType entityType, Level world) { + super(entityType, world); + } + + @Override + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, + DifficultyInstance difficulty, + MobSpawnType spawnReason, + SpawnGroupData entityData, + CompoundTag entityTag) { + SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); + + if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) { + this.entityData.set(VARIANT, (byte) 1); + } + + if (entityTag != null) { + if (entityTag.contains("Variant")) { + this.entityData.set(VARIANT, entityTag.getByte("Variant")); + } + if (entityTag.contains("Scale")) { + this.entityData.set(SCALE, entityTag.getByte("Scale")); + } + } + + this.refreshDimensions(); + return data; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(VARIANT, (byte) 0); + this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16)); + } + + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putByte("Variant", (byte) getVariant()); + tag.putByte("Scale", getByteScale()); + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + if (tag.contains("Variant")) { + this.entityData.set(VARIANT, tag.getByte("Variant")); + } + if (tag.contains("Scale")) { + this.entityData.set(SCALE, tag.getByte("Scale")); + } + } + + @Override + public ItemStack getBucketItemStack() { + ItemStack bucket = EndItems.BUCKET_CUBOZOA.getDefaultInstance(); + CompoundTag tag = bucket.getOrCreateTag(); + tag.putByte("Variant", entityData.get(VARIANT)); + tag.putByte("Scale", entityData.get(SCALE)); + return bucket; + } + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity + .createLivingAttributes() + .add(Attributes.MAX_HEALTH, 2.0) + .add(Attributes.FOLLOW_RANGE, 16.0) + .add(Attributes.MOVEMENT_SPEED, 0.5); + } + + public int getVariant() { + return (int) this.entityData.get(VARIANT); + } + + public byte getByteScale() { + return this.entityData.get(SCALE); + } + + public float getScale() { + return getByteScale() / 32F + 0.75F; + } + + protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { + return dimensions.height * 0.5F; + } + + @Override + protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { + int count = random.nextInt(3); + if (count > 0) { + ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.GELATINE, count)); + this.level.addFreshEntity(drop); + } + } + + @Override + protected SoundEvent getFlopSound() { + return SoundEvents.SALMON_FLOP; + } + + @Override + public void playerTouch(Player player) { + if (player instanceof ServerPlayer && player.hurt(DamageSource.mobAttack(this), 0.5F)) { + if (!this.isSilent()) { + ((ServerPlayer) player).connection.send(new ClientboundGameEventPacket( + ClientboundGameEventPacket.PUFFER_FISH_STING, + 0.0F + )); + } + if (random.nextBoolean()) { + player.addEffect(new MobEffectInstance(MobEffects.POISON, 20, 0)); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/entity/DragonflyEntity.java b/src/main/java/org/betterx/betterend/entity/DragonflyEntity.java new file mode 100644 index 00000000..843ba31a --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/DragonflyEntity.java @@ -0,0 +1,214 @@ +package org.betterx.betterend.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.*; +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.control.LookControl; +import net.minecraft.world.entity.ai.goal.BreedGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.FollowParentGoal; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos; +import net.minecraft.world.entity.ai.util.HoverRandomPos; +import net.minecraft.world.entity.animal.FlyingAnimal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.phys.Vec3; + +import org.betterx.bclib.entity.DespawnableAnimal; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndSounds; + +import java.util.EnumSet; + +public class DragonflyEntity extends DespawnableAnimal implements FlyingAnimal { + public DragonflyEntity(EntityType entityType, Level world) { + super(entityType, world); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.lookControl = new DragonflyLookControl(this); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.xpReward = 1; + } + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity + .createLivingAttributes() + .add(Attributes.MAX_HEALTH, 8.0D) + .add(Attributes.FOLLOW_RANGE, 16.0D) + .add(Attributes.FLYING_SPEED, 1.0D) + .add(Attributes.MOVEMENT_SPEED, 0.1D); + } + + @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override + protected PathNavigation createNavigation(Level world) { + FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) { + public boolean isStableDestination(BlockPos pos) { + BlockState state = this.level.getBlockState(pos); + return state.isAir() || !state.getMaterial().blocksMotion(); + } + + public void tick() { + super.tick(); + } + }; + birdNavigation.setCanOpenDoors(false); + birdNavigation.setCanFloat(false); + birdNavigation.setCanPassDoors(true); + return birdNavigation; + } + + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader world) { + return world.getBlockState(pos).isAir() ? 10.0F : 0.0F; + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new FollowParentGoal(this, 1.0D)); + this.goalSelector.addGoal(4, new WanderAroundGoal()); + } + + @Override + public boolean isPushable() { + return false; + } + + @Override + public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { + return false; + } + + @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override + public boolean isFlying() { + return !this.onGround; + } + + @Override + public boolean isNoGravity() { + return true; + } + + @Override + public SoundEvent getAmbientSound() { + return EndSounds.ENTITY_DRAGONFLY; + } + + @Override + protected float getSoundVolume() { + return MHelper.randRange(0.25F, 0.5F, random); + } + + class DragonflyLookControl extends LookControl { + DragonflyLookControl(Mob entity) { + super(entity); + } + + protected boolean resetXRotOnTick() { + return true; + } + } + + class WanderAroundGoal extends Goal { + WanderAroundGoal() { + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + public boolean canUse() { + return DragonflyEntity.this.navigation.isDone() && DragonflyEntity.this.random.nextInt(10) == 0; + } + + public boolean canContinueToUse() { + return DragonflyEntity.this.navigation.isInProgress(); + } + + public void start() { + Vec3 vec3d = this.getRandomLocation(); + if (vec3d != null) { + BlockPos pos = new BlockPos(vec3d); + try { + Path path = DragonflyEntity.this.navigation.createPath(pos, 1); + if (path != null) { + DragonflyEntity.this.navigation.moveTo(path, 1.0D); + } + } catch (Exception e) { + } + } + super.start(); + } + + private Vec3 getRandomLocation() { + int h = BlocksHelper.downRay(DragonflyEntity.this.level, DragonflyEntity.this.blockPosition(), 16); + Vec3 rotation = DragonflyEntity.this.getViewVector(0.0F); + Vec3 airPos = HoverRandomPos.getPos(DragonflyEntity.this, 8, 7, rotation.x, rotation.z, 1.5707964F, 3, 1); + if (airPos != null) { + if (isInVoid(airPos)) { + for (int i = 0; i < 8; i++) { + airPos = HoverRandomPos.getPos( + DragonflyEntity.this, + 16, + 7, + rotation.x, + rotation.z, + MHelper.PI2, + 3, + 1 + ); + if (airPos != null && !isInVoid(airPos)) { + return airPos; + } + } + return null; + } + if (h > 5 && airPos.y() >= DragonflyEntity.this.blockPosition().getY()) { + airPos = new Vec3(airPos.x, airPos.y - h * 0.5, airPos.z); + } + return airPos; + } + return AirAndWaterRandomPos.getPos( + DragonflyEntity.this, + 8, + 4, + -2, + rotation.x, + rotation.z, + 1.5707963705062866D + ); + } + + private boolean isInVoid(Vec3 pos) { + int h = BlocksHelper.downRay(DragonflyEntity.this.level, new BlockPos(pos), 128); + return h > 100; + } + } + + @Override + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { + return EndEntities.DRAGONFLY.create(world); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/EndFishEntity.java b/src/main/java/org/betterx/betterend/entity/EndFishEntity.java new file mode 100644 index 00000000..4b3e0a3b --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/EndFishEntity.java @@ -0,0 +1,175 @@ +package org.betterx.betterend.entity; + +import net.minecraft.core.particles.ParticleTypes; +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.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.EntityDamageSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.SpawnGroupData; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.AbstractSchoolingFish; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndItems; + +public class EndFishEntity extends AbstractSchoolingFish { + public static final int VARIANTS_NORMAL = 5; + public static final int VARIANTS_SULPHUR = 3; + public static final int VARIANTS = VARIANTS_NORMAL + VARIANTS_SULPHUR; + private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( + EndFishEntity.class, + EntityDataSerializers.BYTE + ); + private static final EntityDataAccessor SCALE = SynchedEntityData.defineId( + EndFishEntity.class, + EntityDataSerializers.BYTE + ); + + public EndFishEntity(EntityType entityType, Level world) { + super(entityType, world); + } + + @Override + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, + DifficultyInstance difficulty, + MobSpawnType spawnReason, + SpawnGroupData entityData, + CompoundTag entityTag) { + SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); + + if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) { + this.entityData.set(VARIANT, (byte) (random.nextInt(VARIANTS_SULPHUR) + VARIANTS_NORMAL)); + } + + if (entityTag != null) { + if (entityTag.contains("Variant")) { + this.entityData.set(VARIANT, entityTag.getByte("variant")); + } + if (entityTag.contains("Scale")) { + this.entityData.set(SCALE, entityTag.getByte("scale")); + } + } + + this.refreshDimensions(); + return data; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(VARIANT, (byte) this.getRandom().nextInt(VARIANTS_NORMAL)); + this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16)); + } + + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putByte("Variant", (byte) getVariant()); + tag.putByte("Scale", getByteScale()); + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + if (tag.contains("Variant")) { + this.entityData.set(VARIANT, tag.getByte("Variant")); + } + if (tag.contains("Scale")) { + this.entityData.set(SCALE, tag.getByte("Scale")); + } + } + + @Override + public ItemStack getBucketItemStack() { + ItemStack bucket = EndItems.BUCKET_END_FISH.getDefaultInstance(); + CompoundTag tag = bucket.getOrCreateTag(); + tag.putByte("variant", entityData.get(VARIANT)); + tag.putByte("scale", entityData.get(SCALE)); + return bucket; + } + + @Override + protected SoundEvent getFlopSound() { + return SoundEvents.TROPICAL_FISH_FLOP; + } + + @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SALMON_AMBIENT; + } + + @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SALMON_DEATH; + } + + @Override + protected SoundEvent getHurtSound(DamageSource source) { + return SoundEvents.SALMON_HURT; + } + + @Override + public void tick() { + super.tick(); + if (random.nextInt(8) == 0 && getFeetBlockState().is(Blocks.WATER)) { + double x = getX() + random.nextGaussian() * 0.2; + double y = getY() + random.nextGaussian() * 0.2; + double z = getZ() + random.nextGaussian() * 0.2; + level.addParticle(ParticleTypes.BUBBLE, x, y, z, 0, 0, 0); + } + } + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity + .createLivingAttributes() + .add(Attributes.MAX_HEALTH, 2.0) + .add(Attributes.FOLLOW_RANGE, 16.0) + .add(Attributes.MOVEMENT_SPEED, 0.75); + } + + public int getVariant() { + return (int) this.entityData.get(VARIANT); + } + + public byte getByteScale() { + return this.entityData.get(SCALE); + } + + public float getScale() { + return getByteScale() / 32F + 0.75F; + } + + @Override + protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { + Item item = source.isFire() ? EndItems.END_FISH_COOKED : EndItems.END_FISH_RAW; + if (causedByPlayer && source instanceof EntityDamageSource) { + EntityDamageSource damageSource = (EntityDamageSource) source; + ItemStack handItem = ((Player) damageSource.getEntity()).getItemInHand(InteractionHand.MAIN_HAND); + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FIRE_ASPECT, handItem) > 0) { + item = EndItems.END_FISH_COOKED; + } + } + ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(item)); + this.level.addFreshEntity(drop); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java b/src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java new file mode 100644 index 00000000..9e187143 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java @@ -0,0 +1,431 @@ +package org.betterx.betterend.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +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.util.RandomSource; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.SpawnGroupData; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.Slime; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.betterend.interfaces.ISlime; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.util.GlobalState; + +import java.util.EnumSet; + +public class EndSlimeEntity extends Slime { + private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( + EndSlimeEntity.class, + EntityDataSerializers.BYTE + ); + + public EndSlimeEntity(EntityType entityType, Level world) { + super(entityType, world); + this.moveControl = new EndSlimeMoveControl(this); + } + + protected void registerGoals() { + this.goalSelector.addGoal(1, new SwimmingGoal()); + this.goalSelector.addGoal(2, new FaceTowardTargetGoal()); + this.goalSelector.addGoal(3, new RandomLookGoal()); + this.goalSelector.addGoal(5, new MoveGoal()); + this.targetSelector.addGoal( + 1, + new NearestAttackableTargetGoal(this, Player.class, 10, true, false, (livingEntity) -> { + return Math.abs(livingEntity.getY() - this.getY()) <= 4.0D; + }) + ); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal(this, IronGolem.class, true)); + } + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity + .createLivingAttributes() + .add(Attributes.MAX_HEALTH, 1.0D) + .add(Attributes.ATTACK_DAMAGE, 1.0D) + .add(Attributes.FOLLOW_RANGE, 16.0D) + .add(Attributes.MOVEMENT_SPEED, 0.15D); + } + + @Override + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, + DifficultyInstance difficulty, + MobSpawnType spawnReason, + SpawnGroupData entityData, + CompoundTag entityTag) { + SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); + BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(blockPosition())); + if (biome == EndBiomes.FOGGY_MUSHROOMLAND) { + this.setMossy(); + } else if (biome == EndBiomes.MEGALAKE || biome == EndBiomes.MEGALAKE_GROVE) { + this.setLake(); + } else if (biome == EndBiomes.AMBER_LAND) { + this.setAmber(true); + } + this.refreshDimensions(); + return data; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(VARIANT, (byte) 0); + } + + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putByte("Variant", (byte) getSlimeType()); + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + if (tag.contains("Variant")) { + this.entityData.set(VARIANT, tag.getByte("Variant")); + } + } + + @Override + protected ParticleOptions getParticleType() { + return ParticleTypes.PORTAL; + } + + @Override + public void remove(RemovalReason reason) { + int i = this.getSize(); + if (!this.level.isClientSide && i > 1 && this.isDeadOrDying()) { + Component text = this.getCustomName(); + boolean bl = this.isNoAi(); + float f = (float) i / 4.0F; + int j = i / 2; + int k = 2 + this.random.nextInt(3); + int type = this.getSlimeType(); + + for (int l = 0; l < k; ++l) { + float g = ((float) (l % 2) - 0.5F) * f; + float h = ((float) (l / 2) - 0.5F) * f; + EndSlimeEntity slimeEntity = (EndSlimeEntity) this.getType().create(this.level); + if (this.isPersistenceRequired()) { + slimeEntity.setPersistenceRequired(); + } + + slimeEntity.setSlimeType(type); + slimeEntity.setCustomName(text); + slimeEntity.setNoAi(bl); + slimeEntity.setInvulnerable(this.isInvulnerable()); + ((ISlime) slimeEntity).be_setSlimeSize(j, true); + slimeEntity.refreshDimensions(); + slimeEntity.moveTo( + this.getX() + (double) g, + this.getY() + 0.5D, + this.getZ() + (double) h, + this.random.nextFloat() * 360.0F, + 0.0F + ); + this.level.addFreshEntity(slimeEntity); + } + } + + ((ISlime) this).entityRemove(reason); + } + + @Override + protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { + int maxCount = this.getSize(); + int minCount = maxCount >> 1; + if (minCount < 1) { + minCount = 1; + } + if (causedByPlayer && this.lastHurtByPlayer != null) { + int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer); + minCount += looting; + } + int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount; + ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(Items.SLIME_BALL, count)); + this.level.addFreshEntity(drop); + } + + public int getSlimeType() { + return this.entityData.get(VARIANT).intValue(); + } + + public void setSlimeType(int value) { + this.entityData.set(VARIANT, (byte) value); + } + + protected void setMossy() { + setSlimeType(1); + } + + public boolean isMossy() { + return getSlimeType() == 1; + } + + protected void setLake() { + setSlimeType(2); + } + + public boolean isLake() { + return getSlimeType() == 2; + } + + protected void setAmber(boolean mossy) { + this.entityData.set(VARIANT, (byte) 3); + } + + public boolean isAmber() { + return this.entityData.get(VARIANT) == 3; + } + + public boolean isChorus() { + return this.entityData.get(VARIANT) == 0; + } + + public static boolean canSpawn(EntityType entityType, + LevelAccessor world, + MobSpawnType spawnType, + BlockPos pos, + RandomSource random) { + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { + return false; + } + BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(pos)); + if (biome == EndBiomes.CHORUS_FOREST || biome == EndBiomes.MEGALAKE) { + return true; + } + if (biome == EndBiomes.MEGALAKE_GROVE && random.nextBoolean()) { + return true; + } + return random.nextInt(4) == 0 && isWaterNear(world, pos); + } + + private static boolean isWaterNear(LevelAccessor world, BlockPos pos) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + + for (int x = pos.getX() - 32; x <= pos.getX() + 32; x++) { + POS.setX(x); + for (int z = pos.getZ() - 32; z <= pos.getZ() + 32; z++) { + POS.setZ(z); + for (int y = pos.getY() - 8; y <= pos.getY() + 8; y++) { + POS.setY(y); + if (world.getBlockState(POS).getBlock() == Blocks.WATER) { + return true; + } + } + } + } + return false; + } + + class MoveGoal extends Goal { + public MoveGoal() { + this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); + } + + public boolean canUse() { + if (EndSlimeEntity.this.isPassenger()) { + return false; + } + + float yaw = EndSlimeEntity.this.getYHeadRot(); + float speed = EndSlimeEntity.this.getSpeed(); + if (speed > 0.1) { + float dx = Mth.sin(-yaw * 0.017453292F); + float dz = Mth.cos(-yaw * 0.017453292F); + BlockPos pos = EndSlimeEntity.this.blockPosition().offset(dx * speed * 4, 0, dz * speed * 4); + int down = BlocksHelper.downRay(EndSlimeEntity.this.level, pos, 16); + return down < 5; + } + + return true; + } + + public void tick() { + ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.0D); + } + } + + class SwimmingGoal extends Goal { + public SwimmingGoal() { + this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); + EndSlimeEntity.this.getNavigation().setCanFloat(true); + } + + public boolean canUse() { + return (EndSlimeEntity.this.isInWater() || EndSlimeEntity.this.isInLava()) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl; + } + + public void tick() { + if (EndSlimeEntity.this.getRandom().nextFloat() < 0.8F) { + EndSlimeEntity.this.getJumpControl().jump(); + } + + ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.2D); + } + } + + class RandomLookGoal extends Goal { + private float targetYaw; + private int timer; + + public RandomLookGoal() { + this.setFlags(EnumSet.of(Goal.Flag.LOOK)); + } + + public boolean canUse() { + return EndSlimeEntity.this.getTarget() == null && (EndSlimeEntity.this.onGround || EndSlimeEntity.this.isInWater() || EndSlimeEntity.this + .isInLava() || EndSlimeEntity.this.hasEffect(MobEffects.LEVITATION)) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl; + } + + public void tick() { + if (--this.timer <= 0) { + this.timer = 40 + EndSlimeEntity.this.getRandom().nextInt(60); + this.targetYaw = (float) EndSlimeEntity.this.getRandom().nextInt(360); + } + + ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look(this.targetYaw, false); + } + } + + class FaceTowardTargetGoal extends Goal { + private int ticksLeft; + + public FaceTowardTargetGoal() { + this.setFlags(EnumSet.of(Goal.Flag.LOOK)); + } + + public boolean canUse() { + LivingEntity livingEntity = EndSlimeEntity.this.getTarget(); + if (livingEntity == null) { + return false; + } else if (!livingEntity.isAlive()) { + return false; + } else { + return (!(livingEntity instanceof Player) || !((Player) livingEntity).getAbilities().invulnerable) && EndSlimeEntity.this + .getMoveControl() instanceof EndSlimeMoveControl; + } + } + + public void start() { + this.ticksLeft = 300; + super.start(); + } + + public boolean canContinueToUse() { + LivingEntity livingEntity = EndSlimeEntity.this.getTarget(); + if (livingEntity == null) { + return false; + } else if (!livingEntity.isAlive()) { + return false; + } else if (livingEntity instanceof Player && ((Player) livingEntity).getAbilities().invulnerable) { + return false; + } else { + return --this.ticksLeft > 0; + } + } + + public void tick() { + EndSlimeEntity.this.lookAt(EndSlimeEntity.this.getTarget(), 10.0F, 10.0F); + ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look( + EndSlimeEntity.this.getYRot(), + EndSlimeEntity.this.isDealsDamage() + ); + } + } + + class EndSlimeMoveControl extends MoveControl { + private float targetYaw; + private int ticksUntilJump; + private boolean jumpOften; + + public EndSlimeMoveControl(EndSlimeEntity slime) { + super(slime); + this.targetYaw = 180.0F * slime.getYRot() / 3.1415927F; + } + + public void look(float targetYaw, boolean jumpOften) { + this.targetYaw = targetYaw; + this.jumpOften = jumpOften; + } + + public void move(double speed) { + this.speedModifier = speed; + this.operation = MoveControl.Operation.MOVE_TO; + } + + public void tick() { + this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.targetYaw, 90.0F)); + this.mob.yHeadRot = this.mob.getYRot(); + this.mob.yBodyRot = this.mob.getYRot(); + if (this.operation != MoveControl.Operation.MOVE_TO) { + this.mob.setZza(0.0F); + } else { + this.operation = MoveControl.Operation.WAIT; + if (this.mob.isOnGround()) { + this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); + if (this.ticksUntilJump-- <= 0) { + this.ticksUntilJump = EndSlimeEntity.this.getJumpDelay(); + if (this.jumpOften) { + this.ticksUntilJump /= 3; + } + + EndSlimeEntity.this.getJumpControl().jump(); + if (EndSlimeEntity.this.doPlayJumpSound()) { + EndSlimeEntity.this.playSound( + EndSlimeEntity.this.getJumpSound(), + EndSlimeEntity.this.getSoundVolume(), + getJumpSoundPitch() + ); + } + } else { + EndSlimeEntity.this.xxa = 0.0F; + EndSlimeEntity.this.zza = 0.0F; + this.mob.setSpeed(0.0F); + } + } else { + this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); + } + + } + } + + private float getJumpSoundPitch() { + float f = EndSlimeEntity.this.isTiny() ? 1.4F : 0.8F; + return ((EndSlimeEntity.this.random.nextFloat() - EndSlimeEntity.this.random.nextFloat()) * 0.2F + 1.0F) * f; + } + } +} diff --git a/src/main/java/org/betterx/betterend/entity/ShadowWalkerEntity.java b/src/main/java/org/betterx/betterend/entity/ShadowWalkerEntity.java new file mode 100644 index 00000000..71b9ecc9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/ShadowWalkerEntity.java @@ -0,0 +1,149 @@ +package org.betterx.betterend.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +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.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +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.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndSounds; + +public class ShadowWalkerEntity extends Monster { + public ShadowWalkerEntity(EntityType entityType, Level world) { + super(entityType, world); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(2, new AttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createMobAttributes() { + return Monster + .createMonsterAttributes() + .add(Attributes.FOLLOW_RANGE, 35.0) + .add(Attributes.MOVEMENT_SPEED, 0.15) + .add(Attributes.ATTACK_DAMAGE, 4.5) + .add(Attributes.ARMOR, 2.0) + .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); + } + + @Override + public void tick() { + super.tick(); + level.addParticle( + ParticleTypes.ASH, + getX() + random.nextGaussian() * 0.2, + getY() + random.nextGaussian() * 0.5 + 1, + getZ() + random.nextGaussian() * 0.2, + 0, + 0, + 0 + ); + level.addParticle( + ParticleTypes.SMOKE, + getX() + random.nextGaussian() * 0.2, + getY() + random.nextGaussian() * 0.5 + 1, + getZ() + random.nextGaussian() * 0.2, + 0, + 0, + 0 + ); + level.addParticle( + ParticleTypes.ENTITY_EFFECT, + getX() + random.nextGaussian() * 0.2, + getY() + random.nextGaussian() * 0.5 + 1, + getZ() + random.nextGaussian() * 0.2, + 0, + 0, + 0 + ); + } + + @Override + protected SoundEvent getAmbientSound() { + return EndSounds.ENTITY_SHADOW_WALKER; + } + + @Override + protected SoundEvent getHurtSound(DamageSource source) { + return EndSounds.ENTITY_SHADOW_WALKER_DAMAGE; + } + + @Override + protected SoundEvent getDeathSound() { + return EndSounds.ENTITY_SHADOW_WALKER_DEATH; + } + + @Override + protected void playStepSound(BlockPos pos, BlockState state) { + } + + @Override + protected float getSoundVolume() { + return MHelper.randRange(0.25F, 0.5F, random); + } + + @Override + public float getVoicePitch() { + return MHelper.randRange(0.75F, 1.25F, random); + } + + @Override + public boolean doHurtTarget(Entity target) { + boolean attack = super.doHurtTarget(target); + if (attack && target instanceof LivingEntity) { + LivingEntity living = (LivingEntity) target; + if (!(living.hasEffect(MobEffects.BLINDNESS))) { + living.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 60)); + } + } + return attack; + } + + private final class AttackGoal extends MeleeAttackGoal { + private final ShadowWalkerEntity walker; + private int ticks; + + public AttackGoal(ShadowWalkerEntity walker, double speed, boolean pauseWhenMobIdle) { + super(walker, speed, pauseWhenMobIdle); + this.walker = walker; + } + + public void start() { + super.start(); + this.ticks = 0; + } + + public void stop() { + super.stop(); + this.walker.setAggressive(false); + } + + public void tick() { + super.tick(); + ++this.ticks; + this.walker.setAggressive(this.ticks >= 5 && this.getTicksUntilNextAttack() < this.getAttackInterval() / 2); + } + } +} diff --git a/src/main/java/org/betterx/betterend/entity/SilkMothEntity.java b/src/main/java/org/betterx/betterend/entity/SilkMothEntity.java new file mode 100644 index 00000000..99afa1dd --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/SilkMothEntity.java @@ -0,0 +1,321 @@ +package org.betterx.betterend.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.*; +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.control.LookControl; +import net.minecraft.world.entity.ai.goal.BreedGoal; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.FollowParentGoal; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos; +import net.minecraft.world.entity.ai.util.HoverRandomPos; +import net.minecraft.world.entity.animal.FlyingAnimal; +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.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.phys.Vec3; + +import org.betterx.bclib.entity.DespawnableAnimal; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndBlockProperties; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndItems; + +import java.util.EnumSet; +import org.jetbrains.annotations.Nullable; + +public class SilkMothEntity extends DespawnableAnimal implements FlyingAnimal { + private BlockPos hivePos; + private BlockPos entrance; + private Level hiveWorld; + + public SilkMothEntity(EntityType entityType, Level world) { + super(entityType, world); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.lookControl = new MothLookControl(this); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.xpReward = 1; + } + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity + .createLivingAttributes() + .add(Attributes.MAX_HEALTH, 2.0D) + .add(Attributes.FOLLOW_RANGE, 16.0D) + .add(Attributes.FLYING_SPEED, 0.4D) + .add(Attributes.MOVEMENT_SPEED, 0.1D); + } + + public void setHive(Level world, BlockPos hive) { + this.hivePos = hive; + this.hiveWorld = world; + } + + @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override + public void addAdditionalSaveData(CompoundTag tag) { + if (hivePos != null) { + tag.put("HivePos", NbtUtils.writeBlockPos(hivePos)); + tag.putString("HiveWorld", hiveWorld.dimension().location().toString()); + } + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + if (tag.contains("HivePos")) { + hivePos = NbtUtils.readBlockPos(tag.getCompound("HivePos")); + ResourceLocation worldID = new ResourceLocation(tag.getString("HiveWorld")); + try { + hiveWorld = level.getServer().getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, worldID)); + } catch (Exception e) { + BetterEnd.LOGGER.warning("Silk Moth Hive World {} is missing!", worldID); + hivePos = null; + } + } + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new ReturnToHiveGoal()); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(8, new WanderAroundGoal()); + this.goalSelector.addGoal(9, new FloatGoal(this)); + } + + @Override + protected PathNavigation createNavigation(Level world) { + FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) { + public boolean isStableDestination(BlockPos pos) { + BlockState state = this.level.getBlockState(pos); + return state.isAir() || !state.getMaterial().blocksMotion(); + } + + public void tick() { + super.tick(); + } + }; + birdNavigation.setCanOpenDoors(false); + birdNavigation.setCanFloat(false); + birdNavigation.setCanPassDoors(true); + return birdNavigation; + } + + @Override + public boolean isPushable() { + return false; + } + + @Override + public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { + return false; + } + + @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override + public boolean isFlying() { + return !this.onGround; + } + + @Override + public boolean isNoGravity() { + return true; + } + + @Override + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { + return EndEntities.SILK_MOTH.create(world); + } + + @Override + protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { + int minCount = 0; + int maxCount = 1; + if (causedByPlayer && this.lastHurtByPlayer != null) { + int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer); + minCount += looting; + maxCount += looting; + if (maxCount > 2) { + maxCount = 2; + } + } + int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount; + ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.SILK_FIBER, count)); + this.level.addFreshEntity(drop); + } + + class MothLookControl extends LookControl { + MothLookControl(Mob entity) { + super(entity); + } + + protected boolean resetXRotOnTick() { + return true; + } + } + + class WanderAroundGoal extends Goal { + WanderAroundGoal() { + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + @Override + public boolean canUse() { + return SilkMothEntity.this.navigation.isDone() && SilkMothEntity.this.random.nextInt(10) == 0; + } + + @Override + public boolean canContinueToUse() { + return SilkMothEntity.this.navigation.isInProgress(); + } + + @Override + public void start() { + Vec3 vec3d = null; + if (SilkMothEntity.this.hivePos != null && SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level) { + if (SilkMothEntity.this.position() + .distanceToSqr(SilkMothEntity.this.hivePos.getX(), + SilkMothEntity.this.hivePos.getY(), + SilkMothEntity.this.hivePos.getZ()) > 16) { + vec3d = SilkMothEntity.this.position().add(random.nextGaussian() * 2, 0, random.nextGaussian() * 2); + } + } + vec3d = vec3d == null ? this.getRandomLocation() : vec3d; + if (vec3d != null) { + try { + SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(new BlockPos(vec3d), + 1), 1.0D); + } catch (Exception e) { + } + } + } + + @Nullable + private Vec3 getRandomLocation() { + Vec3 vec3d3 = SilkMothEntity.this.getViewVector(0.0F); + Vec3 vec3d4 = HoverRandomPos.getPos(SilkMothEntity.this, 8, 7, vec3d3.x, vec3d3.z, 1.5707964F, 3, 1); + return vec3d4 != null ? vec3d4 : AirAndWaterRandomPos.getPos( + SilkMothEntity.this, + 8, + 4, + -2, + vec3d3.x, + vec3d3.z, + 1.5707963705062866D + ); + } + } + + class ReturnToHiveGoal extends Goal { + ReturnToHiveGoal() { + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + @Override + public boolean canUse() { + return SilkMothEntity.this.hivePos != null && + SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level && + SilkMothEntity.this.navigation.isDone() && + SilkMothEntity.this.random.nextInt(8) == 0 && + SilkMothEntity.this.position().distanceToSqr( + SilkMothEntity.this.hivePos.getX(), + SilkMothEntity.this.hivePos.getY(), + SilkMothEntity.this.hivePos.getZ() + ) < 16384; + } + + @Override + public boolean canContinueToUse() { + return SilkMothEntity.this.navigation.isInProgress() && level.getBlockState(entrance) + .isAir() && (level.getBlockState(hivePos) + .is(EndBlocks.SILK_MOTH_NEST) || level + .getBlockState(hivePos) + .is(EndBlocks.SILK_MOTH_HIVE)); + } + + @Override + public void start() { + BlockState state = SilkMothEntity.this.level.getBlockState(SilkMothEntity.this.hivePos); + if (!state.is(EndBlocks.SILK_MOTH_NEST) && !state.is(EndBlocks.SILK_MOTH_HIVE)) { + SilkMothEntity.this.hivePos = null; + return; + } + try { + SilkMothEntity.this.entrance = SilkMothEntity.this.hivePos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING)); + SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(entrance, 1), 1.0D); + } catch (Exception e) { + } + } + + @Override + public void tick() { + super.tick(); + if (SilkMothEntity.this.entrance == null) { + return; + } + double dx = Math.abs(SilkMothEntity.this.entrance.getX() - SilkMothEntity.this.getX()); + double dy = Math.abs(SilkMothEntity.this.entrance.getY() - SilkMothEntity.this.getY()); + double dz = Math.abs(SilkMothEntity.this.entrance.getZ() - SilkMothEntity.this.getZ()); + if (dx + dy + dz < 1) { + BlockState state = SilkMothEntity.this.level.getBlockState(hivePos); + if (state.is(EndBlocks.SILK_MOTH_NEST) || state.is(EndBlocks.SILK_MOTH_HIVE)) { + int fullness = state.getValue(EndBlockProperties.FULLNESS); + boolean isHive = state.is(EndBlocks.SILK_MOTH_HIVE); + if (fullness < 3 && (isHive || SilkMothEntity.this.random.nextBoolean())) { + fullness += isHive ? MHelper.randRange(1, 2, random) : 1; + if (fullness > 3) { + fullness = 3; + } + BlocksHelper.setWithUpdate( + SilkMothEntity.this.hiveWorld, + SilkMothEntity.this.hivePos, + state.setValue(EndBlockProperties.FULLNESS, fullness) + ); + } + SilkMothEntity.this.level.playSound( + null, + SilkMothEntity.this.entrance, + SoundEvents.BEEHIVE_ENTER, + SoundSource.BLOCKS, + 1, + 1 + ); + SilkMothEntity.this.discard(); + } else { + SilkMothEntity.this.hivePos = null; + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/entity/model/CubozoaEntityModel.java b/src/main/java/org/betterx/betterend/entity/model/CubozoaEntityModel.java new file mode 100644 index 00000000..e05e251d --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/model/CubozoaEntityModel.java @@ -0,0 +1,102 @@ +package org.betterx.betterend.entity.model; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.RenderType; +import net.minecraft.util.Mth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.entity.CubozoaEntity; + +public class CubozoaEntityModel extends EntityModel { + private final static int TENTACLE_COUNT = 4; + + private final ModelPart model; + private final ModelPart[] tentacle_center; + private final ModelPart[] tentacle; + private float scaleY; + private float scaleXZ; + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + PartDefinition bodyPart = modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(0, 17).addBox(-2.0F, -12.5F, -2.0F, 4.0F, 4.0F, 4.0F), + PartPose.offset(0.0F, 24.0F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + "main_cube_r1", + CubeListBuilder.create().texOffs(0, 0).addBox(-5.0F, -7.0F, -5.0F, 10.0F, 7.0F, 10.0F), + PartPose.offsetAndRotation(0.0F, -14.0F, 0.0F, 0.0F, 0.0F, -3.1416F) + ); + + for (int i = 1; i <= TENTACLE_COUNT; i++) { + PartDefinition tentaclePart = bodyPart.addOrReplaceChild( + "tentacle_center_" + i, + CubeListBuilder.create(), + PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.0F, i * 1.5708F, 0.0F) + ); + + tentaclePart.addOrReplaceChild( + "tentacle_" + i, + CubeListBuilder.create().texOffs(16, 17).addBox(-4.0F, 0.0F, 0.0F, 8.0F, 7.0F, 0.0F), + PartPose.offset(0.0F, -7.0F, 4.5F) + ); + } + + return LayerDefinition.create(modelData, 48, 48); + } + + public CubozoaEntityModel(ModelPart modelPart) { + super(RenderType::entityTranslucent); + tentacle = new ModelPart[TENTACLE_COUNT]; + tentacle_center = new ModelPart[TENTACLE_COUNT]; + + model = modelPart.getChild(PartNames.BODY); + for (int i = 1; i <= TENTACLE_COUNT; i++) { + tentacle_center[i - 1] = model.getChild("tentacle_center_" + i); + tentacle[i - 1] = tentacle_center[i - 1].getChild("tentacle_" + i); + } + } + + @Override + public void setupAnim(CubozoaEntity entity, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch) { + float sin = Mth.sin(animationProgress * 0.13F); + scaleY = sin * 0.1F + 0.9F; + scaleXZ = Mth.sin(animationProgress * 0.13F + 3.14F) * 0.1F + 0.9F; + + for (int i = 0; i < TENTACLE_COUNT; i++) { + tentacle[i].xRot = sin * 0.15f; + } + } + + @Override + public void renderToBuffer(PoseStack matrices, + VertexConsumer vertices, + int light, + int overlay, + float red, + float green, + float blue, + float alpha) { + matrices.pushPose(); + matrices.scale(scaleXZ, scaleY, scaleXZ); + model.render(matrices, vertices, light, overlay); + matrices.popPose(); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/model/DragonflyEntityModel.java b/src/main/java/org/betterx/betterend/entity/model/DragonflyEntityModel.java new file mode 100644 index 00000000..7514b88f --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/model/DragonflyEntityModel.java @@ -0,0 +1,144 @@ +package org.betterx.betterend.entity.model; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.RenderType; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.entity.DragonflyEntity; + +public class DragonflyEntityModel extends EntityModel { + private final ModelPart model; + private final ModelPart head; + private final ModelPart tail; + private final ModelPart tail_2; + private final ModelPart wing_1; + private final ModelPart wing_2; + private final ModelPart wing_3; + private final ModelPart wing_4; + private final ModelPart legs_1; + private final ModelPart legs_2; + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + PartDefinition bodyPart = modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -4.0F, 0.0F, 4.0F, 4.0F, 9.0F), + PartPose.offset(2.0F, 21.5F, -4.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.HEAD, + CubeListBuilder.create().texOffs(17, 0).addBox(-1.5F, -1.5F, -2.5F, 3.0F, 3.0F, 3.0F), + PartPose.offsetAndRotation(-2.0F, -2.0F, 0.0F, 0.3491F, 0.0F, 0.0F) + ); + + PartDefinition tailPart = bodyPart.addOrReplaceChild( + PartNames.TAIL, + CubeListBuilder.create().texOffs(26, 0).addBox(-1.5F, -1.5F, 0.0F, 3.0F, 3.0F, 7.0F), + PartPose.offset(-2.0F, -2.0F, 9.0F) + ); + + tailPart.addOrReplaceChild( + PartNames.TAIL_FIN, + CubeListBuilder.create().texOffs(36, 0).addBox(-1.0F, -1.0F, 0.0F, 2.0F, 2.0F, 10.0F), + PartPose.offset(0.0F, 0.0F, 7.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.LEFT_WING, + CubeListBuilder.create().texOffs(0, 13).addBox(-15.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F), + PartPose.offset(-2.0F, -4.0F, 4.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.RIGHT_WING, + CubeListBuilder.create().mirror().texOffs(0, 13).addBox(0.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F), + PartPose.offset(-2.0F, -4.0F, 4.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.LEFT_WING_BASE, + CubeListBuilder.create().texOffs(4, 17).addBox(-12.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F), + PartPose.offset(-2.0F, -4.0F, 8.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.RIGHT_WING_BASE, + CubeListBuilder.create().mirror().texOffs(4, 17).addBox(0.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F), + PartPose.offset(-2.0F, -4.0F, 8.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.LEFT_LEG, + CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F), + PartPose.offsetAndRotation(-1.0F, 0.0F, 1.0F, 0.0F, 0.0F, -0.5236F) + ); + + bodyPart.addOrReplaceChild( + PartNames.RIGHT_LEG, + CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F), + PartPose.offsetAndRotation(-3.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.5236F) + ); + + return LayerDefinition.create(modelData, 64, 64); + } + + public DragonflyEntityModel(ModelPart modelPart) { + super(RenderType::entityCutout); + + model = modelPart.getChild(PartNames.BODY); + head = model.getChild(PartNames.HEAD); + tail = model.getChild(PartNames.TAIL); + tail_2 = tail.getChild(PartNames.TAIL_FIN); + wing_1 = model.getChild(PartNames.LEFT_WING); + wing_2 = model.getChild(PartNames.RIGHT_WING); + wing_3 = model.getChild(PartNames.LEFT_WING_BASE); + wing_4 = model.getChild(PartNames.RIGHT_WING_BASE); + legs_1 = model.getChild(PartNames.LEFT_LEG); + legs_2 = model.getChild(PartNames.RIGHT_LEG); + } + + @Override + public void setupAnim(DragonflyEntity entity, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch) { + float progress = animationProgress * 2F; + + wing_1.zRot = 0.3491F + (float) Math.sin(progress) * 0.3491F; + wing_2.zRot = -wing_1.zRot; + + wing_3.zRot = 0.3491F + (float) Math.cos(progress) * 0.3491F; + wing_4.zRot = -wing_3.zRot; + + progress = animationProgress * 0.05F; + + head.xRot = 0.3491F + (float) Math.sin(progress * 0.7F) * 0.1F; + tail.xRot = (float) Math.cos(progress) * 0.05F - 0.05F; + tail_2.xRot = -tail.xRot * 1.5F; + } + + @Override + public void renderToBuffer(PoseStack matrices, + VertexConsumer vertices, + int light, + int overlay, + float red, + float green, + float blue, + float alpha) { + model.render(matrices, vertices, light, overlay); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/model/EndFishEntityModel.java b/src/main/java/org/betterx/betterend/entity/model/EndFishEntityModel.java new file mode 100644 index 00000000..e2469612 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/model/EndFishEntityModel.java @@ -0,0 +1,106 @@ +package org.betterx.betterend.entity.model; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.RenderType; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.entity.EndFishEntity; + +public class EndFishEntityModel extends EntityModel { + private final ModelPart model; + private final ModelPart fin_top; + private final ModelPart fin_bottom; + private final ModelPart flipper; + private final ModelPart fin_right; + private final ModelPart fin_left; + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + PartDefinition bodyPart = modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -2.0F, -4.0F, 2.0F, 4.0F, 8.0F), + PartPose.offset(0.0F, 20.0F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.TOP_FIN, + CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, -8.0F, 0.0F, 0.0F, 8.0F, 6.0F), + PartPose.offsetAndRotation(0.0F, -2.0F, -4.0F, -0.6981F, 0.0F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.BOTTOM_FIN, + CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, 0.0F, 0.0F, 0.0F, 8.0F, 6.0F), + PartPose.offsetAndRotation(0.0F, 2.0F, -4.0F, 0.6981F, 0.0F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.TAIL_FIN, + CubeListBuilder.create().texOffs(0, 15).addBox(0.0F, -5.0F, 0.0F, 0.0F, 5.0F, 5.0F), + PartPose.offsetAndRotation(0.0F, 0.0F, 2.0F, -0.7854F, 0.0F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.RIGHT_FIN, + CubeListBuilder.create().texOffs(0, 25).addBox(-3.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F), + PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, 0.7854F, 0.0F) + ); + + bodyPart.addOrReplaceChild( + PartNames.LEFT_FIN, + CubeListBuilder.create().mirror().texOffs(0, 25).addBox(0.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F), + PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, -0.7854F, 0.0F) + ); + + return LayerDefinition.create(modelData, 32, 32); + } + + public EndFishEntityModel(ModelPart modelPart) { + super(RenderType::entityCutout); + + model = modelPart.getChild(PartNames.BODY); + fin_top = model.getChild(PartNames.TOP_FIN); + fin_bottom = model.getChild(PartNames.BOTTOM_FIN); + flipper = model.getChild(PartNames.TAIL_FIN); + fin_right = model.getChild(PartNames.RIGHT_FIN); + fin_left = model.getChild(PartNames.LEFT_FIN); + } + + @Override + public void setupAnim(EndFishEntity entity, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch) { + float s1 = (float) Math.sin(animationProgress * 0.1); + float s2 = (float) Math.sin(animationProgress * 0.05); + flipper.yRot = s1 * 0.3F; + fin_top.xRot = s2 * 0.02F - 0.6981F; + fin_bottom.xRot = 0.6981F - s2 * 0.02F; + fin_left.yRot = s1 * 0.3F - 0.7854F; + fin_right.yRot = 0.7854F - s1 * 0.3F; + } + + @Override + public void renderToBuffer(PoseStack matrices, + VertexConsumer vertices, + int light, + int overlay, + float red, + float green, + float blue, + float alpha) { + model.render(matrices, vertices, light, overlay); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/model/EndSlimeEntityModel.java b/src/main/java/org/betterx/betterend/entity/model/EndSlimeEntityModel.java new file mode 100644 index 00000000..fa68c541 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/model/EndSlimeEntityModel.java @@ -0,0 +1,153 @@ +package org.betterx.betterend.entity.model; + +import net.minecraft.client.model.ListModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.RenderType; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.entity.EndSlimeEntity; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class EndSlimeEntityModel extends ListModel { + private final ModelPart innerCube; + private final ModelPart rightEye; + private final ModelPart leftEye; + private final ModelPart mouth; + private final ModelPart flower; + private final ModelPart crop; + + public static LayerDefinition getShellOnlyTexturedModelData() { + return getTexturedModelData(true); + } + + public static LayerDefinition getCompleteTexturedModelData() { + return getTexturedModelData(false); + } + + private static LayerDefinition getTexturedModelData(boolean onlyShell) { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + if (onlyShell) { + modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, 16.0F, -4.0F, 8.0F, 8.0F, 8.0F), + PartPose.ZERO + ); + } else { + modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(0, 16).addBox(-3.0F, 17.0F, -3.0F, 6.0F, 6.0F, 6.0F), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + PartNames.RIGHT_EYE, + CubeListBuilder.create().texOffs(32, 0).addBox(-3.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + PartNames.LEFT_EYE, + CubeListBuilder.create().texOffs(32, 4).addBox(1.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + PartNames.MOUTH, + CubeListBuilder.create().texOffs(32, 8).addBox(0.0F, 21.0F, -3.5F, 1.0F, 1.0F, 1.0F), + PartPose.ZERO + ); + + PartDefinition flowerPart = modelPartData.addOrReplaceChild( + "flower", + CubeListBuilder.create(), + PartPose.ZERO + ); + PartDefinition cropPart = modelPartData.addOrReplaceChild("crop", CubeListBuilder.create(), PartPose.ZERO); + + for (int i = 0; i < 6; i++) { + final PartDefinition parent = i < 4 ? flowerPart : cropPart; + final float rot = MHelper.degreesToRadians(i < 4 ? (i * 45F) : ((i - 4) * 90F + 45F)); + + PartDefinition petalRotPart = parent.addOrReplaceChild( + "petalRot_" + i, + CubeListBuilder.create(), + PartPose.offsetAndRotation(0, 0, 0, 0, rot, 0) + ); + + + petalRotPart.addOrReplaceChild( + "petal_" + i, + CubeListBuilder.create().texOffs(40, 0).addBox(0.0F, 0.0F, 0.0F, 8.0F, 8.0F, 0.0F), + PartPose.offset(-4, 8, 0) + ); + } + } + + return LayerDefinition.create(modelData, 64, 32); + } + + public EndSlimeEntityModel(EntityModelSet modelSet, boolean onlyShell) { + super(RenderType::entityCutout); + + ModelPart modelPart = modelSet.bakeLayer(onlyShell + ? EndEntitiesRenders.END_SLIME_SHELL_MODEL + : EndEntitiesRenders.END_SLIME_MODEL); + + innerCube = modelPart.getChild(PartNames.BODY); + if (!onlyShell) { + rightEye = modelPart.getChild(PartNames.RIGHT_EYE); + leftEye = modelPart.getChild(PartNames.LEFT_EYE); + mouth = modelPart.getChild(PartNames.MOUTH); + flower = modelPart.getChild("flower"); + crop = modelPart.getChild("crop"); + } else { + rightEye = null; + leftEye = null; + mouth = null; + flower = null; + crop = null; + } + } + + @Override + public void setupAnim(T entity, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch) { + } + + public void renderFlower(PoseStack matrices, VertexConsumer vertices, int light, int overlay) { + flower.render(matrices, vertices, light, overlay); + } + + public void renderCrop(PoseStack matrices, VertexConsumer vertices, int light, int overlay) { + crop.render(matrices, vertices, light, overlay); + } + + private boolean isOnlyShell() { + return rightEye == null; + } + + @Override + public Iterable parts() { + if (isOnlyShell()) { + return ImmutableList.of(this.innerCube); + } else { + return ImmutableList.of(this.innerCube, this.rightEye, this.leftEye, this.mouth); + } + } +} diff --git a/src/main/java/org/betterx/betterend/entity/model/SilkMothEntityModel.java b/src/main/java/org/betterx/betterend/entity/model/SilkMothEntityModel.java new file mode 100644 index 00000000..8541016f --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/model/SilkMothEntityModel.java @@ -0,0 +1,183 @@ +package org.betterx.betterend.entity.model; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.RenderType; +import net.minecraft.util.Mth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.entity.SilkMothEntity; + +public class SilkMothEntityModel extends EntityModel { + private final ModelPart legsL; + private final ModelPart cube_r1; + private final ModelPart cube_r2; + private final ModelPart cube_r3; + private final ModelPart legsR; + private final ModelPart cube_r4; + private final ModelPart cube_r5; + private final ModelPart cube_r6; + private final ModelPart head_pivot; + private final ModelPart tendril_r_r1; + private final ModelPart tendril_r_r2; + private final ModelPart bb_main; + private final ModelPart wingR_r1; + private final ModelPart wingL_r1; + private final ModelPart abdomen_r1; + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + PartDefinition legsL = modelPartData.addOrReplaceChild( + PartNames.LEFT_LEG, + CubeListBuilder.create().texOffs(0, 0), + PartPose.offsetAndRotation(1.5f, 19.9f, -0.45f, 0.0f, 0.0f, 0.6981f) + ); + + legsL.addOrReplaceChild( + "cube_r1", + CubeListBuilder.create().texOffs(0, 13).addBox(0.0216f, 0.0f, -0.5976f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f) + ); + + legsL.addOrReplaceChild( + "cube_r2", + CubeListBuilder.create().texOffs(0, 15).addBox(0.0f, 0.0f, -0.6f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f) + ); + + legsL.addOrReplaceChild( + "cube_r3", + CubeListBuilder.create().texOffs(0, 14).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f) + ); + + PartDefinition legsR = modelPartData.addOrReplaceChild( + PartNames.RIGHT_LEG, + CubeListBuilder.create().texOffs(0, 0), + PartPose.offsetAndRotation(-1.5f, 19.9f, -0.55f, 0.0f, 3.1416f, -0.6545f) + ); + + legsR.addOrReplaceChild( + "cube_r4", + CubeListBuilder.create().texOffs(0, 10).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f) + ); + + legsR.addOrReplaceChild( + "cube_r5", + CubeListBuilder.create().texOffs(0, 11).addBox(0.0f, 0.0f, -0.4f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f) + ); + + legsR.addOrReplaceChild( + "cube_r6", + CubeListBuilder.create().texOffs(0, 12).addBox(0.0216f, 0.0f, -0.4024f, 3.0f, 0.0f, 1.0f), + PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f) + ); + + PartDefinition head_pivot = modelPartData.addOrReplaceChild( + PartNames.HEAD, + CubeListBuilder.create().texOffs(15, 10).addBox(-1.5f, -1.5f, -2.0f, 3.0f, 3.0f, 3.0f), + PartPose.offset(0.0f, 18.0f, -3.0f) + ); + + head_pivot.addOrReplaceChild( + "tendril_r_r1", + CubeListBuilder.create().mirror().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f), + PartPose.offsetAndRotation(1.0f, -1.15f, -1.0f, 0.0f, 0.0f, 0.3927f) + ); + + head_pivot.addOrReplaceChild( + "tendril_r_r2", + CubeListBuilder.create().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f), + PartPose.offsetAndRotation(-1.0f, -1.15f, -1.0f, 0.0f, 0.0f, -0.3927f) + ); + + PartDefinition bb_main = modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(19, 19).addBox(-2.5f, -8.5f, -3.0f, 5.0f, 5.0f, 3.0f), + PartPose.offset(0.0f, 24.0f, 0.0f) + ); + + bb_main.addOrReplaceChild( + PartNames.RIGHT_WING, + CubeListBuilder.create().mirror().texOffs(0, 5).addBox(-7.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f), + PartPose.offsetAndRotation(-1.5f, -6.5f, 0.5f, 0.0f, 0.0f, 0.3927f) + ); + + bb_main.addOrReplaceChild( + PartNames.LEFT_WING, + CubeListBuilder.create().texOffs(0, 5).addBox(-2.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f), + PartPose.offsetAndRotation(1.5f, -6.5f, 0.5f, 0.0f, 0.0f, -0.3927f) + ); + + bb_main.addOrReplaceChild( + "abdomen_r1", + CubeListBuilder.create().texOffs(0, 10).addBox(-3.0f, -4.0f, -1.0f, 4.0f, 4.0f, 7.0f), + PartPose.offsetAndRotation(1.0f, -3.9f, 0.0f, -0.3927f, 0.0f, 0.0f) + ); + + return LayerDefinition.create(modelData, 64, 64); + } + + public SilkMothEntityModel(ModelPart modelPart) { + super(RenderType::entityCutout); + + legsL = modelPart.getChild(PartNames.LEFT_LEG); + cube_r1 = legsL.getChild("cube_r1"); + cube_r2 = legsL.getChild("cube_r2"); + cube_r3 = legsL.getChild("cube_r3"); + legsR = modelPart.getChild(PartNames.RIGHT_LEG); + cube_r4 = legsR.getChild("cube_r4"); + cube_r5 = legsR.getChild("cube_r5"); + cube_r6 = legsR.getChild("cube_r6"); + head_pivot = modelPart.getChild(PartNames.HEAD); + tendril_r_r1 = head_pivot.getChild("tendril_r_r1"); + tendril_r_r2 = head_pivot.getChild("tendril_r_r2"); + bb_main = modelPart.getChild(PartNames.BODY); + wingR_r1 = bb_main.getChild(PartNames.RIGHT_WING); + wingL_r1 = bb_main.getChild(PartNames.LEFT_WING); + abdomen_r1 = bb_main.getChild("abdomen_r1"); + } + + @Override + public void setupAnim(SilkMothEntity entity, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch) { + wingR_r1.zRot = Mth.sin(animationProgress * 2F) * 0.4F + 0.3927F; + wingL_r1.zRot = -wingR_r1.zRot; + head_pivot.xRot = Mth.sin(animationProgress * 0.03F) * 0.1F; + tendril_r_r1.zRot = Mth.sin(animationProgress * 0.07F) * 0.2F + 0.3927F; + tendril_r_r2.zRot = -tendril_r_r1.zRot; + abdomen_r1.xRot = Mth.sin(animationProgress * 0.05F) * 0.1F - 0.3927F; + legsR.zRot = Mth.sin(animationProgress * 0.07F) * 0.1F - 0.6545F; + legsL.zRot = -legsR.zRot; + } + + @Override + public void renderToBuffer(PoseStack matrices, + VertexConsumer vertices, + int light, + int overlay, + float red, + float green, + float blue, + float alpha) { + bb_main.render(matrices, vertices, light, overlay); + head_pivot.render(matrices, vertices, light, overlay); + legsL.render(matrices, vertices, light, overlay); + legsR.render(matrices, vertices, light, overlay); + } +} diff --git a/src/main/java/org/betterx/betterend/entity/render/RendererEntityCubozoa.java b/src/main/java/org/betterx/betterend/entity/render/RendererEntityCubozoa.java new file mode 100644 index 00000000..8ab67c9f --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/RendererEntityCubozoa.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.client.renderer.entity.layers.EyesLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.CubozoaEntity; +import org.betterx.betterend.entity.model.CubozoaEntityModel; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class RendererEntityCubozoa extends MobRenderer { + private static final ResourceLocation[] TEXTURE = new ResourceLocation[2]; + private static final RenderType[] GLOW = new RenderType[2]; + + public RendererEntityCubozoa(EntityRendererProvider.Context ctx) { + super(ctx, new CubozoaEntityModel(ctx.bakeLayer(EndEntitiesRenders.CUBOZOA_MODEL)), 0.5f); + this.addLayer(new EyesLayer(this) { + @Override + public RenderType renderType() { + return GLOW[0]; + } + + @Override + public void render(PoseStack matrices, + MultiBufferSource vertexConsumers, + int light, + CubozoaEntity entity, + float limbAngle, + float limbDistance, + float tickDelta, + float animationProgress, + float headYaw, + float headPitch) { + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]); + this.getParentModel() + .renderToBuffer(matrices, + vertexConsumer, + 15728640, + OverlayTexture.NO_OVERLAY, + 1.0F, + 1.0F, + 1.0F, + 1.0F + ); + } + }); + } + + @Override + protected void scale(CubozoaEntity entity, PoseStack matrixStack, float f) { + float scale = entity.getScale(); + matrixStack.scale(scale, scale, scale); + } + + @Override + public ResourceLocation getTextureLocation(CubozoaEntity entity) { + return TEXTURE[entity.getVariant()]; + } + + static { + TEXTURE[0] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa.png"); + TEXTURE[1] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur.png"); + + GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_glow.png")); + GLOW[1] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur_glow.png")); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/entity/render/RendererEntityDragonfly.java b/src/main/java/org/betterx/betterend/entity/render/RendererEntityDragonfly.java new file mode 100644 index 00000000..174ab06b --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/RendererEntityDragonfly.java @@ -0,0 +1,32 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.client.renderer.entity.layers.EyesLayer; +import net.minecraft.resources.ResourceLocation; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.DragonflyEntity; +import org.betterx.betterend.entity.model.DragonflyEntityModel; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class RendererEntityDragonfly extends MobRenderer { + private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/dragonfly.png"); + private static final RenderType GLOW = RenderType.eyes(BetterEnd.makeID("textures/entity/dragonfly_glow.png")); + + public RendererEntityDragonfly(EntityRendererProvider.Context ctx) { + super(ctx, new DragonflyEntityModel(ctx.bakeLayer(EndEntitiesRenders.DRAGONFLY_MODEL)), 0.5f); + this.addLayer(new EyesLayer(this) { + @Override + public RenderType renderType() { + return GLOW; + } + }); + } + + @Override + public ResourceLocation getTextureLocation(DragonflyEntity entity) { + return TEXTURE; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndFish.java b/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndFish.java new file mode 100644 index 00000000..66937bc4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndFish.java @@ -0,0 +1,73 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.client.renderer.entity.layers.EyesLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.EndFishEntity; +import org.betterx.betterend.entity.model.EndFishEntityModel; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class RendererEntityEndFish extends MobRenderer { + private static final ResourceLocation[] TEXTURE = new ResourceLocation[EndFishEntity.VARIANTS]; + private static final RenderType[] GLOW = new RenderType[EndFishEntity.VARIANTS]; + + public RendererEntityEndFish(EntityRendererProvider.Context ctx) { + super(ctx, new EndFishEntityModel(ctx.bakeLayer(EndEntitiesRenders.END_FISH_MODEL)), 0.5f); + this.addLayer(new EyesLayer(this) { + @Override + public RenderType renderType() { + return GLOW[0]; + } + + @Override + public void render(PoseStack matrices, + MultiBufferSource vertexConsumers, + int light, + EndFishEntity entity, + float limbAngle, + float limbDistance, + float tickDelta, + float animationProgress, + float headYaw, + float headPitch) { + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]); + this.getParentModel() + .renderToBuffer(matrices, + vertexConsumer, + 15728640, + OverlayTexture.NO_OVERLAY, + 1.0F, + 1.0F, + 1.0F, + 1.0F + ); + } + }); + } + + @Override + protected void scale(EndFishEntity entity, PoseStack matrixStack, float f) { + float scale = entity.getScale(); + matrixStack.scale(scale, scale, scale); + } + + @Override + public ResourceLocation getTextureLocation(EndFishEntity entity) { + return TEXTURE[entity.getVariant()]; + } + + static { + for (int i = 0; i < EndFishEntity.VARIANTS; i++) { + TEXTURE[i] = BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + ".png"); + GLOW[i] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + "_glow.png")); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndSlime.java b/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndSlime.java new file mode 100644 index 00000000..47e0dba9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/RendererEntityEndSlime.java @@ -0,0 +1,161 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.EyesLayer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.EndSlimeEntity; +import org.betterx.betterend.entity.model.EndSlimeEntityModel; + +public class RendererEntityEndSlime extends MobRenderer> { + private static final ResourceLocation[] TEXTURE = new ResourceLocation[4]; + private static final RenderType[] GLOW = new RenderType[4]; + + public RendererEntityEndSlime(EntityRendererProvider.Context ctx) { + super(ctx, new EndSlimeEntityModel<>(ctx.getModelSet(), false), 0.25f); + this.addLayer(new OverlayFeatureRenderer(this, ctx)); + this.addLayer(new EyesLayer>(this) { + @Override + public RenderType renderType() { + return GLOW[0]; + } + + @Override + public void render(PoseStack matrices, + MultiBufferSource vertexConsumers, + int light, + EndSlimeEntity entity, + float limbAngle, + float limbDistance, + float tickDelta, + float animationProgress, + float headYaw, + float headPitch) { + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getSlimeType()]); + this.getParentModel() + .renderToBuffer(matrices, + vertexConsumer, + 15728640, + OverlayTexture.NO_OVERLAY, + 1.0F, + 1.0F, + 1.0F, + 1.0F + ); + if (entity.isLake()) { + this.getParentModel().renderFlower(matrices, vertexConsumer, 15728640, OverlayTexture.NO_OVERLAY); + } + } + }); + } + + @Override + public ResourceLocation getTextureLocation(EndSlimeEntity entity) { + return TEXTURE[entity.getSlimeType()]; + } + + @Override + public void render(EndSlimeEntity slimeEntity, + float f, + float g, + PoseStack matrixStack, + MultiBufferSource vertexConsumerProvider, + int i) { + this.shadowRadius = 0.25F * (float) slimeEntity.getSize(); + super.render(slimeEntity, f, g, matrixStack, vertexConsumerProvider, i); + } + + @Override + protected void scale(EndSlimeEntity slimeEntity, PoseStack matrixStack, float f) { + matrixStack.scale(0.999F, 0.999F, 0.999F); + matrixStack.translate(0.0D, 0.0010000000474974513D, 0.0D); + float h = (float) slimeEntity.getSize(); + float i = Mth.lerp(f, slimeEntity.oSquish, slimeEntity.squish) / (h * 0.5F + 1.0F); + float j = 1.0F / (i + 1.0F); + matrixStack.scale(j * h, 1.0F / j * h, j * h); + } + + private final class OverlayFeatureRenderer extends RenderLayer> { + private final EndSlimeEntityModel modelOrdinal; + private final EndSlimeEntityModel modelLake; + + public OverlayFeatureRenderer(RenderLayerParent> featureRendererContext, + EntityRendererProvider.Context ctx) { + super(featureRendererContext); + modelOrdinal = new EndSlimeEntityModel<>(ctx.getModelSet(), true); + modelLake = new EndSlimeEntityModel<>(ctx.getModelSet(), true); + } + + public void render(PoseStack matrixStack, + MultiBufferSource vertexConsumerProvider, + int i, + T livingEntity, + float f, + float g, + float h, + float j, + float k, + float l) { + if (!livingEntity.isInvisible()) { + if (livingEntity.isLake()) { + VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation( + livingEntity))); + this.getParentModel() + .renderFlower(matrixStack, + vertexConsumer, + i, + LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F) + ); + } else if (livingEntity.isAmber() || livingEntity.isChorus()) { + VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation( + livingEntity))); + this.getParentModel() + .renderCrop(matrixStack, + vertexConsumer, + i, + LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F) + ); + } + + EndSlimeEntityModel model = livingEntity.getSlimeType() == 1 ? modelLake : modelOrdinal; + this.getParentModel().copyPropertiesTo(model); + model.prepareMobModel(livingEntity, f, g, h); + model.setupAnim(livingEntity, f, g, j, k, l); + VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityTranslucent(this.getTextureLocation( + livingEntity))); + model.renderToBuffer( + matrixStack, + vertexConsumer, + i, + LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F), + 1.0F, + 1.0F, + 1.0F, + 1.0F + ); + } + } + } + + static { + TEXTURE[0] = BetterEnd.makeID("textures/entity/end_slime/end_slime.png"); + TEXTURE[1] = BetterEnd.makeID("textures/entity/end_slime/end_slime_mossy.png"); + TEXTURE[2] = BetterEnd.makeID("textures/entity/end_slime/end_slime_lake.png"); + TEXTURE[3] = BetterEnd.makeID("textures/entity/end_slime/end_slime_amber.png"); + GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_glow.png")); + GLOW[1] = GLOW[0]; + GLOW[2] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_lake_glow.png")); + GLOW[3] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_amber_glow.png")); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/entity/render/RendererEntityShadowWalker.java b/src/main/java/org/betterx/betterend/entity/render/RendererEntityShadowWalker.java new file mode 100644 index 00000000..bebf5a08 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/RendererEntityShadowWalker.java @@ -0,0 +1,24 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.HumanoidMobRenderer; +import net.minecraft.resources.ResourceLocation; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.ShadowWalkerEntity; + +public class RendererEntityShadowWalker extends HumanoidMobRenderer> { + private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/shadow_walker.png"); + + public RendererEntityShadowWalker(EntityRendererProvider.Context ctx) { + super(ctx, new PlayerModel(ctx.bakeLayer(ModelLayers.PLAYER), false), 0.5F); + //super(entityRenderDispatcher, new PlayerModel(0.0F, false), 0.5F); + } + + @Override + public ResourceLocation getTextureLocation(ShadowWalkerEntity zombieEntity) { + return TEXTURE; + } +} diff --git a/src/main/java/org/betterx/betterend/entity/render/SilkMothEntityRenderer.java b/src/main/java/org/betterx/betterend/entity/render/SilkMothEntityRenderer.java new file mode 100644 index 00000000..4e335d17 --- /dev/null +++ b/src/main/java/org/betterx/betterend/entity/render/SilkMothEntityRenderer.java @@ -0,0 +1,23 @@ +package org.betterx.betterend.entity.render; + +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.SilkMothEntity; +import org.betterx.betterend.entity.model.SilkMothEntityModel; +import org.betterx.betterend.registry.EndEntitiesRenders; + +public class SilkMothEntityRenderer extends MobRenderer { + private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/silk_moth.png"); + + public SilkMothEntityRenderer(EntityRendererProvider.Context ctx) { + super(ctx, new SilkMothEntityModel(ctx.bakeLayer(EndEntitiesRenders.SILK_MOTH_MODEL)), 0.5f); + } + + @Override + public ResourceLocation getTextureLocation(SilkMothEntity entity) { + return TEXTURE; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/events/ItemTooltipCallback.java b/src/main/java/org/betterx/betterend/events/ItemTooltipCallback.java new file mode 100644 index 00000000..f236d9f7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/events/ItemTooltipCallback.java @@ -0,0 +1,36 @@ +package org.betterx.betterend.events; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +import java.util.List; + +@Environment(EnvType.CLIENT) +public interface ItemTooltipCallback { + /** + * Fired after the game has appended all base tooltip lines to the list. + */ + Event EVENT = EventFactory.createArrayBacked( + ItemTooltipCallback.class, + callbacks -> (player, stack, context, lines) -> { + for (ItemTooltipCallback callback : callbacks) { + callback.getTooltip(player, stack, context, lines); + } + } + ); + + /** + * Called when an item stack's tooltip is rendered. Text added to {@code lines} will be + * rendered with the tooltip. + * + * @param lines the list containing the lines of text displayed on the stack's tooltip + */ + void getTooltip(Player player, ItemStack stack, TooltipFlag context, List lines); +} diff --git a/src/main/java/org/betterx/betterend/events/PlayerAdvancementsCallback.java b/src/main/java/org/betterx/betterend/events/PlayerAdvancementsCallback.java new file mode 100644 index 00000000..80302353 --- /dev/null +++ b/src/main/java/org/betterx/betterend/events/PlayerAdvancementsCallback.java @@ -0,0 +1,21 @@ +package org.betterx.betterend.events; + +import net.minecraft.advancements.Advancement; +import net.minecraft.server.level.ServerPlayer; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +public interface PlayerAdvancementsCallback { + + Event PLAYER_ADVANCEMENT_COMPLETE = EventFactory.createArrayBacked( + PlayerAdvancementsCallback.class, + callbacks -> (player, advancement, criterionName) -> { + for (PlayerAdvancementsCallback event : callbacks) { + event.onAdvancementComplete(player, advancement, criterionName); + } + } + ); + + void onAdvancementComplete(ServerPlayer player, Advancement advancement, String criterionName); +} diff --git a/src/main/java/org/betterx/betterend/integration/EndBiomeIntegration.java b/src/main/java/org/betterx/betterend/integration/EndBiomeIntegration.java new file mode 100644 index 00000000..d57bf4cb --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/EndBiomeIntegration.java @@ -0,0 +1,5 @@ +package org.betterx.betterend.integration; + +public interface EndBiomeIntegration { + void addBiomes(); +} diff --git a/src/main/java/org/betterx/betterend/integration/EnderscapeIntegration.java b/src/main/java/org/betterx/betterend/integration/EnderscapeIntegration.java new file mode 100644 index 00000000..4cfffec0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/EnderscapeIntegration.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.integration; + +import net.minecraft.core.Holder; +import net.minecraft.core.MappedRegistry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.integration.ModIntegration; +import org.betterx.bclib.world.features.BCLFeature; + +public class EnderscapeIntegration extends ModIntegration { + public EnderscapeIntegration() { + super("enderscape"); + } + + @Override + public void init() { + Class enderscape = getClass("net.enderscape.Enderscape"); + Class enderscapeIslandsBiome = getClass("net.enderscape.world.biomes.EnderscapeIslandsBiome"); + MappedRegistry biomes = getStaticFieldValue(enderscape, "ENDERSCAPE_BIOME"); + biomes.entrySet().forEach(entry -> { + ResourceKey key = entry.getKey(); + Holder biome = getBiome(key.location().getPath()); + if (enderscapeIslandsBiome.isInstance(entry.getValue())) { + BiomeAPI.registerEndVoidBiome(biome); + } else { + BiomeAPI.registerEndLandBiome(biome); + } + }); + + BCLFeature scatteredShadowQuartzOre = getFeature("scattered_shadow_quartz_ore", + Decoration.UNDERGROUND_DECORATION); + BCLFeature voidNebuliteOre = getFeature("void_nebulite_ore", Decoration.UNDERGROUND_DECORATION); + BCLFeature nebuliteOre = getFeature("nebulite_ore", Decoration.UNDERGROUND_DECORATION); + + BiomeAPI.registerEndBiomeModification((biomeID, biome) -> { + if (!biomeID.getNamespace().equals("enderscape")) { + BiomeAPI.addBiomeFeature(biome, scatteredShadowQuartzOre); + BiomeAPI.addBiomeFeature(biome, voidNebuliteOre); + BiomeAPI.addBiomeFeature(biome, nebuliteOre); + } + }); + + TagAPI.addBlockTag(CommonBlockTags.END_STONES, getBlock("nebulite_ore")); + TagAPI.addBlockTag(CommonBlockTags.END_STONES, getBlock("shadow_quartz_ore")); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/FlamboyantRefabricatedIntegration.java b/src/main/java/org/betterx/betterend/integration/FlamboyantRefabricatedIntegration.java new file mode 100644 index 00000000..db1df8a6 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/FlamboyantRefabricatedIntegration.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.integration; + +import net.minecraft.world.level.ItemLike; + +import com.google.common.collect.Maps; +import org.betterx.bclib.integration.ModIntegration; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.betterend.blocks.HydraluxPetalColoredBlock; +import org.betterx.betterend.complexmaterials.ColoredMaterial; +import org.betterx.betterend.registry.EndBlocks; + +import java.awt.*; +import java.util.Map; + +public class FlamboyantRefabricatedIntegration extends ModIntegration { + public FlamboyantRefabricatedIntegration() { + super("flamboyant"); + } + + @Override + public void init() { + Map colors = Maps.newHashMap(); + Map dyes = Maps.newHashMap(); + + addColor("fead1d", "amber", colors, dyes); + addColor("bd9a5f", "beige", colors, dyes); + addColor("edeada", "cream", colors, dyes); + addColor("33430e", "dark_green", colors, dyes); + addColor("639920", "forest_green", colors, dyes); + addColor("f0618c", "hot_pink", colors, dyes); + addColor("491c7b", "indigo", colors, dyes); + addColor("65291b", "maroon", colors, dyes); + addColor("2c3969", "navy", colors, dyes); + addColor("827c17", "olive", colors, dyes); + addColor("7bc618", "pale_green", colors, dyes); + addColor("f4a4bd", "pale_pink", colors, dyes); + addColor("f8d45a", "pale_yellow", colors, dyes); + addColor("6bb1cf", "sky_blue", colors, dyes); + addColor("6e8c9c", "slate_gray", colors, dyes); + addColor("b02454", "violet", colors, dyes); + + new ColoredMaterial(HydraluxPetalColoredBlock::new, EndBlocks.HYDRALUX_PETAL_BLOCK, colors, dyes, true); + } + + private void addColor(String hex, String name, Map colors, Map dyes) { + int color = ColorUtil.color(hex); + colors.put(color, name); + dyes.put(color, getItem(name + "_dye")); + + System.out.println(name + " " + color + " " + new Color(color)); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/Integrations.java b/src/main/java/org/betterx/betterend/integration/Integrations.java new file mode 100644 index 00000000..4521d7d5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/Integrations.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.integration; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +import net.fabricmc.loader.api.FabricLoader; + +import org.betterx.bclib.api.ModIntegrationAPI; +import org.betterx.bclib.integration.ModIntegration; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.events.PlayerAdvancementsCallback; +import org.betterx.betterend.integration.byg.BYGIntegration; +import org.betterx.betterend.item.GuideBookItem; +import org.betterx.betterend.registry.EndItems; + +public class Integrations { + public static final ModIntegration BYG = ModIntegrationAPI.register(new BYGIntegration()); + public static final ModIntegration NOURISH = ModIntegrationAPI.register(new NourishIntegration()); + public static final ModIntegration FLAMBOYANT_REFABRICATED = ModIntegrationAPI.register(new FlamboyantRefabricatedIntegration()); + public static final ModIntegration ENDERSCAPE = ModIntegrationAPI.register(new EnderscapeIntegration()); + + private static boolean hasHydrogen; + + public static void init() { + if (hasGuideBook()) { + GuideBookItem.register(); + + PlayerAdvancementsCallback.PLAYER_ADVANCEMENT_COMPLETE.register((player, advancement, criterionName) -> { + ResourceLocation advId = new ResourceLocation("minecraft:end/enter_end_gateway"); + if (advId.equals(advancement.getId())) { + player.addItem(new ItemStack(GuideBookItem.GUIDE_BOOK)); + } + }); + + GridRecipe.make(BetterEnd.MOD_ID, "guide_book", GuideBookItem.GUIDE_BOOK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("D", "B", "C") + .addMaterial('D', EndItems.ENDER_DUST) + .addMaterial('B', Items.BOOK) + .addMaterial('C', EndItems.CRYSTAL_SHARDS) + .build(); + } + hasHydrogen = FabricLoader.getInstance().isModLoaded("hydrogen"); + } + + public static boolean hasGuideBook() { + return FabricLoader.getInstance().isModLoaded("patchouli"); + } + + public static boolean hasHydrogen() { + return hasHydrogen; + } +} diff --git a/src/main/java/org/betterx/betterend/integration/NourishIntegration.java b/src/main/java/org/betterx/betterend/integration/NourishIntegration.java new file mode 100644 index 00000000..a152a838 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/NourishIntegration.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.integration; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.integration.ModIntegration; +import org.betterx.betterend.registry.EndItems; + +public class NourishIntegration extends ModIntegration { + public NourishIntegration() { + super("nourish"); + } + + @Override + public void init() { + TagKey fats = getItemTag("fats"); + TagKey fruit = getItemTag("fruit"); + TagKey protein = getItemTag("protein"); + TagKey sweets = getItemTag("sweets"); + + TagAPI.addItemTag(fats, EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED); + TagAPI.addItemTag( + fruit, + EndItems.SHADOW_BERRY_RAW, + EndItems.SHADOW_BERRY_COOKED, + EndItems.BLOSSOM_BERRY, + EndItems.SHADOW_BERRY_JELLY, + EndItems.SWEET_BERRY_JELLY, + EndItems.BLOSSOM_BERRY_JELLY, + EndItems.AMBER_ROOT_RAW, + EndItems.CHORUS_MUSHROOM_RAW, + EndItems.CHORUS_MUSHROOM_COOKED, + EndItems.BOLUX_MUSHROOM_COOKED + ); + TagAPI.addItemTag( + protein, + EndItems.END_FISH_RAW, + EndItems.END_FISH_COOKED, + EndItems.CHORUS_MUSHROOM_COOKED, + EndItems.BOLUX_MUSHROOM_COOKED, + EndItems.CAVE_PUMPKIN_PIE + ); + TagAPI.addItemTag( + sweets, + EndItems.SHADOW_BERRY_JELLY, + EndItems.SWEET_BERRY_JELLY, + EndItems.BLOSSOM_BERRY_JELLY, + EndItems.CAVE_PUMPKIN_PIE + ); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/BYGBlocks.java b/src/main/java/org/betterx/betterend/integration/byg/BYGBlocks.java new file mode 100644 index 00000000..d494feb8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/BYGBlocks.java @@ -0,0 +1,17 @@ +package org.betterx.betterend.integration.byg; + +import net.minecraft.world.level.block.Block; + +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.betterend.blocks.basis.EndWallPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class BYGBlocks { + public static final Block IVIS_MOSS = EndBlocks.registerBlock("ivis_moss", new EndWallPlantBlock()); + public static final Block NIGHTSHADE_MOSS = EndBlocks.registerBlock("nightshade_moss", new EndWallPlantBlock()); + + public static final Block IVIS_VINE = EndBlocks.registerBlock("ivis_vine", new BaseVineBlock()); + + public static void register() { + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/BYGIntegration.java b/src/main/java/org/betterx/betterend/integration/byg/BYGIntegration.java new file mode 100644 index 00000000..d358da0c --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/BYGIntegration.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.integration.byg; + +import org.betterx.bclib.integration.ModIntegration; +import org.betterx.betterend.integration.EndBiomeIntegration; + +public class BYGIntegration extends ModIntegration implements EndBiomeIntegration { + public BYGIntegration() { + super("byg"); + } + + @Override + public void init() { + /*Block block = Integrations.BYG.getBlock("ivis_phylium"); + if (block != null) { + TagAPI.addTags(block, CommonBlockTags.END_STONES, CommonBlockTags.GEN_END_STONES); + } + BYGBlocks.register(); + BYGFeatures.register(); + BYGBiomes.register();*/ + } + + @Override + public void addBiomes() { + //BYGBiomes.addBiomes(); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/biomes/BYGBiomes.java b/src/main/java/org/betterx/betterend/integration/byg/biomes/BYGBiomes.java new file mode 100644 index 00000000..25a6922d --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/biomes/BYGBiomes.java @@ -0,0 +1,23 @@ +package org.betterx.betterend.integration.byg.biomes; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.world.biome.EndBiome; + +public class BYGBiomes { + // New Biomes + public static final EndBiome OLD_BULBIS_GARDENS = EndBiomes.registerSubBiomeIntegration(new OldBulbisGardens()); + public static final EndBiome NIGHTSHADE_REDWOODS = EndBiomes.registerSubBiomeIntegration(new NightshadeRedwoods()); + //public static final EndBiome ETHERIAL_GROVE = EndBiomes.registerSubBiomeIntegration(new EterialGrove()); + + public static void register() { + BetterEnd.LOGGER.info("Registered " + OLD_BULBIS_GARDENS); + } + + public static void addBiomes() { + EndBiomes.addSubBiomeIntegration(OLD_BULBIS_GARDENS, Integrations.BYG.getID("bulbis_gardens")); + EndBiomes.addSubBiomeIntegration(NIGHTSHADE_REDWOODS, Integrations.BYG.getID("nightshade_forest")); + //EndBiomes.addSubBiomeIntegration(ETHERIAL_GROVE, Integrations.BYG.getID("ethereal_islands")); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/biomes/NightshadeRedwoods.java b/src/main/java/org/betterx/betterend/integration/byg/biomes/NightshadeRedwoods.java new file mode 100644 index 00000000..956ff692 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/biomes/NightshadeRedwoods.java @@ -0,0 +1,87 @@ +package org.betterx.betterend.integration.byg.biomes; + +import net.minecraft.core.Holder; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSpecialEffects; +import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; + +import org.betterx.bclib.BCLib; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.integration.byg.features.BYGFeatures; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.List; + +public class NightshadeRedwoods extends EndBiome.Config { + public NightshadeRedwoods() { + super("nightshade_redwoods"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + Holder biome = Integrations.BYG.getBiome("nightshade_forest"); + BiomeSpecialEffects effects = biome.value().getSpecialEffects(); + + builder.fogColor(140, 108, 47) + .fogDensity(1.5F) + .waterAndFogColor(55, 70, 186) + .foliageColor(122, 17, 155) + .particles( + ParticleTypes.REVERSE_PORTAL, + 0.002F + ) + //TODO: 1.18 surface rules +// .setSurface(biome.getGenerationSettings() +// .getSurfaceBuilder() +// .get()) + .grassColor(48, 13, 89) + .plantsColor(200, 125, 9) + .feature(EndFeatures.END_LAKE_RARE) + .feature(BYGFeatures.NIGHTSHADE_REDWOOD_TREE) + .feature(BYGFeatures.NIGHTSHADE_MOSS_WOOD) + .feature(BYGFeatures.NIGHTSHADE_MOSS); + + if (BCLib.isClient()) { + SoundEvent loop = effects.getAmbientLoopSoundEvent() + .get(); + SoundEvent music = effects.getBackgroundMusic() + .get() + .getEvent(); + SoundEvent additions = effects.getAmbientAdditionsSettings() + .get() + .getSoundEvent(); + SoundEvent mood = effects.getAmbientMoodSettings() + .get() + .getSoundEvent(); + builder.loop(loop) + .music(music) + .additions(additions) + .mood(mood); + } + biome.value().getGenerationSettings() + .features() + .forEach((list) -> { + list.forEach((feature) -> { + builder.feature(Decoration.VEGETAL_DECORATION, feature); + }); + }); + + for (MobCategory group : MobCategory.values()) { + List list = biome.value() + .getMobSettings() + .getMobs(group) + .unwrap(); + list.forEach((entry) -> { + builder.spawn((EntityType) entry.type, 1, entry.minCount, entry.maxCount); + }); + } + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/biomes/OldBulbisGardens.java b/src/main/java/org/betterx/betterend/integration/byg/biomes/OldBulbisGardens.java new file mode 100644 index 00000000..0d71d145 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/biomes/OldBulbisGardens.java @@ -0,0 +1,120 @@ +package org.betterx.betterend.integration.byg.biomes; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSpecialEffects; +import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; + +import org.betterx.bclib.BCLib; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.integration.byg.features.BYGFeatures; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.List; +import java.util.function.Supplier; + + +public class OldBulbisGardens extends EndBiome.Config { + public OldBulbisGardens() { + super("old_bulbis_gardens"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + Holder biome = Integrations.BYG.getBiome("bulbis_gardens"); + BiomeSpecialEffects effects = biome.value().getSpecialEffects(); + + Block ivis = Integrations.BYG.getBlock("ivis_phylium"); +// Block origin = biome.getGenerationSettings() +// .getSurfaceBuilderConfig() +// .getTopMaterial() +// .getBlock(); + builder.fogColor(215, 132, 207) + .fogDensity(1.8F) + .waterAndFogColor(40, 0, 56) + .foliageColor(122, 17, 155) + .particles( + ParticleTypes.REVERSE_PORTAL, + 0.002F + ) + //TODO: 1.18 surface rules + //.surface(ivis, origin) + .feature(EndFeatures.END_LAKE_RARE) + .feature(BYGFeatures.OLD_BULBIS_TREE); + + if (BCLib.isClient()) { + SoundEvent loop = effects.getAmbientLoopSoundEvent() + .get(); + SoundEvent music = effects.getBackgroundMusic() + .get() + .getEvent(); + SoundEvent additions = effects.getAmbientAdditionsSettings() + .get() + .getSoundEvent(); + SoundEvent mood = effects.getAmbientMoodSettings() + .get() + .getSoundEvent(); + builder.loop(loop) + .music(music) + .additions(additions) + .mood(mood); + } + + for (MobCategory group : MobCategory.values()) { + List list = biome.value() + .getMobSettings() + .getMobs(group) + .unwrap(); + list.forEach((entry) -> { + builder.spawn((EntityType) entry.type, 1, entry.minCount, entry.maxCount); + }); + } + + List> features = biome.value().getGenerationSettings() + .features(); + HolderSet vegetal = features.get(Decoration.VEGETAL_DECORATION.ordinal()); + if (vegetal.size() > 2) { + Supplier getter; + //TODO: 1.18.2 BRING BACK FEATURE COPY CODE + for (var placed : vegetal) { + System.out.print(placed); + } +// // Trees (first two features) +// // I couldn't process them with conditions, so that's why they are hardcoded (paulevs) +// for (int i = 0; i < 2; i++) { +// getter = vegetal.get(i); +// Holder feature = getter.get(); +// ResourceLocation id = BetterEnd.makeID("obg_feature_" + i); +// feature = Registry.register( +// BuiltinRegistries.PLACED_FEATURE, +// id, +// feature +// ); +// builder.feature(Decoration.VEGETAL_DECORATION, feature); +// } +// // Grasses and other features +// for (int i = 2; i < vegetal.size(); i++) { +// getter = vegetal.get(i); +// Holder feature = getter.get(); +// builder.feature(Decoration.VEGETAL_DECORATION, feature); +// } + } + + builder.feature(EndFeatures.PURPLE_POLYPORE) + .feature(BYGFeatures.IVIS_MOSS_WOOD) + .feature(BYGFeatures.IVIS_MOSS) + .feature(BYGFeatures.IVIS_VINE) + .feature(BYGFeatures.IVIS_SPROUT); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/features/BYGFeatures.java b/src/main/java/org/betterx/betterend/integration/byg/features/BYGFeatures.java new file mode 100644 index 00000000..e75a25bd --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/features/BYGFeatures.java @@ -0,0 +1,66 @@ +package org.betterx.betterend.integration.byg.features; + +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.features.BCLCommonFeatures; +import org.betterx.bclib.world.features.BCLFeature; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.integration.byg.BYGBlocks; +import org.betterx.betterend.world.features.SinglePlantFeature; +import org.betterx.betterend.world.features.VineFeature; +import org.betterx.betterend.world.features.WallPlantFeature; +import org.betterx.betterend.world.features.WallPlantOnLogFeature; + +public class BYGFeatures { + public static final BCLFeature OLD_BULBIS_TREE = redisterVegetation( + "old_bulbis_tree", + new OldBulbisTreeFeature(), + 1 + ); + public static final BCLFeature IVIS_SPROUT = redisterVegetation( + "ivis_sprout", + new SinglePlantFeature(Integrations.BYG.getBlock("ivis_sprout"), 6, 2), + 6 + ); + public static final BCLFeature IVIS_VINE = redisterVegetation( + "ivis_vine", + new VineFeature(BYGBlocks.IVIS_VINE, 24), + 5 + ); + public static final BCLFeature IVIS_MOSS = redisterVegetation( + "ivis_moss", + new WallPlantFeature(BYGBlocks.IVIS_MOSS, 6), + 1 + ); + public static final BCLFeature IVIS_MOSS_WOOD = redisterVegetation( + "ivis_moss_wood", + new WallPlantOnLogFeature(BYGBlocks.IVIS_MOSS, 6), + 15 + ); + public static final BCLFeature NIGHTSHADE_MOSS = redisterVegetation( + "nightshade_moss", + new WallPlantFeature(BYGBlocks.NIGHTSHADE_MOSS, 5), + 2 + ); + public static final BCLFeature NIGHTSHADE_MOSS_WOOD = redisterVegetation( + "nightshade_moss_wood", + new WallPlantOnLogFeature(BYGBlocks.NIGHTSHADE_MOSS, 5), + 8 + ); + + public static final BCLFeature NIGHTSHADE_REDWOOD_TREE = redisterVegetation( + "nightshade_redwood_tree", + new NightshadeRedwoodTreeFeature(), + 1 + ); + public static final BCLFeature BIG_ETHER_TREE = redisterVegetation("big_ether_tree", new BigEtherTreeFeature(), 1); + + public static void register() { + } + + private static BCLFeature redisterVegetation(String name, Feature feature, int density) { + return BCLCommonFeatures.makeVegetationFeature(BetterEnd.makeID(name), feature, density); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/features/BigEtherTreeFeature.java b/src/main/java/org/betterx/betterend/integration/byg/features/BigEtherTreeFeature.java new file mode 100644 index 00000000..dcc586a2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/features/BigEtherTreeFeature.java @@ -0,0 +1,80 @@ +package org.betterx.betterend.integration.byg.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.base.Function; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.integration.Integrations; + +import java.util.List; + +public class BigEtherTreeFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + + BlockState log = Integrations.BYG.getDefaultState("ether_log"); + BlockState wood = Integrations.BYG.getDefaultState("ether_wood"); + Function splinePlacer = (bpos) -> { + return log; + }; + Function replace = (state) -> { + return state.is(CommonBlockTags.END_STONES) || state.getMaterial() + .equals(Material.PLANT) || state.getMaterial() + .isReplaceable(); + }; + + int height = MHelper.randRange(40, 60, random); + List trunk = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, height / 4); + SplineHelper.offsetParts(trunk, random, 2F, 0, 2F); + SDF sdf = SplineHelper.buildSDF(trunk, 2.3F, 0.8F, splinePlacer); + + int count = height / 15; + for (int i = 1; i < count; i++) { + float splinePos = (float) i / (float) count; + float startAngle = random.nextFloat() * MHelper.PI2; + float length = (1 - splinePos) * height * 0.4F; + int points = (int) (length / 3); + List branch = SplineHelper.makeSpline(0, 0, 0, length, 0, 0, points < 2 ? 2 : points); + SplineHelper.powerOffset(branch, length, 2F); + int rotCount = MHelper.randRange(5, 7, random); + Vector3f start = SplineHelper.getPos(trunk, splinePos * (trunk.size() - 1)); + for (int j = 0; j < rotCount; j++) { + float angle = startAngle + (float) j / rotCount * MHelper.PI2; + List br = SplineHelper.copySpline(branch); + SplineHelper.offsetParts(br, random, 0, 1, 1); + SplineHelper.rotateSpline(br, angle); + + SplineHelper.offset(br, start); + SplineHelper.fillSpline(br, world, wood, pos, replace); + } + } + + sdf.setReplaceFunction((state) -> { + return state.is(CommonBlockTags.END_STONES) || state.getMaterial() + .equals(Material.PLANT) || state.getMaterial() + .isReplaceable(); + }).addPostProcess((info) -> { + if (info.getState().equals(log) && (!info.getStateUp().equals(log) || !info.getStateDown().equals(log))) { + return wood; + } + return info.getState(); + }).fillRecursive(world, pos); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java b/src/main/java/org/betterx/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java new file mode 100644 index 00000000..92253551 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java @@ -0,0 +1,200 @@ +package org.betterx.betterend.integration.byg.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFFlatWave; +import org.betterx.bclib.sdf.operator.SDFSmoothUnion; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.integration.Integrations; + +import java.util.List; + +public class NightshadeRedwoodTreeFeature extends DefaultFeature { + private static final List BRANCH; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + + BlockState log = Integrations.BYG.getDefaultState("nightshade_log"); + BlockState wood = Integrations.BYG.getDefaultState("nightshade_wood"); + BlockState leaves = Integrations.BYG.getDefaultState("nightshade_leaves"); + BlockState leaves_flower = Integrations.BYG.getDefaultState("flowering_nightshade_leaves"); + + Function splinePlacer = (bpos) -> { + return log; + }; + Function replace = (state) -> { + return state.is(CommonBlockTags.END_STONES) || state.getMaterial() + .equals(Material.PLANT) || state.getMaterial() + .isReplaceable(); + }; + Function post = (info) -> { + if (info.getState().equals(log) && (!info.getStateUp().equals(log) || !info.getStateDown().equals(log))) { + return wood; + } + return info.getState(); + }; + Function ignore = (state) -> { + return state.equals(log) || state.equals(wood); + }; + + int height = MHelper.randRange(40, 60, random); + List trunk = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, height / 4); + SplineHelper.offsetParts(trunk, random, 0.8F, 0, 0.8F); + + if (!SplineHelper.canGenerate(trunk, pos, world, replace)) { + return false; + } + + int count = height >> 2; + float start = trunk.size() / 3F; + float delta = trunk.size() * 0.6F; + float max = height - 7; + float startAngle = random.nextFloat() * MHelper.PI2; + for (int i = 0; i < count; i++) { + float scale = (float) (count - i) / count * 15; + Vector3f offset = SplineHelper.getPos(trunk, (float) i / count * delta + start); + if (offset.y() > max) { + break; + } + List branch = SplineHelper.copySpline(BRANCH); + SplineHelper.rotateSpline(branch, i * 1.3F + startAngle); + SplineHelper.scale(branch, scale); + SplineHelper.offsetParts(branch, random, 0.3F, 0.3F, 0.3F); + SplineHelper.offset(branch, offset); + SplineHelper.fillSpline(branch, world, wood, pos, replace); + } + + SDF sdf = SplineHelper.buildSDF(trunk, 2.3F, 0.8F, splinePlacer); + SDF roots = new SDFSphere().setRadius(2F).setBlock(log); + roots = new SDFFlatWave().setIntensity(2F) + .setRaysCount(MHelper.randRange(5, 7, random)) + .setAngle(random.nextFloat() * MHelper.PI2) + .setSource(roots); + sdf = new SDFSmoothUnion().setRadius(2F).setSourceA(sdf).setSourceB(roots); + sdf.setReplaceFunction(replace).addPostProcess(post).fillRecursive(world, pos); + Vector3f last = SplineHelper.getPos(trunk, trunk.size() - 1.35F); + for (int y = 0; y < 8; y++) { + BlockPos p = pos.offset(last.x() + 0.5, last.y() + y, last.z() + 0.5); + BlocksHelper.setWithoutUpdate(world, p, y == 4 ? wood : log); + } + + for (int y = 0; y < 16; y++) { + BlockPos p = pos.offset(last.x() + 0.5, last.y() + y, last.z() + 0.5); + if (world.isEmptyBlock(p)) { + BlocksHelper.setWithoutUpdate(world, p, leaves); + } + float radius = (1 - y / 16F) * 3F; + int rad = (int) (radius + 1); + radius *= radius; + for (int x = -rad; x <= rad; x++) { + int x2 = x * x; + for (int z = -rad; z <= rad; z++) { + int z2 = z * z; + if (x2 + z2 < radius - random.nextFloat() * rad) { + BlockPos lp = p.offset(x, 0, z); + if (world.isEmptyBlock(lp)) { + BlocksHelper.setWithoutUpdate(world, lp, leaves); + } + } + } + } + } + + MutableBlockPos mut = new MutableBlockPos(); + Function leavesPost1 = (info) -> { + if (info.getState().equals(log) || info.getState().equals(wood)) { + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }; + Function leavesPost2 = (info) -> { + if (info.getState().getBlock() instanceof LeavesBlock) { + int distance = info.getState().getValue(LeavesBlock.DISTANCE); + if (distance > MHelper.randRange(2, 4, random)) { + return Blocks.AIR.defaultBlockState(); + } + for (Direction d : BlocksHelper.DIRECTIONS) { + int airCount = 0; + if (info.getState(d).isAir()) { + airCount++; + } + if (airCount > 5) { + return Blocks.AIR.defaultBlockState(); + } + } + if (random.nextInt(8) == 0) { + return leaves_flower.setValue(LeavesBlock.DISTANCE, distance); + } + } + return info.getState(); + }; + + SDF canopy = new SDFCappedCone().setRadius1(12F).setRadius2(1f).setHeight(height * 0.3F).setBlock(leaves); + canopy = new SDFDisplacement().setFunction((vec) -> { + return MHelper.randRange(-3F, 3F, random); + }).setSource(canopy); + canopy.addPostProcess(leavesPost1) + .addPostProcess(leavesPost2) + .fillRecursiveIgnore(world, pos.offset(0, height * 0.75, 0), ignore); + + return true; + } + + static { + BRANCH = Lists.newArrayList( + new Vector3f(0, 0, 0), + new Vector3f(0.25F, 0.1F, 0), + new Vector3f(0.40F, 0.2F, 0), + new Vector3f(0.50F, 0.4F, 0), + new Vector3f(0.55F, 0.6F, 0) + ); + } +} diff --git a/src/main/java/org/betterx/betterend/integration/byg/features/OldBulbisTreeFeature.java b/src/main/java/org/betterx/betterend/integration/byg/features/OldBulbisTreeFeature.java new file mode 100644 index 00000000..d16e69d5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/byg/features/OldBulbisTreeFeature.java @@ -0,0 +1,214 @@ +package org.betterx.betterend.integration.byg.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.AABB; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.operator.SDFUnion; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.integration.Integrations; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.List; +import java.util.function.Function; + +public class OldBulbisTreeFeature extends DefaultFeature { + private static final List SPLINE; + private static final List ROOT; + private static final List LEAF; + private static final List SIDE; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + if (!world.getBlockState(pos.below(4)).is(CommonBlockTags.GEN_END_STONES)) return false; + + BlockState stem = Integrations.BYG.getDefaultState("bulbis_stem"); + BlockState wood = Integrations.BYG.getDefaultState("bulbis_wood"); + BlockState cap = Integrations.BYG.getDefaultState(random.nextBoolean() + ? "bulbis_shell" + : "purple_bulbis_shell"); + BlockState glow = Integrations.BYG.getDefaultState("purple_shroomlight"); + + Function replacement = (state) -> { + if (state.equals(stem) || state.equals(wood) || state.is(CommonBlockTags.END_STONES) || state.getMaterial() + .equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + float size = MHelper.randRange(10, 20, random); + float addSize = MHelper.randRange(1, 1.7F, random); + float addRad = addSize * 0.5F + 0.5F; + int count = (int) (size * 0.15F); + size *= addSize; + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + SDF sdf = null; + int x1 = ((pos.getX() >> 4) << 4) - 16; + int z1 = ((pos.getZ() >> 4) << 4) - 16; + AABB limits = new AABB(x1, pos.getY() - 5, z1, x1 + 47, pos.getY() + size * 2, z1 + 47); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + float sizeXZ = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.7F; + SplineHelper.scale(spline, sizeXZ, sizeXZ * 1.5F + MHelper.randRange(0, size * 0.5F, random), sizeXZ); + SplineHelper.offset(spline, new Vector3f(size * random.nextFloat() * 0.3F, 0, 0)); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F);// 1.3F 0.8F + SDF branch = SplineHelper.buildSDF(spline, 2.3F * addRad, 1.3F * addRad, (bpos) -> { + return stem; + }); + + Vector3f vec = spline.get(spline.size() - 1); + float radius = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.35F; + bigSphere(world, pos.offset(vec.x(), vec.y(), vec.z()), radius, cap, glow, wood, replacement, random); + vec = SplineHelper.getPos(spline, 0.3F); + makeRoots(world, pos.offset(vec.x(), vec.y(), vec.z()), size * 0.4F + 5, random, wood, replacement); + + sdf = (sdf == null) ? branch : new SDFUnion().setSourceA(sdf).setSourceB(branch); + } + + sdf.setReplaceFunction(replacement).addPostProcess((info) -> { + if (info.getState().equals(stem) && (!info.getStateUp().equals(stem) || !info.getStateDown() + .equals(stem))) { + return wood; + } + return info.getState(); + }).fillArea(world, pos, limits); + + return true; + } + + private void bigSphere(WorldGenLevel world, + BlockPos pos, + float radius, + BlockState cap, + BlockState glow, + BlockState wood, + Function replacement, + RandomSource random) { + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + SDF sphere = new SDFSphere().setRadius(radius).setBlock(cap); + + SDF sphereInner = new SDFSphere().setRadius(radius * 0.53F).setBlock(Blocks.AIR); + sphereInner = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); + }).setSource(sphereInner); + + SDF sphereGlow = new SDFSphere().setRadius(radius * 0.6F).setBlock(glow); + sphereGlow = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1) * 2F; + }).setSource(sphereGlow); + sphereGlow = new SDFSubtraction().setSourceA(sphereGlow).setSourceB(sphereInner); + + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sphereGlow); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sphereInner); + + float offsetY = radius * 1.7F; + sphere = new SDFUnion().setSourceA(sphere).setSourceB(sphereGlow); + sphere = new SDFTranslate().setTranslate(0, offsetY, 0).setSource(sphere); + + int leafCount = (int) (radius * 0.5F) + 2; + for (int i = 0; i < 4; i++) { + float angle = (float) i / 4 * MHelper.PI2; + List spline = SplineHelper.copySpline(LEAF); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.scale(spline, radius * 1.4F); + SplineHelper.fillSplineForce(spline, world, wood, pos, replacement); + + for (int j = 0; j < leafCount; j++) { + float delta = ((float) j / (float) (leafCount - 1)); + float scale = (float) Math.sin(delta * Math.PI) * 0.8F + 0.2F; + float index = Mth.lerp(delta, 1F, 3.9F); + Vector3f point = SplineHelper.getPos(spline, index); + + List side = SplineHelper.copySpline(SIDE); + SplineHelper.rotateSpline(side, angle); + SplineHelper.scale(side, scale * radius); + BlockPos p = pos.offset(point.x() + 0.5F, point.y() + 0.5F, point.z() + 0.5F); + SplineHelper.fillSplineForce(side, world, wood, p, replacement); + } + } + + sphere.fillArea(world, pos, new AABB(pos.above((int) offsetY)).inflate(radius * 1.3F)); + } + + private void makeRoots(WorldGenLevel world, + BlockPos pos, + float radius, + RandomSource random, + BlockState wood, + Function replacement) { + int count = (int) (radius * 1.5F); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(ROOT); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + Vector3f last = branch.get(branch.size() - 1); + if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { + SplineHelper.fillSpline(branch, world, wood, pos, replacement); + } + } + } + + static { + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); + + ROOT = Lists.newArrayList( + new Vector3f(0F, 1F, 0), + new Vector3f(0.1F, 0.70F, 0), + new Vector3f(0.3F, 0.30F, 0), + new Vector3f(0.7F, 0.05F, 0), + new Vector3f(0.8F, -0.20F, 0) + ); + SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); + + LEAF = Lists.newArrayList( + new Vector3f(0.00F, 0.0F, 0), + new Vector3f(0.10F, 0.4F, 0), + new Vector3f(0.40F, 0.8F, 0), + new Vector3f(0.75F, 0.9F, 0), + new Vector3f(1.00F, 0.8F, 0) + ); + + SIDE = Lists.newArrayList( + new Vector3f(0, -0.3F, -0.5F), + new Vector3f(0, -0.1F, -0.3F), + new Vector3f(0, 0.0F, 0.0F), + new Vector3f(0, -0.1F, 0.3F), + new Vector3f(0, -0.3F, 0.5F) + ); + } +} diff --git a/src/main/java/ru/betterend/integration/rei/REIAlloyingCategory.java b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingCategory.java similarity index 96% rename from src/main/java/ru/betterend/integration/rei/REIAlloyingCategory.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAlloyingCategory.java index 6fb5112f..a33b2178 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAlloyingCategory.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingCategory.java @@ -1,118 +1,118 @@ -package ru.betterend.integration.rei; - -/* -import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; -import it.unimi.dsi.fastutil.ints.IntList; -import me.shedaniel.math.Point; -import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; -import me.shedaniel.rei.api.client.registry.display.DisplayCategory; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.entry.EntryStack; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.network.chat.Component; - -import org.jetbrains.annotations.NotNull; -import ru.betterend.registry.EndBlocks; - -import java.text.DecimalFormat; -import java.util.List; - -public class REIAlloyingCategory implements DisplayCategory { - private final EntryStack ICON; - - REIAlloyingCategory(EntryStack icon) { - ICON = icon; - } - - @Override - public @NotNull CategoryIdentifier getCategoryIdentifier() { - return REIPlugin.ALLOYING; - } - - @Override - public @NotNull Component getTitle() { - return Component.translatable(EndBlocks.END_STONE_SMELTER.getDescriptionId()); - } - - @Override - public @NotNull EntryStack getIcon() { - return ICON; - } - - @Override - public @NotNull List setupDisplay(REIAlloyingDisplay display, Rectangle bounds) { - Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10); - double smeltTime = display.getSmeltTime(); - DecimalFormat df = new DecimalFormat("###.##"); - List widgets = Lists.newArrayList(); - widgets.add(Widgets.createRecipeBase(bounds)); - widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 9))); - widgets.add(Widgets.createBurningFire(new Point(startPoint.x - 9, startPoint.y + 20)) - .animationDurationMS(10000)); - widgets.add(Widgets.createLabel( - new Point(bounds.x + bounds.width - 5, bounds.y + 5), - Component.translatable("category.rei.cooking.time&xp", - df.format(display.getXp()), - df.format(smeltTime / 20D) - ) - ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); - widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)) - .animationDurationTicks(smeltTime)); - List inputEntries = display.getInputEntries(); - widgets.add(Widgets.createSlot(new Point(startPoint.x - 20, startPoint.y + 1)) - .entries(inputEntries.get(0)) - .markInput()); - if (inputEntries.size() > 1) { - widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)) - .entries(inputEntries.get(1)) - .markInput()); - } - else { - widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)) - .entries(Lists.newArrayList()) - .markInput()); - } - widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)) - .entries(display.getOutputEntries().get(0)) - .disableBackground() - .markOutput()); - return widgets; - } - - //TODO: 1.18 REI find replacement - //@Override - public void renderRedSlots(PoseStack matrices, List widgets, Rectangle bounds, REIAlloyingDisplay display, IntList redSlots) { - Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27); - matrices.pushPose(); - matrices.translate(0, 0, 400); - if (redSlots.contains(0)) { - GuiComponent.fill( - matrices, - startPoint.x - 20, - startPoint.y + 1, - startPoint.x - 20 + 16, - startPoint.y + 1 + 16, - 1090453504 - ); - GuiComponent.fill( - matrices, - startPoint.x + 1, - startPoint.y + 1, - startPoint.x + 1 + 16, - startPoint.y + 1 + 16, - 1090453504 - ); - } - matrices.popPose(); - } - - @Override - public int getDisplayHeight() { - return 49; - } -} +package org.betterx.betterend.integration.rei; + +/* +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.ints.IntList; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; +import ru.betterend.registry.EndBlocks; + +import java.text.DecimalFormat; +import java.util.List; + +public class REIAlloyingCategory implements DisplayCategory { + private final EntryStack ICON; + + REIAlloyingCategory(EntryStack icon) { + ICON = icon; + } + + @Override + public @NotNull CategoryIdentifier getCategoryIdentifier() { + return REIPlugin.ALLOYING; + } + + @Override + public @NotNull Component getTitle() { + return Component.translatable(EndBlocks.END_STONE_SMELTER.getDescriptionId()); + } + + @Override + public @NotNull EntryStack getIcon() { + return ICON; + } + + @Override + public @NotNull List setupDisplay(REIAlloyingDisplay display, Rectangle bounds) { + Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10); + double smeltTime = display.getSmeltTime(); + DecimalFormat df = new DecimalFormat("###.##"); + List widgets = Lists.newArrayList(); + widgets.add(Widgets.createRecipeBase(bounds)); + widgets.add(Widgets.createResultSlotBackground(new Point(startPoint.x + 61, startPoint.y + 9))); + widgets.add(Widgets.createBurningFire(new Point(startPoint.x - 9, startPoint.y + 20)) + .animationDurationMS(10000)); + widgets.add(Widgets.createLabel( + new Point(bounds.x + bounds.width - 5, bounds.y + 5), + Component.translatable("category.rei.cooking.time&xp", + df.format(display.getXp()), + df.format(smeltTime / 20D) + ) + ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); + widgets.add(Widgets.createArrow(new Point(startPoint.x + 24, startPoint.y + 8)) + .animationDurationTicks(smeltTime)); + List inputEntries = display.getInputEntries(); + widgets.add(Widgets.createSlot(new Point(startPoint.x - 20, startPoint.y + 1)) + .entries(inputEntries.get(0)) + .markInput()); + if (inputEntries.size() > 1) { + widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)) + .entries(inputEntries.get(1)) + .markInput()); + } + else { + widgets.add(Widgets.createSlot(new Point(startPoint.x + 1, startPoint.y + 1)) + .entries(Lists.newArrayList()) + .markInput()); + } + widgets.add(Widgets.createSlot(new Point(startPoint.x + 61, startPoint.y + 9)) + .entries(display.getOutputEntries().get(0)) + .disableBackground() + .markOutput()); + return widgets; + } + + //TODO: 1.18 REI find replacement + //@Override + public void renderRedSlots(PoseStack matrices, List widgets, Rectangle bounds, REIAlloyingDisplay display, IntList redSlots) { + Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27); + matrices.pushPose(); + matrices.translate(0, 0, 400); + if (redSlots.contains(0)) { + GuiComponent.fill( + matrices, + startPoint.x - 20, + startPoint.y + 1, + startPoint.x - 20 + 16, + startPoint.y + 1 + 16, + 1090453504 + ); + GuiComponent.fill( + matrices, + startPoint.x + 1, + startPoint.y + 1, + startPoint.x + 1 + 16, + startPoint.y + 1 + 16, + 1090453504 + ); + } + matrices.popPose(); + } + + @Override + public int getDisplayHeight() { + return 49; + } +} */ \ No newline at end of file diff --git a/src/main/java/ru/betterend/integration/rei/REIAlloyingDisplay.java b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingDisplay.java similarity index 98% rename from src/main/java/ru/betterend/integration/rei/REIAlloyingDisplay.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAlloyingDisplay.java index 0c714110..4c4ed565 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAlloyingDisplay.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingDisplay.java @@ -1,4 +1,4 @@ -package ru.betterend.integration.rei; +package org.betterx.betterend.integration.rei; /* import me.shedaniel.rei.api.common.category.CategoryIdentifier; diff --git a/src/main/java/ru/betterend/integration/rei/REIAlloyingFuelCategory.java b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelCategory.java similarity index 96% rename from src/main/java/ru/betterend/integration/rei/REIAlloyingFuelCategory.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelCategory.java index 4ba94b9e..0daa6d1b 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAlloyingFuelCategory.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelCategory.java @@ -1,108 +1,108 @@ -package ru.betterend.integration.rei; -/* -import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.math.Point; -import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.client.gui.DisplayRenderer; -import me.shedaniel.rei.api.client.gui.widgets.Slot; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; -import me.shedaniel.rei.api.client.registry.display.DisplayCategory; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.util.EntryStacks; -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; - -import net.minecraft.world.item.Items; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.text.DecimalFormat; -import java.util.List; - -public class REIAlloyingFuelCategory implements DisplayCategory { - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); - - @Override - public @NotNull CategoryIdentifier getCategoryIdentifier() { - return REIPlugin.ALLOYING_FUEL; - } - - @Override - public @NotNull Component getTitle() { - return Component.translatable("category.rei.fuel"); - } - - @Override - public int getDisplayHeight() { - return 49; - } - - @Override - public @NotNull EntryStack getIcon() { - return EntryStacks.of(Items.COAL); - } - - @Override - public List setupDisplay(REIAlloyingFuelDisplay recipeDisplay, Rectangle bounds) { - Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 17); - String burnTime = DECIMAL_FORMAT.format(recipeDisplay.getFuelTime()); - List widgets = Lists.newArrayList(); - widgets.add(Widgets.createRecipeBase(bounds)); - widgets.add(Widgets.createLabel( - new Point(bounds.x + 26, bounds.getMaxY() - 15), - Component.translatable("category.rei.fuel.time", burnTime) - ).color(0xFF404040, 0xFFBBBBBB).noShadow().leftAligned()); - widgets.add(Widgets.createBurningFire(new Point(bounds.x + 6, startPoint.y + 1)) - .animationDurationTicks(recipeDisplay.getFuelTime())); - widgets.add(Widgets.createSlot(new Point(bounds.x + 6, startPoint.y + 18)) - .entries(recipeDisplay.getInputEntries().get(0)) - .markInput()); - return widgets; - } - - @Override - public DisplayRenderer getDisplayRenderer(REIAlloyingFuelDisplay recipe) { - Slot slot = Widgets.createSlot(new Point(0, 0)) - .entries(recipe.getInputEntries().get(0)) - .disableBackground() - .disableHighlight(); - String burnItems = DECIMAL_FORMAT.format(recipe.getFuelTime() / 200d); - return new DisplayRenderer() { - private TranslatableComponent text = Component.translatable( - "category.rei.fuel.time_short.items", - burnItems - ); - - @Override - public int getHeight() { - return 22; - } - - @Nullable - @Override - public Tooltip getTooltip(Point point) { - if (slot.containsMouse(point)) return slot.getCurrentTooltip(point); - return null; - } - - @Override - public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { - slot.setZ(getZ() + 50); - slot.getBounds().setLocation(bounds.x + 4, bounds.y + 2); - slot.render(matrices, mouseX, mouseY, delta); - Minecraft.getInstance().font.drawShadow( - matrices, - text.getVisualOrderText(), - bounds.x + 25, - bounds.y + 8, - -1 - ); - } - }; - } -} +package org.betterx.betterend.integration.rei; +/* +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.DisplayRenderer; +import me.shedaniel.rei.api.client.gui.widgets.Slot; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; + +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.text.DecimalFormat; +import java.util.List; + +public class REIAlloyingFuelCategory implements DisplayCategory { + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); + + @Override + public @NotNull CategoryIdentifier getCategoryIdentifier() { + return REIPlugin.ALLOYING_FUEL; + } + + @Override + public @NotNull Component getTitle() { + return Component.translatable("category.rei.fuel"); + } + + @Override + public int getDisplayHeight() { + return 49; + } + + @Override + public @NotNull EntryStack getIcon() { + return EntryStacks.of(Items.COAL); + } + + @Override + public List setupDisplay(REIAlloyingFuelDisplay recipeDisplay, Rectangle bounds) { + Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 17); + String burnTime = DECIMAL_FORMAT.format(recipeDisplay.getFuelTime()); + List widgets = Lists.newArrayList(); + widgets.add(Widgets.createRecipeBase(bounds)); + widgets.add(Widgets.createLabel( + new Point(bounds.x + 26, bounds.getMaxY() - 15), + Component.translatable("category.rei.fuel.time", burnTime) + ).color(0xFF404040, 0xFFBBBBBB).noShadow().leftAligned()); + widgets.add(Widgets.createBurningFire(new Point(bounds.x + 6, startPoint.y + 1)) + .animationDurationTicks(recipeDisplay.getFuelTime())); + widgets.add(Widgets.createSlot(new Point(bounds.x + 6, startPoint.y + 18)) + .entries(recipeDisplay.getInputEntries().get(0)) + .markInput()); + return widgets; + } + + @Override + public DisplayRenderer getDisplayRenderer(REIAlloyingFuelDisplay recipe) { + Slot slot = Widgets.createSlot(new Point(0, 0)) + .entries(recipe.getInputEntries().get(0)) + .disableBackground() + .disableHighlight(); + String burnItems = DECIMAL_FORMAT.format(recipe.getFuelTime() / 200d); + return new DisplayRenderer() { + private TranslatableComponent text = Component.translatable( + "category.rei.fuel.time_short.items", + burnItems + ); + + @Override + public int getHeight() { + return 22; + } + + @Nullable + @Override + public Tooltip getTooltip(Point point) { + if (slot.containsMouse(point)) return slot.getCurrentTooltip(point); + return null; + } + + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + slot.setZ(getZ() + 50); + slot.getBounds().setLocation(bounds.x + 4, bounds.y + 2); + slot.render(matrices, mouseX, mouseY, delta); + Minecraft.getInstance().font.drawShadow( + matrices, + text.getVisualOrderText(), + bounds.x + 25, + bounds.y + 8, + -1 + ); + } + }; + } +} */ \ No newline at end of file diff --git a/src/main/java/ru/betterend/integration/rei/REIAlloyingFuelDisplay.java b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelDisplay.java similarity index 95% rename from src/main/java/ru/betterend/integration/rei/REIAlloyingFuelDisplay.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelDisplay.java index cb5c3221..36287722 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAlloyingFuelDisplay.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAlloyingFuelDisplay.java @@ -1,4 +1,4 @@ -package ru.betterend.integration.rei; +package org.betterx.betterend.integration.rei; /* import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.basic.BasicDisplay; diff --git a/src/main/java/ru/betterend/integration/rei/REIAnvilCategory.java b/src/main/java/org/betterx/betterend/integration/rei/REIAnvilCategory.java similarity index 96% rename from src/main/java/ru/betterend/integration/rei/REIAnvilCategory.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAnvilCategory.java index 15369ee3..90520e15 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAnvilCategory.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAnvilCategory.java @@ -1,122 +1,122 @@ -package ru.betterend.integration.rei; -/* -import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; -import it.unimi.dsi.fastutil.ints.IntList; -import me.shedaniel.math.Point; -import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; -import me.shedaniel.rei.api.client.registry.display.DisplayCategory; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.entry.EntryStack; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.network.chat.Component; - -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import org.jetbrains.annotations.NotNull; -import ru.betterend.blocks.basis.EndAnvilBlock; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class REIAnvilCategory implements DisplayCategory { - private final EntryStack[] ANVILS; - - REIAnvilCategory(EntryStack[] anvils) { - ANVILS = anvils; - } - - @Override - public CategoryIdentifier getCategoryIdentifier() { - return REIPlugin.SMITHING; - } - - @Override - public @NotNull Component getTitle() { - return Component.translatable(Blocks.ANVIL.getDescriptionId()); - } - - @Override - public @NotNull EntryStack getIcon() { - return ANVILS[0]; - } - - - @Override - public @NotNull List setupDisplay(REIAnvilDisplay display, Rectangle bounds) { - Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10); - List widgets = Lists.newArrayList(); - widgets.add(Widgets.createRecipeBase(bounds)); - int x = startPoint.x + 10; - int y = startPoint.y; - widgets.add(Widgets.createResultSlotBackground(new Point(x + 61, y + 5))); - List inputEntries = display.getInputEntries(); - EntryIngredient materials = inputEntries.get(1); - int anvilLevel = display.getAnvilLevel(); - List> anvils = Arrays.stream(ANVILS).filter(anvil -> { - Object value = anvil.getValue(); - if (value instanceof ItemStack) { - value = ((ItemStack) value).getItem(); - } - Block block = ((BlockItem) value).getBlock(); - if (block instanceof EndAnvilBlock) { - return ((EndAnvilBlock) block).getCraftingLevel() >= anvilLevel; - } - return anvilLevel == 1; - }).collect(Collectors.toList()); - widgets.add(Widgets.createArrow(new Point(x + 24, y + 4))); - widgets.add(Widgets.createLabel( - new Point(bounds.x + bounds.width - 7, bounds.y + bounds.height - 15), - Component.translatable("category.rei.damage.amount&dmg", display.getDamage()) - ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); - widgets.add(Widgets.createSlot(new Point(x - 20, y + 4)).entries(materials).markInput()); - widgets.add(Widgets.createSlot(new Point(x + 1, y + 4)).entries(inputEntries.get(0)).markInput()); - widgets.add(Widgets.createSlot(new Point(x + 61, y + 5)) - .entries(display.getOutputEntries().get(0)) - .disableBackground() - .markOutput()); - widgets.add(Widgets.createSlot(new Point(x - 9, y + 25)).entries(anvils)); - - return widgets; - } - - //TODO: 1.18 REI, find replacement - //@Override - public void renderRedSlots(PoseStack matrices, List widgets, Rectangle bounds, REIAnvilDisplay display, IntList redSlots) { - Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27); - matrices.pushPose(); - matrices.translate(0, 0, 400); - if (redSlots.contains(0)) { - GuiComponent.fill( - matrices, - startPoint.x - 20, - startPoint.y + 3, - startPoint.x - 20 + 16, - startPoint.y + 3 + 16, - 1090453504 - ); - GuiComponent.fill( - matrices, - startPoint.x + 1, - startPoint.y + 3, - startPoint.x + 1 + 16, - startPoint.y + 3 + 16, - 1090453504 - ); - } - matrices.popPose(); - } - - @Override - public int getDisplayHeight() { - return 60; - } - -} +package org.betterx.betterend.integration.rei; +/* +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.ints.IntList; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.network.chat.Component; + +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import org.jetbrains.annotations.NotNull; +import ru.betterend.blocks.basis.EndAnvilBlock; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class REIAnvilCategory implements DisplayCategory { + private final EntryStack[] ANVILS; + + REIAnvilCategory(EntryStack[] anvils) { + ANVILS = anvils; + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return REIPlugin.SMITHING; + } + + @Override + public @NotNull Component getTitle() { + return Component.translatable(Blocks.ANVIL.getDescriptionId()); + } + + @Override + public @NotNull EntryStack getIcon() { + return ANVILS[0]; + } + + + @Override + public @NotNull List setupDisplay(REIAnvilDisplay display, Rectangle bounds) { + Point startPoint = new Point(bounds.getCenterX() - 41, bounds.y + 10); + List widgets = Lists.newArrayList(); + widgets.add(Widgets.createRecipeBase(bounds)); + int x = startPoint.x + 10; + int y = startPoint.y; + widgets.add(Widgets.createResultSlotBackground(new Point(x + 61, y + 5))); + List inputEntries = display.getInputEntries(); + EntryIngredient materials = inputEntries.get(1); + int anvilLevel = display.getAnvilLevel(); + List> anvils = Arrays.stream(ANVILS).filter(anvil -> { + Object value = anvil.getValue(); + if (value instanceof ItemStack) { + value = ((ItemStack) value).getItem(); + } + Block block = ((BlockItem) value).getBlock(); + if (block instanceof EndAnvilBlock) { + return ((EndAnvilBlock) block).getCraftingLevel() >= anvilLevel; + } + return anvilLevel == 1; + }).collect(Collectors.toList()); + widgets.add(Widgets.createArrow(new Point(x + 24, y + 4))); + widgets.add(Widgets.createLabel( + new Point(bounds.x + bounds.width - 7, bounds.y + bounds.height - 15), + Component.translatable("category.rei.damage.amount&dmg", display.getDamage()) + ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); + widgets.add(Widgets.createSlot(new Point(x - 20, y + 4)).entries(materials).markInput()); + widgets.add(Widgets.createSlot(new Point(x + 1, y + 4)).entries(inputEntries.get(0)).markInput()); + widgets.add(Widgets.createSlot(new Point(x + 61, y + 5)) + .entries(display.getOutputEntries().get(0)) + .disableBackground() + .markOutput()); + widgets.add(Widgets.createSlot(new Point(x - 9, y + 25)).entries(anvils)); + + return widgets; + } + + //TODO: 1.18 REI, find replacement + //@Override + public void renderRedSlots(PoseStack matrices, List widgets, Rectangle bounds, REIAnvilDisplay display, IntList redSlots) { + Point startPoint = new Point(bounds.getCenterX() - 41, bounds.getCenterY() - 27); + matrices.pushPose(); + matrices.translate(0, 0, 400); + if (redSlots.contains(0)) { + GuiComponent.fill( + matrices, + startPoint.x - 20, + startPoint.y + 3, + startPoint.x - 20 + 16, + startPoint.y + 3 + 16, + 1090453504 + ); + GuiComponent.fill( + matrices, + startPoint.x + 1, + startPoint.y + 3, + startPoint.x + 1 + 16, + startPoint.y + 3 + 16, + 1090453504 + ); + } + matrices.popPose(); + } + + @Override + public int getDisplayHeight() { + return 60; + } + +} */ \ No newline at end of file diff --git a/src/main/java/ru/betterend/integration/rei/REIAnvilDisplay.java b/src/main/java/org/betterx/betterend/integration/rei/REIAnvilDisplay.java similarity index 94% rename from src/main/java/ru/betterend/integration/rei/REIAnvilDisplay.java rename to src/main/java/org/betterx/betterend/integration/rei/REIAnvilDisplay.java index addf055b..ea5aab0c 100644 --- a/src/main/java/ru/betterend/integration/rei/REIAnvilDisplay.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIAnvilDisplay.java @@ -1,4 +1,4 @@ -package ru.betterend.integration.rei; +package org.betterx.betterend.integration.rei; /* import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.SimpleGridMenuDisplay; @@ -8,7 +8,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import org.jetbrains.annotations.NotNull; -import ru.bclib.recipes.AnvilRecipe; +import org.betterx.bclib.recipes.AnvilRecipe; import java.util.Collections; import java.util.Optional; diff --git a/src/main/java/ru/betterend/integration/rei/REIBlastingDisplay.java b/src/main/java/org/betterx/betterend/integration/rei/REIBlastingDisplay.java similarity index 84% rename from src/main/java/ru/betterend/integration/rei/REIBlastingDisplay.java rename to src/main/java/org/betterx/betterend/integration/rei/REIBlastingDisplay.java index 457b973f..f59b632f 100644 --- a/src/main/java/ru/betterend/integration/rei/REIBlastingDisplay.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIBlastingDisplay.java @@ -1,4 +1,4 @@ -package ru.betterend.integration.rei; +package org.betterx.betterend.integration.rei; /* import net.minecraft.world.item.crafting.BlastingRecipe; diff --git a/src/main/java/org/betterx/betterend/integration/rei/REIContainer.java b/src/main/java/org/betterx/betterend/integration/rei/REIContainer.java new file mode 100644 index 00000000..c715eccd --- /dev/null +++ b/src/main/java/org/betterx/betterend/integration/rei/REIContainer.java @@ -0,0 +1,9 @@ +package org.betterx.betterend.integration.rei; + +public class REIContainer implements Runnable { + + @Override + public void run() { + //ContainerInfoHandler.registerContainerInfo(AlloyingRecipe.ID, CraftingContainerInfoWrapper.create(EndStoneSmelterScreenHandler.class)); + } +} diff --git a/src/main/java/ru/betterend/integration/rei/REIInfusionCategory.java b/src/main/java/org/betterx/betterend/integration/rei/REIInfusionCategory.java similarity index 95% rename from src/main/java/ru/betterend/integration/rei/REIInfusionCategory.java rename to src/main/java/org/betterx/betterend/integration/rei/REIInfusionCategory.java index fc3e7b3e..a3bf48e4 100644 --- a/src/main/java/ru/betterend/integration/rei/REIInfusionCategory.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIInfusionCategory.java @@ -1,111 +1,111 @@ -package ru.betterend.integration.rei; -/* -import com.google.common.collect.Lists; -import me.shedaniel.math.Point; -import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; -import me.shedaniel.rei.api.client.registry.display.DisplayCategory; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.entry.EntryStack; -import net.minecraft.network.chat.Component; - -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndBlocks; - -import java.util.ArrayList; -import java.util.List; - -public class REIInfusionCategory implements DisplayCategory { - - private final static ResourceLocation BACKGROUND = BetterEnd.makeID("textures/gui/rei_infusion.png"); - private final EntryStack ICON; - - REIInfusionCategory(EntryStack icon) { - ICON = icon; - } - - @Override - public @NotNull CategoryIdentifier getCategoryIdentifier() { - return REIPlugin.INFUSION; - } - - @Override - public @NotNull Component getTitle() { - return Component.translatable(EndBlocks.INFUSION_PEDESTAL.getDescriptionId()); - } - - @Override - public @NotNull EntryStack getIcon() { - return ICON; - } - - @Override - public @NotNull List setupDisplay(REIInfusionDisplay display, Rectangle bounds) { - Point centerPoint = new Point(bounds.getCenterX() - 34, bounds.getCenterY() - 2); - List widgets = Lists.newArrayList(); - widgets.add(Widgets.createRecipeBase(bounds)); - List inputEntries = display.getInputEntries(); - List outputEntries = display.getOutputEntries(); - if (inputEntries.size() < 9) { - List newList = new ArrayList(9); - newList.addAll(inputEntries); - for (int i = inputEntries.size(); i < 9; i++) { - newList.add(EntryIngredient.empty()); - } - inputEntries = newList; - } - widgets.add(Widgets.createTexturedWidget(BACKGROUND, bounds.x, bounds.y, 0, 0, 150, 104, 150, 104)); - widgets.add(Widgets.createSlot(centerPoint).entries(inputEntries.get(0)).disableBackground().markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x, centerPoint.y - 28)) - .entries(inputEntries.get(1)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x + 28, centerPoint.y)) - .entries(inputEntries.get(3)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x, centerPoint.y + 28)) - .entries(inputEntries.get(5)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x - 28, centerPoint.y)) - .entries(inputEntries.get(7)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x + 24, centerPoint.y - 24)) - .entries(inputEntries.get(2)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x + 24, centerPoint.y + 24)) - .entries(inputEntries.get(4)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x - 24, centerPoint.y + 24)) - .entries(inputEntries.get(6)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x - 24, centerPoint.y - 24)) - .entries(inputEntries.get(8)) - .disableBackground() - .markInput()); - widgets.add(Widgets.createSlot(new Point(centerPoint.x + 80, centerPoint.y)) - .entries(outputEntries.get(0)) - .disableBackground() - .markOutput()); - widgets.add(Widgets.createLabel( - new Point(bounds.getMaxX() - 5, bounds.y + 6), - Component.translatable("category.rei.infusion.time&val", display.getInfusionTime()) - ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); - return widgets; - } - - @Override - public int getDisplayHeight() { - return 104; - } -} - */ +package org.betterx.betterend.integration.rei; +/* +import com.google.common.collect.Lists; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import net.minecraft.network.chat.Component; + +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; +import org.betterx.betterend.BetterEnd; +import ru.betterend.registry.EndBlocks; + +import java.util.ArrayList; +import java.util.List; + +public class REIInfusionCategory implements DisplayCategory { + + private final static ResourceLocation BACKGROUND = BetterEnd.makeID("textures/gui/rei_infusion.png"); + private final EntryStack ICON; + + REIInfusionCategory(EntryStack icon) { + ICON = icon; + } + + @Override + public @NotNull CategoryIdentifier getCategoryIdentifier() { + return REIPlugin.INFUSION; + } + + @Override + public @NotNull Component getTitle() { + return Component.translatable(EndBlocks.INFUSION_PEDESTAL.getDescriptionId()); + } + + @Override + public @NotNull EntryStack getIcon() { + return ICON; + } + + @Override + public @NotNull List setupDisplay(REIInfusionDisplay display, Rectangle bounds) { + Point centerPoint = new Point(bounds.getCenterX() - 34, bounds.getCenterY() - 2); + List widgets = Lists.newArrayList(); + widgets.add(Widgets.createRecipeBase(bounds)); + List inputEntries = display.getInputEntries(); + List outputEntries = display.getOutputEntries(); + if (inputEntries.size() < 9) { + List newList = new ArrayList(9); + newList.addAll(inputEntries); + for (int i = inputEntries.size(); i < 9; i++) { + newList.add(EntryIngredient.empty()); + } + inputEntries = newList; + } + widgets.add(Widgets.createTexturedWidget(BACKGROUND, bounds.x, bounds.y, 0, 0, 150, 104, 150, 104)); + widgets.add(Widgets.createSlot(centerPoint).entries(inputEntries.get(0)).disableBackground().markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x, centerPoint.y - 28)) + .entries(inputEntries.get(1)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x + 28, centerPoint.y)) + .entries(inputEntries.get(3)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x, centerPoint.y + 28)) + .entries(inputEntries.get(5)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x - 28, centerPoint.y)) + .entries(inputEntries.get(7)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x + 24, centerPoint.y - 24)) + .entries(inputEntries.get(2)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x + 24, centerPoint.y + 24)) + .entries(inputEntries.get(4)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x - 24, centerPoint.y + 24)) + .entries(inputEntries.get(6)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x - 24, centerPoint.y - 24)) + .entries(inputEntries.get(8)) + .disableBackground() + .markInput()); + widgets.add(Widgets.createSlot(new Point(centerPoint.x + 80, centerPoint.y)) + .entries(outputEntries.get(0)) + .disableBackground() + .markOutput()); + widgets.add(Widgets.createLabel( + new Point(bounds.getMaxX() - 5, bounds.y + 6), + Component.translatable("category.rei.infusion.time&val", display.getInfusionTime()) + ).noShadow().rightAligned().color(0xFF404040, 0xFFBBBBBB)); + return widgets; + } + + @Override + public int getDisplayHeight() { + return 104; + } +} + */ diff --git a/src/main/java/ru/betterend/integration/rei/REIInfusionDisplay.java b/src/main/java/org/betterx/betterend/integration/rei/REIInfusionDisplay.java similarity index 97% rename from src/main/java/ru/betterend/integration/rei/REIInfusionDisplay.java rename to src/main/java/org/betterx/betterend/integration/rei/REIInfusionDisplay.java index 50b16531..2b3303ba 100644 --- a/src/main/java/ru/betterend/integration/rei/REIInfusionDisplay.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIInfusionDisplay.java @@ -1,4 +1,4 @@ -package ru.betterend.integration.rei; +package org.betterx.betterend.integration.rei; /* import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.SimpleGridMenuDisplay; diff --git a/src/main/java/ru/betterend/integration/rei/REIPlugin.java b/src/main/java/org/betterx/betterend/integration/rei/REIPlugin.java similarity index 94% rename from src/main/java/ru/betterend/integration/rei/REIPlugin.java rename to src/main/java/org/betterx/betterend/integration/rei/REIPlugin.java index f2685f5f..295b2e80 100644 --- a/src/main/java/ru/betterend/integration/rei/REIPlugin.java +++ b/src/main/java/org/betterx/betterend/integration/rei/REIPlugin.java @@ -1,99 +1,99 @@ -package ru.betterend.integration.rei; -/* -import com.google.common.collect.Lists; -import me.shedaniel.rei.api.client.plugins.REIClientPlugin; -import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; -import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.util.EntryIngredients; -import me.shedaniel.rei.api.common.util.EntryStacks; -import me.shedaniel.rei.plugin.common.DefaultPlugin; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.BlastingRecipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.blocks.BaseFurnaceBlock; -import ru.bclib.recipes.AnvilRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.basis.EndAnvilBlock; -import ru.betterend.recipe.builders.AlloyingRecipe; -import ru.betterend.recipe.builders.InfusionRecipe; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.stream.Collectors; - - -//https://github.com/shedaniel/RoughlyEnoughItems/blob/6.x-1.17/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java -public class REIPlugin implements REIClientPlugin { - public final static ResourceLocation PLUGIN_ID = BetterEnd.makeID("rei_plugin"); - public final static CategoryIdentifier ALLOYING_FUEL = CategoryIdentifier.of( - BetterEnd.MOD_ID, - "alloying_fuel" - ); - public final static CategoryIdentifier ALLOYING = CategoryIdentifier.of( - BetterEnd.MOD_ID, - AlloyingRecipe.GROUP - ); - public final static CategoryIdentifier SMITHING = CategoryIdentifier.of( - BetterEnd.MOD_ID, - AnvilRecipe.ID.getPath() - ); - public final static CategoryIdentifier INFUSION = CategoryIdentifier.of( - BetterEnd.MOD_ID, - InfusionRecipe.GROUP - ); - - @Override - public void registerDisplays(DisplayRegistry registry) { - registry.registerRecipeFiller(AlloyingRecipe.class, AlloyingRecipe.TYPE, REIAlloyingDisplay::new); - registry.registerRecipeFiller(BlastingRecipe.class, RecipeType.BLASTING, REIBlastingDisplay::new); - registry.registerRecipeFiller(AnvilRecipe.class, AnvilRecipe.TYPE, REIAnvilDisplay::new); - registry.registerRecipeFiller(InfusionRecipe.class, InfusionRecipe.TYPE, REIInfusionDisplay::new); - - //TODO: 1.18 REI fix this -// FuelRegistryImpl.INSTANCE.getFuelTimes().forEach((item, time) -> { -// if (time >= 2000) { -// final List list = Collections.singletonList(EntryIngredients.of(item)); -// registry.add(new REIAlloyingFuelDisplay(list, time)); -// } -// }); - } - - @Override - public void registerCategories(CategoryRegistry registry) { - EntryStack endStoneSmelter = EntryStacks.of(EndBlocks.END_STONE_SMELTER); - EntryStack infusionRitual = EntryStacks.of(EndBlocks.INFUSION_PEDESTAL); - List> anvils = Lists.newArrayList(EntryIngredients.ofItems(EndBlocks.getModBlocks() - .stream() - .filter(EndAnvilBlock.class::isInstance) - .collect(Collectors.toList()))); - anvils.add(0, EntryStacks.of(Blocks.ANVIL)); - List> ITEM_FURNACES = Lists.newArrayList(EntryIngredients.ofItems(EndBlocks.getModBlocks() - .stream() - .filter(BaseFurnaceBlock.class::isInstance) - .collect(Collectors.toList()))); - EntryStack[] anvilsArray = anvils.toArray(new EntryStack[0]); - EntryStack[] ITEM_FURNACESArray = ITEM_FURNACES.toArray(new EntryStack[0]); - - registry.add( - new REIAlloyingFuelCategory(), - new REIAlloyingCategory(endStoneSmelter), - new REIInfusionCategory(infusionRitual), - new REIAnvilCategory(anvilsArray) - ); - - registry.addWorkstations(ALLOYING_FUEL, endStoneSmelter); - registry.addWorkstations(ALLOYING, endStoneSmelter); - registry.addWorkstations(INFUSION, infusionRitual); - registry.addWorkstations(SMITHING, anvilsArray); - registry.removePlusButton(ALLOYING_FUEL); - registry.removePlusButton(SMITHING); - - registry.addWorkstations(DefaultPlugin.SMELTING, ITEM_FURNACESArray); - registry.addWorkstations(DefaultPlugin.FUEL, ITEM_FURNACESArray); - } -} +package org.betterx.betterend.integration.rei; +/* +import com.google.common.collect.Lists; +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.plugin.common.DefaultPlugin; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.BlastingRecipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.block.Blocks; +import org.betterx.bclib.blocks.BaseFurnaceBlock; +import org.betterx.bclib.recipes.AnvilRecipe; +import org.betterx.betterend.BetterEnd; +import ru.betterend.blocks.basis.EndAnvilBlock; +import ru.betterend.recipe.builders.AlloyingRecipe; +import ru.betterend.recipe.builders.InfusionRecipe; +import ru.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.stream.Collectors; + + +//https://github.com/shedaniel/RoughlyEnoughItems/blob/6.x-1.17/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java +public class REIPlugin implements REIClientPlugin { + public final static ResourceLocation PLUGIN_ID = BetterEnd.makeID("rei_plugin"); + public final static CategoryIdentifier ALLOYING_FUEL = CategoryIdentifier.of( + BetterEnd.MOD_ID, + "alloying_fuel" + ); + public final static CategoryIdentifier ALLOYING = CategoryIdentifier.of( + BetterEnd.MOD_ID, + AlloyingRecipe.GROUP + ); + public final static CategoryIdentifier SMITHING = CategoryIdentifier.of( + BetterEnd.MOD_ID, + AnvilRecipe.ID.getPath() + ); + public final static CategoryIdentifier INFUSION = CategoryIdentifier.of( + BetterEnd.MOD_ID, + InfusionRecipe.GROUP + ); + + @Override + public void registerDisplays(DisplayRegistry registry) { + registry.registerRecipeFiller(AlloyingRecipe.class, AlloyingRecipe.TYPE, REIAlloyingDisplay::new); + registry.registerRecipeFiller(BlastingRecipe.class, RecipeType.BLASTING, REIBlastingDisplay::new); + registry.registerRecipeFiller(AnvilRecipe.class, AnvilRecipe.TYPE, REIAnvilDisplay::new); + registry.registerRecipeFiller(InfusionRecipe.class, InfusionRecipe.TYPE, REIInfusionDisplay::new); + + //TODO: 1.18 REI fix this +// FuelRegistryImpl.INSTANCE.getFuelTimes().forEach((item, time) -> { +// if (time >= 2000) { +// final List list = Collections.singletonList(EntryIngredients.of(item)); +// registry.add(new REIAlloyingFuelDisplay(list, time)); +// } +// }); + } + + @Override + public void registerCategories(CategoryRegistry registry) { + EntryStack endStoneSmelter = EntryStacks.of(EndBlocks.END_STONE_SMELTER); + EntryStack infusionRitual = EntryStacks.of(EndBlocks.INFUSION_PEDESTAL); + List> anvils = Lists.newArrayList(EntryIngredients.ofItems(EndBlocks.getModBlocks() + .stream() + .filter(EndAnvilBlock.class::isInstance) + .collect(Collectors.toList()))); + anvils.add(0, EntryStacks.of(Blocks.ANVIL)); + List> ITEM_FURNACES = Lists.newArrayList(EntryIngredients.ofItems(EndBlocks.getModBlocks() + .stream() + .filter(BaseFurnaceBlock.class::isInstance) + .collect(Collectors.toList()))); + EntryStack[] anvilsArray = anvils.toArray(new EntryStack[0]); + EntryStack[] ITEM_FURNACESArray = ITEM_FURNACES.toArray(new EntryStack[0]); + + registry.add( + new REIAlloyingFuelCategory(), + new REIAlloyingCategory(endStoneSmelter), + new REIInfusionCategory(infusionRitual), + new REIAnvilCategory(anvilsArray) + ); + + registry.addWorkstations(ALLOYING_FUEL, endStoneSmelter); + registry.addWorkstations(ALLOYING, endStoneSmelter); + registry.addWorkstations(INFUSION, infusionRitual); + registry.addWorkstations(SMITHING, anvilsArray); + registry.removePlusButton(ALLOYING_FUEL); + registry.removePlusButton(SMITHING); + + registry.addWorkstations(DefaultPlugin.SMELTING, ITEM_FURNACESArray); + registry.addWorkstations(DefaultPlugin.FUEL, ITEM_FURNACESArray); + } +} */ \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/interfaces/BETargetChecker.java b/src/main/java/org/betterx/betterend/interfaces/BETargetChecker.java new file mode 100644 index 00000000..8735ca5a --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/BETargetChecker.java @@ -0,0 +1,6 @@ +package org.betterx.betterend.interfaces; + +public interface BETargetChecker { + boolean be_isTarget(); + void be_setTarget(boolean target); +} diff --git a/src/main/java/org/betterx/betterend/interfaces/FallFlyingItem.java b/src/main/java/org/betterx/betterend/interfaces/FallFlyingItem.java new file mode 100644 index 00000000..5ac62812 --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/FallFlyingItem.java @@ -0,0 +1,9 @@ +package org.betterx.betterend.interfaces; + +import net.minecraft.resources.ResourceLocation; + +public interface FallFlyingItem { + ResourceLocation getModelTexture(); + + double getMovementFactor(); +} diff --git a/src/main/java/org/betterx/betterend/interfaces/ISlime.java b/src/main/java/org/betterx/betterend/interfaces/ISlime.java new file mode 100644 index 00000000..23834d2f --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/ISlime.java @@ -0,0 +1,9 @@ +package org.betterx.betterend.interfaces; + +import net.minecraft.world.entity.Entity; + +public interface ISlime { + void be_setSlimeSize(int size, boolean heal); + + void entityRemove(Entity.RemovalReason removalReason); +} diff --git a/src/main/java/ru/betterend/interfaces/MobEffectApplier.java b/src/main/java/org/betterx/betterend/interfaces/MobEffectApplier.java similarity index 51% rename from src/main/java/ru/betterend/interfaces/MobEffectApplier.java rename to src/main/java/org/betterx/betterend/interfaces/MobEffectApplier.java index 7aee65f6..41b90dce 100644 --- a/src/main/java/ru/betterend/interfaces/MobEffectApplier.java +++ b/src/main/java/org/betterx/betterend/interfaces/MobEffectApplier.java @@ -1,7 +1,7 @@ -package ru.betterend.interfaces; +package org.betterx.betterend.interfaces; import net.minecraft.world.entity.LivingEntity; public interface MobEffectApplier { - void applyEffect(LivingEntity owner); + void applyEffect(LivingEntity owner); } diff --git a/src/main/java/org/betterx/betterend/interfaces/MultiModelItem.java b/src/main/java/org/betterx/betterend/interfaces/MultiModelItem.java new file mode 100644 index 00000000..f0cda2f5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/MultiModelItem.java @@ -0,0 +1,19 @@ +package org.betterx.betterend.interfaces; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.registry.EndItems; + +public interface MultiModelItem { + @Environment(EnvType.CLIENT) + void registerModelPredicate(); + + static void register() { + EndItems.getModItems().forEach(item -> { + if (item instanceof MultiModelItem) { + ((MultiModelItem) item).registerModelPredicate(); + } + }); + } +} diff --git a/src/main/java/org/betterx/betterend/interfaces/PottablePlant.java b/src/main/java/org/betterx/betterend/interfaces/PottablePlant.java new file mode 100644 index 00000000..3756138d --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/PottablePlant.java @@ -0,0 +1,19 @@ +package org.betterx.betterend.interfaces; + +import net.minecraft.world.level.block.Block; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +public interface PottablePlant { + boolean canPlantOn(Block block); + + default boolean canBePotted() { + return true; + } + + @Environment(EnvType.CLIENT) + default String getPottedState() { + return ""; + } +} diff --git a/src/main/java/org/betterx/betterend/interfaces/PottableTerrain.java b/src/main/java/org/betterx/betterend/interfaces/PottableTerrain.java new file mode 100644 index 00000000..e4bafe97 --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/PottableTerrain.java @@ -0,0 +1,7 @@ +package org.betterx.betterend.interfaces; + +public interface PottableTerrain { + default boolean canBePotted() { + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/interfaces/TeleportingEntity.java b/src/main/java/org/betterx/betterend/interfaces/TeleportingEntity.java new file mode 100644 index 00000000..d5c38f97 --- /dev/null +++ b/src/main/java/org/betterx/betterend/interfaces/TeleportingEntity.java @@ -0,0 +1,11 @@ +package org.betterx.betterend.interfaces; + +import net.minecraft.core.BlockPos; + +public interface TeleportingEntity { + void be_setExitPos(BlockPos pos); + + void be_resetExitPos(); + + boolean be_canTeleport(); +} diff --git a/src/main/java/org/betterx/betterend/item/ArmoredElytra.java b/src/main/java/org/betterx/betterend/item/ArmoredElytra.java new file mode 100644 index 00000000..01ec6aeb --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/ArmoredElytra.java @@ -0,0 +1,99 @@ +package org.betterx.betterend.item; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.*; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; + +import org.betterx.bclib.items.BaseArmorItem; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.interfaces.MultiModelItem; +import org.betterx.betterend.registry.EndItems; + +public class ArmoredElytra extends BaseArmorItem implements MultiModelItem, FallFlyingItem { + private final ResourceLocation wingTexture; + private final Item repairItem; + private final double movementFactor; + private final float toughness; + private final int defense; + + public ArmoredElytra(String name, + ArmorMaterial material, + Item repairItem, + int durability, + double movementFactor, + boolean fireproof) { + super( + material, + EquipmentSlot.CHEST, + fireproof ? EndItems + .makeEndItemSettings() + .durability(durability) + .rarity(Rarity.EPIC) + .fireResistant() : EndItems.makeEndItemSettings().durability(durability).rarity(Rarity.EPIC) + ); + this.wingTexture = BetterEnd.makeID("textures/entity/" + name + ".png"); + this.repairItem = repairItem; + this.movementFactor = movementFactor; + this.defense = (int) ((double) material.getDefenseForSlot(EquipmentSlot.CHEST) / 1.75); + this.toughness = material.getToughness() / 1.75F; + addAttributeModifier( + Attributes.ARMOR, + new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], + "Armor modifier", + defense, + AttributeModifier.Operation.ADDITION + ) + ); + addAttributeModifier( + Attributes.ARMOR_TOUGHNESS, + new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], + "Armor toughness", + toughness, + AttributeModifier.Operation.ADDITION + ) + ); + } + + @Override + public double getMovementFactor() { + return movementFactor; + } + + @Override + @Environment(EnvType.CLIENT) + public ResourceLocation getModelTexture() { + return wingTexture; + } + + @Override + public boolean isValidRepairItem(ItemStack itemStack, ItemStack itemStack2) { + return super.isValidRepairItem(itemStack, itemStack2) || itemStack2.getItem() == repairItem; + } + + @Override + public int getDefense() { + return defense; + } + + @Override + public float getToughness() { + return toughness; + } + + @Override + @Environment(EnvType.CLIENT) + public void registerModelPredicate() { + FabricModelPredicateProviderRegistry.register( + this, + new ResourceLocation("broken"), + (itemStack, clientLevel, livingEntity, id) -> ElytraItem.isFlyEnabled(itemStack) ? 0.0F : 1.0F + ); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteArmor.java b/src/main/java/org/betterx/betterend/item/CrystaliteArmor.java new file mode 100644 index 00000000..6a138c13 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteArmor.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.item; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; + +import org.betterx.bclib.items.BaseArmorItem; +import org.betterx.betterend.effects.EndStatusEffects; +import org.betterx.betterend.item.material.EndArmorMaterial; + +public class CrystaliteArmor extends BaseArmorItem { + + public final static MutableComponent CHEST_DESC; + public final static MutableComponent BOOTS_DESC; + + public CrystaliteArmor(EquipmentSlot equipmentSlot, Properties settings) { + super(EndArmorMaterial.CRYSTALITE, equipmentSlot, settings); + } + + public static boolean hasFullSet(LivingEntity owner) { + for (ItemStack armorStack : owner.getArmorSlots()) { + if (!(armorStack.getItem() instanceof CrystaliteArmor)) { + return false; + } + } + return true; + } + + public static void applySetEffect(LivingEntity owner) { + if ((owner.tickCount & 63) == 0) { + owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_HEALTH_REGEN)); + } + } + + static { + Style descStyle = Style.EMPTY.applyFormats(ChatFormatting.DARK_AQUA, ChatFormatting.ITALIC); + CHEST_DESC = Component.translatable("tooltip.armor.crystalite_chest"); + CHEST_DESC.setStyle(descStyle); + BOOTS_DESC = Component.translatable("tooltip.armor.crystalite_boots"); + BOOTS_DESC.setStyle(descStyle); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteBoots.java b/src/main/java/org/betterx/betterend/item/CrystaliteBoots.java new file mode 100644 index 00000000..a8640b86 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteBoots.java @@ -0,0 +1,42 @@ +package org.betterx.betterend.item; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.effects.EndStatusEffects; +import org.betterx.betterend.interfaces.MobEffectApplier; +import org.betterx.betterend.registry.EndItems; + +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class CrystaliteBoots extends CrystaliteArmor implements MobEffectApplier { + + public CrystaliteBoots() { + super(EquipmentSlot.FEET, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); + } + + @Override + public void applyEffect(LivingEntity owner) { + if ((owner.tickCount & 63) == 0) { + owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_MOVE_SPEED)); + } + } + + @Override + @Environment(EnvType.CLIENT) + public void appendHoverText(ItemStack stack, @Nullable Level level, List lines, TooltipFlag tooltip) { + super.appendHoverText(stack, level, lines, tooltip); + lines.add(1, Component.empty()); + lines.add(2, BOOTS_DESC); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteChestplate.java b/src/main/java/org/betterx/betterend/item/CrystaliteChestplate.java new file mode 100644 index 00000000..81969d47 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteChestplate.java @@ -0,0 +1,40 @@ +package org.betterx.betterend.item; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.effects.EndStatusEffects; +import org.betterx.betterend.interfaces.MobEffectApplier; +import org.betterx.betterend.registry.EndItems; + +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class CrystaliteChestplate extends CrystaliteArmor implements MobEffectApplier { + + public CrystaliteChestplate() { + super(EquipmentSlot.CHEST, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); + } + + @Override + public void applyEffect(LivingEntity owner) { + owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_DIG_SPEED)); + } + + @Override + @Environment(EnvType.CLIENT) + public void appendHoverText(ItemStack stack, @Nullable Level level, List lines, TooltipFlag tooltip) { + super.appendHoverText(stack, level, lines, tooltip); + lines.add(1, Component.empty()); + lines.add(2, CHEST_DESC); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteElytra.java b/src/main/java/org/betterx/betterend/item/CrystaliteElytra.java new file mode 100644 index 00000000..55d606e7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteElytra.java @@ -0,0 +1,85 @@ +package org.betterx.betterend.item; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.interfaces.MultiModelItem; +import org.betterx.betterend.registry.EndItems; + +public class CrystaliteElytra extends CrystaliteArmor implements MultiModelItem, FallFlyingItem { + + private final ResourceLocation wingTexture; + private final double movementFactor; + private final int defense; + private final float toughness; + + public CrystaliteElytra(int durability, double movementFactor) { + super(EquipmentSlot.CHEST, EndItems.makeEndItemSettings().durability(durability).rarity(Rarity.EPIC)); + this.wingTexture = BetterEnd.makeID("textures/entity/elytra_crystalite.png"); + this.movementFactor = movementFactor; + this.defense = (int) ((double) material.getDefenseForSlot(EquipmentSlot.CHEST) / 1.75); + this.toughness = material.getToughness() / 1.75F; + addAttributeModifier( + Attributes.ARMOR, + new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], + "Armor modifier", + defense, + AttributeModifier.Operation.ADDITION + ) + ); + addAttributeModifier( + Attributes.ARMOR_TOUGHNESS, + new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], + "Armor toughness", + toughness, + AttributeModifier.Operation.ADDITION + ) + ); + } + + @Override + public boolean isValidRepairItem(ItemStack itemStack, ItemStack itemStack2) { + return super.isValidRepairItem(itemStack, itemStack2) || itemStack2.getItem() == EndItems.ENCHANTED_MEMBRANE; + } + + @Override + public double getMovementFactor() { + return movementFactor; + } + + @Override + @Environment(EnvType.CLIENT) + public ResourceLocation getModelTexture() { + return wingTexture; + } + + @Override + public int getDefense() { + return defense; + } + + @Override + public float getToughness() { + return toughness; + } + + @Override + public void registerModelPredicate() { + FabricModelPredicateProviderRegistry.register( + this, + new ResourceLocation("broken"), + (itemStack, clientLevel, livingEntity, i) -> ElytraItem.isFlyEnabled(itemStack) ? 0.0F : 1.0F + ); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteHelmet.java b/src/main/java/org/betterx/betterend/item/CrystaliteHelmet.java new file mode 100644 index 00000000..3c6ec876 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteHelmet.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.item; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.item.Rarity; + +import org.betterx.betterend.registry.EndAttributes; +import org.betterx.betterend.registry.EndItems; + +import java.util.UUID; + +public class CrystaliteHelmet extends CrystaliteArmor { + + public CrystaliteHelmet() { + super(EquipmentSlot.HEAD, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); + UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.HEAD.getIndex()]; + addAttributeModifier( + EndAttributes.BLINDNESS_RESISTANCE, + new AttributeModifier(uuid, "Helmet blindness resistance", 1.0, AttributeModifier.Operation.ADDITION) + ); + } +} diff --git a/src/main/java/org/betterx/betterend/item/CrystaliteLeggings.java b/src/main/java/org/betterx/betterend/item/CrystaliteLeggings.java new file mode 100644 index 00000000..b6e61bc2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/CrystaliteLeggings.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.item; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.Rarity; + +import org.betterx.betterend.registry.EndItems; + +import java.util.UUID; + +public class CrystaliteLeggings extends CrystaliteArmor { + + public CrystaliteLeggings() { + super(EquipmentSlot.LEGS, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); + UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.LEGS.getIndex()]; + addAttributeModifier( + Attributes.MAX_HEALTH, + new AttributeModifier(uuid, "Armor health boost", 4.0, AttributeModifier.Operation.ADDITION) + ); + } +} diff --git a/src/main/java/org/betterx/betterend/item/EnchantedItem.java b/src/main/java/org/betterx/betterend/item/EnchantedItem.java new file mode 100644 index 00000000..20e63f35 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/EnchantedItem.java @@ -0,0 +1,37 @@ +package org.betterx.betterend.item; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.items.ModelProviderItem; +import org.betterx.betterend.registry.EndItems; + +public class EnchantedItem extends ModelProviderItem { + + private final Item source; + + public EnchantedItem(Item source) { + super(EndItems.makeEndItemSettings().rarity(Rarity.RARE).stacksTo(16)); + this.source = source; + } + + @Override + public boolean isFoil(ItemStack stack) { + return true; + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + ResourceLocation sourceId = Registry.ITEM.getKey(source); + return ModelsHelper.createItemModel(sourceId); + } +} diff --git a/src/main/java/org/betterx/betterend/item/EndArmorItem.java b/src/main/java/org/betterx/betterend/item/EndArmorItem.java new file mode 100644 index 00000000..4dd48fca --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/EndArmorItem.java @@ -0,0 +1,62 @@ +package org.betterx.betterend.item; + +import net.minecraft.world.entity.EquipmentSlot; +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.ArmorItem; +import net.minecraft.world.item.ArmorMaterial; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import org.betterx.bclib.interfaces.ItemModelProvider; + +import java.util.UUID; + +public class EndArmorItem extends ArmorItem implements ItemModelProvider { + + protected 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") + }; + + protected final Multimap defaultModifiers; + + public EndArmorItem(ArmorMaterial material, EquipmentSlot equipmentSlot, Properties settings) { + super(material, equipmentSlot, settings); + this.defaultModifiers = HashMultimap.create(); + UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[equipmentSlot.getIndex()]; + addAttributeModifier( + Attributes.ARMOR, + new AttributeModifier(uuid, "Armor modifier", getDefense(), AttributeModifier.Operation.ADDITION) + ); + addAttributeModifier( + Attributes.ARMOR_TOUGHNESS, + new AttributeModifier(uuid, "Armor toughness", getToughness(), AttributeModifier.Operation.ADDITION) + ); + if (knockbackResistance > 0.0F) { + addAttributeModifier( + Attributes.KNOCKBACK_RESISTANCE, + new AttributeModifier(uuid, + "Armor knockback resistance", + knockbackResistance, + AttributeModifier.Operation.ADDITION + ) + ); + } + } + + @Override + public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentSlot) { + return equipmentSlot == slot ? defaultModifiers : super.getDefaultAttributeModifiers(equipmentSlot); + } + + protected void addAttributeModifier(Attribute attribute, AttributeModifier modifier) { + if (defaultModifiers.containsKey(attribute)) { + defaultModifiers.removeAll(attribute); + } + defaultModifiers.put(attribute, modifier); + } +} diff --git a/src/main/java/org/betterx/betterend/item/EndAttribute.java b/src/main/java/org/betterx/betterend/item/EndAttribute.java new file mode 100644 index 00000000..ff084d7c --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/EndAttribute.java @@ -0,0 +1,10 @@ +package org.betterx.betterend.item; + +import net.minecraft.world.entity.ai.attributes.Attribute; + +public class EndAttribute extends Attribute { + + public EndAttribute(String description, double value) { + super(description, value); + } +} diff --git a/src/main/java/org/betterx/betterend/item/EndBucketItem.java b/src/main/java/org/betterx/betterend/item/EndBucketItem.java new file mode 100644 index 00000000..f60bb88a --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/EndBucketItem.java @@ -0,0 +1,15 @@ +package org.betterx.betterend.item; + +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.MobBucketItem; +import net.minecraft.world.level.material.Fluids; + +import org.betterx.bclib.interfaces.ItemModelProvider; +import org.betterx.betterend.registry.EndItems; + +public class EndBucketItem extends MobBucketItem implements ItemModelProvider { + public EndBucketItem(EntityType type) { + super(type, Fluids.WATER, SoundEvents.BUCKET_EMPTY, EndItems.makeEndItemSettings().stacksTo(1)); + } +} diff --git a/src/main/java/org/betterx/betterend/item/EternalCrystalItem.java b/src/main/java/org/betterx/betterend/item/EternalCrystalItem.java new file mode 100644 index 00000000..7323479a --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/EternalCrystalItem.java @@ -0,0 +1,12 @@ +package org.betterx.betterend.item; + +import net.minecraft.world.item.Rarity; + +import org.betterx.bclib.items.ModelProviderItem; +import org.betterx.betterend.registry.EndItems; + +public class EternalCrystalItem extends ModelProviderItem { + public EternalCrystalItem() { + super(EndItems.makeEndItemSettings().stacksTo(16).rarity(Rarity.EPIC)); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/item/GuideBookItem.java b/src/main/java/org/betterx/betterend/item/GuideBookItem.java new file mode 100644 index 00000000..a833c026 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/GuideBookItem.java @@ -0,0 +1,48 @@ +package org.betterx.betterend.item; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import org.betterx.bclib.items.ModelProviderItem; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndItems; +import org.betterx.betterend.util.LangUtil; + +import java.util.List; + +public class GuideBookItem extends ModelProviderItem { + public final static ResourceLocation BOOK_ID = BetterEnd.makeID("guidebook"); + public static final Item GUIDE_BOOK = EndItems.getItemRegistry().register(BOOK_ID, new GuideBookItem()); + + public static void register() { + } + + public GuideBookItem() { + super(EndItems.makeEndItemSettings().stacksTo(1)); + } + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { + if (!world.isClientSide && user instanceof ServerPlayer) { + //TODO: reanable Patchouli once it is available for 1.18 + //PatchouliAPI.get().openBookGUI((ServerPlayer) user, BOOK_ID); + return InteractionResultHolder.success(user.getItemInHand(hand)); + } + return InteractionResultHolder.consume(user.getItemInHand(hand)); + } + + @Override + public void appendHoverText(ItemStack stack, Level world, List tooltip, TooltipFlag context) { + tooltip.add(LangUtil.getText("book.betterend", "subtitle") + .withStyle(ChatFormatting.DARK_PURPLE, ChatFormatting.ITALIC)); + } +} diff --git a/src/main/java/org/betterx/betterend/item/material/EndArmorMaterial.java b/src/main/java/org/betterx/betterend/item/material/EndArmorMaterial.java new file mode 100644 index 00000000..d638f1b7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/material/EndArmorMaterial.java @@ -0,0 +1,96 @@ +package org.betterx.betterend.item.material; + +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.LazyLoadedValue; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.crafting.Ingredient; + +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.function.Supplier; + +public enum EndArmorMaterial implements ArmorMaterial { + THALLASIUM("thallasium", 17, new int[]{1, 4, 5, 2}, 12, SoundEvents.ARMOR_EQUIP_IRON, 0.0F, 0.0F, () -> { + return Ingredient.of(EndBlocks.THALLASIUM.ingot); + }), TERMINITE("terminite", 26, new int[]{3, 6, 7, 3}, 14, SoundEvents.ARMOR_EQUIP_IRON, 1.0F, 0.05F, () -> { + return Ingredient.of(EndBlocks.TERMINITE.ingot); + }), AETERNIUM("aeternium", 40, new int[]{4, 7, 9, 4}, 18, SoundEvents.ARMOR_EQUIP_NETHERITE, 3.5F, 0.2F, () -> { + return Ingredient.of(EndItems.AETERNIUM_INGOT); + }), CRYSTALITE("crystalite", 30, new int[]{3, 6, 8, 3}, 24, SoundEvents.ARMOR_EQUIP_DIAMOND, 1.2F, 0.1F, () -> { + return Ingredient.of(EndBlocks.TERMINITE.ingot); + }); + + private static final int[] BASE_DURABILITY = new int[]{13, 15, 16, 11}; + private final String name; + private final int durabilityMultiplier; + private final int[] protectionAmounts; + private final int enchantability; + private final SoundEvent equipSound; + private final float toughness; + private final float knockbackResistance; + @SuppressWarnings("deprecation") + private final LazyLoadedValue repairIngredient; + + @SuppressWarnings("deprecation") + EndArmorMaterial(String name, + int durabilityMultiplier, + int[] protectionAmounts, + int enchantability, + SoundEvent equipSound, + float toughness, + float knockbackResistance, + Supplier repairIngredient) { + this.name = name; + this.durabilityMultiplier = durabilityMultiplier; + this.protectionAmounts = protectionAmounts; + this.enchantability = enchantability; + this.equipSound = equipSound; + this.toughness = toughness; + this.knockbackResistance = knockbackResistance; + this.repairIngredient = new LazyLoadedValue<>(repairIngredient); + } + + @Override + public int getDurabilityForSlot(EquipmentSlot slot) { + return BASE_DURABILITY[slot.getIndex()] * this.durabilityMultiplier; + } + + @Override + public int getDefenseForSlot(EquipmentSlot slot) { + return this.protectionAmounts[slot.getIndex()]; + } + + @Override + public int getEnchantmentValue() { + return this.enchantability; + } + + @Override + public SoundEvent getEquipSound() { + return this.equipSound; + } + + @Override + public Ingredient getRepairIngredient() { + return this.repairIngredient.get(); + } + + @Override + public String getName() { + return this.name; + } + + @Override + public float getToughness() { + return this.toughness; + } + + @Override + public float getKnockbackResistance() { + return this.knockbackResistance; + } + +} diff --git a/src/main/java/org/betterx/betterend/item/material/EndToolMaterial.java b/src/main/java/org/betterx/betterend/item/material/EndToolMaterial.java new file mode 100644 index 00000000..4a026fa9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/material/EndToolMaterial.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.item.material; + +import net.minecraft.util.LazyLoadedValue; +import net.minecraft.world.item.Tier; +import net.minecraft.world.item.crafting.Ingredient; + +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.function.Supplier; + +public enum EndToolMaterial implements Tier { + THALLASIUM(2, 320, 7.0F, 1.5F, 12, () -> { + return Ingredient.of(EndBlocks.THALLASIUM.ingot); + }), TERMINITE(3, 1230, 8.5F, 3.0F, 14, () -> { + return Ingredient.of(EndBlocks.TERMINITE.ingot); + }), AETERNIUM(5, 2196, 10.0F, 4.5F, 18, () -> { + return Ingredient.of(EndItems.AETERNIUM_INGOT); + }); + + private final int durability; + private final float miningSpeed; + private final float attackDamage; + private final int miningLevel; + private final int enchantability; + @SuppressWarnings("deprecation") + private final LazyLoadedValue repairIngredient; + + @SuppressWarnings("deprecation") + EndToolMaterial(int miningLevel, + int durability, + float miningSpeed, + float attackDamage, + int enchantability, + Supplier repairIngredient) { + this.durability = durability; + this.miningSpeed = miningSpeed; + this.attackDamage = attackDamage; + this.miningLevel = miningLevel; + this.enchantability = enchantability; + this.repairIngredient = new LazyLoadedValue<>(repairIngredient); + } + + @Override + public int getUses() { + return this.durability; + } + + @Override + public float getSpeed() { + return this.miningSpeed; + } + + @Override + public float getAttackDamageBonus() { + return this.attackDamage; + } + + @Override + public int getLevel() { + return this.miningLevel; + } + + @Override + public int getEnchantmentValue() { + return this.enchantability; + } + + @Override + public Ingredient getRepairIngredient() { + return this.repairIngredient.get(); + } + +} diff --git a/src/main/java/org/betterx/betterend/item/model/ArmoredElytraModel.java b/src/main/java/org/betterx/betterend/item/model/ArmoredElytraModel.java new file mode 100644 index 00000000..3a757d7d --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/ArmoredElytraModel.java @@ -0,0 +1,95 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +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.player.AbstractClientPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.phys.Vec3; + +import com.google.common.collect.ImmutableList; + +public class ArmoredElytraModel extends AgeableListModel { + private final ModelPart rightWing; + private final ModelPart leftWing; + + public static LayerDefinition getTexturedModelData() { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + modelPartData.addOrReplaceChild( + PartNames.LEFT_WING, + CubeListBuilder.create().texOffs(22, 0).addBox(-10.0f, 0.0f, 0.0f, 10.0f, 20.0f, 2.0f), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + PartNames.RIGHT_WING, + CubeListBuilder.create().mirror().texOffs(22, 0).addBox(0.0f, 0.0f, 0.0f, 10.0f, 20.0f, 2.0f), + PartPose.ZERO + ); + + return LayerDefinition.create(modelData, 64, 32); + } + + public ArmoredElytraModel(ModelPart modelPart) { + leftWing = modelPart.getChild(PartNames.LEFT_WING); + rightWing = modelPart.getChild(PartNames.RIGHT_WING); + } + + protected Iterable headParts() { + return ImmutableList.of(); + } + + protected Iterable bodyParts() { + return ImmutableList.of(leftWing, rightWing); + } + + public void setupAnim(T livingEntity, float f, float g, float h, float i, float j) { + float rotX = 0.2617994F; + float rotZ = -0.2617994F; + float rotY = 0.0F; + float wingY = 0.0F; + if (livingEntity.isFallFlying()) { + float coef = 1.0F; + Vec3 vec3 = livingEntity.getDeltaMovement(); + if (vec3.y < 0.0D) { + Vec3 normalized = vec3.normalize(); + coef = 1.0F - (float) Math.pow(-normalized.y, 2.5D); + } + rotX = coef * 0.34906584F + (1.0F - coef) * rotX; + rotZ = coef * -1.5707964F + (1.0F - coef) * rotZ; + } else if (livingEntity.isCrouching()) { + rotX = 0.6981317F; + rotZ = -0.7853982F; + rotY = 0.08726646F; + wingY = 3.0F; + } + + leftWing.x = 5.0F; + leftWing.y = wingY; + if (livingEntity instanceof AbstractClientPlayer) { + AbstractClientPlayer abstractClientPlayer = (AbstractClientPlayer) livingEntity; + abstractClientPlayer.elytraRotX = (float) ((double) abstractClientPlayer.elytraRotX + (double) (rotX - abstractClientPlayer.elytraRotX) * 0.1D); + abstractClientPlayer.elytraRotY = (float) ((double) abstractClientPlayer.elytraRotY + (double) (rotY - abstractClientPlayer.elytraRotY) * 0.1D); + abstractClientPlayer.elytraRotZ = (float) ((double) abstractClientPlayer.elytraRotZ + (double) (rotZ - abstractClientPlayer.elytraRotZ) * 0.1D); + leftWing.xRot = abstractClientPlayer.elytraRotX; + leftWing.yRot = abstractClientPlayer.elytraRotY; + leftWing.zRot = abstractClientPlayer.elytraRotZ; + } else { + leftWing.xRot = rotX; + leftWing.zRot = rotZ; + leftWing.yRot = rotY; + } + + rightWing.x = -leftWing.x; + rightWing.yRot = -leftWing.yRot; + rightWing.y = leftWing.y; + rightWing.xRot = leftWing.xRot; + rightWing.zRot = -leftWing.zRot; + } +} diff --git a/src/main/java/org/betterx/betterend/item/model/CrystaliteArmorProvider.java b/src/main/java/org/betterx/betterend/item/model/CrystaliteArmorProvider.java new file mode 100644 index 00000000..7ec4e088 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/CrystaliteArmorProvider.java @@ -0,0 +1,92 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.google.common.collect.Lists; +import org.betterx.betterend.item.CrystaliteArmor; +import org.betterx.betterend.registry.EndItems; +import shadow.fabric.api.client.rendering.v1.ArmorRenderingRegistry; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@Environment(EnvType.CLIENT) +public class CrystaliteArmorProvider implements ArmorRenderingRegistry.ModelProvider, ArmorRenderingRegistry.TextureProvider { + //TODO: find new registry + private final static ResourceLocation FIRST_LAYER = new ResourceLocation( + "textures/models/armor/crystalite_layer_1.png"); + private final static ResourceLocation SECOND_LAYER = new ResourceLocation( + "textures/models/armor/crystalite_layer_2.png"); + private final static CrystaliteHelmetModel HELMET_MODEL = CrystaliteHelmetModel.createModel(null); + private final static CrystaliteChestplateModel CHEST_MODEL = CrystaliteChestplateModel.createRegularModel(null); + private final static CrystaliteChestplateModel CHEST_MODEL_SLIM = CrystaliteChestplateModel.createThinModel(null); + private final static CrystaliteLeggingsModel LEGGINGS_MODEL = CrystaliteLeggingsModel.createModel(null); + private final static CrystaliteBootsModel BOOTS_MODEL = CrystaliteBootsModel.createModel(null); + + //@Override + public @NotNull ResourceLocation getArmorTexture(LivingEntity entity, + ItemStack stack, + EquipmentSlot slot, + boolean secondLayer, + @Nullable String suffix, + ResourceLocation defaultTexture) { + if (!isStackValid(stack)) return defaultTexture; + if (secondLayer) return SECOND_LAYER; + return FIRST_LAYER; + } + + //@Override + public @NotNull HumanoidModel getArmorModel(LivingEntity entity, + ItemStack stack, + EquipmentSlot slot, + HumanoidModel defaultModel) { + if (!isStackValid(stack)) return defaultModel; + switch (slot) { + case HEAD: { + return HELMET_MODEL; + } + case CHEST: { + if (entity instanceof AbstractClientPlayer && ((AbstractClientPlayer) entity).getModelName() + .equals("slim")) { + CHEST_MODEL_SLIM.copyPropertiesTo(defaultModel); + return CHEST_MODEL_SLIM; + } + CHEST_MODEL.copyPropertiesTo(defaultModel); + return CHEST_MODEL; + } + case LEGS: { + return LEGGINGS_MODEL; + } + case FEET: { + BOOTS_MODEL.copyPropertiesTo(defaultModel); + return BOOTS_MODEL; + } + default: { + return defaultModel; + } + } + } + + public Iterable getRenderedItems() { + return Lists.newArrayList( + EndItems.CRYSTALITE_HELMET, + EndItems.CRYSTALITE_CHESTPLATE, + EndItems.CRYSTALITE_ELYTRA, + EndItems.CRYSTALITE_LEGGINGS, + EndItems.CRYSTALITE_BOOTS + ); + } + + private boolean isStackValid(ItemStack stack) { + return stack.getItem() instanceof CrystaliteArmor; + } +} diff --git a/src/main/java/org/betterx/betterend/item/model/CrystaliteBootsModel.java b/src/main/java/org/betterx/betterend/item/model/CrystaliteBootsModel.java new file mode 100644 index 00000000..1f2d3ebe --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/CrystaliteBootsModel.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.entity.LivingEntity; + +import com.google.common.collect.Lists; +import org.betterx.betterend.registry.EndEntitiesRenders; + +import java.util.Collections; + +public class CrystaliteBootsModel extends HumanoidModel { + + public ModelPart leftBoot; + public ModelPart rightBoot; + + public static LayerDefinition getTexturedModelData() { + final float scale = 1.0f; + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + // TODO: see if we need to subclass HumanoidModel + // Humanoid model tries to retrieve all parts in it's constructor, + // so we need to add empty Nodes + modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); + + CubeDeformation deformation = new CubeDeformation(scale + 0.25f); + modelPartData.addOrReplaceChild( + "leftBoot", + CubeListBuilder.create().texOffs(0, 32).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(1.9f, 12.0f, 0.0f) + ); + + modelPartData.addOrReplaceChild( + "rightBoot", + CubeListBuilder.create().texOffs(0, 16).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(-1.9f, 12.0f, 0.0f) + ); + + return LayerDefinition.create(modelData, 64, 48); + } + + public static CrystaliteBootsModel createModel(EntityModelSet entityModelSet) { + return new CrystaliteBootsModel(entityModelSet == null + ? getTexturedModelData().bakeRoot() + : entityModelSet.bakeLayer( + EndEntitiesRenders.CRYSTALITE_BOOTS)); + } + + public CrystaliteBootsModel(ModelPart modelPart) { + super(modelPart, RenderType::entityTranslucent); + + leftBoot = modelPart.getChild("leftBoot"); + rightBoot = modelPart.getChild("rightBoot"); + } + + @Override + public void copyPropertiesTo(HumanoidModel bipedEntityModel) { + super.copyPropertiesTo(bipedEntityModel); + this.leftBoot.copyFrom(leftLeg); + this.rightBoot.copyFrom(rightLeg); + } + + @Override + protected Iterable headParts() { + return Collections::emptyIterator; + } + + @Override + protected Iterable bodyParts() { + return Lists.newArrayList(leftBoot, rightBoot); + } +} diff --git a/src/main/java/org/betterx/betterend/item/model/CrystaliteChestplateModel.java b/src/main/java/org/betterx/betterend/item/model/CrystaliteChestplateModel.java new file mode 100644 index 00000000..8140757d --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/CrystaliteChestplateModel.java @@ -0,0 +1,150 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; + +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import org.betterx.betterend.registry.EndEntitiesRenders; + +import java.util.Collections; + +public class CrystaliteChestplateModel extends HumanoidModel { + + public ModelPart leftShoulder; + public ModelPart rightShoulder; + private final boolean thinArms; + + public static LayerDefinition getRegularTexturedModelData() { + return getTexturedModelData(1.0f, false); + } + + public static LayerDefinition getThinTexturedModelData() { + return getTexturedModelData(1.0f, true); + } + + private static LayerDefinition getTexturedModelData(float scale, boolean thinArms) { + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + // TODO: see if we need to subclass HumanoidModel + // Humanoid model tries to retrieve all parts in it's constructor, + // so we need to add empty Nodes + modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); + // modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); + + CubeDeformation deformation = new CubeDeformation(scale + 0.25F); + PartDefinition body = modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(16, 16).addBox(-4.0f, 0.0f, -2.0f, 8.0f, 12.0f, 4.0f, deformation), + PartPose.ZERO + ); + + if (thinArms) { + deformation = new CubeDeformation(scale + 0.45F); + PartDefinition leftShoulder = modelPartData.addOrReplaceChild( + "leftShoulder", + CubeListBuilder.create() + .mirror() + .texOffs(40, 32) + .addBox(-1.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(5.0f, 2.0f, 0.0f) + ); + + PartDefinition rightShoulder = modelPartData.addOrReplaceChild( + "rightShoulder", + CubeListBuilder.create() + .texOffs(40, 16) + .addBox(-3.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(-5.0f, 2.0f, 10.0f) + ); + } else { + deformation = new CubeDeformation(scale + 0.45F); + PartDefinition leftShoulder = modelPartData.addOrReplaceChild( + "leftShoulder", + CubeListBuilder.create() + .mirror() + .texOffs(40, 32) + .addBox(-1.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(5.0f, 2.0f, 0.0f) + ); + + PartDefinition rightShoulder = modelPartData.addOrReplaceChild( + "rightShoulder", + CubeListBuilder.create() + .texOffs(40, 16) + .addBox(-3.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(-5.0f, 2.0f, 10.0f) + ); + } + return LayerDefinition.create(modelData, 64, 48); + } + + final ModelPart localBody; + + public static CrystaliteChestplateModel createRegularModel(EntityModelSet entityModelSet) { + return new CrystaliteChestplateModel(entityModelSet == null + ? getRegularTexturedModelData().bakeRoot() + : entityModelSet + .bakeLayer(EndEntitiesRenders.CRYSTALITE_CHESTPLATE), + false); + } + + public static CrystaliteChestplateModel createThinModel(EntityModelSet entityModelSet) { + return new CrystaliteChestplateModel(entityModelSet == null + ? getThinTexturedModelData().bakeRoot() + : entityModelSet + .bakeLayer(EndEntitiesRenders.CRYSTALITE_CHESTPLATE_THIN), + true); + } + + protected CrystaliteChestplateModel(ModelPart modelPart, boolean thinArms) { + super(modelPart, RenderType::entityTranslucent); + this.thinArms = thinArms; + localBody = modelPart.getChild(PartNames.BODY); + leftShoulder = modelPart.getChild("leftShoulder"); + rightShoulder = modelPart.getChild("rightShoulder"); + } + + @Override + public void copyPropertiesTo(HumanoidModel bipedEntityModel) { + super.copyPropertiesTo(bipedEntityModel); + this.leftShoulder.copyFrom(leftArm); + this.rightShoulder.copyFrom(rightArm); + } + + @Override + protected Iterable headParts() { + return Collections::emptyIterator; + } + + @Override + protected Iterable bodyParts() { + return Lists.newArrayList(localBody, leftShoulder, rightShoulder); + } + + @Override + public void translateToHand(HumanoidArm arm, PoseStack matrices) { + ModelPart modelPart = this.getArm(arm); + if (this.thinArms) { + float f = 0.5F * (float) (arm == HumanoidArm.RIGHT ? 1 : -1); + modelPart.x += f; + modelPart.translateAndRotate(matrices); + modelPart.x -= f; + } else { + modelPart.translateAndRotate(matrices); + } + } +} diff --git a/src/main/java/org/betterx/betterend/item/model/CrystaliteHelmetModel.java b/src/main/java/org/betterx/betterend/item/model/CrystaliteHelmetModel.java new file mode 100644 index 00000000..63e091fc --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/CrystaliteHelmetModel.java @@ -0,0 +1,73 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.entity.LivingEntity; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.google.common.collect.Lists; +import org.betterx.betterend.registry.EndEntitiesRenders; + +import java.util.Collections; + +@Environment(EnvType.CLIENT) +public class CrystaliteHelmetModel extends HumanoidModel { + final ModelPart myHat; + + public static LayerDefinition getTexturedModelData() { + final float scale = 1.0f; + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + // TODO: see if we need to subclass HumanoidModel + // Humanoid model tries to retrieve all parts in it's constructor, + // so we need to add empty Nodes + modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); + //modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); + + CubeDeformation deformation_hat = new CubeDeformation(scale + 0.5f); + PartDefinition hat = modelPartData.addOrReplaceChild( + PartNames.HAT, + CubeListBuilder.create().texOffs(0, 0).addBox(-4.0f, -8.0f, -4.0f, 8.0f, 8.0f, 8.0f, deformation_hat), + PartPose.ZERO + ); + + return LayerDefinition.create(modelData, 64, 48); + } + + public static CrystaliteHelmetModel createModel(EntityModelSet entityModelSet) { + return new CrystaliteHelmetModel(entityModelSet == null + ? getTexturedModelData().bakeRoot() + : entityModelSet.bakeLayer( + EndEntitiesRenders.CRYSTALITE_HELMET)); + } + + + public CrystaliteHelmetModel(ModelPart modelPart) { + super(modelPart, RenderType::entityTranslucent); + + myHat = modelPart.getChild(PartNames.HAT); + } + + @Override + protected Iterable headParts() { + return Collections::emptyIterator; + } + + @Override + protected Iterable bodyParts() { + return Lists.newArrayList(myHat); + } +} diff --git a/src/main/java/org/betterx/betterend/item/model/CrystaliteLeggingsModel.java b/src/main/java/org/betterx/betterend/item/model/CrystaliteLeggingsModel.java new file mode 100644 index 00000000..3945c3a0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/model/CrystaliteLeggingsModel.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.item.model; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartNames; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.entity.LivingEntity; + +import com.google.common.collect.Lists; +import org.betterx.betterend.registry.EndEntitiesRenders; + +import java.util.Collections; + +public class CrystaliteLeggingsModel extends HumanoidModel { + public static LayerDefinition getTexturedModelData() { + float scale = 1.0f; + MeshDefinition modelData = new MeshDefinition(); + PartDefinition modelPartData = modelData.getRoot(); + + // TODO: see if we need to subclass HumanoidModel + // Humanoid model tries to retrieve all parts in it's constructor, + // so we need to add empty Nodes + modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); + // modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); + modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); + // modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); + // modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); + + CubeDeformation deformation = new CubeDeformation(scale); + modelPartData.addOrReplaceChild( + PartNames.BODY, + CubeListBuilder.create().texOffs(16, 16).addBox(-4.0f, 0.0f, -2.0f, 8.0f, 12.0f, 4.0f, deformation), + PartPose.ZERO + ); + + modelPartData.addOrReplaceChild( + PartNames.LEFT_LEG, + CubeListBuilder.create().texOffs(0, 32).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(1.9f, 12.0f, 0.0f) + ); + + modelPartData.addOrReplaceChild( + PartNames.RIGHT_LEG, + CubeListBuilder.create().texOffs(0, 16).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), + PartPose.offset(-1.9f, 12.0f, 0.0f) + ); + + return LayerDefinition.create(modelData, 64, 48); + } + + final ModelPart myBody; + final ModelPart myLeftLeg; + final ModelPart myRightLeg; + + public static CrystaliteLeggingsModel createModel(EntityModelSet entityModelSet) { + return new CrystaliteLeggingsModel(entityModelSet == null + ? getTexturedModelData().bakeRoot() + : entityModelSet.bakeLayer( + EndEntitiesRenders.CRYSTALITE_LEGGINGS)); + } + + public CrystaliteLeggingsModel(ModelPart modelPart) { + super(modelPart, RenderType::entityTranslucent); + + myBody = modelPart.getChild(PartNames.BODY); + myLeftLeg = modelPart.getChild(PartNames.LEFT_LEG); + myRightLeg = modelPart.getChild(PartNames.RIGHT_LEG); + } + + @Override + protected Iterable headParts() { + return Collections::emptyIterator; + } + + @Override + protected Iterable bodyParts() { + return Lists.newArrayList(myBody, myRightLeg, myLeftLeg); + } +} diff --git a/src/main/java/org/betterx/betterend/item/tool/EndHammerItem.java b/src/main/java/org/betterx/betterend/item/tool/EndHammerItem.java new file mode 100644 index 00000000..93349b36 --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/tool/EndHammerItem.java @@ -0,0 +1,156 @@ +package org.betterx.betterend.item.tool; + +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.EquipmentSlot; +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.entity.player.Player; +import net.minecraft.world.item.DiggerItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Tier; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; +import com.google.common.collect.Multimap; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.api.tag.CommonItemTags; +import org.betterx.bclib.client.models.ModelsHelper; +import org.betterx.bclib.interfaces.ItemModelProvider; +import org.betterx.bclib.interfaces.TagProvider; +import org.betterx.bclib.util.MHelper; + +import java.util.List; +import java.util.UUID; + +public class EndHammerItem extends DiggerItem implements ItemModelProvider, TagProvider { + public final static UUID ATTACK_KNOCKBACK_MODIFIER_ID = Mth.createInsecureUUID(MHelper.RANDOM_SOURCE); + + private final Multimap attributeModifiers; + + public EndHammerItem(Tier material, float attackDamage, float attackSpeed, double knockback, Properties settings) { + super(attackDamage, attackSpeed, material, CommonBlockTags.MINABLE_WITH_HAMMER, settings); + + Builder builder = ImmutableMultimap.builder(); + builder.put( + Attributes.ATTACK_DAMAGE, + new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, + "Weapon modifier", + attackDamage + material.getAttackDamageBonus(), + AttributeModifier.Operation.ADDITION + ) + ); + builder.put( + Attributes.ATTACK_SPEED, + new AttributeModifier(BASE_ATTACK_SPEED_UUID, + "Weapon modifier", + attackSpeed, + AttributeModifier.Operation.ADDITION + ) + ); + builder.put( + Attributes.ATTACK_KNOCKBACK, + new AttributeModifier(ATTACK_KNOCKBACK_MODIFIER_ID, + "Weapon modifier", + knockback, + AttributeModifier.Operation.ADDITION + ) + ); + this.attributeModifiers = builder.build(); + } + + @Override + public boolean canAttackBlock(BlockState state, Level world, BlockPos pos, Player miner) { + return state.getMaterial().equals(Material.STONE) || state.getMaterial().equals(Material.GLASS) || state.is( + Blocks.DIAMOND_BLOCK) || state.is(Blocks.EMERALD_BLOCK) || state.is(Blocks.LAPIS_BLOCK) || state.is( + Blocks.REDSTONE_BLOCK); + } + + @Override + public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { + stack.hurtAndBreak(1, attacker, ((entity) -> entity.broadcastBreakEvent(EquipmentSlot.MAINHAND))); + + return true; + } + + @Override + public boolean mineBlock(ItemStack stack, Level world, BlockState state, BlockPos pos, LivingEntity miner) { + if (state.getDestroySpeed(world, pos) != 0.0F) { + stack.hurtAndBreak(1, miner, ((entity) -> entity.broadcastBreakEvent(EquipmentSlot.MAINHAND))); + } + + return true; + } + + @Override + public float getDestroySpeed(ItemStack stack, BlockState state) { + if (state.getMaterial().equals(Material.GLASS)) { + return this.getTier().getSpeed() * 2.0F; + } + if (isCorrectToolForDrops(state)) { + float mult; + if (state.is(Blocks.DIAMOND_BLOCK) || state.is(Blocks.EMERALD_BLOCK) || state.is(Blocks.LAPIS_BLOCK) || state + .is(Blocks.REDSTONE_BLOCK)) { + mult = this.getTier().getSpeed(); + } else { + mult = this.getTier().getSpeed() / 2.0F; + } + return Math.max(mult, 1.0F); + } + return 1.0F; + } + + @Override + public boolean isCorrectToolForDrops(BlockState state) { + if (state.getMaterial().equals(Material.GLASS)) { + return true; + } + if (!state.is(Blocks.REDSTONE_BLOCK) && !state.is(Blocks.DIAMOND_BLOCK) && !state.is(Blocks.EMERALD_BLOCK) && !state + .is(Blocks.LAPIS_BLOCK) && !state.getMaterial().equals(Material.STONE)) { + return false; + } + int level = this.getTier().getLevel(); + if (state.is(Blocks.IRON_ORE) || state.is(Blocks.LAPIS_BLOCK) || state.is(Blocks.LAPIS_ORE)) { + return level >= 1; + } + if (state.is(Blocks.DIAMOND_BLOCK) && !state.is(Blocks.DIAMOND_ORE) || state.is(Blocks.EMERALD_ORE) || state.is( + Blocks.EMERALD_BLOCK) || state.is(Blocks.GOLD_ORE) || state.is(Blocks.REDSTONE_ORE)) { + return level >= 2; + } + if (state.is(Blocks.OBSIDIAN) || state.is(Blocks.CRYING_OBSIDIAN) || state.is(Blocks.RESPAWN_ANCHOR) || state.is( + Blocks.ANCIENT_DEBRIS)) { + return level >= 3; + } + return true; + } + + @Override + public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { + return slot == EquipmentSlot.MAINHAND ? this.attributeModifiers : super.getDefaultAttributeModifiers(slot); + } + + @Override + @Environment(EnvType.CLIENT) + public BlockModel getItemModel(ResourceLocation resourceLocation) { + return ModelsHelper.createHandheldItem(resourceLocation); + } + + @Override + public void addTags(List> blockTags, List> itemTags) { + itemTags.add(CommonItemTags.HAMMERS); + } +} diff --git a/src/main/java/org/betterx/betterend/item/tool/EndPickaxe.java b/src/main/java/org/betterx/betterend/item/tool/EndPickaxe.java new file mode 100644 index 00000000..7213121e --- /dev/null +++ b/src/main/java/org/betterx/betterend/item/tool/EndPickaxe.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.item.tool; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Tier; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.items.tool.BasePickaxeItem; + +public class EndPickaxe extends BasePickaxeItem { + public EndPickaxe(Tier material, int attackDamage, float attackSpeed, Properties settings) { + super(material, attackDamage, attackSpeed, settings); + } + + @Override + public float getDestroySpeed(ItemStack stack, BlockState state) { + if (state.is(Blocks.END_STONE) && this.getTier().getLevel() > 2) { + return this.speed * 3; + } + return super.getDestroySpeed(stack, state); + } +} diff --git a/src/main/java/ru/betterend/mixin/client/AbstractSoundInstanceAccessor.java b/src/main/java/org/betterx/betterend/mixin/client/AbstractSoundInstanceAccessor.java similarity index 70% rename from src/main/java/ru/betterend/mixin/client/AbstractSoundInstanceAccessor.java rename to src/main/java/org/betterx/betterend/mixin/client/AbstractSoundInstanceAccessor.java index 9c94ed93..81476c74 100644 --- a/src/main/java/ru/betterend/mixin/client/AbstractSoundInstanceAccessor.java +++ b/src/main/java/org/betterx/betterend/mixin/client/AbstractSoundInstanceAccessor.java @@ -1,11 +1,12 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.resources.sounds.AbstractSoundInstance; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(AbstractSoundInstance.class) -public interface AbstractSoundInstanceAccessor { - @Accessor("volume") - void setVolume(float volume); -} +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.resources.sounds.AbstractSoundInstance; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AbstractSoundInstance.class) +public interface AbstractSoundInstanceAccessor { + @Accessor("volume") + void setVolume(float volume); +} diff --git a/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java b/src/main/java/org/betterx/betterend/mixin/client/ArmorStandRendererMixin.java similarity index 57% rename from src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java rename to src/main/java/org/betterx/betterend/mixin/client/ArmorStandRendererMixin.java index 05433101..54a71f35 100644 --- a/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/client/ArmorStandRendererMixin.java @@ -1,25 +1,26 @@ -package ru.betterend.mixin.client; +package org.betterx.betterend.mixin.client; import net.minecraft.client.model.ArmorStandArmorModel; import net.minecraft.client.renderer.entity.ArmorStandRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.world.entity.decoration.ArmorStand; + +import org.betterx.betterend.client.render.ArmoredElytraLayer; 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 ru.betterend.client.render.ArmoredElytraLayer; @Mixin(ArmorStandRenderer.class) public abstract class ArmorStandRendererMixin extends LivingEntityRenderer { - - public ArmorStandRendererMixin(EntityRendererProvider.Context context, ArmorStandArmorModel entityModel, float f) { - super(context, entityModel, f); - } - - @Inject(method = "*", at = @At("TAIL")) - public void be_addCustomLayer(EntityRendererProvider.Context context, CallbackInfo ci) { - addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); - } + + public ArmorStandRendererMixin(EntityRendererProvider.Context context, ArmorStandArmorModel entityModel, float f) { + super(context, entityModel, f); + } + + @Inject(method = "*", at = @At("TAIL")) + public void be_addCustomLayer(EntityRendererProvider.Context context, CallbackInfo ci) { + addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); + } } diff --git a/src/main/java/org/betterx/betterend/mixin/client/BiomeColorsMixin.java b/src/main/java/org/betterx/betterend/mixin/client/BiomeColorsMixin.java new file mode 100644 index 00000000..342224cc --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/BiomeColorsMixin.java @@ -0,0 +1,62 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BiomeColors; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.world.level.BlockAndTintGetter; + +import net.fabricmc.loader.api.FabricLoader; + +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.client.ClientOptions; +import org.betterx.betterend.registry.EndBlocks; +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.CallbackInfoReturnable; + +import java.awt.*; +import java.util.Arrays; +import java.util.Comparator; + +@Mixin(BiomeColors.class) +public class BiomeColorsMixin { + private static final int POISON_COLOR = ColorUtil.color(92, 160, 78); + private static final int STREAM_COLOR = ColorUtil.color(105, 213, 244); + private static final Point[] OFFSETS; + private static final boolean HAS_SODIUM; + + @Inject(method = "getAverageWaterColor", at = @At("RETURN"), cancellable = true) + private static void be_getWaterColor(BlockAndTintGetter world, BlockPos pos, CallbackInfoReturnable info) { + if (ClientOptions.useSulfurWaterColor()) { + BlockAndTintGetter view = HAS_SODIUM ? Minecraft.getInstance().level : world; + MutableBlockPos mut = new MutableBlockPos(); + mut.setY(pos.getY()); + for (int i = 0; i < OFFSETS.length; i++) { + mut.setX(pos.getX() + OFFSETS[i].x); + mut.setZ(pos.getZ() + OFFSETS[i].y); + if ((view.getBlockState(mut).is(EndBlocks.BRIMSTONE))) { + info.setReturnValue(i < 4 ? POISON_COLOR : STREAM_COLOR); + return; + } + } + } + } + + static { + HAS_SODIUM = FabricLoader.getInstance().isModLoaded("sodium"); + + int index = 0; + OFFSETS = new Point[20]; + for (int x = -2; x < 3; x++) { + for (int z = -2; z < 3; z++) { + if ((x != 0 || z != 0) && (Math.abs(x) != 2 || Math.abs(z) != 2)) { + OFFSETS[index++] = new Point(x, z); + } + } + } + Arrays.sort(OFFSETS, Comparator.comparingInt(pos -> MHelper.sqr(pos.x) + MHelper.sqr(pos.y))); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/CapeLayerMixin.java b/src/main/java/org/betterx/betterend/mixin/client/CapeLayerMixin.java new file mode 100644 index 00000000..e4e92128 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/CapeLayerMixin.java @@ -0,0 +1,36 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.layers.CapeLayer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; + +import com.mojang.blaze3d.vertex.PoseStack; +import org.betterx.betterend.item.ArmoredElytra; +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; + +@Mixin(CapeLayer.class) +public class CapeLayerMixin { + + @Inject(method = "render", at = @At("HEAD"), cancellable = true) + public void be_checkCustomElytra(PoseStack poseStack, + MultiBufferSource multiBufferSource, + int i, + AbstractClientPlayer abstractClientPlayer, + float f, + float g, + float h, + float j, + float k, + float l, + CallbackInfo info) { + ItemStack itemStack = abstractClientPlayer.getItemBySlot(EquipmentSlot.CHEST); + if (itemStack.getItem() instanceof ArmoredElytra) { + info.cancel(); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/EndEffectsMixin.java b/src/main/java/org/betterx/betterend/mixin/client/EndEffectsMixin.java new file mode 100644 index 00000000..368d151a --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/EndEffectsMixin.java @@ -0,0 +1,27 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.renderer.DimensionSpecialEffects.EndEffects; +import net.minecraft.world.phys.Vec3; + +import org.betterx.betterend.integration.Integrations; +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.CallbackInfoReturnable; + +@Mixin(value = EndEffects.class, priority = 10) +public class EndEffectsMixin { + @Inject(method = "getBrightnessDependentFogColor", at = @At("HEAD"), cancellable = true) + private void be_restoreBrightness(Vec3 color, float sunHeight, CallbackInfoReturnable info) { + if (Integrations.ENDERSCAPE.modIsInstalled()) { + info.setReturnValue(color.scale(0.15000000596046448D)); + } + } + + @Inject(method = "isFoggyAt", at = @At("HEAD"), cancellable = true) + private void be_restoreFog(int camX, int camY, CallbackInfoReturnable info) { + if (Integrations.ENDERSCAPE.modIsInstalled()) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/HumanoidMobRendererMixin.java b/src/main/java/org/betterx/betterend/mixin/client/HumanoidMobRendererMixin.java new file mode 100644 index 00000000..b84492a2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/HumanoidMobRendererMixin.java @@ -0,0 +1,32 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.HumanoidMobRenderer; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.world.entity.Mob; + +import org.betterx.betterend.client.render.ArmoredElytraLayer; +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; + +@Mixin(HumanoidMobRenderer.class) +public abstract class HumanoidMobRendererMixin> extends MobRenderer { + + public HumanoidMobRendererMixin(EntityRendererProvider.Context context, M entityModel, float f) { + super(context, entityModel, f); + } + + @Inject(method = "(Lnet/minecraft/client/renderer/entity/EntityRendererProvider$Context;Lnet/minecraft/client/model/HumanoidModel;FFFF)V", at = @At("TAIL")) + public void be_addCustomLayer(EntityRendererProvider.Context context, + M humanoidModel, + float f, + float g, + float h, + float i, + CallbackInfo ci) { + addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/ItemStackMixin.java b/src/main/java/org/betterx/betterend/mixin/client/ItemStackMixin.java new file mode 100644 index 00000000..8a062f9a --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/ItemStackMixin.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; + +import org.betterx.betterend.events.ItemTooltipCallback; +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.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ItemStack.class) +public class ItemStackMixin { + @Inject(method = "getTooltipLines", at = @At("RETURN")) + private void be_getTooltip(Player entity, + TooltipFlag tooltipContext, + CallbackInfoReturnable> info) { + ItemTooltipCallback.EVENT.invoker() + .getTooltip(entity, ItemStack.class.cast(this), tooltipContext, info.getReturnValue()); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/LocalPlayerMixin.java b/src/main/java/org/betterx/betterend/mixin/client/LocalPlayerMixin.java new file mode 100644 index 00000000..69036a63 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/LocalPlayerMixin.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.ProfilePublicKey; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.ItemStack; + +import com.mojang.authlib.GameProfile; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import org.jetbrains.annotations.Nullable; + +@Mixin(LocalPlayer.class) +public abstract class LocalPlayerMixin extends AbstractClientPlayer { + @Final + @Shadow + public ClientPacketListener connection; + + public LocalPlayerMixin(ClientLevel clientLevel, + GameProfile gameProfile, + @Nullable ProfilePublicKey profilePublicKey) { + super(clientLevel, gameProfile, profilePublicKey); + } + + @Inject(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getItemBySlot(Lnet/minecraft/world/entity/EquipmentSlot;)Lnet/minecraft/world/item/ItemStack;", shift = Shift.AFTER)) + public void be_aiStep(CallbackInfo info) { + ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); + if (itemStack.getItem() instanceof FallFlyingItem && ElytraItem.isFlyEnabled(itemStack) && tryToStartFallFlying()) { + connection.send(new ServerboundPlayerCommandPacket( + LocalPlayer.class.cast(this), + ServerboundPlayerCommandPacket.Action.START_FALL_FLYING + )); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/MinecraftClientMixin.java b/src/main/java/org/betterx/betterend/mixin/client/MinecraftClientMixin.java new file mode 100644 index 00000000..d60767d2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/MinecraftClientMixin.java @@ -0,0 +1,57 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.WinScreen; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.sounds.Music; +import net.minecraft.sounds.Musics; +import net.minecraft.world.level.Level; + +import org.betterx.bclib.util.MHelper; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Minecraft.class) +public class MinecraftClientMixin { + @Shadow + public LocalPlayer player; + + @Shadow + public Screen screen; + + @Final + @Shadow + public Gui gui; + + @Shadow + public ClientLevel level; + + @Inject(method = "getSituationalMusic", at = @At("HEAD"), cancellable = true) + private void be_getEndMusic(CallbackInfoReturnable info) { + if (!(this.screen instanceof WinScreen) && this.player != null) { + if (this.player.level.dimension() == Level.END) { + if (this.gui.getBossOverlay().shouldPlayMusic() && MHelper.lengthSqr( + this.player.getX(), + this.player.getZ() + ) < 250000) { + info.setReturnValue(Musics.END_BOSS); + } else { + Music sound = this.level.getBiomeManager() + .getNoiseBiomeAtPosition(this.player.blockPosition()) + .value() + .getBackgroundMusic() + .orElse(Musics.END); + info.setReturnValue(sound); + } + info.cancel(); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/ModelLoaderMixin.java b/src/main/java/org/betterx/betterend/mixin/client/ModelLoaderMixin.java new file mode 100644 index 00000000..afe83fd6 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/ModelLoaderMixin.java @@ -0,0 +1,29 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.resources.ResourceLocation; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(ModelBakery.class) +public abstract class ModelLoaderMixin { + @ModifyVariable(method = "loadModel", ordinal = 2, at = @At(value = "INVOKE")) + public ResourceLocation be_switchModel(ResourceLocation id) { + if (GeneratorOptions.changeChorusPlant() && be_changeModel(id)) { + String path = id.getPath().replace("chorus", "custom_chorus"); + id = BetterEnd.makeID(path); + } + return id; + } + + private boolean be_changeModel(ResourceLocation id) { + return id.getNamespace().equals("minecraft") + && id.getPath().startsWith("blockstates/") + && id.getPath().contains("chorus") + && !id.getPath().contains("custom_"); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/client/MusicTrackerMixin.java b/src/main/java/org/betterx/betterend/mixin/client/MusicTrackerMixin.java new file mode 100644 index 00000000..ab065970 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/client/MusicTrackerMixin.java @@ -0,0 +1,105 @@ +package org.betterx.betterend.mixin.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.AbstractSoundInstance; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.client.sounds.MusicManager; +import net.minecraft.sounds.Music; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.betterend.client.ClientOptions; +import org.betterx.betterend.world.biome.EndBiome; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MusicManager.class) +public abstract class MusicTrackerMixin { + @Final + @Shadow + private Minecraft minecraft; + + @Final + @Shadow + private RandomSource random; + + @Shadow + private SoundInstance currentMusic; + + @Shadow + private int nextSongDelay; + + private static float volume = 1; + private static float srcVolume = 0; + private static long time; + + @Inject(method = "tick", at = @At("HEAD"), cancellable = true) + public void be_onTick(CallbackInfo info) { + if (ClientOptions.blendBiomeMusic()) { + Music musicSound = minecraft.getSituationalMusic(); + if (be_checkNullSound(musicSound) && volume > 0 && be_shouldChangeSound(musicSound) && be_isCorrectBiome()) { + if (volume > 0) { + if (srcVolume < 0) { + srcVolume = currentMusic.getVolume(); + } + if (currentMusic instanceof AbstractSoundInstance) { + ((AbstractSoundInstanceAccessor) currentMusic).setVolume(volume); + } + minecraft.getSoundManager() + .updateSourceVolume(currentMusic.getSource(), currentMusic.getVolume() * volume); + long t = System.currentTimeMillis(); + if (volume == 1 && time == 0) { + time = t; + } + float delta = (t - time) * 0.0005F; + time = t; + volume -= delta; + if (volume < 0) { + volume = 0; + } + } + if (volume == 0) { + volume = 1; + time = 0; + srcVolume = -1; + this.minecraft.getSoundManager().stop(this.currentMusic); + this.nextSongDelay = Mth.nextInt(this.random, 0, musicSound.getMinDelay() / 2); + this.currentMusic = null; + } + if (this.currentMusic == null && this.nextSongDelay-- <= 0) { + this.startPlaying(musicSound); + } + info.cancel(); + } else { + volume = 1; + } + } + } + + private boolean be_isCorrectBiome() { + if (minecraft.level == null) { + return false; + } + return BiomeAPI.getRenderBiome(minecraft.level.getBiome(minecraft.player.blockPosition()) + .value()) instanceof EndBiome; + } + + private boolean be_shouldChangeSound(Music musicSound) { + return currentMusic != null && !musicSound + .getEvent() + .getLocation() + .equals(this.currentMusic.getLocation()) && musicSound.replaceCurrentMusic(); + } + + private boolean be_checkNullSound(Music musicSound) { + return musicSound != null && musicSound.getEvent() != null; + } + + @Shadow + public abstract void startPlaying(Music type); +} diff --git a/src/main/java/ru/betterend/mixin/client/PlayerRendererMixin.java b/src/main/java/org/betterx/betterend/mixin/client/PlayerRendererMixin.java similarity index 53% rename from src/main/java/ru/betterend/mixin/client/PlayerRendererMixin.java rename to src/main/java/org/betterx/betterend/mixin/client/PlayerRendererMixin.java index 52cb8ff4..871b104b 100644 --- a/src/main/java/ru/betterend/mixin/client/PlayerRendererMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/client/PlayerRendererMixin.java @@ -1,25 +1,28 @@ -package ru.betterend.mixin.client; +package org.betterx.betterend.mixin.client; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.player.PlayerRenderer; + +import org.betterx.betterend.client.render.ArmoredElytraLayer; 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 ru.betterend.client.render.ArmoredElytraLayer; @Mixin(PlayerRenderer.class) public abstract class PlayerRendererMixin extends LivingEntityRenderer> { - - public PlayerRendererMixin(EntityRendererProvider.Context context, PlayerModel entityModel, float f) { - super(context, entityModel, f); - } - - @Inject(method = "*", at = @At("TAIL")) - public void be_addCustomLayer(EntityRendererProvider.Context context, boolean bl, CallbackInfo ci) { - addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); - } + + public PlayerRendererMixin(EntityRendererProvider.Context context, + PlayerModel entityModel, + float f) { + super(context, entityModel, f); + } + + @Inject(method = "*", at = @At("TAIL")) + public void be_addCustomLayer(EntityRendererProvider.Context context, boolean bl, CallbackInfo ci) { + addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); + } } diff --git a/src/main/java/org/betterx/betterend/mixin/common/BlockBehaviourMixin.java b/src/main/java/org/betterx/betterend/mixin/common/BlockBehaviourMixin.java new file mode 100644 index 00000000..b48a39fc --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/BlockBehaviourMixin.java @@ -0,0 +1,49 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + +import com.google.common.collect.Lists; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.item.tool.EndHammerItem; +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.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(BlockBehaviour.class) +public abstract class BlockBehaviourMixin { + @Inject(method = "getDrops", at = @At("HEAD"), cancellable = true) + public void be_getDroppedStacks(BlockState state, + LootContext.Builder builder, + CallbackInfoReturnable> info) { + if (state.is(Blocks.GLOWSTONE)) { + ItemStack tool = builder.getParameter(LootContextParams.TOOL); + if (tool != null && tool.getItem() instanceof EndHammerItem) { + int min = 3; + int max = 4; + int count = 0; + int fortune = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool); + if (fortune > 0) { + fortune /= Enchantments.BLOCK_FORTUNE.getMaxLevel(); + min = Mth.clamp(min + fortune, min, max); + if (min == max) { + info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, max))); + } + } + count = MHelper.randRange(min, max, MHelper.RANDOM_SOURCE); + info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, count))); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/ChorusFlowerBlockMixin.java b/src/main/java/org/betterx/betterend/mixin/common/ChorusFlowerBlockMixin.java new file mode 100644 index 00000000..69824413 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/ChorusFlowerBlockMixin.java @@ -0,0 +1,100 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ChorusFlowerBlock; +import net.minecraft.world.level.block.ChorusPlantBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; + +@Mixin(value = ChorusFlowerBlock.class, priority = 100) +public abstract class ChorusFlowerBlockMixin extends Block { + private static final VoxelShape SHAPE_FULL = Block.box(0, 0, 0, 16, 16, 16); + private static final VoxelShape SHAPE_HALF = Block.box(0, 0, 0, 16, 4, 16); + + public ChorusFlowerBlockMixin(Properties settings) { + super(settings); + } + + @Final + @Shadow + private ChorusPlantBlock plant; + + @Inject(method = "canSurvive", at = @At("HEAD"), cancellable = true) + private void be_canSurvive(BlockState state, + LevelReader world, + BlockPos pos, + CallbackInfoReturnable info) { + if (world.getBlockState(pos.below()).is(EndBlocks.CHORUS_NYLIUM)) { + info.setReturnValue(true); + info.cancel(); + } + } + + @Inject(method = "randomTick", at = @At("HEAD"), cancellable = true) + private void be_randomTick(BlockState state, + ServerLevel world, + BlockPos pos, + RandomSource random, + CallbackInfo info) { + if (world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { + BlockPos up = pos.above(); + if (world.isEmptyBlock(up) && up.getY() < 256) { + int i = state.getValue(ChorusFlowerBlock.AGE); + if (i < 5) { + this.placeGrownFlower(world, up, i + 1); + BlocksHelper.setWithoutUpdate(world, + pos, + plant.defaultBlockState() + .setValue(ChorusPlantBlock.UP, true) + .setValue(ChorusPlantBlock.DOWN, true)); + info.cancel(); + } + } + } + } + + @Shadow + private void placeGrownFlower(Level world, BlockPos pos, int age) { + } + + @Override + @SuppressWarnings("deprecation") + public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { + if (GeneratorOptions.changeChorusPlant()) { + return state.getValue(ChorusFlowerBlock.AGE) == 5 ? SHAPE_HALF : SHAPE_FULL; + } else { + return super.getShape(state, world, pos, context); + } + } + + @Inject(method = "placeDeadFlower", at = @At("HEAD"), cancellable = true) + private void be_placeDeadFlower(Level world, BlockPos pos, CallbackInfo info) { + BlockState down = world.getBlockState(pos.below()); + if (down.is(Blocks.CHORUS_PLANT) || down.is(CommonBlockTags.GEN_END_STONES)) { + world.setBlock(pos, this.defaultBlockState().setValue(BlockStateProperties.AGE_5, 5), 2); + world.levelEvent(1034, pos, 0); + } + info.cancel(); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantBlockMixin.java b/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantBlockMixin.java new file mode 100644 index 00000000..c6ca4dd4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantBlockMixin.java @@ -0,0 +1,76 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ChorusPlantBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.betterend.registry.EndBlocks; +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.CallbackInfoReturnable; + +@Mixin(value = ChorusPlantBlock.class, priority = 100) +public abstract class ChorusPlantBlockMixin extends Block { + public ChorusPlantBlockMixin(Properties settings) { + super(settings); + } + + @Inject(method = "getStateForPlacement(Lnet/minecraft/world/item/context/BlockPlaceContext;)Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), cancellable = true) + private void be_getStateForPlacement(BlockPlaceContext ctx, CallbackInfoReturnable info) { + BlockPos pos = ctx.getClickedPos(); + Level world = ctx.getLevel(); + BlockState plant = info.getReturnValue(); + if (ctx.canPlace() && plant.is(Blocks.CHORUS_PLANT) && world.getBlockState(pos.below()) + .is(CommonBlockTags.END_STONES)) { + info.setReturnValue(plant.setValue(BlockStateProperties.DOWN, true)); + } + } + + @Inject(method = "Lnet/minecraft/world/level/block/ChorusPlantBlock;getStateForPlacement" + "(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)" + "Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), cancellable = true) + private void be_getStateForPlacement(BlockGetter blockGetter, + BlockPos blockPos, + CallbackInfoReturnable info) { + BlockState plant = info.getReturnValue(); + if (plant.is(Blocks.CHORUS_PLANT) && blockGetter.getBlockState(blockPos.below()) + .is(CommonBlockTags.END_STONES)) { + info.setReturnValue(plant.setValue(BlockStateProperties.DOWN, true)); + } + } + + @Inject(method = "canSurvive", at = @At("HEAD"), cancellable = true) + private void be_canSurvive(BlockState state, + LevelReader world, + BlockPos pos, + CallbackInfoReturnable info) { + BlockState down = world.getBlockState(pos.below()); + if (down.is(EndBlocks.CHORUS_NYLIUM) || down.is(Blocks.END_STONE)) { + info.setReturnValue(true); + } + } + + @Inject(method = "updateShape", at = @At("RETURN"), cancellable = true) + private void be_updateShape(BlockState state, + Direction direction, + BlockState newState, + LevelAccessor world, + BlockPos pos, + BlockPos posFrom, + CallbackInfoReturnable info) { + BlockState plant = info.getReturnValue(); + if (plant.is(Blocks.CHORUS_PLANT) && world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { + plant = plant.setValue(BlockStateProperties.DOWN, true); + info.setReturnValue(plant); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantFeatureMixin.java b/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantFeatureMixin.java new file mode 100644 index 00000000..bcab1ed7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/ChorusPlantFeatureMixin.java @@ -0,0 +1,44 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ChorusFlowerBlock; +import net.minecraft.world.level.block.PipeBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.ChorusPlantFeature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +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.CallbackInfoReturnable; + +@Mixin(ChorusPlantFeature.class) +public class ChorusPlantFeatureMixin { + @Inject(method = "place", at = @At("HEAD"), cancellable = true) + private void be_place(FeaturePlaceContext featureConfig, + CallbackInfoReturnable info) { + final RandomSource random = featureConfig.random(); + final BlockPos blockPos = featureConfig.origin(); + final WorldGenLevel structureWorldAccess = featureConfig.level(); + if (structureWorldAccess.isEmptyBlock(blockPos) && structureWorldAccess.getBlockState(blockPos.below()) + .is(EndBlocks.CHORUS_NYLIUM)) { + ChorusFlowerBlock.generatePlant(structureWorldAccess, blockPos, random, MHelper.randRange(8, 16, random)); + BlockState bottom = structureWorldAccess.getBlockState(blockPos); + if (bottom.is(Blocks.CHORUS_PLANT)) { + BlocksHelper.setWithoutUpdate( + structureWorldAccess, + blockPos, + bottom.setValue(PipeBlock.DOWN, true) + ); + } + info.setReturnValue(true); + } + } +} diff --git a/src/main/java/ru/betterend/mixin/common/CraftingMenuMixin.java b/src/main/java/org/betterx/betterend/mixin/common/CraftingMenuMixin.java similarity index 55% rename from src/main/java/ru/betterend/mixin/common/CraftingMenuMixin.java rename to src/main/java/org/betterx/betterend/mixin/common/CraftingMenuMixin.java index 8dfce982..ee74d62b 100644 --- a/src/main/java/ru/betterend/mixin/common/CraftingMenuMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/common/CraftingMenuMixin.java @@ -1,28 +1,29 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ContainerLevelAccess; -import net.minecraft.world.inventory.CraftingMenu; -import net.minecraft.world.level.block.CraftingTableBlock; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(CraftingMenu.class) -public abstract class CraftingMenuMixin { - @Final - @Shadow - private ContainerLevelAccess access; - - @Inject(method = "stillValid", at = @At("HEAD"), cancellable = true) - private void be_stillValid(Player player, CallbackInfoReturnable info) { - if (access.evaluate((world, pos) -> { - return world.getBlockState(pos).getBlock() instanceof CraftingTableBlock; - }, true)) { - info.setReturnValue(true); - } - } -} +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.CraftingMenu; +import net.minecraft.world.level.block.CraftingTableBlock; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(CraftingMenu.class) +public abstract class CraftingMenuMixin { + @Final + @Shadow + private ContainerLevelAccess access; + + @Inject(method = "stillValid", at = @At("HEAD"), cancellable = true) + private void be_stillValid(Player player, CallbackInfoReturnable info) { + if (access.evaluate((world, pos) -> { + return world.getBlockState(pos).getBlock() instanceof CraftingTableBlock; + }, true)) { + info.setReturnValue(true); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EnchantmentMenuMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EnchantmentMenuMixin.java new file mode 100644 index 00000000..a537fd32 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EnchantmentMenuMixin.java @@ -0,0 +1,147 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.Registry; +import net.minecraft.util.RandomSource; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.*; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.EnchantmentInstance; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(EnchantmentMenu.class) +public abstract class EnchantmentMenuMixin extends AbstractContainerMenu { + @Final + @Shadow + private Container enchantSlots; + + @Final + @Shadow + private ContainerLevelAccess access; + + @Final + @Shadow + private RandomSource random; + + @Final + @Shadow + private DataSlot enchantmentSeed; + + @Shadow + @Final + public int[] costs; + + @Shadow + @Final + public int[] enchantClue; + + @Shadow + @Final + public int[] levelClue; + + protected EnchantmentMenuMixin(MenuType type, int syncId) { + super(type, syncId); + } + + @Inject(method = "slotsChanged", at = @At("HEAD"), cancellable = true) + private void be_slotsChanged(Container inventory, CallbackInfo info) { + if (inventory == this.enchantSlots) { + ItemStack itemStack = inventory.getItem(0); + if (!itemStack.isEmpty() && itemStack.isEnchantable()) { + this.access.execute((world, blockPos) -> { + int i = 0; + + int j; + for (j = -1; j <= 1; ++j) { + for (int k = -1; k <= 1; ++k) { + if ((j != 0 || k != 0) && world.isEmptyBlock(blockPos.offset( + k, + 0, + j + )) && world.isEmptyBlock( + blockPos.offset(k, 1, j))) { + if (world.getBlockState(blockPos.offset(k * 2, 0, j * 2)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + + if (world.getBlockState(blockPos.offset(k * 2, 1, j * 2)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + + if (k != 0 && j != 0) { + if (world.getBlockState(blockPos.offset(k * 2, 0, j)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + + if (world.getBlockState(blockPos.offset(k * 2, 1, j)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + + if (world.getBlockState(blockPos.offset(k, 0, j * 2)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + + if (world.getBlockState(blockPos.offset(k, 1, j * 2)) + .is(CommonBlockTags.BOOKSHELVES)) { + ++i; + } + } + } + } + } + + random.setSeed(enchantmentSeed.get()); + + for (j = 0; j < 3; ++j) { + costs[j] = EnchantmentHelper.getEnchantmentCost(this.random, j, i, itemStack); + enchantClue[j] = -1; + levelClue[j] = -1; + if (costs[j] < j + 1) { + costs[j] = 0; + } + } + + for (j = 0; j < 3; ++j) { + if (this.costs[j] > 0) { + List list = this.getEnchantmentList(itemStack, j, this.costs[j]); + if (list != null && !list.isEmpty()) { + EnchantmentInstance enchantmentLevelEntry = list.get(this.random.nextInt( + list.size())); + enchantClue[j] = Registry.ENCHANTMENT.getId(enchantmentLevelEntry.enchantment); + levelClue[j] = enchantmentLevelEntry.level; + } + } + } + + broadcastChanges(); + }); + } else { + for (int i = 0; i < 3; ++i) { + costs[i] = 0; + enchantClue[i] = -1; + levelClue[i] = -1; + } + } + info.cancel(); + } + } + + @Shadow + private List getEnchantmentList(ItemStack stack, int slot, int level) { + return null; + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EndCityFeatureMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EndCityFeatureMixin.java new file mode 100644 index 00000000..0fd6665d --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EndCityFeatureMixin.java @@ -0,0 +1,33 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.world.level.levelgen.XoroshiroRandomSource; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.structures.EndCityStructure; + +import org.betterx.betterend.world.generator.GeneratorOptions; +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.CallbackInfoReturnable; + +import java.util.Optional; + +@Mixin(EndCityStructure.class) +public class EndCityFeatureMixin { + @Inject(method = "findGenerationPoint", at = @At("HEAD"), cancellable = true) + private void be_findGenerationPoint(Structure.GenerationContext context, + CallbackInfoReturnable> info) { + final ChunkPos pos = context.chunkPos(); + WorldgenRandom chunkRandom = new WorldgenRandom(new XoroshiroRandomSource(pos.x, pos.z)); + + if (GeneratorOptions.useNewGenerator()) { + int chance = GeneratorOptions.getEndCityFailChance(); + if (chance > 0 && chunkRandom.nextInt(chance) != 0) { + info.setReturnValue(Optional.empty()); + info.cancel(); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EndDragonFightMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EndDragonFightMixin.java new file mode 100644 index 00000000..5b8fcfad --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EndDragonFightMixin.java @@ -0,0 +1,100 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.pattern.BlockPattern; +import net.minecraft.world.level.dimension.end.DragonRespawnAnimation; +import net.minecraft.world.level.dimension.end.EndDragonFight; +import net.minecraft.world.phys.AABB; + +import com.google.common.collect.Lists; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(EndDragonFight.class) +public class EndDragonFightMixin { + @Shadow + private DragonRespawnAnimation respawnStage; + @Shadow + private boolean dragonKilled; + @Shadow + private BlockPos portalLocation; + @Shadow + @Final + private static Logger LOGGER; + @Final + @Shadow + private ServerLevel level; + + @Shadow + private BlockPattern.BlockPatternMatch findExitPortal() { + return null; + } + + @Shadow + private void spawnExitPortal(boolean bl) { + } + + @Shadow + private void respawnDragon(List list) { + } + + @Inject(method = "tryRespawn", at = @At("HEAD"), cancellable = true) + private void be_tryRespawnDragon(CallbackInfo info) { + if (GeneratorOptions.replacePortal() && GeneratorOptions.hasDragonFights() && this.dragonKilled && this.respawnStage == null) { + BlockPos blockPos = portalLocation; + if (blockPos == null) { + LOGGER.debug("Tried to respawn, but need to find the portal first."); + BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); + if (blockPatternMatch == null) { + LOGGER.debug("Couldn't find a portal, so we made one."); + spawnExitPortal(true); + } else { + LOGGER.debug("Found the exit portal & temporarily using it."); + } + } + + List crystals = Lists.newArrayList(); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos central = BlockPos.ZERO.relative(dir, 4); + List crystalList = level.getEntitiesOfClass( + EndCrystal.class, + new AABB(central.below(255).south().west(), central.above(255).north().east()) + ); + + int count = crystalList.size(); + for (int n = 0; n < count; n++) { + EndCrystal crystal = crystalList.get(n); + if (!level.getBlockState(crystal.blockPosition().below()).is(Blocks.BEDROCK)) { + crystalList.remove(n); + count--; + n--; + } + } + + if (crystalList.isEmpty()) { + info.cancel(); + return; + } + + crystals.addAll(crystalList); + } + + LOGGER.debug("Found all crystals, respawning dragon."); + respawnDragon(crystals); + info.cancel(); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EndPodiumFeatureMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EndPodiumFeatureMixin.java new file mode 100644 index 00000000..9f33b4da --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EndPodiumFeatureMixin.java @@ -0,0 +1,93 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.feature.EndPodiumFeature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import org.betterx.bclib.api.WorldDataAPI; +import org.betterx.bclib.util.StructureHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + +@Mixin(EndPodiumFeature.class) +public class EndPodiumFeatureMixin { + private static BlockPos be_portalPosition; + + @Final + @Shadow + private boolean active; + + @Inject(method = "place", at = @At("HEAD"), cancellable = true) + private void be_place(FeaturePlaceContext featurePlaceContext, + CallbackInfoReturnable info) { + if (!GeneratorOptions.hasPortal()) { + info.setReturnValue(false); + info.cancel(); + } else if (GeneratorOptions.replacePortal()) { + RandomSource random = featurePlaceContext.random(); + WorldGenLevel world = featurePlaceContext.level(); + BlockPos blockPos = be_updatePortalPos(world); + StructureTemplate structure = StructureHelper.readStructure(BetterEnd.makeID(active + ? "portal/end_portal_active" + : "portal/end_portal_inactive")); + Vec3i size = structure.getSize(); + blockPos = blockPos.offset(-(size.getX() >> 1), -3, -(size.getZ() >> 1)); + structure.placeInWorld(world, blockPos, blockPos, new StructurePlaceSettings(), random, 2); + info.setReturnValue(true); + info.cancel(); + } + } + + @ModifyVariable(method = "place", ordinal = 0, at = @At("HEAD")) + private FeaturePlaceContext be_setPosOnGround(FeaturePlaceContext featurePlaceContext) { + WorldGenLevel world = featurePlaceContext.level(); + BlockPos pos = be_updatePortalPos(world); + return new FeaturePlaceContext( + Optional.empty(), + world, + featurePlaceContext.chunkGenerator(), + featurePlaceContext.random(), + pos, + featurePlaceContext.config() + ); + } + + private BlockPos be_updatePortalPos(WorldGenLevel world) { + CompoundTag compound = WorldDataAPI.getRootTag(BetterEnd.MOD_ID).getCompound("portal"); + be_portalPosition = NbtUtils.readBlockPos(compound); + + if (be_portalPosition.getY() == 0) { + /*if (GeneratorOptions.useNewGenerator()) { + int y = TerrainGenerator.getHeight(0, 0, world.getLevel().getChunkSource().getGenerator().getBiomeSource()); + be_portalPosition = new BlockPos(0, y, 0); + } + else { + be_portalPosition = new BlockPos(0, 65, 0); + }*/ + int y = world.getHeight(Types.WORLD_SURFACE, 0, 0); + be_portalPosition = new BlockPos(0, y, 0); + WorldDataAPI.getRootTag(BetterEnd.MOD_ID).put("portal", NbtUtils.writeBlockPos(be_portalPosition)); + WorldDataAPI.saveFile(BetterEnd.MOD_ID); + } + + return be_portalPosition; + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EndSpikeMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EndSpikeMixin.java new file mode 100644 index 00000000..b9a336be --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EndSpikeMixin.java @@ -0,0 +1,44 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.levelgen.feature.SpikeFeature.EndSpike; + +import org.betterx.bclib.api.WorldDataAPI; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EndSpike.class) +public class EndSpikeMixin { + @Final + @Shadow + private int height; + + @Inject(method = "getHeight", at = @At("HEAD"), cancellable = true) + private void be_getSpikeHeight(CallbackInfoReturnable info) { + if (!GeneratorOptions.isDirectSpikeHeight()) { + int x = getCenterX(); + int z = getCenterZ(); + String pillarID = String.format("%d_%d", x, z); + CompoundTag pillar = WorldDataAPI.getCompoundTag(BetterEnd.MOD_ID, "pillars"); + int minY = pillar.contains(pillarID) ? pillar.getInt(pillarID) : 65; + int maxY = minY + height - 54; + info.setReturnValue(maxY); + } + } + + @Shadow + public int getCenterX() { + return 0; + } + + @Shadow + public int getCenterZ() { + return 0; + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EnderManMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EnderManMixin.java new file mode 100644 index 00000000..477aad27 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EnderManMixin.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.enchantment.EnchantmentHelper; + +import org.betterx.betterend.effects.EndStatusEffects; +import org.betterx.betterend.registry.EndEnchantments; +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.CallbackInfoReturnable; + +@Mixin(EnderMan.class) +public abstract class EnderManMixin { + @Inject(method = "isLookingAtMe", at = @At("HEAD"), cancellable = true) + private void be_isLookingAtMe(Player player, CallbackInfoReturnable info) { + if (player.isCreative() || player.hasEffect(EndStatusEffects.END_VEIL) || EnchantmentHelper.getItemEnchantmentLevel( + EndEnchantments.END_VEIL, + player.getItemBySlot(EquipmentSlot.HEAD) + ) > 0) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/EntityMixin.java b/src/main/java/org/betterx/betterend/mixin/common/EntityMixin.java new file mode 100644 index 00000000..b8f29579 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/EntityMixin.java @@ -0,0 +1,110 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.portal.PortalInfo; +import net.minecraft.world.phys.Vec3; + +import org.betterx.betterend.interfaces.TeleportingEntity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Entity.class) +public abstract class EntityMixin implements TeleportingEntity { + @Shadow + private float yRot; + @Shadow + private float xRot; + + @Shadow + public Level level; + + @Final + @Shadow + public abstract void unRide(); + + @Shadow + public abstract Vec3 getDeltaMovement(); + + @Shadow + public abstract EntityType getType(); + + @Shadow + protected abstract PortalInfo findDimensionEntryPoint(ServerLevel destination); + + @Shadow + protected abstract void removeAfterChangingDimensions(); + + @Shadow + public abstract boolean isRemoved(); + + private BlockPos exitPos; + + @Inject(method = "changeDimension", at = @At("HEAD"), cancellable = true) + public void be_changeDimension(ServerLevel destination, CallbackInfoReturnable info) { + if (!isRemoved() && be_canTeleport() && level instanceof ServerLevel) { + unRide(); + level.getProfiler().push("changeDimension"); + level.getProfiler().push("reposition"); + PortalInfo teleportTarget = findDimensionEntryPoint(destination); + if (teleportTarget != null) { + level.getProfiler().popPush("reloading"); + Entity entity = getType().create(destination); + if (entity != null) { + entity.restoreFrom(Entity.class.cast(this)); + entity.moveTo( + teleportTarget.pos.x, + teleportTarget.pos.y, + teleportTarget.pos.z, + teleportTarget.yRot, + entity.getXRot() + ); + entity.setDeltaMovement(teleportTarget.speed); + destination.addDuringTeleport(entity); + } + + this.removeAfterChangingDimensions(); + level.getProfiler().pop(); + ((ServerLevel) level).resetEmptyTime(); + destination.resetEmptyTime(); + level.getProfiler().pop(); + be_resetExitPos(); + info.setReturnValue(entity); + } + } + } + + @Inject(method = "findDimensionEntryPoint", at = @At("HEAD"), cancellable = true) + protected void be_findDimensionEntryPoint(ServerLevel destination, CallbackInfoReturnable info) { + if (be_canTeleport()) { + info.setReturnValue(new PortalInfo( + new Vec3(exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5), + getDeltaMovement(), + yRot, + xRot + )); + } + } + + @Override + public void be_setExitPos(BlockPos pos) { + this.exitPos = pos.immutable(); + } + + @Override + public void be_resetExitPos() { + this.exitPos = null; + } + + @Override + public boolean be_canTeleport() { + return this.exitPos != null; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/LevelMixin.java b/src/main/java/org/betterx/betterend/mixin/common/LevelMixin.java similarity index 88% rename from src/main/java/ru/betterend/mixin/common/LevelMixin.java rename to src/main/java/org/betterx/betterend/mixin/common/LevelMixin.java index 49d3f80f..7649b06b 100644 --- a/src/main/java/ru/betterend/mixin/common/LevelMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/common/LevelMixin.java @@ -1,14 +1,14 @@ -package ru.betterend.mixin.common; +package org.betterx.betterend.mixin.common; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; +import org.betterx.betterend.world.generator.GeneratorOptions; 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.CallbackInfoReturnable; -import ru.betterend.world.generator.GeneratorOptions; @Mixin(Level.class) public class LevelMixin { diff --git a/src/main/java/org/betterx/betterend/mixin/common/LivingEntityMixin.java b/src/main/java/org/betterx/betterend/mixin/common/LivingEntityMixin.java new file mode 100644 index 00000000..031a24a2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/LivingEntityMixin.java @@ -0,0 +1,288 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.EntityTypeTags; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeMap; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.FlyingAnimal; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.interfaces.MobEffectApplier; +import org.betterx.betterend.item.CrystaliteArmor; +import org.betterx.betterend.registry.EndAttributes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Collection; + +@Mixin(value = LivingEntity.class, priority = 200) +public abstract class LivingEntityMixin extends Entity { + + public LivingEntityMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + @Shadow + protected int fallFlyTicks; + + @Shadow + public abstract boolean hasEffect(MobEffect mobEffect); + + @Shadow + public abstract ItemStack getItemBySlot(EquipmentSlot equipmentSlot); + + @Shadow + public abstract void calculateEntityAnimation(LivingEntity livingEntity, boolean b); + + @Shadow + protected abstract SoundEvent getFallDamageSound(int i); + + @Shadow + public abstract boolean isFallFlying(); + + @Shadow + public abstract AttributeMap getAttributes(); + + private Entity lastAttacker; + + @Inject(method = "createLivingAttributes", at = @At("RETURN"), cancellable = true) + private static void be_addLivingAttributes(CallbackInfoReturnable info) { + EndAttributes.addLivingEntityAttributes(info.getReturnValue()); + } + + @Inject(method = "tickEffects", at = @At("HEAD")) + protected void be_applyEffects(CallbackInfo info) { + if (!level.isClientSide()) { + LivingEntity owner = LivingEntity.class.cast(this); + if (CrystaliteArmor.hasFullSet(owner)) { + CrystaliteArmor.applySetEffect(owner); + } + getArmorSlots().forEach(itemStack -> { + if (itemStack.getItem() instanceof MobEffectApplier) { + ((MobEffectApplier) itemStack.getItem()).applyEffect(owner); + } + }); + } + } + + @Inject(method = "canBeAffected", at = @At("HEAD"), cancellable = true) + public void be_canBeAffected(MobEffectInstance mobEffectInstance, CallbackInfoReturnable info) { + try { + if (mobEffectInstance.getEffect() == MobEffects.BLINDNESS && getAttributes().getValue(EndAttributes.BLINDNESS_RESISTANCE) > 0.0) { + info.setReturnValue(false); + } + } catch (Exception ex) { + BetterEnd.LOGGER.warning("Blindness resistance attribute haven't been registered."); + } + } + + @Inject(method = "hurt", at = @At("HEAD")) + public void be_hurt(DamageSource source, float amount, CallbackInfoReturnable info) { + this.lastAttacker = source.getEntity(); + } + + @ModifyArg(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), index = 0) + private double be_increaseKnockback(double value, double x, double z) { + if (lastAttacker != null && lastAttacker instanceof LivingEntity) { + LivingEntity attacker = (LivingEntity) lastAttacker; + value += this.be_getKnockback(attacker.getMainHandItem().getItem()); + } + return value; + } + + // FlyFallingLib (part of Origin) redirected the call to updateFallFlying, + // so we inject our code before the actual call and cancel the execution if the player is still + // flying. That means we have to replicate all vanilla code that happens after the call to + // updateFallFlying. We do this in vanillaAfterUpdateFallFlying + @Inject(method = "aiStep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;updateFallFlying()V")) + private void be_updateFallFlying_originFix(CallbackInfo info) { + //run be_updateFallFlying instead + if (!BetterEnd.RUNS_FALL_FLYING_LIB) return; + + if (be_updateFallFlyingCommon()) { + vanillaAfterUpdateFallFlying(); + info.cancel(); + } + } + + @Inject(method = "updateFallFlying", at = @At("HEAD"), cancellable = true) + private void be_updateFallFlying(CallbackInfo info) { + //run be_updateFallFlying_originFix instead? + if (BetterEnd.RUNS_FALL_FLYING_LIB) return; + if (be_updateFallFlyingCommon()) { + info.cancel(); + } + } + + private boolean be_updateFallFlyingCommon() { + ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); + if (!level.isClientSide && itemStack.getItem() instanceof FallFlyingItem) { + boolean isFlying = getSharedFlag(7); + if (isFlying && !onGround && !isPassenger() && !hasEffect(MobEffects.LEVITATION)) { + if (ElytraItem.isFlyEnabled(itemStack)) { + int level = 20 + EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, itemStack) * 5; + if ((fallFlyTicks + 1) % level == 0) { + itemStack.hurtAndBreak( + 1, + LivingEntity.class.cast(this), + livingEntity -> livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST) + ); + } + isFlying = true; + } else { + isFlying = false; + } + } else { + isFlying = false; + } + setSharedFlag(7, isFlying); + return isFlying; + } + return false; + } + + @Shadow + protected abstract void removeFrost(); + @Shadow + protected abstract void tryAddFrost(); + @Shadow + protected abstract void pushEntities(); + @Shadow + protected abstract void checkAutoSpinAttack(AABB aABB, AABB aABB2); + + @Shadow + protected int autoSpinAttackTicks; + + private void vanillaAfterUpdateFallFlying() { + LivingEntity self = (LivingEntity) (Object) this; + AABB aABB = this.getBoundingBox(); + self.travel(new Vec3(self.xxa, self.yya, self.zza)); + this.level.getProfiler().pop(); + this.level.getProfiler().push("freezing"); + boolean bl2 = this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES); + int o; + if (!this.level.isClientSide && !self.isDeadOrDying()) { + o = this.getTicksFrozen(); + if (this.isInPowderSnow && this.canFreeze()) { + this.setTicksFrozen(Math.min(this.getTicksRequiredToFreeze(), o + 1)); + } else { + this.setTicksFrozen(Math.max(0, o - 2)); + } + } + + this.removeFrost(); + this.tryAddFrost(); + if (!this.level.isClientSide && this.tickCount % 40 == 0 && this.isFullyFrozen() && this.canFreeze()) { + o = bl2 ? 5 : 1; + this.hurt(DamageSource.FREEZE, (float) o); + } + + this.level.getProfiler().pop(); + this.level.getProfiler().push("push"); + if (this.autoSpinAttackTicks > 0) { + --this.autoSpinAttackTicks; + this.checkAutoSpinAttack(aABB, this.getBoundingBox()); + } + + this.pushEntities(); + this.level.getProfiler().pop(); + if (!this.level.isClientSide && self.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); + } + } + + + @Inject(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isFallFlying()Z", shift = Shift.AFTER), cancellable = true) + public void be_travel(Vec3 vec3, CallbackInfo info) { + ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); + if (isFallFlying() && itemStack.getItem() instanceof FallFlyingItem) { + Vec3 moveDelta = getDeltaMovement(); + if (moveDelta.y > -0.5D) { + fallDistance = 1.0F; + } + + Vec3 lookAngle = getLookAngle(); + double d = 0.08D; + float rotX = getXRot() * 0.017453292F; + double k = Math.sqrt(lookAngle.x * lookAngle.x + lookAngle.z * lookAngle.z); + double l = moveDelta.horizontalDistance(); + double lookLen = lookAngle.length(); + float n = Mth.cos(rotX); + n = (float) (n * n * Math.min(1.0D, lookLen / 0.4D)); + moveDelta = getDeltaMovement().add(0.0D, d * (-1.0D + (double) n * 0.75D), 0.0D); + double coef; + if (moveDelta.y < 0.0D && k > 0.0D) { + coef = moveDelta.y * -0.1D * (double) n; + moveDelta = moveDelta.add(lookAngle.x * coef / k, coef, lookAngle.z * coef / k); + } + + if (rotX < 0.0F && k > 0.0D) { + coef = l * (double) (-Mth.sin(rotX)) * 0.04D; + moveDelta = moveDelta.add(-lookAngle.x * coef / k, coef * 3.2D, -lookAngle.z * coef / k); + } + + if (k > 0.0D) { + moveDelta = moveDelta.add( + (lookAngle.x / k * l - moveDelta.x) * 0.1D, + 0.0D, + (lookAngle.z / k * l - moveDelta.z) * 0.1D + ); + } + moveDelta = moveDelta.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D); + double movementFactor = ((FallFlyingItem) itemStack.getItem()).getMovementFactor(); + moveDelta = moveDelta.multiply(movementFactor, 1.0D, movementFactor); + setDeltaMovement(moveDelta); + move(MoverType.SELF, moveDelta); + if (!level.isClientSide) { + if (horizontalCollision) { + coef = moveDelta.horizontalDistance(); + double r = l - coef; + float dmg = (float) (r * 10.0D - 3.0D); + if (dmg > 0.0F) { + playSound(getFallDamageSound((int) dmg), 1.0F, 1.0F); + hurt(DamageSource.FLY_INTO_WALL, dmg); + } + } + if (onGround) { + setSharedFlag(7, false); + } + } + + calculateEntityAnimation(LivingEntity.class.cast(this), this instanceof FlyingAnimal); + info.cancel(); + } + } + + private double be_getKnockback(Item tool) { + if (tool == null) return 0.0D; + Collection modifiers = tool.getDefaultAttributeModifiers(EquipmentSlot.MAINHAND) + .get(Attributes.ATTACK_KNOCKBACK); + if (modifiers.size() > 0) { + return modifiers.iterator().next().getAmount(); + } + return 0.0D; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/MappedRegistryMixin.java b/src/main/java/org/betterx/betterend/mixin/common/MappedRegistryMixin.java similarity index 54% rename from src/main/java/ru/betterend/mixin/common/MappedRegistryMixin.java rename to src/main/java/org/betterx/betterend/mixin/common/MappedRegistryMixin.java index 323872c3..a70235f5 100644 --- a/src/main/java/ru/betterend/mixin/common/MappedRegistryMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/common/MappedRegistryMixin.java @@ -1,7 +1,8 @@ -package ru.betterend.mixin.common; +package org.betterx.betterend.mixin.common; import net.minecraft.core.MappedRegistry; import net.minecraft.resources.ResourceKey; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -9,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(MappedRegistry.class) public class MappedRegistryMixin { - // TODO Make this a part of BCLib (implement froze/unfroze methods) - @Inject(method = "validateWrite", at = @At("HEAD"), cancellable = true) - private void be_validateWrite(ResourceKey resourceKey, CallbackInfo info) { - info.cancel(); - } + // TODO Make this a part of BCLib (implement froze/unfroze methods) + @Inject(method = "validateWrite", at = @At("HEAD"), cancellable = true) + private void be_validateWrite(ResourceKey resourceKey, CallbackInfo info) { + info.cancel(); + } } diff --git a/src/main/java/org/betterx/betterend/mixin/common/MonsterMixin.java b/src/main/java/org/betterx/betterend/mixin/common/MonsterMixin.java new file mode 100644 index 00000000..977fdd32 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/MonsterMixin.java @@ -0,0 +1,37 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.phys.AABB; + +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.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(Monster.class) +public class MonsterMixin { + @Inject(method = "checkMonsterSpawnRules", at = @At(value = "RETURN"), cancellable = true) + private static void be_checkMonsterSpawnRules(EntityType type, + ServerLevelAccessor serverWorldAccess, + MobSpawnType spawnReason, + BlockPos pos, + RandomSource random, + CallbackInfoReturnable info) { + boolean canSpawn = info.getReturnValue(); + if (canSpawn && spawnReason == MobSpawnType.NATURAL && type == EntityType.ENDERMAN) { + AABB box = new AABB(pos).inflate(16); + List entities = serverWorldAccess.getEntitiesOfClass(EnderMan.class, box, (entity) -> { + return true; + }); + info.setReturnValue(entities.size() < 6); + } + } +} diff --git a/src/main/java/ru/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java b/src/main/java/org/betterx/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java similarity index 74% rename from src/main/java/ru/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java rename to src/main/java/org/betterx/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java index ed2963d1..2cd456cd 100644 --- a/src/main/java/ru/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java +++ b/src/main/java/org/betterx/betterend/mixin/common/NoiseBasedChunkGeneratorAccessor.java @@ -1,13 +1,14 @@ -package ru.betterend.mixin.common; +package org.betterx.betterend.mixin.common; import net.minecraft.core.Holder; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(NoiseBasedChunkGenerator.class) public interface NoiseBasedChunkGeneratorAccessor { - @Accessor("settings") - Holder be_getSettings(); + @Accessor("settings") + Holder be_getSettings(); } diff --git a/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkAccessor.java b/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkAccessor.java new file mode 100644 index 00000000..73bdbfa6 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkAccessor.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.level.levelgen.NoiseChunk; +import net.minecraft.world.level.levelgen.NoiseSettings; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(NoiseChunk.class) +public interface NoiseChunkAccessor { + @Accessor("noiseSettings") + NoiseSettings bnv_getNoiseSettings(); + + @Accessor("cellCountXZ") + int bnv_getCellCountXZ(); + + @Accessor("cellCountY") + int bnv_getCellCountY(); + + @Accessor("firstCellZ") + int bnv_getFirstCellZ(); + + @Accessor("cellNoiseMinY") + int bnv_getCellNoiseMinY(); +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkMixin.java b/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkMixin.java new file mode 100644 index 00000000..82fc06c0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/NoiseChunkMixin.java @@ -0,0 +1,79 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.level.levelgen.*; +import net.minecraft.world.level.levelgen.blending.Blender; + +import org.betterx.bclib.BCLib; +import org.betterx.betterend.interfaces.BETargetChecker; +import org.betterx.betterend.world.generator.TerrainGenerator; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(NoiseChunk.class) +public class NoiseChunkMixin implements BETargetChecker { + private boolean be_isEndGenerator; + + @Inject(method = "*", at = @At("TAIL")) + private void be_onNoiseChunkInit(int i, + RandomState randomState, + int j, + int k, + NoiseSettings noiseSettings, + DensityFunctions.BeardifierOrMarker beardifierOrMarker, + NoiseGeneratorSettings noiseGeneratorSettings, + Aquifer.FluidPicker fluidPicker, + Blender blender, + CallbackInfo ci) { + var o = BETargetChecker.class.cast(noiseGeneratorSettings); + if (o != null) be_isEndGenerator = o.be_isTarget(); + else BCLib.LOGGER.warning(noiseGeneratorSettings + " has unknown implementation."); + } + + @Override + public boolean be_isTarget() { + return be_isEndGenerator; + } + + @Override + public void be_setTarget(boolean target) { + be_isEndGenerator = target; + } + + @Shadow + @Final + private List interpolators; + + @Inject(method = "fillSlice", at = @At("HEAD"), cancellable = true) + private void be_fillSlice(boolean primarySlice, int x, CallbackInfo info) { + if (!be_isTarget()) return; + + info.cancel(); + + NoiseChunkAccessor accessor = (NoiseChunkAccessor) this; + NoiseSettings noiseSettings = accessor.bnv_getNoiseSettings(); + + final int sizeY = noiseSettings.getCellHeight(); + final int sizeXZ = noiseSettings.getCellWidth(); + final int cellSizeXZ = accessor.bnv_getCellCountXZ() + 1; + final int firstCellZ = accessor.bnv_getFirstCellZ(); + + x *= sizeXZ; + for (int cellXZ = 0; cellXZ < cellSizeXZ; ++cellXZ) { + int z = (firstCellZ + cellXZ) * sizeXZ; + for (NoiseChunk.NoiseInterpolator noiseInterpolator : this.interpolators) { + if (noiseInterpolator instanceof NoiseInterpolatorAccessor interpolator) { + final double[] ds = (primarySlice + ? interpolator.be_getSlice0() + : interpolator.be_getSlice1())[cellXZ]; + TerrainGenerator.fillTerrainDensity(ds, x, z, sizeXZ, sizeY); + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/NoiseGeneratorSettingsMixin.java b/src/main/java/org/betterx/betterend/mixin/common/NoiseGeneratorSettingsMixin.java new file mode 100644 index 00000000..f2cd7e3a --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/NoiseGeneratorSettingsMixin.java @@ -0,0 +1,21 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; + +import org.betterx.betterend.interfaces.BETargetChecker; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(NoiseGeneratorSettings.class) +public class NoiseGeneratorSettingsMixin implements BETargetChecker { + private boolean be_isTargetGenerator; + + @Override + public boolean be_isTarget() { + return be_isTargetGenerator; + } + + @Override + public void be_setTarget(boolean target) { + be_isTargetGenerator = target; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/NoiseInterpolatorAccessor.java b/src/main/java/org/betterx/betterend/mixin/common/NoiseInterpolatorAccessor.java similarity index 60% rename from src/main/java/ru/betterend/mixin/common/NoiseInterpolatorAccessor.java rename to src/main/java/org/betterx/betterend/mixin/common/NoiseInterpolatorAccessor.java index c630b42a..d94d8df7 100644 --- a/src/main/java/ru/betterend/mixin/common/NoiseInterpolatorAccessor.java +++ b/src/main/java/org/betterx/betterend/mixin/common/NoiseInterpolatorAccessor.java @@ -1,14 +1,15 @@ -package ru.betterend.mixin.common; +package org.betterx.betterend.mixin.common; import net.minecraft.world.level.levelgen.NoiseChunk; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(NoiseChunk.NoiseInterpolator.class) public interface NoiseInterpolatorAccessor { - @Accessor("slice0") - double[][] be_getSlice0(); + @Accessor("slice0") + double[][] be_getSlice0(); - @Accessor("slice1") - double[][] be_getSlice1(); + @Accessor("slice1") + double[][] be_getSlice1(); } diff --git a/src/main/java/org/betterx/betterend/mixin/common/PlayerAdvancementsMixin.java b/src/main/java/org/betterx/betterend/mixin/common/PlayerAdvancementsMixin.java new file mode 100644 index 00000000..70b3bc56 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/PlayerAdvancementsMixin.java @@ -0,0 +1,28 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.advancements.Advancement; +import net.minecraft.server.PlayerAdvancements; +import net.minecraft.server.level.ServerPlayer; + +import org.betterx.betterend.events.PlayerAdvancementsCallback; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerAdvancements.class) +public abstract class PlayerAdvancementsMixin { + @Shadow + private ServerPlayer player; + + @Inject(method = "award", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/AdvancementRewards;grant(Lnet/minecraft/server/level/ServerPlayer;)V", shift = Shift.AFTER)) + public void be_award(Advancement advancement, String criterionName, CallbackInfoReturnable info) { + PlayerAdvancementsCallback.PLAYER_ADVANCEMENT_COMPLETE.invoker() + .onAdvancementComplete(player, + advancement, + criterionName + ); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/PlayerMixin.java b/src/main/java/org/betterx/betterend/mixin/common/PlayerMixin.java new file mode 100644 index 00000000..2fafab1f --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/PlayerMixin.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.interfaces.FallFlyingItem; +import org.betterx.betterend.registry.EndBlocks; +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.CallbackInfoReturnable; + +import java.util.Optional; + +@Mixin(value = Player.class, priority = 200) +public abstract class PlayerMixin extends LivingEntity { + protected PlayerMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + private static Direction[] horizontal; + + @Inject(method = "findRespawnPositionAndUseSpawnBlock", at = @At(value = "HEAD"), cancellable = true) + private static void be_findRespawnPositionAndUseSpawnBlock(ServerLevel world, + BlockPos pos, + float f, + boolean bl, + boolean bl2, + CallbackInfoReturnable> info) { + BlockState blockState = world.getBlockState(pos); + if (blockState.is(EndBlocks.RESPAWN_OBELISK)) { + info.setReturnValue(be_obeliskRespawnPosition(world, pos, blockState)); + info.cancel(); + } + } + + @Inject(method = "tryToStartFallFlying", at = @At("HEAD"), cancellable = true) + public void be_tryToStartFlying(CallbackInfoReturnable info) { + if (!onGround && !isFallFlying() && !isInWater() && !hasEffect(MobEffects.LEVITATION)) { + ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); + if (itemStack.getItem() instanceof FallFlyingItem && ElytraItem.isFlyEnabled(itemStack)) { + setSharedFlag(7, true); + info.setReturnValue(true); + System.out.println("Started"); + info.cancel(); + } + } + } + + private static Optional be_obeliskRespawnPosition(ServerLevel world, BlockPos pos, BlockState state) { + if (state.getValue(BlockProperties.TRIPLE_SHAPE) == TripleShape.TOP) { + pos = pos.below(2); + } else if (state.getValue(BlockProperties.TRIPLE_SHAPE) == TripleShape.MIDDLE) { + pos = pos.below(); + } + if (horizontal == null) { + horizontal = BlocksHelper.makeHorizontal(); + } + MHelper.shuffle(horizontal, world.getRandom()); + for (Direction dir : horizontal) { + BlockPos p = pos.relative(dir); + BlockState state2 = world.getBlockState(p); + if (!state2.getMaterial().blocksMotion() && state2.getCollisionShape(world, pos).isEmpty()) { + return Optional.of(Vec3.atLowerCornerOf(p).add(0.5, 0, 0.5)); + } + } + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/mixin/common/ServerLevelMixin.java b/src/main/java/org/betterx/betterend/mixin/common/ServerLevelMixin.java new file mode 100644 index 00000000..41717e5b --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/ServerLevelMixin.java @@ -0,0 +1,124 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.progress.ChunkProgressListener; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; +import net.minecraft.world.level.storage.ServerLevelData; +import net.minecraft.world.level.storage.WritableLevelData; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.interfaces.BETargetChecker; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.betterx.betterend.world.generator.TerrainGenerator; +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.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + +@Mixin(ServerLevel.class) +public abstract class ServerLevelMixin extends Level { + protected ServerLevelMixin(WritableLevelData writableLevelData, + ResourceKey resourceKey, + Holder holder, + Supplier supplier, + boolean bl, + boolean bl2, + long l, + int i) { + super(writableLevelData, resourceKey, holder, supplier, bl, bl2, l, i); + } + + private final static List> BE_TEST_DIMENSIONS = List.of(BuiltinDimensionTypes.OVERWORLD, + BuiltinDimensionTypes.OVERWORLD_CAVES, + BuiltinDimensionTypes.NETHER); + + @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/Holder;is(Lnet/minecraft/resources/ResourceKey;)Z")) + ResourceKey be_dragonFight(ResourceKey resourceKey) { + if (!GeneratorOptions.hasDragonFights()) { + //this object would pass the test for the End-Dimension, so make sure we compare against something else to disabled the Dragon-Fight + if (this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) return BuiltinDimensionTypes.OVERWORLD; + } + return resourceKey; + } + + @Inject(method = "*", at = @At("TAIL")) + private void be_onServerWorldInit(MinecraftServer minecraftServer, + Executor executor, + LevelStorageAccess levelStorageAccess, + ServerLevelData serverLevelData, + ResourceKey resourceKey, + LevelStem levelStem, + ChunkProgressListener chunkProgressListener, + boolean bl, + long seed, + List list, + boolean bl2, + CallbackInfo ci) { + ServerLevel level = ServerLevel.class.cast(this); + if (level.dimension() == Level.END) { + final ChunkGenerator chunkGenerator = levelStem.generator(); + if (chunkGenerator instanceof NoiseBasedChunkGenerator) { + Holder sHolder = ((NoiseBasedChunkGeneratorAccessor) chunkGenerator) + .be_getSettings(); + BETargetChecker.class.cast(sHolder.value()).be_setTarget(true); + + } + TerrainGenerator.initNoise(seed, + chunkGenerator.getBiomeSource(), + level.getChunkSource().randomState().sampler()); + } + } + + + @Inject(method = "makeObsidianPlatform", at = @At("HEAD"), cancellable = true) + private static void be_createObsidianPlatform(ServerLevel serverLevel, CallbackInfo info) { + if (!GeneratorOptions.generateObsidianPlatform()) { + info.cancel(); + } else if (GeneratorOptions.changeSpawn()) { + BlockPos blockPos = GeneratorOptions.getSpawn(); + int i = blockPos.getX(); + int j = blockPos.getY() - 2; + int k = blockPos.getZ(); + BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockPosx) -> { + serverLevel.setBlockAndUpdate(blockPosx, Blocks.AIR.defaultBlockState()); + }); + BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockPosx) -> { + serverLevel.setBlockAndUpdate(blockPosx, Blocks.OBSIDIAN.defaultBlockState()); + }); + info.cancel(); + } + } + + @ModifyArg(method = "tickChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) + private BlockState be_modifyTickState(BlockPos pos, BlockState state) { + if (state.is(Blocks.ICE)) { + ResourceLocation biome = BiomeAPI.getBiomeID(getBiome(pos)); + if (biome.getNamespace().equals(BetterEnd.MOD_ID)) { + state = EndBlocks.EMERALD_ICE.defaultBlockState(); + } + } + return state; + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/ServerPlayerMixin.java b/src/main/java/org/betterx/betterend/mixin/common/ServerPlayerMixin.java new file mode 100644 index 00000000..5f4b6b9c --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/ServerPlayerMixin.java @@ -0,0 +1,182 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.network.protocol.game.*; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayerGameMode; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.ProfilePublicKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.BiomeManager; +import net.minecraft.world.level.portal.PortalInfo; +import net.minecraft.world.level.storage.LevelData; +import net.minecraft.world.phys.Vec3; + +import com.mojang.authlib.GameProfile; +import org.betterx.betterend.interfaces.TeleportingEntity; +import org.betterx.betterend.world.generator.GeneratorOptions; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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 org.jetbrains.annotations.Nullable; + +@Mixin(ServerPlayer.class) +public abstract class ServerPlayerMixin extends Player implements TeleportingEntity { + @Shadow + public ServerGamePacketListenerImpl connection; + @Final + @Shadow + public ServerPlayerGameMode gameMode; + @Final + @Shadow + public MinecraftServer server; + @Shadow + private boolean isChangingDimension; + @Shadow + private float lastSentHealth; + @Shadow + private int lastSentFood; + @Shadow + private int lastSentExp; + + private BlockPos exitPos; + private int be_teleportDelay = 0; + + public ServerPlayerMixin(Level level, + BlockPos blockPos, + float f, + GameProfile gameProfile, + @Nullable ProfilePublicKey profilePublicKey) { + super(level, blockPos, f, gameProfile, profilePublicKey); + } + + + @Inject(method = "createEndPlatform", at = @At("HEAD"), cancellable = true) + private void be_createEndSpawnPlatform(ServerLevel world, BlockPos centerPos, CallbackInfo info) { + if (!GeneratorOptions.generateObsidianPlatform()) { + info.cancel(); + } + } + + @Inject(method = "findDimensionEntryPoint", at = @At("HEAD"), cancellable = true) + protected void be_getTeleportTarget(ServerLevel destination, CallbackInfoReturnable info) { + if (be_canTeleport()) { + info.setReturnValue(new PortalInfo( + new Vec3(exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5), + getDeltaMovement(), + getYRot(), + getXRot() + )); + } else if (GeneratorOptions.changeSpawn() && destination.dimension() == Level.END) { + BlockPos spawn = GeneratorOptions.getSpawn(); + Vec3 pos = new Vec3(spawn.getX() + 0.5, spawn.getY(), spawn.getZ() + 0.5); + info.setReturnValue(new PortalInfo(pos, Vec3.ZERO, 90.0F, 0.0F)); + } + } + + @Inject(method = "changeDimension", at = @At("HEAD"), cancellable = true) + public void be_changeDimension(ServerLevel destination, CallbackInfoReturnable info) { + if (be_canTeleport() && level instanceof ServerLevel) { + isChangingDimension = true; + ServerLevel serverWorld = getLevel(); + LevelData worldProperties = destination.getLevelData(); + ServerPlayer player = ServerPlayer.class.cast(this); + connection.send(new ClientboundRespawnPacket( + new Holder.Direct(destination.dimensionType()), + destination.dimension(), + BiomeManager.obfuscateSeed(destination.getSeed()), + gameMode.getGameModeForPlayer(), + gameMode.getPreviousGameModeForPlayer(), + destination.isDebug(), + destination.isFlat(), + true + )); + connection.send(new ClientboundChangeDifficultyPacket( + worldProperties.getDifficulty(), + worldProperties.isDifficultyLocked() + )); + PlayerList playerManager = server.getPlayerList(); + playerManager.sendPlayerPermissionLevel(player); + serverWorld.removePlayerImmediately(player, RemovalReason.CHANGED_DIMENSION); + unsetRemoved(); + PortalInfo teleportTarget = findDimensionEntryPoint(destination); + if (teleportTarget != null) { + serverWorld.getProfiler().push("moving"); + serverWorld.getProfiler().pop(); + serverWorld.getProfiler().push("placing"); + this.level = destination; + destination.addDuringPortalTeleport(player); + setRot(teleportTarget.yRot, teleportTarget.xRot); + moveTo(teleportTarget.pos.x, teleportTarget.pos.y, teleportTarget.pos.z); + serverWorld.getProfiler().pop(); + triggerDimensionChangeTriggers(serverWorld); + gameMode.setLevel(destination); + connection.send(new ClientboundPlayerAbilitiesPacket(getAbilities())); + playerManager.sendLevelInfo(player, destination); + playerManager.sendAllPlayerInfo(player); + + for (MobEffectInstance statusEffectInstance : getActiveEffects()) { + connection.send(new ClientboundUpdateMobEffectPacket(getId(), statusEffectInstance)); + } + + connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); + lastSentExp = -1; + lastSentHealth = -1.0F; + lastSentFood = -1; + } + be_teleportDelay = 100; + be_resetExitPos(); + info.setReturnValue(player); + } + } + + @Inject(method = "tick", at = @At("TAIL")) + public void be_decreaseCooldawn(CallbackInfo info) { + if (be_teleportDelay > 0) be_teleportDelay--; + } + + @Override + public int getDimensionChangingDelay() { + if (be_teleportDelay > 0) { + return be_teleportDelay; + } + return super.getDimensionChangingDelay(); + } + + @Shadow + public abstract ServerLevel getLevel(); + + @Shadow + abstract void triggerDimensionChangeTriggers(ServerLevel origin); + + @Shadow + @Override + protected abstract PortalInfo findDimensionEntryPoint(ServerLevel destination); + + @Override + public void be_setExitPos(BlockPos pos) { + this.exitPos = pos.immutable(); + } + + @Override + public void be_resetExitPos() { + this.exitPos = null; + } + + @Override + public boolean be_canTeleport() { + return this.exitPos != null; + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/SlimeMixin.java b/src/main/java/org/betterx/betterend/mixin/common/SlimeMixin.java new file mode 100644 index 00000000..71261805 --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/SlimeMixin.java @@ -0,0 +1,31 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Slime; +import net.minecraft.world.level.Level; + +import org.betterx.betterend.interfaces.ISlime; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Slime.class) +public abstract class SlimeMixin extends Entity implements ISlime { + public SlimeMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + @Shadow + public void setSize(int size, boolean heal) { + } + + @Override + public void be_setSlimeSize(int size, boolean heal) { + setSize(size, heal); + } + + @Override + public void entityRemove(Entity.RemovalReason removalReason) { + super.remove(removalReason); + } +} diff --git a/src/main/java/org/betterx/betterend/mixin/common/SpikeFeatureMixin.java b/src/main/java/org/betterx/betterend/mixin/common/SpikeFeatureMixin.java new file mode 100644 index 00000000..db40a72b --- /dev/null +++ b/src/main/java/org/betterx/betterend/mixin/common/SpikeFeatureMixin.java @@ -0,0 +1,186 @@ +package org.betterx.betterend.mixin.common; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.IronBarsBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.SpikeFeature; +import net.minecraft.world.level.levelgen.feature.configurations.SpikeConfiguration; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import org.betterx.bclib.api.WorldDataAPI; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.StructureHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.world.generator.GeneratorOptions; +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; + +@Mixin(SpikeFeature.class) +public class SpikeFeatureMixin { + @Inject(method = "place", at = @At("HEAD"), cancellable = true) + private void be_place(FeaturePlaceContext featurePlaceContext, + CallbackInfoReturnable info) { + if (!GeneratorOptions.hasPillars()) { + info.setReturnValue(false); + } + } + + @Inject(method = "placeSpike", at = @At("HEAD"), cancellable = true) + private void be_placeSpike(ServerLevelAccessor world, + RandomSource random, + SpikeConfiguration config, + SpikeFeature.EndSpike spike, + CallbackInfo info) { + int x = spike.getCenterX(); + int z = spike.getCenterZ(); + int radius = spike.getRadius(); + int minY = 0; + + long lx = x; + long lz = z; + if (lx * lx + lz * lz < 10000) { + String pillarID = String.format("%d_%d", x, z); + CompoundTag pillar = WorldDataAPI.getCompoundTag(BetterEnd.MOD_ID, "pillars"); + boolean haveValue = pillar.contains(pillarID); + minY = haveValue + ? pillar.getInt(pillarID) + : world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z); + if (!haveValue) { + pillar.putInt(pillarID, minY); + WorldDataAPI.saveFile(BetterEnd.MOD_ID); + } + } else { + minY = world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z); + } + + GeneratorOptions.setDirectSpikeHeight(); + int maxY = minY + spike.getHeight() - 64; + + if (GeneratorOptions.replacePillars() && be_radiusInRange(radius)) { + radius--; + StructureTemplate base = StructureHelper.readStructure(BetterEnd.makeID("pillars/pillar_base_" + radius)); + StructureTemplate top = StructureHelper.readStructure(BetterEnd.makeID("pillars/pillar_top_" + radius + ( + spike + .isGuarded() + ? "_cage" + : ""))); + Vec3i side = base.getSize(); + BlockPos pos1 = new BlockPos(x - (side.getX() >> 1), minY - 3, z - (side.getZ() >> 1)); + minY = pos1.getY() + side.getY(); + side = top.getSize(); + BlockPos pos2 = new BlockPos(x - (side.getX() >> 1), maxY, z - (side.getZ() >> 1)); + maxY = pos2.getY(); + + StructurePlaceSettings data = new StructurePlaceSettings(); + base.placeInWorld(world, pos1, pos1, data, random, 2); + top.placeInWorld(world, pos2, pos2, data, random, 2); + + int r2 = radius * radius + 1; + MutableBlockPos mut = new MutableBlockPos(); + for (int px = -radius; px <= radius; px++) { + mut.setX(x + px); + int x2 = px * px; + for (int pz = -radius; pz <= radius; pz++) { + mut.setZ(z + pz); + int z2 = pz * pz; + if (x2 + z2 <= r2) { + for (int py = minY; py < maxY; py++) { + mut.setY(py); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + if ((px == radius || px == -radius || pz == radius || pz == -radius) && random.nextInt( + 24) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.CRYING_OBSIDIAN); + } else { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.OBSIDIAN); + } + } + } + } + } + } + } else { + minY -= 15; + int r2 = radius * radius + 1; + MutableBlockPos mut = new MutableBlockPos(); + for (int px = -radius; px <= radius; px++) { + mut.setX(x + px); + int x2 = px * px; + for (int pz = -radius; pz <= radius; pz++) { + mut.setZ(z + pz); + int z2 = pz * pz; + if (x2 + z2 <= r2) { + for (int py = minY; py < maxY; py++) { + mut.setY(py); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.OBSIDIAN); + } + } + } + } + } + mut.setX(x); + mut.setZ(z); + mut.setY(maxY); + BlocksHelper.setWithoutUpdate(world, mut, Blocks.BEDROCK); + + EndCrystal crystal = EntityType.END_CRYSTAL.create(world.getLevel()); + crystal.setBeamTarget(config.getCrystalBeamTarget()); + crystal.setInvulnerable(config.isCrystalInvulnerable()); + crystal.moveTo(x + 0.5D, maxY + 1, z + 0.5D, random.nextFloat() * 360.0F, 0.0F); + world.addFreshEntity(crystal); + + if (spike.isGuarded()) { + for (int px = -2; px <= 2; ++px) { + boolean bl = Mth.abs(px) == 2; + for (int pz = -2; pz <= 2; ++pz) { + boolean bl2 = Mth.abs(pz) == 2; + for (int py = 0; py <= 3; ++py) { + boolean bl3 = py == 3; + if (bl || bl2 || bl3) { + boolean bl4 = px == -2 || px == 2 || bl3; + boolean bl5 = pz == -2 || pz == 2 || bl3; + BlockState blockState = Blocks.IRON_BARS + .defaultBlockState() + .setValue(IronBarsBlock.NORTH, bl4 && pz != -2).setValue( + IronBarsBlock.SOUTH, + bl4 && pz != 2 + ).setValue( + IronBarsBlock.WEST, + bl5 && px != -2).setValue( + IronBarsBlock.EAST, + bl5 && px != 2 + ); + BlocksHelper.setWithoutUpdate( + world, + mut.set(spike.getCenterX() + px, maxY + py, spike.getCenterZ() + pz), + blockState + ); + } + } + } + } + } + } + + info.cancel(); + } + + private boolean be_radiusInRange(int radius) { + return radius > 1 && radius < 6; + } +} diff --git a/src/main/java/ru/betterend/mixin/common/WorldGenRegionMixin.java b/src/main/java/org/betterx/betterend/mixin/common/WorldGenRegionMixin.java similarity index 50% rename from src/main/java/ru/betterend/mixin/common/WorldGenRegionMixin.java rename to src/main/java/org/betterx/betterend/mixin/common/WorldGenRegionMixin.java index fb9c0cf3..744e1ffc 100644 --- a/src/main/java/ru/betterend/mixin/common/WorldGenRegionMixin.java +++ b/src/main/java/org/betterx/betterend/mixin/common/WorldGenRegionMixin.java @@ -1,9 +1,10 @@ -package ru.betterend.mixin.common; +package org.betterx.betterend.mixin.common; import net.minecraft.core.BlockPos; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; + import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -13,16 +14,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(WorldGenRegion.class) public class WorldGenRegionMixin { - @Final - @Shadow - private ChunkAccess center; - - @Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true) - private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable info) { - ChunkPos cPos = center.getPos(); - int x = blockPos.getX() >> 4; - int z = blockPos.getZ() >> 4; - WorldGenRegion region = (WorldGenRegion) (Object) this; - info.setReturnValue(Math.abs(x - cPos.x) < 2 && Math.abs(z - cPos.z) < 2); - } + @Final + @Shadow + private ChunkAccess center; + + @Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true) + private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable info) { + ChunkPos cPos = center.getPos(); + int x = blockPos.getX() >> 4; + int z = blockPos.getZ() >> 4; + WorldGenRegion region = (WorldGenRegion) (Object) this; + info.setReturnValue(Math.abs(x - cPos.x) < 2 && Math.abs(z - cPos.z) < 2); + } } diff --git a/src/main/java/org/betterx/betterend/noise/OpenSimplexNoise.java b/src/main/java/org/betterx/betterend/noise/OpenSimplexNoise.java new file mode 100644 index 00000000..4dc9325c --- /dev/null +++ b/src/main/java/org/betterx/betterend/noise/OpenSimplexNoise.java @@ -0,0 +1,2528 @@ +package org.betterx.betterend.noise; + +/* + * OpenSimplex Noise in Java. + * by Kurt Spencer + * + * v1.1 (October 5, 2014) + * - Added 2D and 4D implementations. + * - Proper gradient sets for all dimensions, from a + * dimensionally-generalizable scheme with an actual + * rhyme and reason behind it. + * - Removed default permutation array in favor of + * default seed. + * - Changed seed-based constructor to be independent + * of any particular randomization library, so results + * will be the same when ported to other languages. + */ + +public final class OpenSimplexNoise { + private static final double STRETCH_CONSTANT_2D = -0.211324865405187; // (1/Math.sqrt(2+1)-1)/2; + private static final double SQUISH_CONSTANT_2D = 0.366025403784439; // (Math.sqrt(2+1)-1)/2; + private static final double STRETCH_CONSTANT_3D = -1.0 / 6; // (1/Math.sqrt(3+1)-1)/3; + private static final double SQUISH_CONSTANT_3D = 1.0 / 3; // (Math.sqrt(3+1)-1)/3; + private static final double STRETCH_CONSTANT_4D = -0.138196601125011; // (1/Math.sqrt(4+1)-1)/4; + private static final double SQUISH_CONSTANT_4D = 0.309016994374947; // (Math.sqrt(4+1)-1)/4; + + private static final double NORM_CONSTANT_2D = 47; + private static final double NORM_CONSTANT_3D = 103; + private static final double NORM_CONSTANT_4D = 30; + + private static final long DEFAULT_SEED = 0; + + private final short[] perm; + private final short[] permGradIndex3D; + + public OpenSimplexNoise() { + this(DEFAULT_SEED); + } + + public OpenSimplexNoise(short[] perm) { + this.perm = perm; + permGradIndex3D = new short[256]; + + for (int i = 0; i < 256; i++) { + // Since 3D has 24 gradients, simple bitmask won't work, so + // precompute modulo array. + permGradIndex3D[i] = (short) ((perm[i] % (gradients3D.length / 3)) * 3); + } + } + + // Initializes the class using a permutation array generated from a 64-bit + // seed. + // Generates a proper permutation (i.e. doesn't merely perform N successive + // pair swaps on a base array) + // Uses a simple 64-bit LCG. + public OpenSimplexNoise(long seed) { + perm = new short[256]; + permGradIndex3D = new short[256]; + short[] source = new short[256]; + for (short i = 0; i < 256; i++) { + source[i] = i; + } + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + for (int i = 255; i >= 0; i--) { + seed = seed * 6364136223846793005l + 1442695040888963407l; + int r = (int) ((seed + 31) % (i + 1)); + if (r < 0) r += (i + 1); + perm[i] = source[r]; + permGradIndex3D[i] = (short) ((perm[i] % (gradients3D.length / 3)) * 3); + source[r] = source[i]; + } + } + + // 2D OpenSimplex Noise. + public double eval(double x, double y) { + + // Place input coordinates onto grid. + double stretchOffset = (x + y) * STRETCH_CONSTANT_2D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + + // Floor to get grid coordinates of rhombus (stretched square) + // super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + + // Skew out to get actual coordinates of rhombus origin. We'll need + // these later. + double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + + // Compute grid coordinates relative to rhombus origin. + double xins = xs - xsb; + double yins = ys - ysb; + + // Sum those together to get a value that determines which region we're + // in. + double inSum = xins + yins; + + // Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + + // We'll be defining these inside the next block and using them + // afterwards. + double dx_ext, dy_ext; + int xsv_ext, ysv_ext; + + double value = 0; + + // Contribution (1,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); + } + + // Contribution (0,1) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); + } + + if (inSum <= 1) { // We're inside the triangle (2-Simplex) at (0,0) + double zins = 1 - inSum; + if (zins > xins || zins > yins) { // (0,0) is one of the closest two + // triangular vertices + if (xins > yins) { + xsv_ext = xsb + 1; + ysv_ext = ysb - 1; + dx_ext = dx0 - 1; + dy_ext = dy0 + 1; + } else { + xsv_ext = xsb - 1; + ysv_ext = ysb + 1; + dx_ext = dx0 + 1; + dy_ext = dy0 - 1; + } + } else { // (1,0) and (0,1) are the closest two vertices. + xsv_ext = xsb + 1; + ysv_ext = ysb + 1; + dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; + } + } else { // We're inside the triangle (2-Simplex) at (1,1) + double zins = 2 - inSum; + if (zins < xins || zins < yins) { // (0,0) is one of the closest two + // triangular vertices + if (xins > yins) { + xsv_ext = xsb + 2; + ysv_ext = ysb + 0; + dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; + } else { + xsv_ext = xsb + 0; + ysv_ext = ysb + 2; + dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; + dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; + } + } else { // (1,0) and (0,1) are the closest two vertices. + dx_ext = dx0; + dy_ext = dy0; + xsv_ext = xsb; + ysv_ext = ysb; + } + xsb += 1; + ysb += 1; + dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; + dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; + } + + // Contribution (0,0) or (1,1) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); + } + + // Extra Vertex + double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; + if (attn_ext > 0) { + attn_ext *= attn_ext; + value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); + } + + return value / NORM_CONSTANT_2D; + } + + // 3D OpenSimplex Noise. + public double eval(double x, double y, double z) { + + // Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + + // Floor to get simplectic honeycomb coordinates of rhombohedron + // (stretched cube) super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + int zsb = fastFloor(zs); + + // Skew out to get actual coordinates of rhombohedron origin. We'll need + // these later. + double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + + // Compute simplectic honeycomb coordinates relative to rhombohedral + // origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + + // Sum those together to get a value that determines which region we're + // in. + double inSum = xins + yins + zins; + + // Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + + // We'll be defining these inside the next block and using them + // afterwards. + double dx_ext0, dy_ext0, dz_ext0; + double dx_ext1, dy_ext1, dz_ext1; + int xsv_ext0, ysv_ext0, zsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1; + + double value = 0; + if (inSum <= 1) { // We're inside the tetrahedron (3-Simplex) at (0,0,0) + + // Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. + byte aPoint = 0x01; + double aScore = xins; + byte bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) { + bScore = zins; + bPoint = 0x04; + } else if (aScore < bScore && zins > aScore) { + aScore = zins; + aPoint = 0x04; + } + + // Now we determine the two lattice points not part of the + // tetrahedron that may contribute. + // This depends on the closest two tetrahedral vertices, including + // (0,0,0) + double wins = 1 - inSum; + if (wins > aScore || wins > bScore) { // (0,0,0) is one of the + // closest two tetrahedral + // vertices. + byte c = (bScore > aScore ? bPoint : aPoint); // Our other + // closest + // vertex is the + // closest out + // of a and b. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx0; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0; + if ((c & 0x01) == 0) { + ysv_ext1 -= 1; + dy_ext1 += 1; + } else { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0; + dz_ext1 = dz0 + 1; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1; + } + } else { // (0,0,0) is not one of the closest two tetrahedral + // vertices. + byte c = (byte) (aPoint | bPoint); // Our two extra vertices are + // determined by the closest + // two. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + } + } + + // Contribution (0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); + } + + // Contribution (1,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + // Contribution (0,1,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + // Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + } else if (inSum >= 2) { // We're inside the tetrahedron (3-Simplex) at + // (1,1,1) + + // Determine which two tetrahedral vertices are the closest, out of + // (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). + byte aPoint = 0x06; + double aScore = xins; + byte bPoint = 0x05; + double bScore = yins; + if (aScore <= bScore && zins < bScore) { + bScore = zins; + bPoint = 0x03; + } else if (aScore > bScore && zins < aScore) { + aScore = zins; + aPoint = 0x03; + } + + // Now we determine the two lattice points not part of the + // tetrahedron that may contribute. + // This depends on the closest two tetrahedral vertices, including + // (1,1,1) + double wins = 3 - inSum; + if (wins < aScore || wins < bScore) { // (1,1,1) is one of the + // closest two tetrahedral + // vertices. + byte c = (bScore < aScore ? bPoint : aPoint); // Our other + // closest + // vertex is the + // closest out + // of a and b. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + if ((c & 0x01) != 0) { + ysv_ext1 += 1; + dy_ext1 -= 1; + } else { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D; + } + } else { // (1,1,1) is not one of the closest two tetrahedral + // vertices. + byte c = (byte) (aPoint & bPoint); // Our two extra vertices are + // determined by the closest + // two. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx0 - SQUISH_CONSTANT_3D; + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysb + 1; + ysv_ext1 = ysb + 2; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy0 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz0 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + } + } + + // Contribution (1,1,0) + double dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); + } + + // Contribution (1,0,1) + double dx2 = dx3; + double dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); + } + + // Contribution (0,1,1) + double dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dy1 = dy3; + double dz1 = dz2; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); + } + + // Contribution (1,1,1) + dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); + } + } else { // We're inside the octahedron (Rectified 3-Simplex) in + // between. + double aScore; + byte aPoint; + boolean aIsFurtherSide; + double bScore; + byte bPoint; + boolean bIsFurtherSide; + + // Decide between point (0,0,1) and (1,1,0) as closest + double p1 = xins + yins; + if (p1 > 1) { + aScore = p1 - 1; + aPoint = 0x03; + aIsFurtherSide = true; + } else { + aScore = 1 - p1; + aPoint = 0x04; + aIsFurtherSide = false; + } + + // Decide between point (0,1,0) and (1,0,1) as closest + double p2 = xins + zins; + if (p2 > 1) { + bScore = p2 - 1; + bPoint = 0x05; + bIsFurtherSide = true; + } else { + bScore = 1 - p2; + bPoint = 0x02; + bIsFurtherSide = false; + } + + // The closest out of the two (1,0,0) and (0,1,1) will replace the + // furthest out of the two decided above, if closer. + double p3 = yins + zins; + if (p3 > 1) { + double score = p3 - 1; + if (aScore <= bScore && aScore < score) { + aScore = score; + aPoint = 0x06; + aIsFurtherSide = true; + } else if (aScore > bScore && bScore < score) { + bScore = score; + bPoint = 0x06; + bIsFurtherSide = true; + } + } else { + double score = 1 - p3; + if (aScore <= bScore && aScore < score) { + aScore = score; + aPoint = 0x01; + aIsFurtherSide = false; + } else if (aScore > bScore && bScore < score) { + bScore = score; + bPoint = 0x01; + bIsFurtherSide = false; + } + } + + // Where each of the two closest points are determines how the extra + // two vertices are calculated. + if (aIsFurtherSide == bIsFurtherSide) { + if (aIsFurtherSide) { // Both closest points on (1,1,1) side + + // One of the two extra points is (1,1,1) + dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + + // Other extra point is based on the shared axis. + byte c = (byte) (aPoint & bPoint); + if ((c & 0x01) != 0) { + dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 2; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + } else if ((c & 0x02) != 0) { + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb + 2; + zsv_ext1 = zsb; + } else { + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb + 2; + } + } else {// Both closest points on (0,0,0) side + + // One of the two extra points is (0,0,0) + dx_ext0 = dx0; + dy_ext0 = dy0; + dz_ext0 = dz0; + xsv_ext0 = xsb; + ysv_ext0 = ysb; + zsv_ext0 = zsb; + + // Other extra point is based on the omitted axis. + byte c = (byte) (aPoint | bPoint); + if ((c & 0x01) == 0) { + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb - 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb + 1; + } else if ((c & 0x02) == 0) { + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb - 1; + zsv_ext1 = zsb + 1; + } else { + dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb - 1; + } + } + } else { // One point on (0,0,0) side, one point on (1,1,1) side + byte c1, c2; + if (aIsFurtherSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + // One contribution is a permutation of (1,1,-1) + if ((c1 & 0x01) == 0) { + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb - 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + } else if ((c1 & 0x02) == 0) { + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb - 1; + zsv_ext0 = zsb + 1; + } else { + dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; + dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; + dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb - 1; + } + + // One contribution is a permutation of (0,0,2) + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + if ((c2 & 0x01) != 0) { + dx_ext1 -= 2; + xsv_ext1 += 2; + } else if ((c2 & 0x02) != 0) { + dy_ext1 -= 2; + ysv_ext1 += 2; + } else { + dz_ext1 -= 2; + zsv_ext1 += 2; + } + } + + // Contribution (1,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + // Contribution (0,1,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + // Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + + // Contribution (1,1,0) + double dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; + double dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); + } + + // Contribution (1,0,1) + double dx5 = dx4; + double dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); + } + + // Contribution (0,1,1) + double dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; + double dy6 = dy4; + double dz6 = dz5; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); + } + } + + // First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; + if (attn_ext0 > 0) { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); + } + + // Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; + if (attn_ext1 > 0) { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); + } + + return value / NORM_CONSTANT_3D; + } + + // 4D OpenSimplex Noise. + public double eval(double x, double y, double z, double w) { + + // Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + double ws = w + stretchOffset; + + // Floor to get simplectic honeycomb coordinates of rhombo-hypercube + // super-cell origin. + int xsb = fastFloor(xs); + int ysb = fastFloor(ys); + int zsb = fastFloor(zs); + int wsb = fastFloor(ws); + + // Skew out to get actual coordinates of stretched rhombo-hypercube + // origin. We'll need these later. + double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + double wb = wsb + squishOffset; + + // Compute simplectic honeycomb coordinates relative to rhombo-hypercube + // origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + double wins = ws - wsb; + + // Sum those together to get a value that determines which region we're + // in. + double inSum = xins + yins + zins + wins; + + // Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + double dw0 = w - wb; + + // We'll be defining these inside the next block and using them + // afterwards. + double dx_ext0, dy_ext0, dz_ext0, dw_ext0; + double dx_ext1, dy_ext1, dz_ext1, dw_ext1; + double dx_ext2, dy_ext2, dz_ext2, dw_ext2; + int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; + int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; + + double value = 0; + if (inSum <= 1) { // We're inside the pentachoron (4-Simplex) at + // (0,0,0,0) + + // Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) + // are closest. + byte aPoint = 0x01; + double aScore = xins; + byte bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) { + bScore = zins; + bPoint = 0x04; + } else if (aScore < bScore && zins > aScore) { + aScore = zins; + aPoint = 0x04; + } + if (aScore >= bScore && wins > bScore) { + bScore = wins; + bPoint = 0x08; + } else if (aScore < bScore && wins > aScore) { + aScore = wins; + aPoint = 0x08; + } + + // Now we determine the three lattice points not part of the + // pentachoron that may contribute. + // This depends on the closest two pentachoron vertices, including + // (0,0,0,0) + double uins = 1 - inSum; + if (uins > aScore || uins > bScore) { // (0,0,0,0) is one of the + // closest two pentachoron + // vertices. + byte c = (bScore > aScore ? bPoint : aPoint); // Our other + // closest + // vertex is the + // closest out + // of a and b. + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx_ext2 = dx0; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0; + if ((c & 0x01) == 0x01) { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0; + if ((c & 0x03) != 0) { + if ((c & 0x03) == 0x03) { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; + } + + if ((c & 0x08) == 0) { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw_ext1 = dw0; + dw_ext2 = dw0 + 1; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; + } + } else { // (0,0,0,0) is not one of the closest two pentachoron + // vertices. + byte c = (byte) (aPoint | bPoint); // Our three extra vertices + // are determined by the + // closest two. + + if ((c & 0x01) == 0) { + xsv_ext0 = xsv_ext2 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext2 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0x01) { + ysv_ext1 -= 1; + dy_ext1 += 1; + } else { + ysv_ext2 -= 1; + dy_ext2 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0x03) { + zsv_ext1 -= 1; + dz_ext1 += 1; + } else { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) == 0) { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - SQUISH_CONSTANT_4D; + dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + } + + // Contribution (0,0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); + } + + // Contribution (1,0,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; + double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + // Contribution (0,1,0,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + // Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + // Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + } else if (inSum >= 3) { // We're inside the pentachoron (4-Simplex) at + // (1,1,1,1) + // Determine which two of (1,1,1,0), + // (1,1,0,1), (1,0,1,1), (0,1,1,1) + // are closest. + byte aPoint = 0x0E; + double aScore = xins; + byte bPoint = 0x0D; + double bScore = yins; + if (aScore <= bScore && zins < bScore) { + bScore = zins; + bPoint = 0x0B; + } else if (aScore > bScore && zins < aScore) { + aScore = zins; + aPoint = 0x0B; + } + if (aScore <= bScore && wins < bScore) { + bScore = wins; + bPoint = 0x07; + } else if (aScore > bScore && wins < aScore) { + aScore = wins; + aPoint = 0x07; + } + + // Now we determine the three lattice points not part of the + // pentachoron that may contribute. + // This depends on the closest two pentachoron vertices, including + // (0,0,0,0) + double uins = 4 - inSum; + if (uins < aScore || uins < bScore) { // (1,1,1,1) is one of the + // closest two pentachoron + // vertices. + byte c = (bScore < aScore ? bPoint : aPoint); // Our other + // closest + // vertex is the + // closest out + // of a and b. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + if ((c & 0x01) != 0) { + ysv_ext1 += 1; + dy_ext1 -= 1; + } else { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + if ((c & 0x03) != 0x03) { + if ((c & 0x03) == 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext2 += 1; + dz_ext2 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D; + } + } else { // (1,1,1,1) is not one of the closest two pentachoron + // vertices. + byte c = (byte) (aPoint & bPoint); // Our three extra vertices + // are determined by the + // closest two. + + if ((c & 0x01) != 0) { + xsv_ext0 = xsv_ext2 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; + dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x01) != 0) { + ysv_ext2 += 1; + dy_ext2 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x03) != 0) { + zsv_ext2 += 1; + dz_ext2 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + } + + // Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + // Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; + double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + // Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + // Contribution (0,1,1,1) + double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + // Contribution (1,1,1,1) + dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); + } + } else if (inSum <= 2) { // We're inside the first dispentachoron + // (Rectified 4-Simplex) + double aScore; + byte aPoint; + boolean aIsBiggerSide = true; + double bScore; + byte bPoint; + boolean bIsBiggerSide = true; + + // Decide between (1,1,0,0) and (0,0,1,1) + if (xins + yins > zins + wins) { + aScore = xins + yins; + aPoint = 0x03; + } else { + aScore = zins + wins; + aPoint = 0x0C; + } + + // Decide between (1,0,1,0) and (0,1,0,1) + if (xins + zins > yins + wins) { + bScore = xins + zins; + bPoint = 0x05; + } else { + bScore = yins + wins; + bPoint = 0x0A; + } + + // Closer between (1,0,0,1) and (0,1,1,0) will replace the further + // of a and b, if closer. + if (xins + wins > yins + zins) { + double score = xins + wins; + if (aScore >= bScore && score > bScore) { + bScore = score; + bPoint = 0x09; + } else if (aScore < bScore && score > aScore) { + aScore = score; + aPoint = 0x09; + } + } else { + double score = yins + zins; + if (aScore >= bScore && score > bScore) { + bScore = score; + bPoint = 0x06; + } else if (aScore < bScore && score > aScore) { + aScore = score; + aPoint = 0x06; + } + } + + // Decide if (1,0,0,0) is closer. + double p1 = 2 - inSum + xins; + if (aScore >= bScore && p1 > bScore) { + bScore = p1; + bPoint = 0x01; + bIsBiggerSide = false; + } else if (aScore < bScore && p1 > aScore) { + aScore = p1; + aPoint = 0x01; + aIsBiggerSide = false; + } + + // Decide if (0,1,0,0) is closer. + double p2 = 2 - inSum + yins; + if (aScore >= bScore && p2 > bScore) { + bScore = p2; + bPoint = 0x02; + bIsBiggerSide = false; + } else if (aScore < bScore && p2 > aScore) { + aScore = p2; + aPoint = 0x02; + aIsBiggerSide = false; + } + + // Decide if (0,0,1,0) is closer. + double p3 = 2 - inSum + zins; + if (aScore >= bScore && p3 > bScore) { + bScore = p3; + bPoint = 0x04; + bIsBiggerSide = false; + } else if (aScore < bScore && p3 > aScore) { + aScore = p3; + aPoint = 0x04; + aIsBiggerSide = false; + } + + // Decide if (0,0,0,1) is closer. + double p4 = 2 - inSum + wins; + if (aScore >= bScore && p4 > bScore) { + bScore = p4; + bPoint = 0x08; + bIsBiggerSide = false; + } else if (aScore < bScore && p4 > aScore) { + aScore = p4; + aPoint = 0x08; + aIsBiggerSide = false; + } + + // Where each of the two closest points are determines how the extra + // three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) { + if (aIsBiggerSide) { // Both closest points on the bigger side + byte c1 = (byte) (aPoint | bPoint); + byte c2 = (byte) (aPoint & bPoint); + if ((c1 & 0x01) == 0) { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) == 0) { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) == 0) { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) == 0) { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + } + + // One combination is a permutation of (0,0,0,2) based on c2 + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) != 0) { + xsv_ext2 += 2; + dx_ext2 -= 2; + } else if ((c2 & 0x02) != 0) { + ysv_ext2 += 2; + dy_ext2 -= 2; + } else if ((c2 & 0x04) != 0) { + zsv_ext2 += 2; + dz_ext2 -= 2; + } else { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + + } else { // Both closest points on the smaller side + // One of the two extra points is (0,0,0,0) + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0; + dy_ext2 = dy0; + dz_ext2 = dz0; + dw_ext2 = dw0; + + // Other two points are based on the omitted axes. + byte c = (byte) (aPoint | bPoint); + + if ((c & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0x01) { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0x03) { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) == 0) { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + + } + } else { // One point on each "side" + byte c1, c2; + if (aIsBiggerSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + // Two contributions are the bigger-sided point with each 0 + // replaced with -1. + if ((c1 & 0x01) == 0) { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) == 0) { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; + if ((c1 & 0x01) == 0x01) { + ysv_ext0 -= 1; + dy_ext0 += 1; + } else { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) == 0) { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; + if ((c1 & 0x03) == 0x03) { + zsv_ext0 -= 1; + dz_ext0 += 1; + } else { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) == 0) { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; + } + + // One contribution is a permutation of (0,0,0,2) based on the + // smaller-sided point + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) != 0) { + xsv_ext2 += 2; + dx_ext2 -= 2; + } else if ((c2 & 0x02) != 0) { + ysv_ext2 += 2; + dy_ext2 -= 2; + } else if ((c2 & 0x04) != 0) { + zsv_ext2 += 2; + dz_ext2 -= 2; + } else { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + } + + // Contribution (1,0,0,0) + double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; + double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; + double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; + double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + // Contribution (0,1,0,0) + double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; + double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + // Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + // Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + + // Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + // Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + // Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + // Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + // Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + // Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } else { // We're inside the second dispentachoron (Rectified 4-Simplex) + double aScore; + byte aPoint; + boolean aIsBiggerSide = true; + double bScore; + byte bPoint; + boolean bIsBiggerSide = true; + + // Decide between (0,0,1,1) and (1,1,0,0) + if (xins + yins < zins + wins) { + aScore = xins + yins; + aPoint = 0x0C; + } else { + aScore = zins + wins; + aPoint = 0x03; + } + + // Decide between (0,1,0,1) and (1,0,1,0) + if (xins + zins < yins + wins) { + bScore = xins + zins; + bPoint = 0x0A; + } else { + bScore = yins + wins; + bPoint = 0x05; + } + + // Closer between (0,1,1,0) and (1,0,0,1) will replace the further + // of a and b, if closer. + if (xins + wins < yins + zins) { + double score = xins + wins; + if (aScore <= bScore && score < bScore) { + bScore = score; + bPoint = 0x06; + } else if (aScore > bScore && score < aScore) { + aScore = score; + aPoint = 0x06; + } + } else { + double score = yins + zins; + if (aScore <= bScore && score < bScore) { + bScore = score; + bPoint = 0x09; + } else if (aScore > bScore && score < aScore) { + aScore = score; + aPoint = 0x09; + } + } + + // Decide if (0,1,1,1) is closer. + double p1 = 3 - inSum + xins; + if (aScore <= bScore && p1 < bScore) { + bScore = p1; + bPoint = 0x0E; + bIsBiggerSide = false; + } else if (aScore > bScore && p1 < aScore) { + aScore = p1; + aPoint = 0x0E; + aIsBiggerSide = false; + } + + // Decide if (1,0,1,1) is closer. + double p2 = 3 - inSum + yins; + if (aScore <= bScore && p2 < bScore) { + bScore = p2; + bPoint = 0x0D; + bIsBiggerSide = false; + } else if (aScore > bScore && p2 < aScore) { + aScore = p2; + aPoint = 0x0D; + aIsBiggerSide = false; + } + + // Decide if (1,1,0,1) is closer. + double p3 = 3 - inSum + zins; + if (aScore <= bScore && p3 < bScore) { + bScore = p3; + bPoint = 0x0B; + bIsBiggerSide = false; + } else if (aScore > bScore && p3 < aScore) { + aScore = p3; + aPoint = 0x0B; + aIsBiggerSide = false; + } + + // Decide if (1,1,1,0) is closer. + double p4 = 3 - inSum + wins; + if (aScore <= bScore && p4 < bScore) { + bScore = p4; + bPoint = 0x07; + bIsBiggerSide = false; + } else if (aScore > bScore && p4 < aScore) { + aScore = p4; + aPoint = 0x07; + aIsBiggerSide = false; + } + + // Where each of the two closest points are determines how the extra + // three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) { + if (aIsBiggerSide) { // Both closest points on the bigger side + byte c1 = (byte) (aPoint & bPoint); + byte c2 = (byte) (aPoint | bPoint); + + // Two contributions are permutations of (0,0,0,1) and + // (0,0,0,2) based on c1 + xsv_ext0 = xsv_ext1 = xsb; + ysv_ext0 = ysv_ext1 = ysb; + zsv_ext0 = zsv_ext1 = zsb; + wsv_ext0 = wsv_ext1 = wsb; + dx_ext0 = dx0 - SQUISH_CONSTANT_4D; + dy_ext0 = dy0 - SQUISH_CONSTANT_4D; + dz_ext0 = dz0 - SQUISH_CONSTANT_4D; + dw_ext0 = dw0 - SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D; + dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D; + dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D; + if ((c1 & 0x01) != 0) { + xsv_ext0 += 1; + dx_ext0 -= 1; + xsv_ext1 += 2; + dx_ext1 -= 2; + } else if ((c1 & 0x02) != 0) { + ysv_ext0 += 1; + dy_ext0 -= 1; + ysv_ext1 += 2; + dy_ext1 -= 2; + } else if ((c1 & 0x04) != 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + zsv_ext1 += 2; + dz_ext1 -= 2; + } else { + wsv_ext0 += 1; + dw_ext0 -= 1; + wsv_ext1 += 2; + dw_ext1 -= 2; + } + + // One contribution is a permutation of (1,1,1,-1) based on + // c2 + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) == 0) { + xsv_ext2 -= 2; + dx_ext2 += 2; + } else if ((c2 & 0x02) == 0) { + ysv_ext2 -= 2; + dy_ext2 += 2; + } else if ((c2 & 0x04) == 0) { + zsv_ext2 -= 2; + dz_ext2 += 2; + } else { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } else { // Both closest points on the smaller side + // One of the two extra points is (1,1,1,1) + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; + + // Other two points are based on the shared axes. + byte c = (byte) (aPoint & bPoint); + + if ((c & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x01) == 0) { + ysv_ext0 += 1; + dy_ext0 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c & 0x03) == 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c & 0x08) != 0) { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + } + } else { // One point on each "side" + byte c1, c2; + if (aIsBiggerSide) { + c1 = aPoint; + c2 = bPoint; + } else { + c1 = bPoint; + c2 = aPoint; + } + + // Two contributions are the bigger-sided point with each 1 + // replaced with 2. + if ((c1 & 0x01) != 0) { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; + dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + } else { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x02) != 0) { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c1 & 0x01) == 0) { + ysv_ext0 += 1; + dy_ext0 -= 1; + } else { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } else { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x04) != 0) { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + if ((c1 & 0x03) == 0) { + zsv_ext0 += 1; + dz_ext0 -= 1; + } else { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } else { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; + } + + if ((c1 & 0x08) != 0) { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; + } else { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; + } + + // One contribution is a permutation of (1,1,1,-1) based on the + // smaller-sided point + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + if ((c2 & 0x01) == 0) { + xsv_ext2 -= 2; + dx_ext2 += 2; + } else if ((c2 & 0x02) == 0) { + ysv_ext2 -= 2; + dy_ext2 += 2; + } else if ((c2 & 0x04) == 0) { + zsv_ext2 -= 2; + dz_ext2 += 2; + } else { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } + + // Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; + double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + // Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; + double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + // Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + // Contribution (0,1,1,1) + double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + // Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + // Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + // Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + // Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + // Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + // Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; + double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; + double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } + + // First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; + if (attn_ext0 > 0) { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate( + xsv_ext0, + ysv_ext0, + zsv_ext0, + wsv_ext0, + dx_ext0, + dy_ext0, + dz_ext0, + dw_ext0 + ); + } + + // Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; + if (attn_ext1 > 0) { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate( + xsv_ext1, + ysv_ext1, + zsv_ext1, + wsv_ext1, + dx_ext1, + dy_ext1, + dz_ext1, + dw_ext1 + ); + } + + // Third extra vertex + double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; + if (attn_ext2 > 0) { + attn_ext2 *= attn_ext2; + value += attn_ext2 * attn_ext2 * extrapolate( + xsv_ext2, + ysv_ext2, + zsv_ext2, + wsv_ext2, + dx_ext2, + dy_ext2, + dz_ext2, + dw_ext2 + ); + } + + return value / NORM_CONSTANT_4D; + } + + private double extrapolate(int xsb, int ysb, double dx, double dy) { + int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; + return gradients2D[index] * dx + gradients2D[index + 1] * dy; + } + + private double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) { + int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; + return gradients3D[index] * dx + gradients3D[index + 1] * dy + gradients3D[index + 2] * dz; + } + + private double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) { + int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; + return gradients4D[index] * dx + gradients4D[index + 1] * dy + gradients4D[index + 2] * dz + gradients4D[index + 3] * dw; + } + + private static int fastFloor(double x) { + int xi = (int) x; + return x < xi ? xi - 1 : xi; + } + + // Gradients for 2D. They approximate the directions to the + // vertices of an octagon from the center. + private static final byte[] gradients2D = new byte[]{5, 2, 2, 5, -5, 2, -2, 5, 5, -2, 2, -5, -5, -2, -2, -5,}; + + // Gradients for 3D. They approximate the directions to the + // vertices of a rhombicuboctahedron from the center, skewed so + // that the triangular and square facets can be inscribed inside + // circles of the same radius. + private static final byte[] gradients3D = new byte[]{ + -11, + 4, + 4, + -4, + 11, + 4, + -4, + 4, + 11, + 11, + 4, + 4, + 4, + 11, + 4, + 4, + 4, + 11, + -11, + -4, + 4, + -4, + -11, + 4, + -4, + -4, + 11, + 11, + -4, + 4, + 4, + -11, + 4, + 4, + -4, + 11, + -11, + 4, + -4, + -4, + 11, + -4, + -4, + 4, + -11, + 11, + 4, + -4, + 4, + 11, + -4, + 4, + 4, + -11, + -11, + -4, + -4, + -4, + -11, + -4, + -4, + -4, + -11, + 11, + -4, + -4, + 4, + -11, + -4, + 4, + -4, + -11, + }; + + // Gradients for 4D. They approximate the directions to the + // vertices of a disprismatotesseractihexadecachoron from the center, + // skewed so that the tetrahedral and cubic facets can be inscribed inside + // spheres of the same radius. + private static final byte[] gradients4D = new byte[]{ + 3, + 1, + 1, + 1, + 1, + 3, + 1, + 1, + 1, + 1, + 3, + 1, + 1, + 1, + 1, + 3, + -3, + 1, + 1, + 1, + -1, + 3, + 1, + 1, + -1, + 1, + 3, + 1, + -1, + 1, + 1, + 3, + 3, + -1, + 1, + 1, + 1, + -3, + 1, + 1, + 1, + -1, + 3, + 1, + 1, + -1, + 1, + 3, + -3, + -1, + 1, + 1, + -1, + -3, + 1, + 1, + -1, + -1, + 3, + 1, + -1, + -1, + 1, + 3, + 3, + 1, + -1, + 1, + 1, + 3, + -1, + 1, + 1, + 1, + -3, + 1, + 1, + 1, + -1, + 3, + -3, + 1, + -1, + 1, + -1, + 3, + -1, + 1, + -1, + 1, + -3, + 1, + -1, + 1, + -1, + 3, + 3, + -1, + -1, + 1, + 1, + -3, + -1, + 1, + 1, + -1, + -3, + 1, + 1, + -1, + -1, + 3, + -3, + -1, + -1, + 1, + -1, + -3, + -1, + 1, + -1, + -1, + -3, + 1, + -1, + -1, + -1, + 3, + 3, + 1, + 1, + -1, + 1, + 3, + 1, + -1, + 1, + 1, + 3, + -1, + 1, + 1, + 1, + -3, + -3, + 1, + 1, + -1, + -1, + 3, + 1, + -1, + -1, + 1, + 3, + -1, + -1, + 1, + 1, + -3, + 3, + -1, + 1, + -1, + 1, + -3, + 1, + -1, + 1, + -1, + 3, + -1, + 1, + -1, + 1, + -3, + -3, + -1, + 1, + -1, + -1, + -3, + 1, + -1, + -1, + -1, + 3, + -1, + -1, + -1, + 1, + -3, + 3, + 1, + -1, + -1, + 1, + 3, + -1, + -1, + 1, + 1, + -3, + -1, + 1, + 1, + -1, + -3, + -3, + 1, + -1, + -1, + -1, + 3, + -1, + -1, + -1, + 1, + -3, + -1, + -1, + 1, + -1, + -3, + 3, + -1, + -1, + -1, + 1, + -3, + -1, + -1, + 1, + -1, + -3, + -1, + 1, + -1, + -1, + -3, + -3, + -1, + -1, + -1, + -1, + -3, + -1, + -1, + -1, + -1, + -3, + -1, + -1, + -1, + -1, + -3, + }; +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/FireflyParticle.java b/src/main/java/org/betterx/betterend/particle/FireflyParticle.java new file mode 100644 index 00000000..27643928 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/FireflyParticle.java @@ -0,0 +1,96 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class FireflyParticle extends SimpleAnimatedParticle { + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected FireflyParticle(ClientLevel world, + double x, + double y, + double z, + SpriteSet sprites, + double r, + double g, + double b) { + super(world, x, y, z, sprites, 0); + setSprite(sprites.get(random)); + this.lifetime = MHelper.randRange(150, 300, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setFadeColor(15916745); + this.setSpriteFromAge(sprites); + this.setAlpha(0); + + preVX = random.nextGaussian() * 0.02; + preVY = random.nextGaussian() * 0.02; + preVZ = random.nextGaussian() * 0.02; + + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + + @Override + public void tick() { + int ticks = this.age & 31; + if (ticks == 0) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + double delta = (double) ticks / 31.0; + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + if (this.age <= 60) { + this.setAlpha(this.age / 60F); + } else if (this.age > lifetime - 60) { + this.setAlpha((lifetime - this.age) / 60F); + } + + super.tick(); + } + + @Environment(EnvType.CLIENT) + public static class FireflyParticleFactory implements ParticleProvider { + private final SpriteSet sprites; + + public FireflyParticleFactory(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new FireflyParticle(world, x, y, z, sprites, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/InfusionParticle.java b/src/main/java/org/betterx/betterend/particle/InfusionParticle.java new file mode 100644 index 00000000..e7d12955 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/InfusionParticle.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +public class InfusionParticle extends TextureSheetParticle { + + private final SpriteSet spriteProvider; + + public InfusionParticle(ClientLevel clientWorld, + double x, + double y, + double z, + double velocityX, + double velocityY, + double velocityZ, + float[] palette, + SpriteSet spriteProvider) { + super(clientWorld, x, y, z, 0.0, 0.0, 0.0); + this.setSpriteFromAge(spriteProvider); + this.spriteProvider = spriteProvider; + this.setColor(palette[0], palette[1], palette[2]); + this.setAlpha(palette[3]); + this.xd = velocityX * 0.1D; + this.yd = velocityY * 0.1D; + this.zd = velocityZ * 0.1D; + this.lifetime = (int) (3.0F / (this.random.nextFloat() * 0.9F + 0.1F)); + this.quadSize *= 0.9F; + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Override + public void tick() { + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; + if (this.age++ >= this.lifetime) { + this.remove(); + } else { + this.setSpriteFromAge(spriteProvider); + double velocityX = 2.0D * this.xd * this.random.nextDouble(); + double velocityY = 3.0D * this.yd * this.random.nextDouble(); + double velocityZ = 2.0D * this.zd * this.random.nextDouble(); + this.move(velocityX, velocityY, velocityZ); + } + } + + @Environment(EnvType.CLIENT) + public static class InfusionFactory implements ParticleProvider { + private final SpriteSet spriteProvider; + + public InfusionFactory(SpriteSet spriteProvider) { + this.spriteProvider = spriteProvider; + } + + public Particle createParticle(InfusionParticleType particleType, + ClientLevel clientWorld, + double d, + double e, + double f, + double g, + double h, + double i) { + return new InfusionParticle(clientWorld, d, e, f, g, h, i, particleType.getPalette(), this.spriteProvider); + } + } +} diff --git a/src/main/java/org/betterx/betterend/particle/InfusionParticleType.java b/src/main/java/org/betterx/betterend/particle/InfusionParticleType.java new file mode 100644 index 00000000..0fbe89ca --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/InfusionParticleType.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.particle; + +import net.minecraft.commands.arguments.item.ItemInput; +import net.minecraft.commands.arguments.item.ItemParser; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.Registry; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.betterend.registry.EndParticles; + +public class InfusionParticleType extends ParticleType implements ParticleOptions { + public static final Codec CODEC = ItemStack.CODEC.xmap(itemStack -> new InfusionParticleType( + EndParticles.INFUSION, + itemStack + ), infusionParticleType -> infusionParticleType.itemStack); + + @SuppressWarnings("deprecation") + public static final ParticleOptions.Deserializer PARAMETERS_FACTORY = new ParticleOptions.Deserializer() { + public InfusionParticleType fromCommand(ParticleType particleType, + StringReader stringReader) throws CommandSyntaxException { + stringReader.expect(' '); + ItemParser.ItemResult itemResult = ItemParser.parseForItem(HolderLookup.forRegistry(Registry.ITEM), + stringReader); + ItemStack itemStack = new ItemInput(itemResult.item(), itemResult.nbt()).createItemStack(1, false); + + return new InfusionParticleType(particleType, itemStack); + } + + public InfusionParticleType fromNetwork(ParticleType particleType, + FriendlyByteBuf packetByteBuf) { + return new InfusionParticleType(particleType, packetByteBuf.readItem()); + } + }; + + private final ParticleType type; + private final ItemStack itemStack; + + public InfusionParticleType(ParticleType particleType, ItemStack stack) { + super(true, PARAMETERS_FACTORY); + this.type = particleType; + this.itemStack = stack; + } + + public InfusionParticleType(ItemStack stack) { + this(EndParticles.INFUSION, stack); + } + + @Environment(EnvType.CLIENT) + public float[] getPalette() { + int color = ColorUtil.extractColor(itemStack.getItem()); + return ColorUtil.toFloatArray(color); + } + + @Override + public ParticleType getType() { + return this.type; + } + + @Override + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeItem(itemStack); + } + + @Override + public String writeToString() { + return Registry.PARTICLE_TYPE.getKey(this).toString(); + } + + @Override + public Codec codec() { + return CODEC; + } +} diff --git a/src/main/java/org/betterx/betterend/particle/ParticleBlackSpore.java b/src/main/java/org/betterx/betterend/particle/ParticleBlackSpore.java new file mode 100644 index 00000000..509011c7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleBlackSpore.java @@ -0,0 +1,103 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleBlackSpore extends SimpleAnimatedParticle { + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected ParticleBlackSpore(ClientLevel world, + double x, + double y, + double z, + double r, + double g, + double b, + SpriteSet sprites) { + super(world, x, y, z, sprites, 0); + setSprite(sprites.get(random)); + + this.lifetime = MHelper.randRange(30, 60, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setColor(1, 1, 1); + this.setAlpha(0); + + preVX = random.nextGaussian() * 0.015; + preVY = 0; + preVZ = random.nextGaussian() * 0.015; + + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextFloat() * 0.02 + 0.01; + nextVZ = random.nextGaussian() * 0.015; + } + + @Override + public void tick() { + int ticks = this.age & 15; + if (ticks == 0) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextFloat() * 0.02 + 0.01; + nextVZ = random.nextGaussian() * 0.015; + } + double delta = (double) ticks / 15.0; + + if (this.age <= 15) { + this.setAlpha(this.age / 15F); + } else if (this.age >= this.lifetime - 15) { + this.setAlpha((this.lifetime - this.age) / 15F); + } + + if (this.age >= this.lifetime) { + this.remove(); + } + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class FactoryBlackSpore implements ParticleProvider { + + private final SpriteSet sprites; + + public FactoryBlackSpore(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleBlackSpore(world, x, y, z, 1, 1, 1, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleGeyser.java b/src/main/java/org/betterx/betterend/particle/ParticleGeyser.java new file mode 100644 index 00000000..653a19a7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleGeyser.java @@ -0,0 +1,89 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.particles.SimpleParticleType; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleGeyser extends TextureSheetParticle { + private final MutableBlockPos mut = new MutableBlockPos(); + private boolean changeDir = false; + private boolean check = true; + + protected ParticleGeyser(ClientLevel world, + double x, + double y, + double z, + double vx, + double vy, + double vz, + SpriteSet sprites) { + super(world, x, y, z, vx, vy, vz); + pickSprite(sprites); + this.lifetime = MHelper.randRange(400, 800, random); + this.quadSize = MHelper.randRange(0.5F, 1.0F, random); + this.xd = vx; + this.zd = vz; + this.yo = y - 0.125; + } + + @Override + public void tick() { + + if (this.yo == this.y || this.age > this.lifetime) { + this.remove(); + } else { + if (this.age >= this.lifetime - 200) { + this.setAlpha((this.lifetime - this.age) / 200F); + } + + this.quadSize += 0.005F; + this.yd = 0.125; + + if (changeDir) { + changeDir = false; + check = false; + this.xd += MHelper.randRange(-0.2, 0.2, random); + this.zd += MHelper.randRange(-0.2, 0.2, random); + } else if (check) { + changeDir = level.getBlockState(mut.set(x, y, z)).getFluidState().isEmpty(); + this.xd = 0; + this.zd = 0; + } + } + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class FactoryGeyser implements ParticleProvider { + + private final SpriteSet sprites; + + public FactoryGeyser(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleGeyser(world, x, y, z, 0, 0.125, 0, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleGlowingSphere.java b/src/main/java/org/betterx/betterend/particle/ParticleGlowingSphere.java new file mode 100644 index 00000000..6c074662 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleGlowingSphere.java @@ -0,0 +1,92 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleGlowingSphere extends SimpleAnimatedParticle { + private int ticks; + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected ParticleGlowingSphere(ClientLevel world, + double x, + double y, + double z, + SpriteSet sprites, + double r, + double g, + double b) { + super(world, x, y, z, sprites, 0); + setSprite(sprites.get(random)); + this.lifetime = MHelper.randRange(150, 300, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setFadeColor(15916745); + this.setSpriteFromAge(sprites); + + preVX = random.nextGaussian() * 0.02; + preVY = random.nextGaussian() * 0.02; + preVZ = random.nextGaussian() * 0.02; + + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + + @Override + public void tick() { + ticks++; + if (ticks > 30) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + ticks = 0; + } + double delta = (double) ticks / 30.0; + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Environment(EnvType.CLIENT) + public static class FactoryGlowingSphere implements ParticleProvider { + + private final SpriteSet sprites; + + public FactoryGlowingSphere(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleGlowingSphere(world, x, y, z, sprites, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleJungleSpore.java b/src/main/java/org/betterx/betterend/particle/ParticleJungleSpore.java new file mode 100644 index 00000000..be7d5e3b --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleJungleSpore.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.particles.SimpleParticleType; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleJungleSpore extends SimpleAnimatedParticle { + + protected ParticleJungleSpore(ClientLevel world, + double x, + double y, + double z, + SpriteSet sprites, + double r, + double g, + double b) { + super(world, x, y, z, sprites, 0); + setSprite(sprites.get(random)); + this.lifetime = MHelper.randRange(150, 300, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setFadeColor(15916745); + this.setSpriteFromAge(sprites); + this.setAlpha(0); + } + + @Override + public void tick() { + super.tick(); + + int ticks = this.age % 30; + if (ticks == 0) { + this.xd = random.nextGaussian() * 0.02; + this.yd = random.nextFloat() * 0.02 + 0.02; + this.zd = random.nextGaussian() * 0.02; + ticks = 0; + } + + if (this.age <= 30) { + float delta = ticks / 30F; + this.setAlpha(delta); + } else if (this.age >= this.lifetime) { + this.setAlpha(0); + } else if (this.age >= this.lifetime - 30) { + this.setAlpha((this.lifetime - this.age) / 30F); + } else { + this.setAlpha(1); + } + + this.yd -= 0.001F; + this.xd *= 0.99F; + this.zd *= 0.99F; + } + + @Environment(EnvType.CLIENT) + public static class FactoryJungleSpore implements ParticleProvider { + private final SpriteSet sprites; + + public FactoryJungleSpore(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleJungleSpore(world, x, y, z, sprites, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleSnowflake.java b/src/main/java/org/betterx/betterend/particle/ParticleSnowflake.java new file mode 100644 index 00000000..3f3585cd --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleSnowflake.java @@ -0,0 +1,107 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleSnowflake extends TextureSheetParticle { + private int ticks; + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected ParticleSnowflake(ClientLevel world, + double x, + double y, + double z, + double r, + double g, + double b, + SpriteSet sprites) { + super(world, x, y, z, r, g, b); + pickSprite(sprites); + + this.lifetime = MHelper.randRange(150, 300, random); + this.quadSize = MHelper.randRange(0.05F, 0.2F, random); + this.setAlpha(0F); + + preVX = random.nextGaussian() * 0.015; + preVY = random.nextGaussian() * 0.015; + preVZ = random.nextGaussian() * 0.015; + + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextGaussian() * 0.015; + nextVZ = random.nextGaussian() * 0.015; + } + + @Override + public void tick() { + ticks++; + if (ticks > 200) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextGaussian() * 0.015; + nextVZ = random.nextGaussian() * 0.015; + if (random.nextInt(4) == 0) { + nextVY = Math.abs(nextVY); + } + ticks = 0; + } + double delta = (double) ticks / 200.0; + + if (this.age <= 40) { + this.setAlpha(this.age / 40F); + } else if (this.age >= this.lifetime - 40) { + this.setAlpha((this.lifetime - this.age) / 40F); + } + + if (this.age >= this.lifetime) { + this.remove(); + } + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class FactorySnowflake implements ParticleProvider { + + private final SpriteSet sprites; + + public FactorySnowflake(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleSnowflake(world, x, y, z, 1, 1, 1, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleSulphur.java b/src/main/java/org/betterx/betterend/particle/ParticleSulphur.java new file mode 100644 index 00000000..33f717bf --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleSulphur.java @@ -0,0 +1,108 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class ParticleSulphur extends TextureSheetParticle { + private int ticks; + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected ParticleSulphur(ClientLevel world, + double x, + double y, + double z, + double r, + double g, + double b, + SpriteSet sprites) { + super(world, x, y, z, r, g, b); + pickSprite(sprites); + + this.lifetime = MHelper.randRange(150, 300, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setColor(1, 1, 1); + this.setAlpha(0); + + preVX = random.nextGaussian() * 0.015; + preVY = random.nextGaussian() * 0.015; + preVZ = random.nextGaussian() * 0.015; + + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextGaussian() * 0.015; + nextVZ = random.nextGaussian() * 0.015; + } + + @Override + public void tick() { + ticks++; + if (ticks > 200) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextGaussian() * 0.015; + nextVZ = random.nextGaussian() * 0.015; + if (random.nextInt(4) == 0) { + nextVY = Math.abs(nextVY); + } + ticks = 0; + } + double delta = (double) ticks / 200.0; + + if (this.age <= 40) { + this.setAlpha(this.age / 40F); + } else if (this.age >= this.lifetime - 40) { + this.setAlpha((this.lifetime - this.age) / 40F); + } + + if (this.age >= this.lifetime) { + this.remove(); + } + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class FactorySulphur implements ParticleProvider { + + private final SpriteSet sprites; + + public FactorySulphur(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleSulphur(world, x, y, z, 1, 1, 1, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/ParticleTenaneaPetal.java b/src/main/java/org/betterx/betterend/particle/ParticleTenaneaPetal.java new file mode 100644 index 00000000..fbd481e2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/ParticleTenaneaPetal.java @@ -0,0 +1,122 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.interfaces.CustomColorProvider; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; + +@Environment(EnvType.CLIENT) +public class ParticleTenaneaPetal extends TextureSheetParticle { + private static BlockColor provider; + + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected ParticleTenaneaPetal(ClientLevel world, + double x, + double y, + double z, + double r, + double g, + double b, + SpriteSet sprites) { + super(world, x, y, z, r, g, b); + pickSprite(sprites); + + if (provider == null) { + CustomColorProvider block = (CustomColorProvider) EndBlocks.TENANEA_FLOWERS; + provider = block.getProvider(); + } + int color = provider.getColor(null, null, new BlockPos(x, y, z), 0); + this.rCol = ((color >> 16) & 255) / 255F; + this.gCol = ((color >> 8) & 255) / 255F; + this.bCol = ((color) & 255) / 255F; + + this.lifetime = MHelper.randRange(120, 200, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setAlpha(0); + + preVX = 0; + preVY = 0; + preVZ = 0; + + nextVX = random.nextGaussian() * 0.02; + nextVY = -random.nextDouble() * 0.02 - 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + + @Override + public int getLightColor(float tint) { + return 15728880; + } + + @Override + public void tick() { + int ticks = this.age & 63; + if (ticks == 0) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.02; + nextVY = -random.nextDouble() * 0.02 - 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + double delta = (double) ticks / 63.0; + + if (this.age <= 40) { + this.setAlpha(this.age / 40F); + } else if (this.age >= this.lifetime - 40) { + this.setAlpha((this.lifetime - this.age) / 40F); + } + + if (this.age >= this.lifetime) { + this.remove(); + } + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class FactoryTenaneaPetal implements ParticleProvider { + + private final SpriteSet sprites; + + public FactoryTenaneaPetal(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new ParticleTenaneaPetal(world, x, y, z, 1, 1, 1, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/particle/PaticlePortalSphere.java b/src/main/java/org/betterx/betterend/particle/PaticlePortalSphere.java new file mode 100644 index 00000000..7d253e61 --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/PaticlePortalSphere.java @@ -0,0 +1,85 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +public class PaticlePortalSphere extends SimpleAnimatedParticle { + private int ticks; + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + public PaticlePortalSphere(ClientLevel world, double x, double y, double z, SpriteSet spriteProvider) { + super(world, x, y, z, spriteProvider, 0); + setSprite(spriteProvider.get(random)); + this.lifetime = MHelper.randRange(20, 80, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setColor(0xFEBBD5); + this.setFadeColor(0xBBFEE4); + this.setSpriteFromAge(spriteProvider); + + preVX = random.nextGaussian() * 0.02; + preVY = random.nextGaussian() * 0.02; + preVZ = random.nextGaussian() * 0.02; + + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + } + + @Override + public void tick() { + ticks++; + if (ticks > 30) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.02; + nextVY = random.nextGaussian() * 0.02; + nextVZ = random.nextGaussian() * 0.02; + ticks = 0; + } + double delta = (double) ticks / 30.0; + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Environment(EnvType.CLIENT) + public static class FactoryPortalSphere implements ParticleProvider { + + private final SpriteSet sprites; + + public FactoryPortalSphere(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new PaticlePortalSphere(world, x, y, z, sprites); + } + } +} diff --git a/src/main/java/org/betterx/betterend/particle/SmaragdantParticle.java b/src/main/java/org/betterx/betterend/particle/SmaragdantParticle.java new file mode 100644 index 00000000..ed88dffb --- /dev/null +++ b/src/main/java/org/betterx/betterend/particle/SmaragdantParticle.java @@ -0,0 +1,103 @@ +package org.betterx.betterend.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.Mth; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.util.MHelper; + +@Environment(EnvType.CLIENT) +public class SmaragdantParticle extends SimpleAnimatedParticle { + private double preVX; + private double preVY; + private double preVZ; + private double nextVX; + private double nextVY; + private double nextVZ; + + protected SmaragdantParticle(ClientLevel world, + double x, + double y, + double z, + double r, + double g, + double b, + SpriteSet sprites) { + super(world, x, y, z, sprites, 0); + setSprite(sprites.get(random)); + + this.lifetime = MHelper.randRange(60, 120, random); + this.quadSize = MHelper.randRange(0.05F, 0.15F, random); + this.setColor(1, 1, 1); + this.setAlpha(0); + + preVX = random.nextGaussian() * 0.01; + preVY = random.nextGaussian() * 0.01; + preVZ = random.nextGaussian() * 0.01; + + nextVX = random.nextGaussian() * 0.01; + nextVY = random.nextGaussian() * 0.01; + nextVZ = random.nextGaussian() * 0.01; + } + + @Override + public void tick() { + int ticks = this.age & 31; + if (ticks == 0) { + preVX = nextVX; + preVY = nextVY; + preVZ = nextVZ; + nextVX = random.nextGaussian() * 0.015; + nextVY = random.nextFloat() * 0.02 + 0.01; + nextVZ = random.nextGaussian() * 0.015; + } + double delta = (double) ticks / 31.0; + + if (this.age <= 31) { + this.setAlpha(this.age / 31F); + } else if (this.age >= this.lifetime - 31) { + this.setAlpha((this.lifetime - this.age) / 31F); + } + + if (this.age >= this.lifetime) { + this.remove(); + } + + this.xd = Mth.lerp(delta, preVX, nextVX); + this.yd = Mth.lerp(delta, preVY, nextVY); + this.zd = Mth.lerp(delta, preVZ, nextVZ); + + super.tick(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + @Environment(EnvType.CLIENT) + public static class SmaragdantParticleFactory implements ParticleProvider { + + private final SpriteSet sprites; + + public SmaragdantParticleFactory(SpriteSet sprites) { + this.sprites = sprites; + } + + @Override + public Particle createParticle(SimpleParticleType type, + ClientLevel world, + double x, + double y, + double z, + double vX, + double vY, + double vZ) { + return new SmaragdantParticle(world, x, y, z, 1, 1, 1, sprites); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/recipe/AlloyingRecipes.java b/src/main/java/org/betterx/betterend/recipe/AlloyingRecipes.java new file mode 100644 index 00000000..f3ef5f19 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/AlloyingRecipes.java @@ -0,0 +1,53 @@ +package org.betterx.betterend.recipe; + +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.betterend.recipe.builders.AlloyingRecipe; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; +import org.betterx.betterend.registry.EndTags; + +public class AlloyingRecipes { + public static void register() { + AlloyingRecipe.Builder.create("additional_iron") + .setInput(EndTags.ALLOYING_IRON, EndTags.ALLOYING_IRON) + .setOutput(Items.IRON_INGOT, 3) + .setExpiriense(2.1F) + .build(); + AlloyingRecipe.Builder.create("additional_gold") + .setInput(EndTags.ALLOYING_GOLD, EndTags.ALLOYING_GOLD) + .setOutput(Items.GOLD_INGOT, 3) + .setExpiriense(3F) + .build(); + AlloyingRecipe.Builder.create("additional_copper") + .setInput(EndTags.ALLOYING_COPPER, EndTags.ALLOYING_COPPER) + .setOutput(Items.COPPER_INGOT, 3) + .setExpiriense(3F) + .build(); + AlloyingRecipe.Builder.create("additional_netherite") + .setInput(Blocks.ANCIENT_DEBRIS, Blocks.ANCIENT_DEBRIS) + .setOutput(Items.NETHERITE_SCRAP, 3) + .setExpiriense(6F) + .setSmeltTime(1000) + .build(); + AlloyingRecipe.Builder.create("terminite_ingot") + .setInput(Items.IRON_INGOT, EndItems.ENDER_DUST) + .setOutput(EndBlocks.TERMINITE.ingot, 1) + .setExpiriense(2.5F) + .setSmeltTime(450) + .build(); + AlloyingRecipe.Builder.create("aeternium_ingot") + .setInput(EndBlocks.TERMINITE.ingot, Items.NETHERITE_INGOT) + .setOutput(EndItems.AETERNIUM_INGOT, 1) + .setExpiriense(4.5F) + .setSmeltTime(850) + .build(); + AlloyingRecipe.Builder.create("terminite_ingot_thallasium") + .setInput(EndBlocks.THALLASIUM.ingot, EndItems.ENDER_DUST) + .setOutput(EndBlocks.TERMINITE.ingot, 1) + .setExpiriense(2.5F) + .setSmeltTime(450) + .build(); + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/AnvilRecipes.java b/src/main/java/org/betterx/betterend/recipe/AnvilRecipes.java new file mode 100644 index 00000000..dfc9bf56 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/AnvilRecipes.java @@ -0,0 +1,85 @@ +package org.betterx.betterend.recipe; + +import net.minecraft.world.item.Items; + +import org.betterx.bclib.recipes.AnvilRecipe; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.item.material.EndToolMaterial; +import org.betterx.betterend.registry.EndItems; + +public class AnvilRecipes { + public static void register() { + AnvilRecipe.create("ender_pearl_to_dust") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(Items.ENDER_PEARL) + .setOutput(EndItems.ENDER_DUST) + .setToolLevel(4) + .setDamage(5) + .build(); + AnvilRecipe.create("ender_shard_to_dust") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.ENDER_SHARD) + .setOutput(EndItems.ENDER_DUST) + .setToolLevel(0) + .setDamage(3) + .build(); + + int anvilLevel = EndToolMaterial.AETERNIUM.getLevel(); + AnvilRecipe.create("aeternium_axe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_AXE_HEAD) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_pickaxe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_PICKAXE_HEAD) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_shovel_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_SHOVEL_HEAD) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_hoe_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_HOE_HEAD) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_hammer_head") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_HAMMER_HEAD) + .setAnvilLevel(anvilLevel) + .setToolLevel(EndToolMaterial.THALLASIUM.getLevel()) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_sword_blade") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_SWORD_BLADE) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + AnvilRecipe.create("aeternium_forged_plate") + .checkConfig(Configs.RECIPE_CONFIG) + .setInput(EndItems.AETERNIUM_INGOT) + .setOutput(EndItems.AETERNIUM_FORGED_PLATE) + .setAnvilLevel(anvilLevel) + .setToolLevel(anvilLevel) + .setDamage(6) + .build(); + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/CraftingRecipes.java b/src/main/java/org/betterx/betterend/recipe/CraftingRecipes.java new file mode 100644 index 00000000..d7d949f8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/CraftingRecipes.java @@ -0,0 +1,484 @@ +package org.betterx.betterend.recipe; + +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.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.bclib.api.tag.CommonItemTags; +import org.betterx.bclib.recipes.GridRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class CraftingRecipes { + + public static void register() { + GridRecipe.make(BetterEnd.MOD_ID, "ender_perl_to_block", EndBlocks.ENDER_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("OO", "OO") + .addMaterial('O', Items.ENDER_PEARL) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "ender_block_to_perl", Items.ENDER_PEARL) + .checkConfig(Configs.RECIPE_CONFIG) + .addMaterial('#', EndBlocks.ENDER_BLOCK) + .setOutputCount(4) + .setList("#") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "end_stone_smelter", EndBlocks.END_STONE_SMELTER) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("T#T", "V V", "T#T") + .addMaterial('#', Blocks.END_STONE_BRICKS) + .addMaterial('T', EndBlocks.THALLASIUM.ingot) + .addMaterial('V', CommonItemTags.FURNACES) + .build(); + + registerPedestal( + "andesite_pedestal", + EndBlocks.ANDESITE_PEDESTAL, + Blocks.POLISHED_ANDESITE_SLAB, + Blocks.POLISHED_ANDESITE + ); + registerPedestal( + "diorite_pedestal", + EndBlocks.DIORITE_PEDESTAL, + Blocks.POLISHED_DIORITE_SLAB, + Blocks.POLISHED_DIORITE + ); + registerPedestal( + "granite_pedestal", + EndBlocks.GRANITE_PEDESTAL, + Blocks.POLISHED_GRANITE_SLAB, + Blocks.POLISHED_GRANITE + ); + registerPedestal("quartz_pedestal", EndBlocks.QUARTZ_PEDESTAL, Blocks.QUARTZ_SLAB, Blocks.QUARTZ_PILLAR); + registerPedestal("purpur_pedestal", EndBlocks.PURPUR_PEDESTAL, Blocks.PURPUR_SLAB, Blocks.PURPUR_PILLAR); + + GridRecipe.make(BetterEnd.MOD_ID, "infusion_pedestal", EndBlocks.INFUSION_PEDESTAL) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape(" Y ", "O#O", " # ") + .addMaterial('O', Items.ENDER_PEARL) + .addMaterial('Y', Items.ENDER_EYE) + .addMaterial('#', Blocks.OBSIDIAN) + .build(); + + String material = "aeternium"; + GridRecipe.make(BetterEnd.MOD_ID, material + "_block", EndBlocks.AETERNIUM_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("III", "III", "III") + .addMaterial('I', EndItems.AETERNIUM_INGOT) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, material + "_block_to_ingot", EndItems.AETERNIUM_INGOT) + .checkConfig(Configs.RECIPE_CONFIG) + .addMaterial('#', EndBlocks.AETERNIUM_BLOCK) + .setOutputCount(9) + .setList("#") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "blue_vine_seed_dye", Items.BLUE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.BLUE_VINE_SEED) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "creeping_moss_dye", Items.CYAN_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CREEPING_MOSS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "umbrella_moss_dye", Items.YELLOW_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.UMBRELLA_MOSS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "umbrella_moss_tall_dye", Items.YELLOW_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(2) + .setList("#") + .addMaterial('#', EndBlocks.UMBRELLA_MOSS_TALL) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "shadow_plant_dye", Items.BLACK_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.SHADOW_PLANT) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "paper", Items.PAPER) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###") + .addMaterial('#', EndItems.END_LILY_LEAF_DRIED) + .setOutputCount(3) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "aurora_block", EndBlocks.AURORA_CRYSTAL) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndItems.CRYSTAL_SHARDS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "lotus_block", EndBlocks.END_LOTUS.getLog()) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndBlocks.END_LOTUS_STEM) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "needlegrass_stick", Items.STICK) + .setList("#") + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(2) + .addMaterial('#', EndBlocks.NEEDLEGRASS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_seeds", EndBlocks.SHADOW_BERRY) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .setOutputCount(4) + .addMaterial('#', EndItems.SHADOW_BERRY_RAW) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "purple_polypore_dye", Items.PURPLE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.PURPLE_POLYPORE) + .build(); + + registerLantern("end_stone_lantern", EndBlocks.END_STONE_LANTERN, Blocks.END_STONE_BRICK_SLAB); + registerLantern("andesite_lantern", EndBlocks.ANDESITE_LANTERN, Blocks.ANDESITE_SLAB); + registerLantern("diorite_lantern", EndBlocks.DIORITE_LANTERN, Blocks.DIORITE_SLAB); + registerLantern("granite_lantern", EndBlocks.GRANITE_LANTERN, Blocks.GRANITE_SLAB); + registerLantern("quartz_lantern", EndBlocks.QUARTZ_LANTERN, Blocks.QUARTZ_SLAB); + registerLantern("purpur_lantern", EndBlocks.PURPUR_LANTERN, Blocks.PURPUR_SLAB); + registerLantern("blackstone_lantern", EndBlocks.BLACKSTONE_LANTERN, Blocks.BLACKSTONE_SLAB); + + GridRecipe.make(BetterEnd.MOD_ID, "amber_gem", EndItems.AMBER_GEM) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndItems.RAW_AMBER) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "amber_block", EndBlocks.AMBER_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndItems.AMBER_GEM) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "amber_gem_block", EndItems.AMBER_GEM) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setList("#") + .addMaterial('#', EndBlocks.AMBER_BLOCK) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "iron_bulb_lantern", EndBlocks.IRON_BULB_LANTERN) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("C", "I", "#") + .addMaterial('C', Items.CHAIN) + .addMaterial('I', Items.IRON_INGOT) + .addMaterial('#', EndItems.GLOWING_BULB) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "twisted_moss_dye", Items.PINK_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.TWISTED_MOSS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "byshy_grass_dye", Items.MAGENTA_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.BUSHY_GRASS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "tail_moss_dye", Items.GRAY_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.TAIL_MOSS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "petal_block", EndBlocks.HYDRALUX_PETAL_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndItems.HYDRALUX_PETAL) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "petal_white_dye", Items.WHITE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndItems.HYDRALUX_PETAL) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "sweet_berry_jelly", EndItems.SWEET_BERRY_JELLY) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("JWSB") + .addMaterial('J', EndItems.GELATINE) + .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) + .addMaterial('S', Items.SUGAR) + .addMaterial('B', Items.SWEET_BERRIES) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_jelly", EndItems.SHADOW_BERRY_JELLY) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("JWSB") + .addMaterial('J', EndItems.GELATINE) + .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) + .addMaterial('S', Items.SUGAR) + .addMaterial('B', EndItems.SHADOW_BERRY_COOKED) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_jelly", EndItems.BLOSSOM_BERRY_JELLY) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("JWSB") + .addMaterial('J', EndItems.GELATINE) + .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) + .addMaterial('S', Items.SUGAR) + .addMaterial('B', EndItems.BLOSSOM_BERRY) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "sulphur_gunpowder", Items.GUNPOWDER) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("SCB") + .addMaterial('S', EndItems.CRYSTALLINE_SULPHUR) + .addMaterial('C', Items.COAL, Items.CHARCOAL) + .addMaterial('B', Items.BONE_MEAL) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "dense_emerald_ice", EndBlocks.DENSE_EMERALD_ICE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndBlocks.EMERALD_ICE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "ancient_emerald_ice", EndBlocks.ANCIENT_EMERALD_ICE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "###", "###") + .addMaterial('#', EndBlocks.DENSE_EMERALD_ICE) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "charnia_cyan_dye", Items.CYAN_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_CYAN) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charnia_green_dye", Items.GREEN_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_GREEN) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charnia_light_blue_dye", Items.LIGHT_BLUE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_LIGHT_BLUE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charnia_orange_dye", Items.ORANGE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_ORANGE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charnia_purple_dye", Items.PURPLE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_PURPLE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charnia_red_dye", Items.RED_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.CHARNIA_RED) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "respawn_obelisk", EndBlocks.RESPAWN_OBELISK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("CSC", "CSC", "AAA") + .addMaterial('C', EndBlocks.AURORA_CRYSTAL) + .addMaterial('S', EndItems.ETERNAL_CRYSTAL) + .addMaterial('A', EndBlocks.AMBER_BLOCK) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "twisted_umbrella_moss_dye", Items.PURPLE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("#") + .addMaterial('#', EndBlocks.TWISTED_UMBRELLA_MOSS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "twisted_umbrella_moss_dye_tall", Items.PURPLE_DYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(2) + .setList("#") + .addMaterial('#', EndBlocks.TWISTED_UMBRELLA_MOSS_TALL) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "leather_to_stripes", EndItems.LEATHER_STRIPE) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("L") + .addMaterial('L', Items.LEATHER) + .setOutputCount(3) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "stripes_to_leather", Items.LEATHER) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("SSS") + .addMaterial('S', EndItems.LEATHER_STRIPE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "leather_wrapped_stick", EndItems.LEATHER_WRAPPED_STICK) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("SL") + .addMaterial('S', Items.STICK) + .addMaterial('L', EndItems.LEATHER_STRIPE) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "fiber_string", Items.STRING) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(6) + .setShape("#", "#", "#") + .addMaterial('#', EndItems.SILK_FIBER) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "ender_eye_amber", Items.ENDER_EYE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("SAS", "APA", "SAS") + .addMaterial('S', EndItems.CRYSTAL_SHARDS) + .addMaterial('A', EndItems.AMBER_GEM) + .addMaterial('P', Items.ENDER_PEARL) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "iron_chandelier", EndBlocks.IRON_CHANDELIER) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("I#I", " # ") + .addMaterial('#', Items.IRON_INGOT) + .addMaterial('I', EndItems.LUMECORN_ROD) + .setGroup("end_metal_chandelier") + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "gold_chandelier", EndBlocks.GOLD_CHANDELIER) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("I#I", " # ") + .addMaterial('#', Items.GOLD_INGOT) + .addMaterial('I', EndItems.LUMECORN_ROD) + .setGroup("end_metal_chandelier") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "missing_tile", EndBlocks.MISSING_TILE) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setShape("#P", "P#") + .addMaterial('#', EndBlocks.VIOLECITE.stone, EndBlocks.VIOLECITE.bricks, EndBlocks.VIOLECITE.tiles) + .addMaterial('P', Blocks.PURPUR_BLOCK) + .build(); + + registerHammer("iron", Items.IRON_INGOT, EndItems.IRON_HAMMER); + registerHammer("golden", Items.GOLD_INGOT, EndItems.GOLDEN_HAMMER); + registerHammer("diamond", Items.DIAMOND, EndItems.DIAMOND_HAMMER); + + GridRecipe.make(BetterEnd.MOD_ID, "charcoal_block", EndBlocks.CHARCOAL_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "###", "###") + .addMaterial('#', Items.CHARCOAL) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "charcoal_from_block", Items.CHARCOAL) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(9) + .setList("#") + .addMaterial('#', EndBlocks.CHARCOAL_BLOCK) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "end_stone_furnace", EndBlocks.END_STONE_FURNACE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "# #", "###") + .addMaterial('#', Blocks.END_STONE) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "filalux_lantern", EndBlocks.FILALUX_LANTERN) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###", "###", "###") + .addMaterial('#', EndBlocks.FILALUX) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "silk_moth_hive", EndBlocks.SILK_MOTH_HIVE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("#L#", "LML", "#L#") + .addMaterial('#', EndBlocks.TENANEA.getBlock("planks")) + .addMaterial('L', EndBlocks.TENANEA_LEAVES) + .addMaterial('M', EndItems.SILK_MOTH_MATRIX) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "cave_pumpkin_pie", EndItems.CAVE_PUMPKIN_PIE) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("SBS", "BPB", "SBS") + .addMaterial('P', EndBlocks.CAVE_PUMPKIN) + .addMaterial('B', EndItems.BLOSSOM_BERRY, EndItems.SHADOW_BERRY_RAW) + .addMaterial('S', Items.SUGAR) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "cave_pumpkin_seeds", EndBlocks.CAVE_PUMPKIN_SEED) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(4) + .setList("#") + .addMaterial('#', EndBlocks.CAVE_PUMPKIN) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block", EndBlocks.NEON_CACTUS_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("##", "##") + .addMaterial('#', EndBlocks.NEON_CACTUS) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block_slab", EndBlocks.NEON_CACTUS_BLOCK_SLAB) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###") + .setOutputCount(6) + .addMaterial('#', EndBlocks.NEON_CACTUS_BLOCK) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block_stairs", EndBlocks.NEON_CACTUS_BLOCK_STAIRS) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("# ", "## ", "###") + .setOutputCount(4) + .addMaterial('#', EndBlocks.NEON_CACTUS_BLOCK) + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "sugar_from_root", Items.SUGAR) + .checkConfig(Configs.RECIPE_CONFIG) + .setList("###") + .addMaterial('#', EndItems.AMBER_ROOT_RAW) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "endstone_flower_pot", EndBlocks.ENDSTONE_FLOWER_POT) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(3) + .setShape("# #", " # ") + .addMaterial('#', Blocks.END_STONE_BRICKS) + .setGroup("end_pots") + .build(); + + GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_block", EndBlocks.DRAGON_BONE_BLOCK) + .checkConfig(Configs.RECIPE_CONFIG) + .setOutputCount(8) + .setShape("###", "#D#", "###") + .addMaterial('#', Blocks.BONE_BLOCK) + .addMaterial('D', Items.DRAGON_BREATH) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_slab", EndBlocks.DRAGON_BONE_SLAB) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("###") + .setOutputCount(6) + .addMaterial('#', EndBlocks.DRAGON_BONE_BLOCK) + .build(); + GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_stairs", EndBlocks.DRAGON_BONE_STAIRS) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("# ", "## ", "###") + .setOutputCount(4) + .addMaterial('#', EndBlocks.DRAGON_BONE_BLOCK) + .build(); + } + + private static void registerLantern(String name, Block lantern, Block slab) { + GridRecipe.make(BetterEnd.MOD_ID, name, lantern) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("S", "#", "S") + .addMaterial('#', EndItems.CRYSTAL_SHARDS) + .addMaterial('S', slab) + .setGroup("end_stone_lanterns") + .build(); + } + + public static void registerPedestal(String name, Block pedestal, Block slab, Block pillar) { + GridRecipe.make(BetterEnd.MOD_ID, name, pedestal) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("S", "#", "S") + .addMaterial('S', slab) + .addMaterial('#', pillar) + .setOutputCount(2) + .build(); + } + + private static void registerHammer(String name, Item material, Item result) { + GridRecipe.make(BetterEnd.MOD_ID, name + "_hammer", result) + .checkConfig(Configs.RECIPE_CONFIG) + .setShape("I I", "I#I", " # ") + .addMaterial('I', material) + .addMaterial('#', Items.STICK) + .build(); + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/FurnaceRecipes.java b/src/main/java/org/betterx/betterend/recipe/FurnaceRecipes.java new file mode 100644 index 00000000..dbf59498 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/FurnaceRecipes.java @@ -0,0 +1,45 @@ +package org.betterx.betterend.recipe; + +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.bclib.recipes.FurnaceRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class FurnaceRecipes { + public static void register() { + FurnaceRecipe.make( + BetterEnd.MOD_ID, + "end_lily_leaf_dried", + EndItems.END_LILY_LEAF, + EndItems.END_LILY_LEAF_DRIED + ).checkConfig(Configs.RECIPE_CONFIG).build(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "end_glass", EndBlocks.ENDSTONE_DUST, Blocks.GLASS) + .checkConfig(Configs.RECIPE_CONFIG) + .build(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "end_berry", EndItems.SHADOW_BERRY_RAW, EndItems.SHADOW_BERRY_COOKED) + .checkConfig(Configs.RECIPE_CONFIG) + .buildFoodlike(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "end_fish", EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED) + .checkConfig(Configs.RECIPE_CONFIG) + .buildFoodlike(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "slime_ball", EndBlocks.JELLYSHROOM_CAP_PURPLE, Items.SLIME_BALL) + .checkConfig(Configs.RECIPE_CONFIG) + .build(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "menger_sponge", EndBlocks.MENGER_SPONGE_WET, EndBlocks.MENGER_SPONGE) + .checkConfig(Configs.RECIPE_CONFIG) + .build(); + FurnaceRecipe.make( + BetterEnd.MOD_ID, + "chorus_mushroom", + EndItems.CHORUS_MUSHROOM_RAW, + EndItems.CHORUS_MUSHROOM_COOKED + ).checkConfig(Configs.RECIPE_CONFIG).buildFoodlike(); + FurnaceRecipe.make(BetterEnd.MOD_ID, "bolux_mushroom", EndBlocks.BOLUX_MUSHROOM, EndItems.BOLUX_MUSHROOM_COOKED) + .checkConfig(Configs.RECIPE_CONFIG) + .buildFoodlike(); + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/InfusionRecipes.java b/src/main/java/org/betterx/betterend/recipe/InfusionRecipes.java new file mode 100644 index 00000000..365becfb --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/InfusionRecipes.java @@ -0,0 +1,615 @@ +package org.betterx.betterend.recipe; + +import net.minecraft.world.item.EnchantedBookItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.betterend.recipe.builders.InfusionRecipe; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class InfusionRecipes { + public static void register() { + InfusionRecipe.Builder.create("runed_flavolite") + .setInput(EndBlocks.FLAVOLITE.polished) + .setOutput(EndBlocks.FLAVOLITE_RUNED) + .addCatalyst(0, EndItems.CRYSTAL_SHARDS) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(100) + .build(); + + InfusionRecipe.Builder.create("eternal_crystal") + .setInput(Items.END_CRYSTAL) + .setOutput(EndItems.ETERNAL_CRYSTAL) + .addCatalyst(0, EndItems.CRYSTAL_SHARDS) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .addCatalyst(1, EndItems.ENDER_SHARD) + .addCatalyst(3, EndItems.ENDER_SHARD) + .addCatalyst(5, EndItems.ENDER_SHARD) + .addCatalyst(7, EndItems.ENDER_SHARD) + .setTime(250) + .build(); + + InfusionRecipe.Builder.create("crystalite_helmet") + .setInput(EndBlocks.TERMINITE.helmet) + .setOutput(EndItems.CRYSTALITE_HELMET) + .addCatalyst(0, EndItems.AMBER_GEM) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(150) + .build(); + InfusionRecipe.Builder.create("crystalite_chestplate") + .setInput(EndBlocks.TERMINITE.chestplate) + .setOutput(EndItems.CRYSTALITE_CHESTPLATE) + .addCatalyst(0, EndItems.AMBER_GEM) + .addCatalyst(1, EndItems.CRYSTAL_SHARDS) + .addCatalyst(3, EndItems.CRYSTAL_SHARDS) + .addCatalyst(5, EndItems.CRYSTAL_SHARDS) + .addCatalyst(7, EndItems.CRYSTAL_SHARDS) + .setTime(300) + .build(); + InfusionRecipe.Builder.create("crystalite_leggings") + .setInput(EndBlocks.TERMINITE.leggings) + .setOutput(EndItems.CRYSTALITE_LEGGINGS) + .addCatalyst(0, EndItems.AMBER_GEM) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(225) + .build(); + InfusionRecipe.Builder.create("crystalite_boots") + .setInput(EndBlocks.TERMINITE.boots) + .setOutput(EndItems.CRYSTALITE_BOOTS) + .addCatalyst(0, EndItems.AMBER_GEM) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(150) + .build(); + + InfusionRecipe.Builder.create("crystalite_elytra") + .setInput(Items.ELYTRA) + .setOutput(EndItems.CRYSTALITE_ELYTRA) + .addCatalyst(0, EndItems.AMBER_GEM) + .addCatalyst(1, EndItems.CRYSTAL_SHARDS) + .addCatalyst(2, EndItems.ENCHANTED_MEMBRANE) + .addCatalyst(3, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.ENCHANTED_MEMBRANE) + .addCatalyst(5, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.ENCHANTED_MEMBRANE) + .addCatalyst(7, EndItems.CRYSTAL_SHARDS) + .setTime(500) + .build(); + + InfusionRecipe.Builder.create("enchanted_petal") + .setInput(EndItems.HYDRALUX_PETAL) + .setOutput(EndItems.ENCHANTED_PETAL) + .addCatalyst(0, EndItems.CRYSTAL_SHARDS) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(75) + .build(); + InfusionRecipe.Builder.create("enchanted_membrane") + .setInput(Items.PHANTOM_MEMBRANE) + .setOutput(EndItems.ENCHANTED_MEMBRANE) + .addCatalyst(0, EndItems.CRYSTAL_SHARDS) + .addCatalyst(2, EndItems.CRYSTAL_SHARDS) + .addCatalyst(4, EndItems.CRYSTAL_SHARDS) + .addCatalyst(6, EndItems.CRYSTAL_SHARDS) + .setTime(75) + .build(); + + InfusionRecipe.Builder.create("protection_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.ALL_DAMAGE_PROTECTION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(4, Items.TURTLE_HELMET) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("fire_protection_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FIRE_PROTECTION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.BLAZE_ROD) + .addCatalyst(4, Items.BLAZE_ROD) + .addCatalyst(6, Items.BLAZE_ROD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("feather_falling_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FALL_PROTECTION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.FEATHER) + .addCatalyst(4, Items.FEATHER) + .addCatalyst(6, Items.FEATHER) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("blast_protection_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.BLAST_PROTECTION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.OBSIDIAN) + .addCatalyst(4, Blocks.OBSIDIAN) + .addCatalyst(6, Blocks.OBSIDIAN) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("projectile_protection_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.PROJECTILE_PROTECTION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.SCUTE) + .addCatalyst(4, Items.SHIELD) + .addCatalyst(6, Items.SCUTE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("respiration_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.RESPIRATION, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.NAUTILUS_SHELL) + .addCatalyst(4, Items.NAUTILUS_SHELL) + .addCatalyst(6, Items.NAUTILUS_SHELL) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("aqua_affinity_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.AQUA_AFFINITY, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.PRISMARINE_CRYSTALS) + .addCatalyst(4, Items.PRISMARINE_CRYSTALS) + .addCatalyst(6, Items.PRISMARINE_CRYSTALS) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("thorns_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.THORNS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.CACTUS) + .addCatalyst(4, Blocks.CACTUS) + .addCatalyst(6, Blocks.CACTUS) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("depth_strider_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.DEPTH_STRIDER, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.LILY_PAD) + .addCatalyst(4, EndBlocks.END_LILY_SEED) + .addCatalyst(6, Blocks.LILY_PAD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("frost_walker_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FROST_WALKER, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(4, EndBlocks.ANCIENT_EMERALD_ICE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("soul_speed_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.SOUL_SPEED, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) + .addCatalyst(4, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) + .addCatalyst(6, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("sharpness_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.SHARPNESS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(4, Items.NETHERITE_SCRAP) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("smite_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.SMITE, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.SUNFLOWER) + .addCatalyst(4, Items.GOLD_INGOT) + .addCatalyst(6, Blocks.SUNFLOWER) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("bane_of_arthropods_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.BANE_OF_ARTHROPODS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.FERMENTED_SPIDER_EYE) + .addCatalyst(4, Items.IRON_INGOT) + .addCatalyst(6, Items.FERMENTED_SPIDER_EYE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("knockback_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.KNOCKBACK, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.REDSTONE) + .addCatalyst(4, Blocks.PISTON) + .addCatalyst(6, Items.REDSTONE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("fire_aspect_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FIRE_ASPECT, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.BLAZE_POWDER) + .addCatalyst(4, Items.MAGMA_CREAM) + .addCatalyst(6, Items.BLAZE_POWDER) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("looting_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.MOB_LOOTING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.EMERALD) + .addCatalyst(4, Items.GOLD_INGOT) + .addCatalyst(6, Items.EMERALD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("sweeping_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.SWEEPING_EDGE, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.GOLDEN_SWORD) + .addCatalyst(4, Items.IRON_SWORD) + .addCatalyst(6, Items.GOLDEN_SWORD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("efficiency_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.BLOCK_EFFICIENCY, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, EndItems.AMBER_GEM) + .addCatalyst(4, EndItems.AMBER_GEM) + .addCatalyst(6, EndItems.AMBER_GEM) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("silk_touch_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.SILK_TOUCH, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Blocks.COBWEB) + .addCatalyst(4, EndItems.ETERNAL_CRYSTAL) + .addCatalyst(6, Blocks.COBWEB) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + InfusionRecipe.Builder.create("unbreaking_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.UNBREAKING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.DIAMOND) + .addCatalyst(4, Items.DIAMOND) + .addCatalyst(6, Items.DIAMOND) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("fortune_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.BLOCK_FORTUNE, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.EMERALD) + .addCatalyst(4, Items.RABBIT_FOOT) + .addCatalyst(6, Items.EMERALD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("power_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.POWER_ARROWS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, EndItems.AMBER_GEM) + .addCatalyst(4, Items.DIAMOND_SWORD) + .addCatalyst(6, EndItems.AMBER_GEM) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("punch_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.PUNCH_ARROWS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.POPPED_CHORUS_FRUIT) + .addCatalyst(4, Items.SPECTRAL_ARROW) + .addCatalyst(6, Items.POPPED_CHORUS_FRUIT) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("flame_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FLAMING_ARROWS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.BLAZE_POWDER) + .addCatalyst(4, Items.SPECTRAL_ARROW) + .addCatalyst(6, Items.BLAZE_POWDER) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("infinity_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.INFINITY_ARROWS, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.SPECTRAL_ARROW) + .addCatalyst(4, EndItems.ETERNAL_CRYSTAL) + .addCatalyst(6, Items.SPECTRAL_ARROW) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + InfusionRecipe.Builder.create("luck_of_sea_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FISHING_LUCK, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.EMERALD) + .addCatalyst(4, Items.FISHING_ROD) + .addCatalyst(6, Items.EMERALD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("lure_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.FISHING_SPEED, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.GOLD_NUGGET) + .addCatalyst(4, Items.FISHING_ROD) + .addCatalyst(6, Items.GOLD_NUGGET) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("loyalty_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.LOYALTY, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.ENDER_EYE) + .addCatalyst(4, Items.HEART_OF_THE_SEA) + .addCatalyst(6, Items.ENDER_EYE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + InfusionRecipe.Builder.create("impaling_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.IMPALING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.PRISMARINE_SHARD) + .addCatalyst(4, Items.IRON_SWORD) + .addCatalyst(6, Items.PRISMARINE_SHARD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("riptide_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.RIPTIDE, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.LEAD) + .addCatalyst(4, Items.HEART_OF_THE_SEA) + .addCatalyst(6, Items.LEAD) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + InfusionRecipe.Builder.create("channeling_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.CHANNELING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.CHAIN) + .addCatalyst(4, Items.HEART_OF_THE_SEA) + .addCatalyst(6, Items.CHAIN) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + InfusionRecipe.Builder.create("multishot_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.MULTISHOT, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.ARROW) + .addCatalyst(4, Items.SPECTRAL_ARROW) + .addCatalyst(6, Items.ARROW) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("quick_charge_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.QUICK_CHARGE, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.QUARTZ) + .addCatalyst(4, Items.GLOWSTONE_DUST) + .addCatalyst(6, Items.QUARTZ) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("piercing_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.PIERCING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.GLOWSTONE_DUST) + .addCatalyst(4, Items.SPECTRAL_ARROW) + .addCatalyst(6, Items.GLOWSTONE_DUST) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(300) + .build(); + InfusionRecipe.Builder.create("mending_book") + .setInput(Items.BOOK) + .setOutput(createEnchantedBook(Enchantments.MENDING, 1)) + .addCatalyst(0, EndItems.ENCHANTED_PETAL) + .addCatalyst(2, Items.EXPERIENCE_BOTTLE) + .addCatalyst(4, Blocks.ANVIL) + .addCatalyst(6, Items.EXPERIENCE_BOTTLE) + .addCatalyst(1, Items.LAPIS_LAZULI) + .addCatalyst(3, Items.LAPIS_LAZULI) + .addCatalyst(5, Items.LAPIS_LAZULI) + .addCatalyst(7, Items.LAPIS_LAZULI) + .setGroup("enchantment") + .setTime(375) + .build(); + } + + private static ItemStack createEnchantedBook(Enchantment enchantment, int level) { + ItemStack book = new ItemStack(Items.ENCHANTED_BOOK); + EnchantedBookItem.addEnchantment(book, new EnchantmentInstance(enchantment, level)); + return book; + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/SmithingRecipes.java b/src/main/java/org/betterx/betterend/recipe/SmithingRecipes.java new file mode 100644 index 00000000..5f028919 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/SmithingRecipes.java @@ -0,0 +1,110 @@ +package org.betterx.betterend.recipe; + +import net.minecraft.world.item.Items; + +import org.betterx.bclib.recipes.SmithingTableRecipe; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class SmithingRecipes { + + public static void register() { + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_sword_handle") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_SWORD_HANDLE) + .setBase(EndBlocks.TERMINITE.ingot) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_sword") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_SWORD) + .setBase(EndItems.AETERNIUM_SWORD_BLADE) + .setAddition(EndItems.AETERNIUM_SWORD_HANDLE) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_pickaxe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_PICKAXE) + .setBase(EndItems.AETERNIUM_PICKAXE_HEAD) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_axe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_AXE) + .setBase(EndItems.AETERNIUM_AXE_HEAD) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_shovel") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_SHOVEL) + .setBase(EndItems.AETERNIUM_SHOVEL_HEAD) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_hoe") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_HOE) + .setBase(EndItems.AETERNIUM_HOE_HEAD) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_hammer") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_HAMMER) + .setBase(EndItems.AETERNIUM_HAMMER_HEAD) + .setAddition(EndItems.LEATHER_WRAPPED_STICK) + .build(); + + SmithingTableRecipe.create(BetterEnd.MOD_ID, "netherite_hammer") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.NETHERITE_HAMMER) + .setBase(EndItems.DIAMOND_HAMMER) + .setAddition(Items.NETHERITE_INGOT) + .build(); + + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_helmet") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_HELMET) + .setBase(EndBlocks.TERMINITE.helmet) + .setAddition(EndItems.AETERNIUM_FORGED_PLATE) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_chestplate") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_CHESTPLATE) + .setBase(EndBlocks.TERMINITE.chestplate) + .setAddition(EndItems.AETERNIUM_FORGED_PLATE) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_leggings") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_LEGGINGS) + .setBase(EndBlocks.TERMINITE.leggings) + .setAddition(EndItems.AETERNIUM_FORGED_PLATE) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_boots") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.AETERNIUM_BOOTS) + .setBase(EndBlocks.TERMINITE.boots) + .setAddition(EndItems.AETERNIUM_FORGED_PLATE) + .build(); + + SmithingTableRecipe.create(BetterEnd.MOD_ID, "thallasium_anvil_updrade") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndBlocks.TERMINITE.anvilBlock.asItem()) + .setBase(EndBlocks.THALLASIUM.anvilBlock.asItem()) + .setAddition(EndBlocks.TERMINITE.block) + .build(); + SmithingTableRecipe.create(BetterEnd.MOD_ID, "terminite_anvil_updrade") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndBlocks.AETERNIUM_ANVIL.asItem()) + .setBase(EndBlocks.TERMINITE.anvilBlock.asItem()) + .setAddition(EndItems.AETERNIUM_INGOT) + .build(); + + SmithingTableRecipe.create(BetterEnd.MOD_ID, "armored_elytra") + .checkConfig(Configs.RECIPE_CONFIG) + .setResult(EndItems.ARMORED_ELYTRA) + .setBase(Items.ELYTRA) + .setAddition(EndItems.AETERNIUM_INGOT) + .build(); + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/builders/AlloyingRecipe.java b/src/main/java/org/betterx/betterend/recipe/builders/AlloyingRecipe.java new file mode 100644 index 00000000..7a3ab27e --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/builders/AlloyingRecipe.java @@ -0,0 +1,298 @@ +package org.betterx.betterend.recipe.builders; + +import net.minecraft.core.NonNullList; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.Container; +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.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.betterx.bclib.interfaces.UnknownReceipBookCategory; +import org.betterx.bclib.recipes.BCLRecipeManager; +import org.betterx.bclib.util.ItemUtil; +import org.betterx.bclib.util.RecipeHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.registry.EndBlocks; + +public class AlloyingRecipe implements Recipe, UnknownReceipBookCategory { + public final static String GROUP = "alloying"; + public final static RecipeType TYPE = BCLRecipeManager.registerType(BetterEnd.MOD_ID, GROUP); + public final static Serializer SERIALIZER = BCLRecipeManager.registerSerializer( + BetterEnd.MOD_ID, + GROUP, + new Serializer() + ); + + protected final RecipeType type; + protected final ResourceLocation id; + protected final Ingredient primaryInput; + protected final Ingredient secondaryInput; + protected final ItemStack output; + protected final String group; + protected final float experience; + protected final int smeltTime; + + public AlloyingRecipe(ResourceLocation id, + String group, + Ingredient primaryInput, + Ingredient secondaryInput, + ItemStack output, + float experience, + int smeltTime) { + this.group = group; + this.id = id; + this.primaryInput = primaryInput; + this.secondaryInput = secondaryInput; + this.output = output; + this.experience = experience; + this.smeltTime = smeltTime; + this.type = TYPE; + } + + public float getExperience() { + return this.experience; + } + + public int getSmeltTime() { + return this.smeltTime; + } + + @Override + public NonNullList getIngredients() { + NonNullList defaultedList = NonNullList.create(); + defaultedList.add(primaryInput); + defaultedList.add(secondaryInput); + + return defaultedList; + } + + @Override + public boolean matches(Container inv, Level world) { + return this.primaryInput.test(inv.getItem(0)) && this.secondaryInput.test(inv.getItem(1)) || this.primaryInput.test( + inv.getItem(1)) && this.secondaryInput.test(inv.getItem(0)); + } + + @Override + public ItemStack assemble(Container inv) { + return this.output.copy(); + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public ItemStack getResultItem() { + return this.output; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + + @Override + public RecipeSerializer getSerializer() { + return SERIALIZER; + } + + @Override + public RecipeType getType() { + return this.type; + } + + @Override + @Environment(EnvType.CLIENT) + public String getGroup() { + return this.group; + } + + @Environment(EnvType.CLIENT) + public ItemStack getToastSymbol() { + return new ItemStack(EndBlocks.END_STONE_SMELTER); + } + + public static class Builder { + private final static Builder INSTANCE = new Builder(); + private static boolean exist; + + public static Builder create(ResourceLocation id) { + INSTANCE.id = id; + INSTANCE.group = String.format("%s_%s", GROUP, id); + INSTANCE.primaryInput = null; + INSTANCE.secondaryInput = null; + INSTANCE.output = null; + INSTANCE.experience = 0.0F; + INSTANCE.smeltTime = 350; + exist = Configs.RECIPE_CONFIG.getBoolean("alloying", id.getPath(), true); + + return INSTANCE; + } + + public static Builder create(String id) { + return create(BetterEnd.makeID(id)); + } + + private ResourceLocation id; + private Ingredient primaryInput; + private Ingredient secondaryInput; + private ItemStack output; + private String group; + private float experience; + private int smeltTime; + private boolean alright = true; + + private Builder() { + } + + public Builder setGroup(String group) { + this.group = group; + return this; + } + + public Builder setPrimaryInput(ItemLike... inputs) { + for (ItemLike item : inputs) { + this.alright &= RecipeHelper.exists(item); + } + this.primaryInput = Ingredient.of(inputs); + return this; + } + + public Builder setSecondaryInput(ItemLike... inputs) { + for (ItemLike item : inputs) { + this.alright &= RecipeHelper.exists(item); + } + this.secondaryInput = Ingredient.of(inputs); + return this; + } + + public Builder setPrimaryInput(TagKey input) { + this.primaryInput = Ingredient.of(input); + return this; + } + + public Builder setSecondaryInput(TagKey input) { + this.secondaryInput = Ingredient.of(input); + return this; + } + + public Builder setInput(ItemLike primaryInput, ItemLike secondaryInput) { + this.setPrimaryInput(primaryInput); + this.setSecondaryInput(secondaryInput); + return this; + } + + public Builder setInput(TagKey primaryInput, TagKey secondaryInput) { + this.setPrimaryInput(primaryInput); + this.setSecondaryInput(secondaryInput); + return this; + } + + public Builder setOutput(ItemLike output, int amount) { + this.alright &= RecipeHelper.exists(output); + this.output = new ItemStack(output, amount); + return this; + } + + public Builder setExpiriense(float amount) { + this.experience = amount; + return this; + } + + public Builder setSmeltTime(int time) { + this.smeltTime = time; + return this; + } + + public void build() { + if (exist) { + if (primaryInput == null) { + BetterEnd.LOGGER.warning( + "Primary input for Alloying recipe can't be 'null', recipe {} will be ignored!", + id + ); + return; + } + if (secondaryInput == null) { + BetterEnd.LOGGER.warning( + "Secondary input for Alloying can't be 'null', recipe {} will be ignored!", + id + ); + return; + } + if (output == null) { + BetterEnd.LOGGER.warning("Output for Alloying can't be 'null', recipe {} will be ignored!", id); + return; + } + if (BCLRecipeManager.getRecipe(TYPE, id) != null) { + BetterEnd.LOGGER.warning("Can't add Alloying recipe! Id {} already exists!", id); + return; + } + if (!alright) { + BetterEnd.LOGGER.debug("Can't add Alloying recipe {}! Ingeredient or output not exists.", id); + return; + } + BCLRecipeManager.addRecipe( + TYPE, + new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime) + ); + } + } + } + + public static class Serializer implements RecipeSerializer { + @Override + public AlloyingRecipe fromJson(ResourceLocation id, JsonObject json) { + JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients"); + Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0)); + Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1)); + String group = GsonHelper.getAsString(json, "group", ""); + JsonObject result = GsonHelper.getAsJsonObject(json, "result"); + ItemStack output = ItemUtil.fromJsonRecipe(result); + if (output == null) { + throw new IllegalStateException("Output item does not exists!"); + } + float experience = GsonHelper.getAsFloat(json, "experience", 0.0F); + int smeltTime = GsonHelper.getAsInt(json, "smelttime", 350); + + return new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime); + } + + @Override + public AlloyingRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf packetBuffer) { + String group = packetBuffer.readUtf(32767); + Ingredient primary = Ingredient.fromNetwork(packetBuffer); + Ingredient secondary = Ingredient.fromNetwork(packetBuffer); + ItemStack output = packetBuffer.readItem(); + float experience = packetBuffer.readFloat(); + int smeltTime = packetBuffer.readVarInt(); + + return new AlloyingRecipe(id, group, primary, secondary, output, experience, smeltTime); + } + + @Override + public void toNetwork(FriendlyByteBuf packetBuffer, AlloyingRecipe recipe) { + packetBuffer.writeUtf(recipe.group); + recipe.primaryInput.toNetwork(packetBuffer); + recipe.secondaryInput.toNetwork(packetBuffer); + packetBuffer.writeItem(recipe.output); + packetBuffer.writeFloat(recipe.experience); + packetBuffer.writeVarInt(recipe.smeltTime); + } + } +} diff --git a/src/main/java/org/betterx/betterend/recipe/builders/InfusionRecipe.java b/src/main/java/org/betterx/betterend/recipe/builders/InfusionRecipe.java new file mode 100644 index 00000000..f1bb7ab6 --- /dev/null +++ b/src/main/java/org/betterx/betterend/recipe/builders/InfusionRecipe.java @@ -0,0 +1,297 @@ +package org.betterx.betterend.recipe.builders; + +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.TagParser; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +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.level.ItemLike; +import net.minecraft.world.level.Level; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import com.google.gson.JsonObject; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.betterx.bclib.interfaces.UnknownReceipBookCategory; +import org.betterx.bclib.recipes.BCLRecipeManager; +import org.betterx.bclib.util.ItemUtil; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.rituals.InfusionRitual; + +import java.util.Arrays; + +public class InfusionRecipe implements Recipe, UnknownReceipBookCategory { + public final static String GROUP = "infusion"; + public final static RecipeType TYPE = BCLRecipeManager.registerType(BetterEnd.MOD_ID, GROUP); + public final static Serializer SERIALIZER = BCLRecipeManager.registerSerializer( + BetterEnd.MOD_ID, + GROUP, + new Serializer() + ); + + private final ResourceLocation id; + private final Ingredient[] catalysts; + private Ingredient input; + private ItemStack output; + private int time = 1; + private String group; + + private InfusionRecipe(ResourceLocation id) { + this(id, null, null); + } + + private InfusionRecipe(ResourceLocation id, Ingredient input, ItemStack output) { + this.id = id; + this.input = input; + this.output = output; + this.catalysts = new Ingredient[8]; + Arrays.fill(catalysts, Ingredient.EMPTY); + } + + public int getInfusionTime() { + return this.time; + } + + @Override + public boolean matches(InfusionRitual inv, Level world) { + boolean valid = this.input.test(inv.getItem(0)); + if (!valid) return false; + for (int i = 0; i < 8; i++) { + valid &= this.catalysts[i].test(inv.getItem(i + 1)); + } + return valid; + } + + @Override + public ItemStack assemble(InfusionRitual ritual) { + return output.copy(); + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public NonNullList getIngredients() { + NonNullList defaultedList = NonNullList.create(); + defaultedList.add(input); + defaultedList.addAll(Arrays.asList(catalysts)); + return defaultedList; + } + + @Override + public ItemStack getResultItem() { + return this.output; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + + @Override + @Environment(EnvType.CLIENT) + public String getGroup() { + return this.group; + } + + @Override + public RecipeSerializer getSerializer() { + return SERIALIZER; + } + + @Override + public RecipeType getType() { + return TYPE; + } + + public static class Builder { + private final static Builder INSTANCE = new Builder(); + private static boolean exist; + + public static Builder create(String id) { + return create(BetterEnd.makeID(id)); + } + + public static Builder create(ResourceLocation id) { + INSTANCE.id = id; + INSTANCE.input = null; + INSTANCE.output = null; + INSTANCE.time = 1; + exist = Configs.RECIPE_CONFIG.getBoolean("infusion", id.getPath(), true); + + Arrays.fill(INSTANCE.catalysts, Ingredient.EMPTY); + + return INSTANCE; + } + + private final Ingredient[] catalysts = new Ingredient[8]; + private ResourceLocation id; + private Ingredient input; + private ItemStack output; + private String group; + private int time = 1; + + private Builder() { + Arrays.fill(catalysts, Ingredient.EMPTY); + } + + public Builder setGroup(String group) { + this.group = group; + return this; + } + + public Builder setInput(ItemLike input) { + this.input = Ingredient.of(input); + return this; + } + + public Builder setOutput(ItemLike output) { + this.output = new ItemStack(output); + this.output.setCount(1); + return this; + } + + public Builder setOutput(ItemStack output) { + this.output = output; + this.output.setCount(1); + return this; + } + + public Builder setTime(int time) { + this.time = time; + return this; + } + + public Builder addCatalyst(int slot, ItemLike... items) { + if (slot > 7) return this; + this.catalysts[slot] = Ingredient.of(items); + return this; + } + + public void build() { + if (exist) { + if (input == null) { + BetterEnd.LOGGER.warning( + "Input for Infusion recipe can't be 'null', recipe {} will be ignored!", + id + ); + return; + } + if (output == null) { + BetterEnd.LOGGER.warning( + "Output for Infusion recipe can't be 'null', recipe {} will be ignored!", + id + ); + return; + } + InfusionRecipe recipe = new InfusionRecipe(id, input, output); + recipe.group = group != null ? group : GROUP; + recipe.time = time; + int empty = 0; + for (int i = 0; i < catalysts.length; i++) { + if (catalysts[i].isEmpty()) empty++; + else recipe.catalysts[i] = catalysts[i]; + } + if (empty == catalysts.length) { + BetterEnd.LOGGER.warning("At least one catalyst must be non empty, recipe {} will be ignored!", id); + return; + } + BCLRecipeManager.addRecipe(TYPE, recipe); + } + } + } + + public static class Serializer implements RecipeSerializer { + @Override + public InfusionRecipe fromJson(ResourceLocation id, JsonObject json) { + InfusionRecipe recipe = new InfusionRecipe(id); + recipe.input = Ingredient.fromJson(json.get("input")); + JsonObject result = GsonHelper.getAsJsonObject(json, "result"); + recipe.output = ItemUtil.fromJsonRecipe(result); + if (recipe.output == null) { + throw new IllegalStateException("Output item does not exists!"); + } + if (result.has("nbt")) { + try { + String nbtData = GsonHelper.getAsString(result, "nbt"); + CompoundTag nbt = TagParser.parseTag(nbtData); + recipe.output.setTag(nbt); + } catch (CommandSyntaxException ex) { + BetterEnd.LOGGER.warning("Error parse nbt data for output.", ex); + } + } + recipe.group = GsonHelper.getAsString(json, "group", GROUP); + recipe.time = GsonHelper.getAsInt(json, "time", 1); + + JsonObject catalysts = GsonHelper.getAsJsonObject(json, "catalysts"); + ItemStack catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north", "")); + recipe.catalysts[0] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_east", "")); + recipe.catalysts[1] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "east", "")); + recipe.catalysts[2] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_east", "")); + recipe.catalysts[3] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south", "")); + recipe.catalysts[4] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_west", "")); + recipe.catalysts[5] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "west", "")); + recipe.catalysts[6] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_west", "")); + recipe.catalysts[7] = (catalyst != null && !catalyst.isEmpty()) + ? Ingredient.of(catalyst.getItem()) + : Ingredient.EMPTY; + + return recipe; + } + + @Override + public InfusionRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) { + InfusionRecipe recipe = new InfusionRecipe(id); + recipe.input = Ingredient.fromNetwork(buffer); + recipe.output = buffer.readItem(); + recipe.group = buffer.readUtf(); + recipe.time = buffer.readVarInt(); + for (int i = 0; i < 8; i++) { + recipe.catalysts[i] = Ingredient.fromNetwork(buffer); + } + return recipe; + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, InfusionRecipe recipe) { + recipe.input.toNetwork(buffer); + buffer.writeItem(recipe.output); + buffer.writeUtf(recipe.group); + buffer.writeVarInt(recipe.time); + for (int i = 0; i < 8; i++) { + recipe.catalysts[i].toNetwork(buffer); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndAttributes.java b/src/main/java/org/betterx/betterend/registry/EndAttributes.java new file mode 100644 index 00000000..c18f611c --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndAttributes.java @@ -0,0 +1,26 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.item.EndAttribute; + +public class EndAttributes { + public final static Attribute BLINDNESS_RESISTANCE = registerAttribute("generic.blindness_resistance", 0.0, true); + + public static Attribute registerAttribute(String name, double value, boolean syncable) { + return Registry.register( + Registry.ATTRIBUTE, + BetterEnd.makeID(name), + new EndAttribute("attribute.name." + name, value).setSyncable(syncable) + ); + } + + public static AttributeSupplier.Builder addLivingEntityAttributes(AttributeSupplier.Builder builder) { + return builder.add(EndAttributes.BLINDNESS_RESISTANCE); + } +} + + diff --git a/src/main/java/org/betterx/betterend/registry/EndBiomes.java b/src/main/java/org/betterx/betterend/registry/EndBiomes.java new file mode 100644 index 00000000..77e50a87 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndBiomes.java @@ -0,0 +1,160 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.biome.Biome; + +import org.betterx.bclib.api.LifeCycleAPI; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.bclib.world.generator.BiomePicker; +import org.betterx.bclib.world.generator.map.hex.HexBiomeMap; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.biome.air.BiomeIceStarfield; +import org.betterx.betterend.world.biome.cave.*; +import org.betterx.betterend.world.biome.land.*; +import org.betterx.betterend.world.generator.BiomeType; +import org.betterx.betterend.world.generator.GeneratorOptions; + +public class EndBiomes { + public static final BiomeAPI.Dimension END_CAVE = new BiomeAPI.Dimension(BiomeAPI.Dimension.END); + + public static BiomePicker CAVE_BIOMES = null; + private static HexBiomeMap caveBiomeMap; + private static long lastSeed; + + // Better End Land + public static final EndBiome FOGGY_MUSHROOMLAND = registerBiome(new FoggyMushroomlandBiome(), BiomeType.LAND); + public static final EndBiome CHORUS_FOREST = registerBiome(new ChorusForestBiome(), BiomeType.LAND); + public static final EndBiome DUST_WASTELANDS = registerBiome(new DustWastelandsBiome(), BiomeType.LAND); + public static final EndBiome MEGALAKE = registerBiome(new MegalakeBiome(), BiomeType.LAND); + public static final EndBiome MEGALAKE_GROVE = registerSubBiome(new MegalakeGroveBiome(), MEGALAKE); + public static final EndBiome CRYSTAL_MOUNTAINS = registerBiome(new CrystalMountainsBiome(), BiomeType.LAND); + public static final EndBiome PAINTED_MOUNTAINS = registerSubBiome(new PaintedMountainsBiome(), DUST_WASTELANDS); + public static final EndBiome SHADOW_FOREST = registerBiome(new ShadowForestBiome(), BiomeType.LAND); + public static final EndBiome AMBER_LAND = registerBiome(new AmberLandBiome(), BiomeType.LAND); + public static final EndBiome BLOSSOMING_SPIRES = registerBiome(new BlossomingSpiresBiome(), BiomeType.LAND); + public static final EndBiome SULPHUR_SPRINGS = registerBiome(new SulphurSpringsBiome(), BiomeType.LAND); + public static final EndBiome UMBRELLA_JUNGLE = registerBiome(new UmbrellaJungleBiome(), BiomeType.LAND); + public static final EndBiome GLOWING_GRASSLANDS = registerBiome(new GlowingGrasslandsBiome(), BiomeType.LAND); + public static final EndBiome DRAGON_GRAVEYARDS = registerBiome(new DragonGraveyardsBiome(), BiomeType.LAND); + public static final EndBiome DRY_SHRUBLAND = registerBiome(new DryShrublandBiome(), BiomeType.LAND); + public static final EndBiome LANTERN_WOODS = registerBiome(new LanternWoodsBiome(), BiomeType.LAND); + public static final EndBiome NEON_OASIS = registerSubBiome(new NeonOasisBiome(), DUST_WASTELANDS); + public static final EndBiome UMBRA_VALLEY = registerBiome(new UmbraValleyBiome(), BiomeType.LAND); + + // Better End Void + public static final EndBiome ICE_STARFIELD = registerBiome(new BiomeIceStarfield(), BiomeType.VOID); + + // Better End Caves + public static final EndCaveBiome EMPTY_END_CAVE = registerCaveBiome(new EmptyEndCaveBiome()); + public static final EndCaveBiome EMPTY_SMARAGDANT_CAVE = registerCaveBiome(new EmptySmaragdantCaveBiome()); + public static final EndCaveBiome LUSH_SMARAGDANT_CAVE = registerCaveBiome(new LushSmaragdantCaveBiome()); + public static final EndCaveBiome EMPTY_AURORA_CAVE = registerCaveBiome(new EmptyAuroraCaveBiome()); + public static final EndCaveBiome LUSH_AURORA_CAVE = registerCaveBiome(new LushAuroraCaveBiome()); + public static final EndCaveBiome JADE_CAVE = registerCaveBiome(new JadeCaveBiome()); + + public static void register() { + LifeCycleAPI.onLevelLoad(EndBiomes::onWorldLoad); + } + + private static void onWorldLoad(ServerLevel level, long seed, Registry registry) { + if (CAVE_BIOMES == null || CAVE_BIOMES.biomeRegistry != registry) { + CAVE_BIOMES = new BiomePicker(registry); + registry.stream() + .filter(biome -> registry.getResourceKey(biome).isPresent()) + .map(biome -> registry.getOrCreateHolder(registry.getResourceKey(biome).get())) + .map(biome -> biome.unwrapKey().orElseThrow().location()) + .filter(id -> BiomeAPI.wasRegisteredAs(id, END_CAVE)) + .map(id -> BiomeAPI.getBiome(id)) + .filter(bcl -> bcl != null) + .forEach(bcl -> CAVE_BIOMES.addBiome(bcl)); + + CAVE_BIOMES.rebuild(); + caveBiomeMap = null; + } + + if (caveBiomeMap == null || lastSeed != seed) { + caveBiomeMap = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeCaves(), CAVE_BIOMES); + lastSeed = seed; + } + } + + /** + * Put existing {@link EndBiome} as a sub-biome into selected parent. + * + * @param biomeConfig - {@link EndBiome.Config} instance + * @param parent - {@link EndBiome} to be linked with + * @return registered {@link EndBiome} + */ + public static EndBiome registerSubBiome(EndBiome.Config biomeConfig, EndBiome parent) { + final EndBiome biome = EndBiome.create(biomeConfig); + + if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { + BiomeAPI.registerSubBiome(parent, biome); + } + return biome; + } + + /** + * Registers {@link EndBiome} and adds it into worldgen. + * + * @param biomeConfig - {@link EndBiome.Config} instance + * @param type - {@link BiomeType} + * @return registered {@link EndBiome} + */ + public static EndBiome registerBiome(EndBiome.Config biomeConfig, BiomeType type) { + final EndBiome biome = EndBiome.create(biomeConfig); + if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { + if (type == BiomeType.LAND) { + BiomeAPI.registerEndLandBiome(biome); + } else { + BiomeAPI.registerEndVoidBiome(biome); + } + } + return biome; + } + + /** + * Put integration sub-biome {@link EndBiome} into subbiomes list and registers it. + * + * @param biomeConfig - {@link EndBiome.Config} instance + * @return registered {@link EndBiome} + */ + public static EndBiome registerSubBiomeIntegration(EndBiome.Config biomeConfig) { + EndBiome biome = EndBiome.create(biomeConfig); + if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { + BiomeAPI.registerBiome(biome, BiomeAPI.Dimension.END); + } + return biome; + } + + /** + * Link integration sub-biome with parent. + * + * @param biome - {@link EndBiome} instance + * @param parent - {@link ResourceLocation} parent id + */ + public static void addSubBiomeIntegration(EndBiome biome, ResourceLocation parent) { + if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { + BCLBiome parentBiome = BiomeAPI.getBiome(parent); + if (parentBiome != null && !parentBiome.containsSubBiome(biome)) { + parentBiome.addSubBiome(biome); + } + } + } + + public static EndCaveBiome registerCaveBiome(EndCaveBiome.Config biomeConfig) { + final EndCaveBiome biome = EndCaveBiome.create(biomeConfig); + if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { + BiomeAPI.registerBiome(biome, END_CAVE); + } + return biome; + } + + public static BiomePicker.ActualBiome getCaveBiome(int x, int z) { + return caveBiomeMap.getBiome(x, 5, z); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndBlockEntities.java b/src/main/java/org/betterx/betterend/registry/EndBlockEntities.java new file mode 100644 index 00000000..414a0a56 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndBlockEntities.java @@ -0,0 +1,53 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndStoneSmelter; +import org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.blocks.entities.*; + +public class EndBlockEntities { + public final static BlockEntityType END_STONE_SMELTER = registerBlockEntity( + EndStoneSmelter.ID, + FabricBlockEntityTypeBuilder.create(EndStoneSmelterBlockEntity::new, EndBlocks.END_STONE_SMELTER) + ); + public final static BlockEntityType PEDESTAL = registerBlockEntity( + "pedestal", + FabricBlockEntityTypeBuilder.create(PedestalBlockEntity::new, getPedestals()) + ); + public final static BlockEntityType ETERNAL_PEDESTAL = registerBlockEntity( + "eternal_pedestal", + FabricBlockEntityTypeBuilder.create(EternalPedestalEntity::new, EndBlocks.ETERNAL_PEDESTAL) + ); + public final static BlockEntityType INFUSION_PEDESTAL = registerBlockEntity( + "infusion_pedestal", + FabricBlockEntityTypeBuilder.create(InfusionPedestalEntity::new, EndBlocks.INFUSION_PEDESTAL) + ); + public final static BlockEntityType HYDROTHERMAL_VENT = registerBlockEntity( + "hydrother_malvent", + FabricBlockEntityTypeBuilder.create(BlockEntityHydrothermalVent::new, EndBlocks.HYDROTHERMAL_VENT) + ); + + public static BlockEntityType registerBlockEntity(String id, + FabricBlockEntityTypeBuilder builder) { + return Registry.register(Registry.BLOCK_ENTITY_TYPE, BetterEnd.makeID(id), builder.build(null)); + + //return Registry.register(Registry.BLOCK_ENTITY_TYPE, BetterEnd.makeID(id), builder.build(null)); + } + + public static void register() { + } + + static Block[] getPedestals() { + return EndBlocks.getModBlocks() + .stream() + .filter(block -> block instanceof PedestalBlock && !((PedestalBlock) block).hasUniqueEntity()) + .toArray(Block[]::new); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndBlockEntityRenders.java b/src/main/java/org/betterx/betterend/registry/EndBlockEntityRenders.java new file mode 100644 index 00000000..e6aeeed5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndBlockEntityRenders.java @@ -0,0 +1,16 @@ +package org.betterx.betterend.registry; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; + +import org.betterx.betterend.client.render.PedestalItemRenderer; + +@Environment(EnvType.CLIENT) +public class EndBlockEntityRenders { + public static void register() { + BlockEntityRendererRegistry.register(EndBlockEntities.PEDESTAL, PedestalItemRenderer::new); + BlockEntityRendererRegistry.register(EndBlockEntities.ETERNAL_PEDESTAL, PedestalItemRenderer::new); + BlockEntityRendererRegistry.register(EndBlockEntities.INFUSION_PEDESTAL, PedestalItemRenderer::new); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndBlocks.java b/src/main/java/org/betterx/betterend/registry/EndBlocks.java new file mode 100644 index 00000000..9cc235bf --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndBlocks.java @@ -0,0 +1,514 @@ +package org.betterx.betterend.registry; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.MaterialColor; + +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; + +import org.betterx.bclib.blocks.*; +import org.betterx.bclib.registry.BlockRegistry; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.*; +import org.betterx.betterend.blocks.basis.*; +import org.betterx.betterend.complexmaterials.*; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.item.material.EndArmorMaterial; +import org.betterx.betterend.item.material.EndToolMaterial; +import org.betterx.betterend.tab.CreativeTabs; + +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class EndBlocks { + private static final BlockRegistry REGISTRY = new BlockRegistry(CreativeTabs.TAB_BLOCKS, Configs.BLOCK_CONFIG); + + // Terrain // + public static final Block ENDSTONE_DUST = registerBlock("endstone_dust", new EndstoneDustBlock()); + public static final Block END_MYCELIUM = registerBlock("end_mycelium", + new EndTerrainBlock(MaterialColor.COLOR_LIGHT_BLUE)); + public static final Block END_MOSS = registerBlock("end_moss", new EndTerrainBlock(MaterialColor.COLOR_CYAN)); + public static final Block CHORUS_NYLIUM = registerBlock("chorus_nylium", + new EndTerrainBlock(MaterialColor.COLOR_MAGENTA)); + public static final Block CAVE_MOSS = registerBlock("cave_moss", new EndTripleTerrain(MaterialColor.COLOR_PURPLE)); + public static final Block CRYSTAL_MOSS = registerBlock("crystal_moss", + new EndTerrainBlock(MaterialColor.COLOR_PINK)); + public static final Block SHADOW_GRASS = registerBlock("shadow_grass", new ShadowGrassBlock()); + public static final Block PINK_MOSS = registerBlock("pink_moss", new EndTerrainBlock(MaterialColor.COLOR_PINK)); + public static final Block AMBER_MOSS = registerBlock("amber_moss", new EndTerrainBlock(MaterialColor.COLOR_ORANGE)); + public static final Block JUNGLE_MOSS = registerBlock("jungle_moss", + new EndTerrainBlock(MaterialColor.COLOR_GREEN)); + public static final Block SANGNUM = registerBlock("sangnum", new EndTerrainBlock(MaterialColor.COLOR_RED)); + public static final Block RUTISCUS = registerBlock("rutiscus", new EndTerrainBlock(MaterialColor.COLOR_ORANGE)); + public static final Block PALLIDIUM_FULL = registerBlock("pallidium_full", new PallidiumBlock("full", null)); + public static final Block PALLIDIUM_HEAVY = registerBlock("pallidium_heavy", + new PallidiumBlock("heavy", PALLIDIUM_FULL)); + public static final Block PALLIDIUM_THIN = registerBlock("pallidium_thin", + new PallidiumBlock("thin", PALLIDIUM_HEAVY)); + public static final Block PALLIDIUM_TINY = registerBlock("pallidium_tiny", + new PallidiumBlock("tiny", PALLIDIUM_THIN)); + + // Roads // + public static final Block END_MYCELIUM_PATH = registerBlock("end_mycelium_path", new BasePathBlock(END_MYCELIUM)); + public static final Block END_MOSS_PATH = registerBlock("end_moss_path", new BasePathBlock(END_MOSS)); + public static final Block CHORUS_NYLIUM_PATH = registerBlock("chorus_nylium_path", + new BasePathBlock(CHORUS_NYLIUM)); + public static final Block CAVE_MOSS_PATH = registerBlock("cave_moss_path", new BasePathBlock(CAVE_MOSS)); + public static final Block CRYSTAL_MOSS_PATH = registerBlock("crystal_moss_path", new BasePathBlock(CRYSTAL_MOSS)); + public static final Block SHADOW_GRASS_PATH = registerBlock("shadow_grass_path", new BasePathBlock(SHADOW_GRASS)); + public static final Block PINK_MOSS_PATH = registerBlock("pink_moss_path", new BasePathBlock(PINK_MOSS)); + public static final Block AMBER_MOSS_PATH = registerBlock("amber_moss_path", new BasePathBlock(AMBER_MOSS)); + public static final Block JUNGLE_MOSS_PATH = registerBlock("jungle_moss_path", new BasePathBlock(JUNGLE_MOSS)); + public static final Block SANGNUM_PATH = registerBlock("sangnum_path", new BasePathBlock(SANGNUM)); + public static final Block RUTISCUS_PATH = registerBlock("rutiscus_path", new BasePathBlock(RUTISCUS)); + + public static final Block MOSSY_OBSIDIAN = registerBlock("mossy_obsidian", new MossyObsidian()); + public static final Block DRAGON_BONE_BLOCK = registerBlock("dragon_bone_block", + new BaseRotatedPillarBlock(Blocks.BONE_BLOCK)); + public static final Block DRAGON_BONE_STAIRS = registerBlock("dragon_bone_stairs", + new BaseStairsBlock(DRAGON_BONE_BLOCK)); + public static final Block DRAGON_BONE_SLAB = registerBlock("dragon_bone_slab", + new BaseSlabBlock(DRAGON_BONE_BLOCK)); + public static final Block MOSSY_DRAGON_BONE = registerBlock("mossy_dragon_bone", new MossyDragonBoneBlock()); + + // Rocks // + public static final StoneMaterial FLAVOLITE = new StoneMaterial("flavolite", MaterialColor.SAND); + public static final StoneMaterial VIOLECITE = new StoneMaterial("violecite", MaterialColor.COLOR_PURPLE); + public static final StoneMaterial SULPHURIC_ROCK = new StoneMaterial("sulphuric_rock", MaterialColor.COLOR_BROWN); + public static final StoneMaterial VIRID_JADESTONE = new StoneMaterial("virid_jadestone", MaterialColor.COLOR_GREEN); + public static final StoneMaterial AZURE_JADESTONE = new StoneMaterial("azure_jadestone", + MaterialColor.COLOR_LIGHT_BLUE); + public static final StoneMaterial SANDY_JADESTONE = new StoneMaterial("sandy_jadestone", + MaterialColor.COLOR_YELLOW); + public static final StoneMaterial UMBRALITH = new StoneMaterial("umbralith", MaterialColor.DEEPSLATE); + public static final Block BRIMSTONE = registerBlock("brimstone", new BrimstoneBlock()); + public static final Block SULPHUR_CRYSTAL = registerBlock("sulphur_crystal", new SulphurCrystalBlock()); + public static final Block MISSING_TILE = registerBlock("missing_tile", new MissingTileBlock()); + public static final Block ENDSTONE_FLOWER_POT = registerBlock("endstone_flower_pot", + new FlowerPotBlock(Blocks.END_STONE)); + + public static final Block FLAVOLITE_RUNED = registerBlock("flavolite_runed", new RunedFlavolite(false)); + public static final Block FLAVOLITE_RUNED_ETERNAL = registerBlock("flavolite_runed_eternal", + new RunedFlavolite(true)); + + public static final Block ANDESITE_PEDESTAL = registerBlock("andesite_pedestal", + new PedestalVanilla(Blocks.ANDESITE)); + public static final Block DIORITE_PEDESTAL = registerBlock("diorite_pedestal", new PedestalVanilla(Blocks.DIORITE)); + public static final Block GRANITE_PEDESTAL = registerBlock("granite_pedestal", new PedestalVanilla(Blocks.GRANITE)); + public static final Block QUARTZ_PEDESTAL = registerBlock("quartz_pedestal", + new PedestalVanilla(Blocks.QUARTZ_BLOCK)); + public static final Block PURPUR_PEDESTAL = registerBlock("purpur_pedestal", + new PedestalVanilla(Blocks.PURPUR_BLOCK)); + + public static final Block HYDROTHERMAL_VENT = registerBlock("hydrothermal_vent", new HydrothermalVentBlock()); + public static final Block VENT_BUBBLE_COLUMN = registerEndBlockOnly("vent_bubble_column", + new VentBubbleColumnBlock()); + + public static final Block DENSE_SNOW = registerBlock("dense_snow", new DenseSnowBlock()); + public static final Block EMERALD_ICE = registerBlock("emerald_ice", new EmeraldIceBlock()); + public static final Block DENSE_EMERALD_ICE = registerBlock("dense_emerald_ice", new DenseEmeraldIceBlock()); + public static final Block ANCIENT_EMERALD_ICE = registerBlock("ancient_emerald_ice", new AncientEmeraldIceBlock()); + + public static final Block END_STONE_STALACTITE = registerBlock("end_stone_stalactite", + new StalactiteBlock(Blocks.END_STONE)); + public static final Block END_STONE_STALACTITE_CAVEMOSS = registerBlock("end_stone_stalactite_cavemoss", + new StalactiteBlock(CAVE_MOSS)); + + // Wooden Materials And Trees // + public static final Block MOSSY_GLOWSHROOM_SAPLING = registerBlock("mossy_glowshroom_sapling", + new MossyGlowshroomSaplingBlock()); + public static final Block MOSSY_GLOWSHROOM_CAP = registerBlock("mossy_glowshroom_cap", + new MossyGlowshroomCapBlock()); + public static final Block MOSSY_GLOWSHROOM_HYMENOPHORE = registerBlock("mossy_glowshroom_hymenophore", + new GlowingHymenophoreBlock()); + public static final Block MOSSY_GLOWSHROOM_FUR = registerBlock("mossy_glowshroom_fur", + new FurBlock(MOSSY_GLOWSHROOM_SAPLING, + 15, + 16, + true)); + public static final EndWoodenComplexMaterial MOSSY_GLOWSHROOM = new EndWoodenComplexMaterial( + "mossy_glowshroom", + MaterialColor.COLOR_GRAY, + MaterialColor.WOOD + ).init(); + + public static final Block PYTHADENDRON_SAPLING = registerBlock("pythadendron_sapling", + new PythadendronSaplingBlock()); + public static final Block PYTHADENDRON_LEAVES = registerBlock("pythadendron_leaves", + new PottableLeavesBlock(PYTHADENDRON_SAPLING, + MaterialColor.COLOR_MAGENTA)); + public static final EndWoodenComplexMaterial PYTHADENDRON = new EndWoodenComplexMaterial( + "pythadendron", + MaterialColor.COLOR_MAGENTA, + MaterialColor.COLOR_PURPLE + ).init(); + + public static final Block END_LOTUS_SEED = registerBlock("end_lotus_seed", new EndLotusSeedBlock()); + public static final Block END_LOTUS_STEM = registerBlock("end_lotus_stem", new EndLotusStemBlock()); + public static final Block END_LOTUS_LEAF = registerEndBlockOnly("end_lotus_leaf", new EndLotusLeafBlock()); + public static final Block END_LOTUS_FLOWER = registerEndBlockOnly("end_lotus_flower", new EndLotusFlowerBlock()); + public static final EndWoodenComplexMaterial END_LOTUS = new EndWoodenComplexMaterial( + "end_lotus", + MaterialColor.COLOR_LIGHT_BLUE, + MaterialColor.COLOR_CYAN + ).init(); + + public static final Block LACUGROVE_SAPLING = registerBlock("lacugrove_sapling", new LacugroveSaplingBlock()); + public static final Block LACUGROVE_LEAVES = registerBlock("lacugrove_leaves", + new PottableLeavesBlock(LACUGROVE_SAPLING, + MaterialColor.COLOR_CYAN)); + public static final EndWoodenComplexMaterial LACUGROVE = new EndWoodenComplexMaterial( + "lacugrove", + MaterialColor.COLOR_BROWN, + MaterialColor.COLOR_YELLOW + ).init(); + + public static final Block DRAGON_TREE_SAPLING = registerBlock("dragon_tree_sapling", new DragonTreeSaplingBlock()); + public static final Block DRAGON_TREE_LEAVES = registerBlock("dragon_tree_leaves", + new PottableLeavesBlock(DRAGON_TREE_SAPLING, + MaterialColor.COLOR_MAGENTA)); + public static final EndWoodenComplexMaterial DRAGON_TREE = new EndWoodenComplexMaterial( + "dragon_tree", + MaterialColor.COLOR_BLACK, + MaterialColor.COLOR_MAGENTA + ).init(); + + public static final Block TENANEA_SAPLING = registerBlock("tenanea_sapling", new TenaneaSaplingBlock()); + public static final Block TENANEA_LEAVES = registerBlock("tenanea_leaves", + new PottableLeavesBlock(TENANEA_SAPLING, + MaterialColor.COLOR_PINK)); + public static final Block TENANEA_FLOWERS = registerBlock("tenanea_flowers", new TenaneaFlowersBlock()); + public static final Block TENANEA_OUTER_LEAVES = registerBlock("tenanea_outer_leaves", + new FurBlock(TENANEA_SAPLING, 32)); + public static final EndWoodenComplexMaterial TENANEA = new EndWoodenComplexMaterial( + "tenanea", + MaterialColor.COLOR_BROWN, + MaterialColor.COLOR_PINK + ).init(); + + public static final Block HELIX_TREE_SAPLING = registerBlock("helix_tree_sapling", new HelixTreeSaplingBlock()); + public static final Block HELIX_TREE_LEAVES = registerBlock("helix_tree_leaves", new HelixTreeLeavesBlock()); + public static final EndWoodenComplexMaterial HELIX_TREE = new EndWoodenComplexMaterial( + "helix_tree", + MaterialColor.COLOR_GRAY, + MaterialColor.COLOR_ORANGE + ).init(); + + public static final Block UMBRELLA_TREE_SAPLING = registerBlock("umbrella_tree_sapling", + new UmbrellaTreeSaplingBlock()); + public static final Block UMBRELLA_TREE_MEMBRANE = registerBlock("umbrella_tree_membrane", + new UmbrellaTreeMembraneBlock()); + public static final Block UMBRELLA_TREE_CLUSTER = registerBlock("umbrella_tree_cluster", + new UmbrellaTreeClusterBlock()); + public static final Block UMBRELLA_TREE_CLUSTER_EMPTY = registerBlock("umbrella_tree_cluster_empty", + new UmbrellaTreeClusterEmptyBlock()); + public static final EndWoodenComplexMaterial UMBRELLA_TREE = new EndWoodenComplexMaterial( + "umbrella_tree", + MaterialColor.COLOR_BLUE, + MaterialColor.COLOR_GREEN + ).init(); + + public static final Block JELLYSHROOM_CAP_PURPLE = registerBlock("jellyshroom_cap_purple", + new JellyshroomCapBlock(217, + 142, + 255, + 164, + 0, + 255)); + public static final EndWoodenComplexMaterial JELLYSHROOM = new EndWoodenComplexMaterial( + "jellyshroom", + MaterialColor.COLOR_PURPLE, + MaterialColor.COLOR_LIGHT_BLUE + ).init(); + + public static final Block LUCERNIA_SAPLING = registerBlock("lucernia_sapling", new LucerniaSaplingBlock()); + public static final Block LUCERNIA_LEAVES = registerBlock("lucernia_leaves", + new PottableLeavesBlock(LUCERNIA_SAPLING, + MaterialColor.COLOR_ORANGE)); + public static final Block LUCERNIA_OUTER_LEAVES = registerBlock("lucernia_outer_leaves", + new FurBlock(LUCERNIA_SAPLING, 32)); + public static final EndWoodenComplexMaterial LUCERNIA = new EndWoodenComplexMaterial( + "lucernia", + MaterialColor.COLOR_ORANGE, + MaterialColor.COLOR_ORANGE + ).init(); + + // Small Plants // + public static final Block UMBRELLA_MOSS = registerBlock("umbrella_moss", new UmbrellaMossBlock()); + public static final Block UMBRELLA_MOSS_TALL = registerBlock("umbrella_moss_tall", new UmbrellaMossTallBlock()); + public static final Block CREEPING_MOSS = registerBlock("creeping_moss", new GlowingMossBlock(11)); + public static final Block CHORUS_GRASS = registerBlock("chorus_grass", new ChorusGrassBlock()); + public static final Block CAVE_GRASS = registerBlock("cave_grass", new TerrainPlantBlock(CAVE_MOSS)); + public static final Block CRYSTAL_GRASS = registerBlock("crystal_grass", new TerrainPlantBlock(CRYSTAL_MOSS)); + public static final Block SHADOW_PLANT = registerBlock("shadow_plant", new TerrainPlantBlock(SHADOW_GRASS)); + public static final Block BUSHY_GRASS = registerBlock("bushy_grass", new TerrainPlantBlock(PINK_MOSS)); + public static final Block AMBER_GRASS = registerBlock("amber_grass", new TerrainPlantBlock(AMBER_MOSS)); + public static final Block TWISTED_UMBRELLA_MOSS = registerBlock("twisted_umbrella_moss", + new TwistedUmbrellaMossBlock()); + public static final Block TWISTED_UMBRELLA_MOSS_TALL = registerBlock("twisted_umbrella_moss_tall", + new TwistedUmbrellaMossTallBlock()); + public static final Block JUNGLE_GRASS = registerBlock("jungle_grass", new TerrainPlantBlock(JUNGLE_MOSS)); + public static final Block BLOOMING_COOKSONIA = registerBlock("blooming_cooksonia", new TerrainPlantBlock(END_MOSS)); + public static final Block SALTEAGO = registerBlock("salteago", new TerrainPlantBlock(END_MOSS)); + public static final Block VAIOLUSH_FERN = registerBlock("vaiolush_fern", new TerrainPlantBlock(END_MOSS)); + public static final Block FRACTURN = registerBlock("fracturn", new TerrainPlantBlock(END_MOSS)); + public static final Block CLAWFERN = registerBlock("clawfern", + new TerrainPlantBlock(SANGNUM, + MOSSY_OBSIDIAN, + MOSSY_DRAGON_BONE)); + public static final Block GLOBULAGUS = registerBlock("globulagus", + new TerrainPlantBlock(SANGNUM, + MOSSY_OBSIDIAN, + MOSSY_DRAGON_BONE)); + public static final Block ORANGO = registerBlock("orango", new TerrainPlantBlock(RUTISCUS)); + public static final Block AERIDIUM = registerBlock("aeridium", new TerrainPlantBlock(RUTISCUS)); + public static final Block LUTEBUS = registerBlock("lutebus", new TerrainPlantBlock(RUTISCUS)); + public static final Block LAMELLARIUM = registerBlock("lamellarium", new TerrainPlantBlock(RUTISCUS)); + public static final Block INFLEXIA = registerBlock("inflexia", + new TerrainPlantBlock(PALLIDIUM_FULL, + PALLIDIUM_HEAVY, + PALLIDIUM_THIN, + PALLIDIUM_TINY)); + public static final Block FLAMMALIX = registerBlock("flammalix", new FlammalixBlock()); + + public static final Block BLUE_VINE_SEED = registerBlock("blue_vine_seed", new BlueVineSeedBlock()); + public static final Block BLUE_VINE = registerEndBlockOnly("blue_vine", new BlueVineBlock()); + public static final Block BLUE_VINE_LANTERN = registerBlock("blue_vine_lantern", new BlueVineLanternBlock()); + public static final Block BLUE_VINE_FUR = registerBlock("blue_vine_fur", + new FurBlock(BLUE_VINE_SEED, 15, 3, false)); + + public static final Block LANCELEAF_SEED = registerBlock("lanceleaf_seed", new LanceleafSeedBlock()); + public static final Block LANCELEAF = registerEndBlockOnly("lanceleaf", new LanceleafBlock()); + + public static final Block GLOWING_PILLAR_SEED = registerBlock("glowing_pillar_seed", new GlowingPillarSeedBlock()); + public static final Block GLOWING_PILLAR_ROOTS = registerEndBlockOnly("glowing_pillar_roots", + new GlowingPillarRootsBlock()); + public static final Block GLOWING_PILLAR_LUMINOPHOR = registerBlock("glowing_pillar_luminophor", + new GlowingPillarLuminophorBlock()); + public static final Block GLOWING_PILLAR_LEAVES = registerBlock("glowing_pillar_leaves", + new FurBlock(GLOWING_PILLAR_SEED, 15, 3, false)); + + public static final Block SMALL_JELLYSHROOM = registerBlock("small_jellyshroom", new SmallJellyshroomBlock()); + public static final Block BOLUX_MUSHROOM = registerBlock("bolux_mushroom", new BoluxMushroomBlock()); + + public static final Block LUMECORN_SEED = registerBlock("lumecorn_seed", new LumecornSeedBlock()); + public static final Block LUMECORN = registerEndBlockOnly("lumecorn", new LumecornBlock()); + + public static final Block SMALL_AMARANITA_MUSHROOM = registerBlock("small_amaranita_mushroom", + new SmallAmaranitaBlock()); + public static final Block LARGE_AMARANITA_MUSHROOM = registerEndBlockOnly("large_amaranita_mushroom", + new LargeAmaranitaBlock()); + public static final Block AMARANITA_STEM = registerBlock("amaranita_stem", new AmaranitaStemBlock()); + public static final Block AMARANITA_HYPHAE = registerBlock("amaranita_hyphae", new AmaranitaStemBlock()); + public static final Block AMARANITA_HYMENOPHORE = registerBlock("amaranita_hymenophore", + new AmaranitaHymenophoreBlock()); + public static final Block AMARANITA_LANTERN = registerBlock("amaranita_lantern", new GlowingHymenophoreBlock()); + public static final Block AMARANITA_FUR = registerBlock("amaranita_fur", + new FurBlock(SMALL_AMARANITA_MUSHROOM, 15, 4, true)); + public static final Block AMARANITA_CAP = registerBlock("amaranita_cap", new AmaranitaCapBlock()); + + public static final Block NEON_CACTUS = registerBlock("neon_cactus", new NeonCactusPlantBlock()); + public static final Block NEON_CACTUS_BLOCK = registerBlock("neon_cactus_block", new NeonCactusBlock()); + public static final Block NEON_CACTUS_BLOCK_STAIRS = registerBlock("neon_cactus_stairs", + new BaseStairsBlock(NEON_CACTUS_BLOCK)); + public static final Block NEON_CACTUS_BLOCK_SLAB = registerBlock("neon_cactus_slab", + new BaseSlabBlock(NEON_CACTUS_BLOCK)); + + // Crops + public static final Block SHADOW_BERRY = registerBlock("shadow_berry", new ShadowBerryBlock()); + public static final Block BLOSSOM_BERRY = registerBlock("blossom_berry_seed", + new PottableCropBlock(EndItems.BLOSSOM_BERRY, PINK_MOSS)); + public static final Block AMBER_ROOT = registerBlock("amber_root_seed", + new PottableCropBlock(EndItems.AMBER_ROOT_RAW, AMBER_MOSS)); + public static final Block CHORUS_MUSHROOM = registerBlock("chorus_mushroom_seed", + new PottableCropBlock(EndItems.CHORUS_MUSHROOM_RAW, + CHORUS_NYLIUM)); + //public static final Block PEARLBERRY = registerBlock("pearlberry_seed", new PottableCropBlock(EndItems.BLOSSOM_BERRY, END_MOSS, END_MYCELIUM)); + public static final Block CAVE_PUMPKIN_SEED = registerBlock("cave_pumpkin_seed", new CavePumpkinVineBlock()); + public static final Block CAVE_PUMPKIN = registerBlock("cave_pumpkin", new CavePumpkinBlock()); + + // Water plants + public static final Block BUBBLE_CORAL = registerBlock("bubble_coral", new BubbleCoralBlock()); + public static final Block MENGER_SPONGE = registerBlock("menger_sponge", new MengerSpongeBlock()); + public static final Block MENGER_SPONGE_WET = registerBlock("menger_sponge_wet", new MengerSpongeWetBlock()); + public static final Block CHARNIA_RED = registerBlock("charnia_red", new CharniaBlock()); + public static final Block CHARNIA_PURPLE = registerBlock("charnia_purple", new CharniaBlock()); + public static final Block CHARNIA_ORANGE = registerBlock("charnia_orange", new CharniaBlock()); + public static final Block CHARNIA_LIGHT_BLUE = registerBlock("charnia_light_blue", new CharniaBlock()); + public static final Block CHARNIA_CYAN = registerBlock("charnia_cyan", new CharniaBlock()); + public static final Block CHARNIA_GREEN = registerBlock("charnia_green", new CharniaBlock()); + + public static final Block END_LILY = registerEndBlockOnly("end_lily", new EndLilyBlock()); + public static final Block END_LILY_SEED = registerBlock("end_lily_seed", new EndLilySeedBlock()); + + public static final Block HYDRALUX_SAPLING = registerBlock("hydralux_sapling", new HydraluxSaplingBlock()); + public static final Block HYDRALUX = registerEndBlockOnly("hydralux", new HydraluxBlock()); + public static final Block HYDRALUX_PETAL_BLOCK = registerBlock("hydralux_petal_block", new HydraluxPetalBlock()); + public static final ColoredMaterial HYDRALUX_PETAL_BLOCK_COLORED = new ColoredMaterial(HydraluxPetalColoredBlock::new, + HYDRALUX_PETAL_BLOCK, + true); + + public static final Block POND_ANEMONE = registerBlock("pond_anemone", new PondAnemoneBlock()); + + public static final Block FLAMAEA = registerBlock("flamaea", new FlamaeaBlock()); + + public static final Block CAVE_BUSH = registerBlock("cave_bush", + new SimpleLeavesBlock(MaterialColor.COLOR_MAGENTA)); + + public static final Block MURKWEED = registerBlock("murkweed", new MurkweedBlock()); + public static final Block NEEDLEGRASS = registerBlock("needlegrass", new NeedlegrassBlock()); + + // Wall Plants // + public static final Block PURPLE_POLYPORE = registerBlock("purple_polypore", new EndWallMushroom(13)); + public static final Block AURANT_POLYPORE = registerBlock("aurant_polypore", new EndWallMushroom(13)); + public static final Block TAIL_MOSS = registerBlock("tail_moss", new EndWallPlantBlock()); + public static final Block CYAN_MOSS = registerBlock("cyan_moss", new EndWallPlantBlock()); + public static final Block TWISTED_MOSS = registerBlock("twisted_moss", new EndWallPlantBlock()); + public static final Block TUBE_WORM = registerBlock("tube_worm", new EndUnderwaterWallPlantBlock()); + public static final Block BULB_MOSS = registerBlock("bulb_moss", new EndWallPlantBlock(12)); + public static final Block JUNGLE_FERN = registerBlock("jungle_fern", new EndWallPlantBlock()); + public static final Block RUSCUS = registerBlock("ruscus", new EndWallPlantBlock()); + + // Vines // + public static final Block DENSE_VINE = registerBlock("dense_vine", new BaseVineBlock(15, true)); + public static final Block TWISTED_VINE = registerBlock("twisted_vine", new BaseVineBlock()); + public static final Block BULB_VINE_SEED = registerBlock("bulb_vine_seed", new BulbVineSeedBlock()); + public static final Block BULB_VINE = registerBlock("bulb_vine", new BulbVineBlock()); + public static final Block JUNGLE_VINE = registerBlock("jungle_vine", new BaseVineBlock()); + public static final Block RUBINEA = registerBlock("rubinea", new BaseVineBlock()); + public static final Block MAGNULA = registerBlock("magnula", new BaseVineBlock()); + public static final Block FILALUX = registerBlock("filalux", new FilaluxBlock()); + public static final Block FILALUX_WINGS = registerBlock("filalux_wings", new FilaluxWingsBlock()); + public static final Block FILALUX_LANTERN = registerBlock("filalux_lantern", new FilaluxLanternBlock()); + + // Mob-Related + public static final Block SILK_MOTH_NEST = registerBlock("silk_moth_nest", new SilkMothNestBlock()); + public static final Block SILK_MOTH_HIVE = registerBlock("silk_moth_hive", new SilkMothHiveBlock()); + + // Ores // + public static final Block ENDER_ORE = registerBlock("ender_ore", + new BaseOreBlock(() -> EndItems.ENDER_SHARD, 1, 3, 5)); + public static final Block AMBER_ORE = registerBlock("amber_ore", + new BaseOreBlock(() -> EndItems.RAW_AMBER, 1, 2, 4)); + + // Materials // + public static final MetalMaterial THALLASIUM = MetalMaterial.makeNormal( + "thallasium", + MaterialColor.COLOR_BLUE, + EndToolMaterial.THALLASIUM, + EndArmorMaterial.THALLASIUM + ); + public static final MetalMaterial TERMINITE = MetalMaterial.makeOreless( + "terminite", + MaterialColor.WARPED_WART_BLOCK, + 7F, + 9F, + EndToolMaterial.TERMINITE, + EndArmorMaterial.TERMINITE + ); + public static final Block AETERNIUM_BLOCK = registerBlock("aeternium_block", new AeterniumBlock()); + public static final Block CHARCOAL_BLOCK = registerBlock("charcoal_block", new CharcoalBlock()); + + public static final Block ENDER_BLOCK = registerBlock("ender_block", new EnderBlock()); + public static final Block AURORA_CRYSTAL = registerBlock("aurora_crystal", new AuroraCrystalBlock()); + public static final Block AMBER_BLOCK = registerBlock("amber_block", new AmberBlock()); + public static final Block SMARAGDANT_CRYSTAL_SHARD = registerBlock( + "smaragdant_crystal_shard", + new SmaragdantCrystalShardBlock() + ); + public static final Block SMARAGDANT_CRYSTAL = registerBlock("smaragdant_crystal", new SmaragdantCrystalBlock()); + public static final CrystalSubblocksMaterial SMARAGDANT_SUBBLOCKS = new CrystalSubblocksMaterial( + "smaragdant_crystal", + SMARAGDANT_CRYSTAL + ); + + public static final Block RESPAWN_OBELISK = registerBlock("respawn_obelisk", new RespawnObeliskBlock()); + + // Lanterns + public static final Block ANDESITE_LANTERN = registerBlock( + "andesite_lantern", + new StoneLanternBlock(Blocks.ANDESITE) + ); + public static final Block DIORITE_LANTERN = registerBlock("diorite_lantern", new StoneLanternBlock(Blocks.DIORITE)); + public static final Block GRANITE_LANTERN = registerBlock("granite_lantern", new StoneLanternBlock(Blocks.GRANITE)); + public static final Block QUARTZ_LANTERN = registerBlock( + "quartz_lantern", + new StoneLanternBlock(Blocks.QUARTZ_BLOCK) + ); + public static final Block PURPUR_LANTERN = registerBlock( + "purpur_lantern", + new StoneLanternBlock(Blocks.PURPUR_BLOCK) + ); + public static final Block END_STONE_LANTERN = registerBlock( + "end_stone_lantern", + new StoneLanternBlock(Blocks.END_STONE) + ); + public static final Block BLACKSTONE_LANTERN = registerBlock( + "blackstone_lantern", + new StoneLanternBlock(Blocks.BLACKSTONE) + ); + + public static final Block IRON_BULB_LANTERN = registerBlock("iron_bulb_lantern", new BulbVineLanternBlock()); + public static final ColoredMaterial IRON_BULB_LANTERN_COLORED = new ColoredMaterial( + BulbVineLanternColoredBlock::new, + IRON_BULB_LANTERN, + false + ); + + public static final Block IRON_CHANDELIER = EndBlocks.registerBlock( + "iron_chandelier", + new ChandelierBlock(Blocks.GOLD_BLOCK) + ); + public static final Block GOLD_CHANDELIER = EndBlocks.registerBlock( + "gold_chandelier", + new ChandelierBlock(Blocks.GOLD_BLOCK) + ); + + // Blocks With Entity // + public static final Block END_STONE_FURNACE = registerBlock( + "end_stone_furnace", + new BaseFurnaceBlock(Blocks.END_STONE) + ); + public static final Block END_STONE_SMELTER = registerBlock("end_stone_smelter", new EndStoneSmelter()); + public static final Block ETERNAL_PEDESTAL = registerBlock("eternal_pedestal", new EternalPedestal()); + public static final Block INFUSION_PEDESTAL = registerBlock("infusion_pedestal", new InfusionPedestal()); + public static final Block AETERNIUM_ANVIL = registerBlock("aeternium_anvil", new AeterniumAnvil()); + + // Technical + public static final Block END_PORTAL_BLOCK = registerEndBlockOnly("end_portal_block", new EndPortalBlock()); + + public static List getModBlocks() { + return BlockRegistry.getModBlocks(BetterEnd.MOD_ID); + } + + public static List getModBlockItems() { + return BlockRegistry.getModBlockItems(BetterEnd.MOD_ID); + } + + public static Block registerBlock(ResourceLocation id, Block block) { + if (!Configs.BLOCK_CONFIG.getBooleanRoot(id.getPath(), true)) { + return block; + } + getBlockRegistry().register(id, block); + return block; + } + + public static Block registerBlock(String name, Block block) { + return registerBlock(BetterEnd.makeID(name), block); + } + + public static Block registerEndBlockOnly(String name, Block block) { + return getBlockRegistry().registerBlockOnly(BetterEnd.makeID(name), block); + } + + public static FabricItemSettings makeBlockItemSettings() { + return getBlockRegistry().makeItemSettings(); + } + + @NotNull + public static BlockRegistry getBlockRegistry() { + return REGISTRY; + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndEnchantments.java b/src/main/java/org/betterx/betterend/registry/EndEnchantments.java new file mode 100644 index 00000000..ddd1b839 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndEnchantments.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.world.item.enchantment.Enchantment; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.effects.enchantment.EndVeilEnchantment; + +public class EndEnchantments { + public final static Enchantment END_VEIL = registerEnchantment("end_veil", new EndVeilEnchantment()); + + public static Enchantment registerEnchantment(String name, Enchantment enchantment) { + if (!Configs.ENCHANTMENT_CONFIG.getBooleanRoot(name, true)) { + return enchantment; + } + return Registry.register(Registry.ENCHANTMENT, BetterEnd.makeID(name), enchantment); + } + + public static void register() { + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndEntities.java b/src/main/java/org/betterx/betterend/registry/EndEntities.java new file mode 100644 index 00000000..7f3fb972 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndEntities.java @@ -0,0 +1,151 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.EntityType.EntityFactory; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder; +import net.minecraft.world.level.levelgen.Heightmap.Types; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; + +import org.betterx.bclib.api.spawning.SpawnRuleBuilder; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.entity.*; + +public class EndEntities { + public static final EntityType DRAGONFLY = register( + "dragonfly", + MobCategory.AMBIENT, + 0.6F, + 0.5F, + DragonflyEntity::new, + DragonflyEntity.createMobAttributes(), + true, + ColorUtil.color(32, 42, 176), + ColorUtil.color(115, 225, 249) + ); + public static final EntityType END_SLIME = register( + "end_slime", + MobCategory.MONSTER, + 2F, + 2F, + EndSlimeEntity::new, + EndSlimeEntity.createMobAttributes(), + false, + ColorUtil.color(28, 28, 28), + ColorUtil.color(99, 11, 99) + ); + public static final EntityType END_FISH = register( + "end_fish", + MobCategory.WATER_AMBIENT, + 0.5F, + 0.5F, + EndFishEntity::new, + EndFishEntity.createMobAttributes(), + true, + ColorUtil.color(3, 50, 76), + ColorUtil.color(120, 206, 255) + ); + public static final EntityType SHADOW_WALKER = register( + "shadow_walker", + MobCategory.MONSTER, + 0.6F, + 1.95F, + ShadowWalkerEntity::new, + ShadowWalkerEntity.createMobAttributes(), + true, + ColorUtil.color(30, 30, 30), + ColorUtil.color(5, 5, 5) + ); + public static final EntityType CUBOZOA = register( + "cubozoa", + MobCategory.WATER_AMBIENT, + 0.6F, + 1F, + CubozoaEntity::new, + CubozoaEntity.createMobAttributes(), + true, + ColorUtil.color(151, 77, 181), + ColorUtil.color(93, 176, 238) + ); + public static final EntityType SILK_MOTH = register( + "silk_moth", + MobCategory.AMBIENT, + 0.6F, + 0.6F, + SilkMothEntity::new, + SilkMothEntity.createMobAttributes(), + true, + ColorUtil.color(198, 138, 204), + ColorUtil.color(242, 220, 236) + ); + + public static void register() { + // Air // + SpawnRuleBuilder.start(DRAGONFLY).aboveGround(2).maxNearby(8).buildNoRestrictions(Types.MOTION_BLOCKING); + SpawnRuleBuilder.start(SILK_MOTH).aboveGround(2).maxNearby(4).buildNoRestrictions(Types.MOTION_BLOCKING); + + // Land // + SpawnRuleBuilder + .start(END_SLIME) + .notPeaceful() + .maxNearby(4, 64) + .onlyOnValidBlocks() + .customRule(EndSlimeEntity::canSpawn) + .buildNoRestrictions(Types.MOTION_BLOCKING); + + SpawnRuleBuilder.start(SHADOW_WALKER) + .vanillaHostile() + .onlyOnValidBlocks() + .maxNearby(8, 64) + .buildNoRestrictions(Types.MOTION_BLOCKING); + + // Water // + SpawnRuleBuilder.start(END_FISH).maxNearby(8, 64).buildInWater(Types.MOTION_BLOCKING); + SpawnRuleBuilder.start(CUBOZOA).maxNearby(8, 64).buildInWater(Types.MOTION_BLOCKING); + } + + protected static EntityType register(String name, + MobCategory group, + float width, + float height, + EntityFactory entity) { + ResourceLocation id = BetterEnd.makeID(name); + EntityType type = FabricEntityTypeBuilder + .create(group, entity) + .dimensions(EntityDimensions.fixed(width, height)) + .build(); + if (Configs.ENTITY_CONFIG.getBooleanRoot(id.getPath(), true)) { + return Registry.register(Registry.ENTITY_TYPE, id, type); + } + return type; + } + + private static EntityType register(String name, + MobCategory group, + float width, + float height, + EntityFactory entity, + Builder attributes, + boolean fixedSize, + int eggColor, + int dotsColor) { + ResourceLocation id = BetterEnd.makeID(name); + EntityType type = FabricEntityTypeBuilder + .create(group, entity) + .dimensions(fixedSize + ? EntityDimensions.fixed(width, height) + : EntityDimensions.scalable(width, height)) + .build(); + if (Configs.ENTITY_CONFIG.getBooleanRoot(id.getPath(), true)) { + FabricDefaultAttributeRegistry.register(type, attributes); + EndItems.registerEndEgg("spawn_egg_" + name, type, eggColor, dotsColor); + return Registry.register(Registry.ENTITY_TYPE, BetterEnd.makeID(name), type); + } + return type; + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndEntitiesRenders.java b/src/main/java/org/betterx/betterend/registry/EndEntitiesRenders.java new file mode 100644 index 00000000..1f6a4910 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndEntitiesRenders.java @@ -0,0 +1,67 @@ +package org.betterx.betterend.registry; + +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.world.entity.EntityType; + +import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.entity.model.*; +import org.betterx.betterend.entity.render.*; +import org.betterx.betterend.item.model.*; + +import java.util.function.Function; + +public class EndEntitiesRenders { + public static final ModelLayerLocation DRAGONFLY_MODEL = registerMain("dragonfly"); + public static final ModelLayerLocation END_SLIME_SHELL_MODEL = registerMain("endslime_shell"); + public static final ModelLayerLocation END_SLIME_MODEL = registerMain("endslime"); + public static final ModelLayerLocation END_FISH_MODEL = registerMain("endfish"); + public static final ModelLayerLocation CUBOZOA_MODEL = registerMain("cubozoa"); + public static final ModelLayerLocation SILK_MOTH_MODEL = registerMain("silkmoth"); + public static final ModelLayerLocation TEST_MODEL = registerMain("test"); + + public static final ModelLayerLocation ARMORED_ELYTRA = registerMain("armored_elytra"); + public static final ModelLayerLocation CRYSTALITE_CHESTPLATE = registerMain("crystalite_chestplate"); + public static final ModelLayerLocation CRYSTALITE_CHESTPLATE_THIN = registerMain("crystalite_chestplate_thin"); + public static final ModelLayerLocation CRYSTALITE_HELMET = registerMain("crystalite_helmet"); + public static final ModelLayerLocation CRYSTALITE_LEGGINGS = registerMain("crystalite_leggings"); + public static final ModelLayerLocation CRYSTALITE_BOOTS = registerMain("crystalite_boots"); + + public static void register() { + register(EndEntities.DRAGONFLY, RendererEntityDragonfly::new); + register(EndEntities.END_SLIME, RendererEntityEndSlime::new); + register(EndEntities.END_FISH, RendererEntityEndFish::new); + register(EndEntities.SHADOW_WALKER, RendererEntityShadowWalker::new); + register(EndEntities.CUBOZOA, RendererEntityCubozoa::new); + register(EndEntities.SILK_MOTH, SilkMothEntityRenderer::new); + + EntityModelLayerRegistry.registerModelLayer(DRAGONFLY_MODEL, DragonflyEntityModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(END_SLIME_SHELL_MODEL, + EndSlimeEntityModel::getShellOnlyTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(END_SLIME_MODEL, EndSlimeEntityModel::getCompleteTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(END_FISH_MODEL, EndFishEntityModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CUBOZOA_MODEL, CubozoaEntityModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(SILK_MOTH_MODEL, SilkMothEntityModel::getTexturedModelData); + + EntityModelLayerRegistry.registerModelLayer(ARMORED_ELYTRA, ArmoredElytraModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_CHESTPLATE, + CrystaliteChestplateModel::getRegularTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_CHESTPLATE_THIN, + CrystaliteChestplateModel::getThinTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_HELMET, CrystaliteHelmetModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_LEGGINGS, CrystaliteLeggingsModel::getTexturedModelData); + EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_BOOTS, CrystaliteBootsModel::getTexturedModelData); + } + + private static void register(EntityType type, Function renderer) { + EntityRendererRegistry.register(type, (context) -> renderer.apply(context)); + } + + private static ModelLayerLocation registerMain(String id) { + return new ModelLayerLocation(BetterEnd.makeID(id), "main"); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndFeatures.java b/src/main/java/org/betterx/betterend/registry/EndFeatures.java new file mode 100644 index 00000000..dff0246a --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndFeatures.java @@ -0,0 +1,591 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.placement.CountPlacement; +import net.minecraft.world.level.levelgen.placement.HeightRangePlacement; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; + +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.features.BCLCommonFeatures; +import org.betterx.bclib.api.features.BCLFeatureBuilder; +import org.betterx.bclib.util.JsonFactory; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.bclib.world.features.BCLFeature; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.bclib.world.features.ListFeature.StructureInfo; +import org.betterx.bclib.world.features.NBTFeature.TerrainMerge; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.complexmaterials.StoneMaterial; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.world.biome.cave.EndCaveBiome; +import org.betterx.betterend.world.biome.land.UmbraValleyBiome; +import org.betterx.betterend.world.features.*; +import org.betterx.betterend.world.features.bushes.*; +import org.betterx.betterend.world.features.terrain.*; +import org.betterx.betterend.world.features.terrain.caves.RoundCaveFeature; +import org.betterx.betterend.world.features.terrain.caves.TunelCaveFeature; +import org.betterx.betterend.world.features.trees.*; + +import java.io.InputStream; +import java.util.List; + +public class EndFeatures { + // Trees // + public static final BCLFeature MOSSY_GLOWSHROOM = redisterVegetation("mossy_glowshroom", + new MossyGlowshroomFeature(), + 2); + public static final BCLFeature PYTHADENDRON_TREE = redisterVegetation("pythadendron_tree", + new PythadendronTreeFeature(), + 1); + public static final BCLFeature LACUGROVE = redisterVegetation("lacugrove", new LacugroveFeature(), 4); + public static final BCLFeature DRAGON_TREE = redisterVegetation("dragon_tree", new DragonTreeFeature(), 2); + public static final BCLFeature TENANEA = redisterVegetation("tenanea", new TenaneaFeature(), 2); + public static final BCLFeature HELIX_TREE = redisterVegetation("helix_tree", new HelixTreeFeature(), 1); + public static final BCLFeature UMBRELLA_TREE = redisterVegetation("umbrella_tree", new UmbrellaTreeFeature(), 2); + public static final BCLFeature JELLYSHROOM = redisterVegetation("jellyshroom", new JellyshroomFeature(), 2); + public static final BCLFeature GIGANTIC_AMARANITA = redisterVegetation("gigantic_amaranita", + new GiganticAmaranitaFeature(), + 1); + public static final BCLFeature LUCERNIA = redisterVegetation("lucernia", new LucerniaFeature(), 3); + + // Bushes // + public static final BCLFeature PYTHADENDRON_BUSH = redisterVegetation("pythadendron_bush", + new BushFeature(EndBlocks.PYTHADENDRON_LEAVES, + EndBlocks.PYTHADENDRON.getBark()), + 3); + public static final BCLFeature DRAGON_TREE_BUSH = redisterVegetation("dragon_tree_bush", + new BushFeature(EndBlocks.DRAGON_TREE_LEAVES, + EndBlocks.DRAGON_TREE.getBark()), + 5); + public static final BCLFeature TENANEA_BUSH = redisterVegetation("tenanea_bush", new TenaneaBushFeature(), 6); + public static final BCLFeature LUMECORN = redisterVegetation("lumecorn", new Lumecorn(), 5); + public static final BCLFeature LARGE_AMARANITA = redisterVegetation("large_amaranita", + new LargeAmaranitaFeature(), + 5); + public static final BCLFeature LUCERNIA_BUSH = redisterVegetation("lucernia_bush", + new BushWithOuterFeature(EndBlocks.LUCERNIA_LEAVES, + EndBlocks.LUCERNIA_OUTER_LEAVES, + EndBlocks.LUCERNIA.getBark()), + 10); + public static final BCLFeature LUCERNIA_BUSH_RARE = redisterVegetation("lucernia_bush_rare", + new BushWithOuterFeature(EndBlocks.LUCERNIA_LEAVES, + EndBlocks.LUCERNIA_OUTER_LEAVES, + EndBlocks.LUCERNIA.getBark()), + 1); + public static final BCLFeature NEON_CACTUS = redisterVegetation("neon_cactus", new NeonCactusFeature(), 2); + + // Plants // + public static final BCLFeature UMBRELLA_MOSS = redisterVegetation("umbrella_moss", + new DoublePlantFeature(EndBlocks.UMBRELLA_MOSS, + EndBlocks.UMBRELLA_MOSS_TALL, + 5), + 3); + public static final BCLFeature CREEPING_MOSS = redisterVegetation("creeping_moss", + new SinglePlantFeature(EndBlocks.CREEPING_MOSS, + 5), + 3); + public static final BCLFeature BLUE_VINE = redisterVegetation("blue_vine", new BlueVineFeature(), 1); + public static final BCLFeature CHORUS_GRASS = redisterVegetation("chorus_grass", + new SinglePlantFeature(EndBlocks.CHORUS_GRASS, 4), + 3); + public static final BCLFeature CRYSTAL_GRASS = redisterVegetation("crystal_grass", + new SinglePlantFeature(EndBlocks.CRYSTAL_GRASS, + 8, + false), + 5); + public static final BCLFeature SHADOW_PLANT = redisterVegetation("shadow_plant", + new SinglePlantFeature(EndBlocks.SHADOW_PLANT, 6), + 5); + public static final BCLFeature MURKWEED = redisterVegetation("murkweed", + new SinglePlantFeature(EndBlocks.MURKWEED, 3), + 2); + public static final BCLFeature NEEDLEGRASS = redisterVegetation("needlegrass", + new SinglePlantFeature(EndBlocks.NEEDLEGRASS, 3), + 1); + public static final BCLFeature SHADOW_BERRY = redisterVegetation("shadow_berry", + new SinglePlantFeature(EndBlocks.SHADOW_BERRY, 2), + 1); + public static final BCLFeature BUSHY_GRASS = redisterVegetation("bushy_grass", + new SinglePlantFeature(EndBlocks.BUSHY_GRASS, + 8, + false), + 10); + public static final BCLFeature BUSHY_GRASS_WG = redisterVegetation("bushy_grass_wg", + new SinglePlantFeature(EndBlocks.BUSHY_GRASS, 5), + 8); + public static final BCLFeature AMBER_GRASS = redisterVegetation("amber_grass", + new SinglePlantFeature(EndBlocks.AMBER_GRASS, 6), + 7); + public static final BCLFeature LANCELEAF = redisterVegetation("lanceleaf", new LanceleafFeature(), 2); + public static final BCLFeature GLOW_PILLAR = redisterVegetation("glow_pillar", new GlowPillarFeature(), 1); + public static final BCLFeature TWISTED_UMBRELLA_MOSS = redisterVegetation("twisted_umbrella_moss", + new DoublePlantFeature(EndBlocks.TWISTED_UMBRELLA_MOSS, + EndBlocks.TWISTED_UMBRELLA_MOSS_TALL, + 6), + 3); + public static final BCLFeature JUNGLE_GRASS = redisterVegetation("jungle_grass", + new SinglePlantFeature(EndBlocks.JUNGLE_GRASS, + 7, + 3), + 6); + public static final BCLFeature SMALL_JELLYSHROOM_FLOOR = redisterVegetation("small_jellyshroom_floor", + new SinglePlantFeature(EndBlocks.SMALL_JELLYSHROOM, + 5, + 5), + 2); + public static final BCLFeature BLOSSOM_BERRY = redisterVegetation("blossom_berry", + new SinglePlantFeature(EndBlocks.BLOSSOM_BERRY, + 3, + 3), + 2); + public static final BCLFeature BLOOMING_COOKSONIA = redisterVegetation("blooming_cooksonia", + new SinglePlantFeature(EndBlocks.BLOOMING_COOKSONIA, + 5), + 5); + public static final BCLFeature SALTEAGO = redisterVegetation("salteago", + new SinglePlantFeature(EndBlocks.SALTEAGO, 5), + 5); + public static final BCLFeature VAIOLUSH_FERN = redisterVegetation("vaiolush_fern", + new SinglePlantFeature(EndBlocks.VAIOLUSH_FERN, + 5), + 5); + public static final BCLFeature FRACTURN = redisterVegetation("fracturn", + new SinglePlantFeature(EndBlocks.FRACTURN, 5), + 5); + public static final BCLFeature UMBRELLA_MOSS_RARE = redisterVegetation("umbrella_moss_rare", + new SinglePlantFeature(EndBlocks.UMBRELLA_MOSS, + 3), + 2); + public static final BCLFeature CREEPING_MOSS_RARE = redisterVegetation("creeping_moss_rare", + new SinglePlantFeature(EndBlocks.CREEPING_MOSS, + 3), + 2); + public static final BCLFeature TWISTED_UMBRELLA_MOSS_RARE = redisterVegetation("twisted_umbrella_moss_rare", + new SinglePlantFeature(EndBlocks.TWISTED_UMBRELLA_MOSS, + 3), + 2); + public static final BCLFeature ORANGO = redisterVegetation("orango", + new SinglePlantFeature(EndBlocks.ORANGO, 5), + 6); + public static final BCLFeature AERIDIUM = redisterVegetation("aeridium", + new SinglePlantFeature(EndBlocks.AERIDIUM, 5, 4), + 5); + public static final BCLFeature LUTEBUS = redisterVegetation("lutebus", + new SinglePlantFeature(EndBlocks.LUTEBUS, 5, 2), + 5); + public static final BCLFeature LAMELLARIUM = redisterVegetation("lamellarium", + new SinglePlantFeature(EndBlocks.LAMELLARIUM, 5), + 6); + public static final BCLFeature SMALL_AMARANITA = redisterVegetation("small_amaranita", + new SinglePlantFeature(EndBlocks.SMALL_AMARANITA_MUSHROOM, + 5, + 5), + 4); + public static final BCLFeature GLOBULAGUS = redisterVegetation("globulagus", + new SinglePlantFeature(EndBlocks.GLOBULAGUS, 5, 3), + 6); + public static final BCLFeature CLAWFERN = redisterVegetation("clawfern", + new SinglePlantFeature(EndBlocks.CLAWFERN, 5, 4), + 5); + public static final BCLFeature BOLUX_MUSHROOM = redisterVegetation("bolux_mushroom", + new SinglePlantFeature(EndBlocks.BOLUX_MUSHROOM, + 5, + 5), + 2); + public static final BCLFeature CHORUS_MUSHROOM = redisterVegetation("chorus_mushroom", + new SinglePlantFeature(EndBlocks.CHORUS_MUSHROOM, + 3, + 5), + 1); + public static final BCLFeature AMBER_ROOT = redisterVegetation("amber_root", + new SinglePlantFeature(EndBlocks.AMBER_ROOT, 5, 5), + 1); + //public static final BCLFeature PEARLBERRY = redisterVegetation("pearlberry", new SinglePlantFeature(EndBlocks.PEARLBERRY, 5, 5), 1); + public static final BCLFeature INFLEXIA = redisterVegetation("inflexia", + new SinglePlantFeature(EndBlocks.INFLEXIA, + 7, + false, + 3), + 16); + public static final BCLFeature FLAMMALIX = redisterVegetation("flammalix", + new SinglePlantFeature(EndBlocks.FLAMMALIX, + 3, + false, + 7), + 5); + + // Vines // + public static final BCLFeature DENSE_VINE = redisterVegetation("dense_vine", + new VineFeature(EndBlocks.DENSE_VINE, 24), + 3); + public static final BCLFeature TWISTED_VINE = redisterVegetation("twisted_vine", + new VineFeature(EndBlocks.TWISTED_VINE, 24), + 1); + public static final BCLFeature BULB_VINE = redisterVegetation("bulb_vine", + new VineFeature(EndBlocks.BULB_VINE, 24), + 3); + public static final BCLFeature JUNGLE_VINE = redisterVegetation("jungle_vine", + new VineFeature(EndBlocks.JUNGLE_VINE, 24), + 5); + + // Ceil plants + public static final BCLFeature SMALL_JELLYSHROOM_CEIL = redisterVegetation("small_jellyshroom_ceil", + new SingleInvertedScatterFeature( + EndBlocks.SMALL_JELLYSHROOM, + 8), + 8); + + // Wall Plants // + public static final BCLFeature PURPLE_POLYPORE = redisterVegetation("purple_polypore", + new WallPlantOnLogFeature(EndBlocks.PURPLE_POLYPORE, + 3), + 5); + public static final BCLFeature AURANT_POLYPORE = redisterVegetation("aurant_polypore", + new WallPlantOnLogFeature(EndBlocks.AURANT_POLYPORE, + 3), + 5); + public static final BCLFeature TAIL_MOSS = redisterVegetation("tail_moss", + new WallPlantFeature(EndBlocks.TAIL_MOSS, 3), + 15); + public static final BCLFeature CYAN_MOSS = redisterVegetation("cyan_moss", + new WallPlantFeature(EndBlocks.CYAN_MOSS, 3), + 15); + public static final BCLFeature TAIL_MOSS_WOOD = redisterVegetation("tail_moss_wood", + new WallPlantOnLogFeature(EndBlocks.TAIL_MOSS, + 4), + 25); + public static final BCLFeature CYAN_MOSS_WOOD = redisterVegetation("cyan_moss_wood", + new WallPlantOnLogFeature(EndBlocks.CYAN_MOSS, + 4), + 25); + public static final BCLFeature TWISTED_MOSS = redisterVegetation("twisted_moss", + new WallPlantFeature(EndBlocks.TWISTED_MOSS, 6), + 15); + public static final BCLFeature TWISTED_MOSS_WOOD = redisterVegetation("twisted_moss_wood", + new WallPlantOnLogFeature(EndBlocks.TWISTED_MOSS, + 6), + 25); + public static final BCLFeature BULB_MOSS = redisterVegetation("bulb_moss", + new WallPlantFeature(EndBlocks.BULB_MOSS, 6), + 1); + public static final BCLFeature BULB_MOSS_WOOD = redisterVegetation("bulb_moss_wood", + new WallPlantOnLogFeature(EndBlocks.BULB_MOSS, + 6), + 15); + public static final BCLFeature SMALL_JELLYSHROOM_WALL = redisterVegetation("small_jellyshroom_wall", + new WallPlantFeature(EndBlocks.SMALL_JELLYSHROOM, + 4), + 4); + public static final BCLFeature SMALL_JELLYSHROOM_WOOD = redisterVegetation("small_jellyshroom_wood", + new WallPlantOnLogFeature(EndBlocks.SMALL_JELLYSHROOM, + 4), + 8); + public static final BCLFeature JUNGLE_FERN_WOOD = redisterVegetation("jungle_fern_wood", + new WallPlantOnLogFeature(EndBlocks.JUNGLE_FERN, + 3), + 12); + public static final BCLFeature RUSCUS = redisterVegetation("ruscus", new WallPlantFeature(EndBlocks.RUSCUS, 6), 10); + public static final BCLFeature RUSCUS_WOOD = redisterVegetation("ruscus_wood", + new WallPlantOnLogFeature(EndBlocks.RUSCUS, 6), + 10); + + // Sky plants + public static final BCLFeature FILALUX = redisterVegetation("filalux", new FilaluxFeature(), 1); + + // Water // + public static final BCLFeature BUBBLE_CORAL = redisterVegetation("bubble_coral", + new UnderwaterPlantFeature(EndBlocks.BUBBLE_CORAL, + 6), + 10); + public static final BCLFeature BUBBLE_CORAL_RARE = redisterVegetation("bubble_coral_rare", + new UnderwaterPlantFeature(EndBlocks.BUBBLE_CORAL, + 3), + 4); + public static final BCLFeature END_LILY = redisterVegetation("end_lily", new EndLilyFeature(6), 10); + public static final BCLFeature END_LILY_RARE = redisterVegetation("end_lily_rare", new EndLilyFeature(3), 4); + public static final BCLFeature END_LOTUS = redisterVegetation("end_lotus", new EndLotusFeature(7), 5); + public static final BCLFeature END_LOTUS_LEAF = redisterVegetation("end_lotus_leaf", + new EndLotusLeafFeature(20), + 25); + public static final BCLFeature HYDRALUX = redisterVegetation("hydralux", new HydraluxFeature(5), 5); + public static final BCLFeature POND_ANEMONE = redisterVegetation("pond_anemone", + new UnderwaterPlantFeature(EndBlocks.POND_ANEMONE, + 6), + 10); + + public static final BCLFeature CHARNIA_RED = redisterVegetation("charnia_red", + new CharniaFeature(EndBlocks.CHARNIA_RED), + 10); + public static final BCLFeature CHARNIA_PURPLE = redisterVegetation("charnia_purple", + new CharniaFeature(EndBlocks.CHARNIA_PURPLE), + 10); + public static final BCLFeature CHARNIA_CYAN = redisterVegetation("charnia_cyan", + new CharniaFeature(EndBlocks.CHARNIA_CYAN), + 10); + public static final BCLFeature CHARNIA_LIGHT_BLUE = redisterVegetation("charnia_light_blue", + new CharniaFeature(EndBlocks.CHARNIA_LIGHT_BLUE), + 10); + public static final BCLFeature CHARNIA_ORANGE = redisterVegetation("charnia_orange", + new CharniaFeature(EndBlocks.CHARNIA_ORANGE), + 10); + public static final BCLFeature CHARNIA_GREEN = redisterVegetation("charnia_green", + new CharniaFeature(EndBlocks.CHARNIA_GREEN), + 10); + public static final BCLFeature MENGER_SPONGE = redisterVegetation("menger_sponge", new MengerSpongeFeature(5), 1); + public static final BCLFeature CHARNIA_RED_RARE = redisterVegetation("charnia_red_rare", + new CharniaFeature(EndBlocks.CHARNIA_RED), + 2); + public static final BCLFeature BIOME_ISLAND = BCLFeatureBuilder.start(BetterEnd.makeID("overworld_island"), + new BiomeIslandFeature()) + .decoration(Decoration.RAW_GENERATION) + .build(); + public static final BCLFeature FLAMAEA = redisterVegetation("flamaea", + new SinglePlantFeature(EndBlocks.FLAMAEA, 12, false, 5), + 20); + + // Terrain // + public static final BCLFeature END_LAKE = registerLake("end_lake", new EndLakeFeature(), 4); + public static final BCLFeature END_LAKE_NORMAL = registerLake("end_lake_normal", new EndLakeFeature(), 20); + public static final BCLFeature END_LAKE_RARE = registerLake("end_lake_rare", new EndLakeFeature(), 40); + public static final BCLFeature DESERT_LAKE = registerLake("desert_lake", new DesertLakeFeature(), 8); + public static final BCLFeature ROUND_CAVE = registerRawGen("round_cave", new RoundCaveFeature(), 2); + public static final BCLFeature SPIRE = registerRawGen("spire", new SpireFeature(), 4); + public static final BCLFeature FLOATING_SPIRE = registerRawGen("floating_spire", new FloatingSpireFeature(), 8); + public static final BCLFeature GEYSER = registerRawGen("geyser", new GeyserFeature(), 8); + public static final BCLFeature SULPHURIC_LAKE = registerLake("sulphuric_lake", new SulphuricLakeFeature(), 8); + public static final BCLFeature SULPHURIC_CAVE = BCLCommonFeatures.makeCountFeature(BetterEnd.makeID("sulphuric_cave"), + Decoration.RAW_GENERATION, + new SulphuricCaveFeature(), + 2); + public static final BCLFeature ICE_STAR = registerRawGen("ice_star", new IceStarFeature(5, 15, 10, 25), 15); + public static final BCLFeature ICE_STAR_SMALL = registerRawGen("ice_star_small", + new IceStarFeature(3, 5, 7, 12), + 8); + public static final BCLFeature SURFACE_VENT = registerChanced("surface_vent", new SurfaceVentFeature(), 4); + public static final BCLFeature SULPHUR_HILL = registerChanced("sulphur_hill", new SulphurHillFeature(), 8); + public static final BCLFeature OBSIDIAN_PILLAR_BASEMENT = registerChanced("obsidian_pillar_basement", + new ObsidianPillarBasementFeature(), + 8); + public static final BCLFeature OBSIDIAN_BOULDER = registerChanced("obsidian_boulder", + new ObsidianBoulderFeature(), + 10); + public static final BCLFeature FALLEN_PILLAR = registerChanced("fallen_pillar", new FallenPillarFeature(), 20); + public static final BCLFeature TUNEL_CAVE = BCLCommonFeatures.makeChunkFeature(BetterEnd.makeID("tunel_cave"), + Decoration.RAW_GENERATION, + new TunelCaveFeature()); + public static final BCLFeature UMBRALITH_ARCH = registerChanced("umbralith_arch", new ArchFeature( + EndBlocks.UMBRALITH.stone, + pos -> UmbraValleyBiome.getSurface(pos.getX(), pos.getZ()).defaultBlockState() + ), 10); + public static final BCLFeature THIN_UMBRALITH_ARCH = registerChanced("thin_umbralith_arch", + new ThinArchFeature(EndBlocks.UMBRALITH.stone), + 15); + + // Ores // + public static final BCLFeature THALLASIUM_ORE = registerOre("thallasium_ore", EndBlocks.THALLASIUM.ore, 24, 8); + public static final BCLFeature ENDER_ORE = registerOre("ender_ore", EndBlocks.ENDER_ORE, 12, 4); + public static final BCLFeature AMBER_ORE = registerOre("amber_ore", EndBlocks.AMBER_ORE, 60, 6); + public static final BCLFeature DRAGON_BONE_BLOCK_ORE = registerOre("dragon_bone_ore", + EndBlocks.DRAGON_BONE_BLOCK, + 24, + 8); + public static final BCLFeature VIOLECITE_LAYER = registerLayer("violecite_layer", + EndBlocks.VIOLECITE, + 15, + 16, + 128, + 8); + public static final BCLFeature FLAVOLITE_LAYER = registerLayer("flavolite_layer", + EndBlocks.FLAVOLITE, + 12, + 16, + 128, + 6); + + // Buildings + public static final BCLFeature CRASHED_SHIP = registerChanced("crashed_ship", new CrashedShipFeature(), 500); + + // Mobs + public static final BCLFeature SILK_MOTH_NEST = registerChanced("silk_moth_nest", new SilkMothNestFeature(), 2); + + // Caves + public static final DefaultFeature SMARAGDANT_CRYSTAL = new SmaragdantCrystalFeature(); + public static final DefaultFeature SMARAGDANT_CRYSTAL_SHARD = new SingleBlockFeature(EndBlocks.SMARAGDANT_CRYSTAL_SHARD); + public static final DefaultFeature BIG_AURORA_CRYSTAL = new BigAuroraCrystalFeature(); + public static final DefaultFeature CAVE_BUSH = new BushFeature(EndBlocks.CAVE_BUSH, EndBlocks.CAVE_BUSH); + public static final DefaultFeature CAVE_GRASS = new SingleBlockFeature(EndBlocks.CAVE_GRASS); + public static final DefaultFeature RUBINEA = new VineFeature(EndBlocks.RUBINEA, 8); + public static final DefaultFeature MAGNULA = new VineFeature(EndBlocks.MAGNULA, 8); + public static final DefaultFeature END_STONE_STALACTITE = new StalactiteFeature( + true, + EndBlocks.END_STONE_STALACTITE, + Blocks.END_STONE + ); + public static final DefaultFeature END_STONE_STALAGMITE = new StalactiteFeature( + false, + EndBlocks.END_STONE_STALACTITE, + Blocks.END_STONE + ); + public static final DefaultFeature END_STONE_STALACTITE_CAVEMOSS = new StalactiteFeature( + true, + EndBlocks.END_STONE_STALACTITE_CAVEMOSS, + Blocks.END_STONE, + EndBlocks.CAVE_MOSS + ); + public static final DefaultFeature END_STONE_STALAGMITE_CAVEMOSS = new StalactiteFeature( + false, + EndBlocks.END_STONE_STALACTITE_CAVEMOSS, + EndBlocks.CAVE_MOSS + ); + public static final DefaultFeature CAVE_PUMPKIN = new CavePumpkinFeature(); + + private static BCLFeature redisterVegetation(String name, Feature feature, int density) { + ResourceLocation id = BetterEnd.makeID(name); + return BCLFeatureBuilder.start(id, feature).countLayersMax(density).onlyInBiome().build(); + } + + private static BCLFeature registerRawGen(String name, Feature feature, int chance) { + return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), Decoration.RAW_GENERATION, feature, chance); + } + + private static BCLFeature registerLake(String name, Feature feature, int chance) { + return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), Decoration.LAKES, feature, chance); + } + + private static BCLFeature registerChanced(String name, Feature feature, int chance) { + return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), + Decoration.SURFACE_STRUCTURES, + feature, + chance); + } + + private static BCLFeature registerOre(String name, Block blockOre, int veins, int veinSize) { + return BCLCommonFeatures.makeOreFeature(BetterEnd.makeID(name), + blockOre, + Blocks.END_STONE, + veins, + veinSize, + 0, + HeightRangePlacement.uniform(VerticalAnchor.bottom(), + VerticalAnchor.absolute(128)), + false); + } + + private static BCLFeature registerLayer(String name, Block block, float radius, int minY, int maxY, int count) { + OreLayerFeature layer = new OreLayerFeature(block.defaultBlockState(), radius, minY, maxY); + return BCLFeatureBuilder + .start(BetterEnd.makeID(name), layer) + .decoration(GenerationStep.Decoration.UNDERGROUND_ORES) + .modifier(CountPlacement.of(count)) + .build(); + } + + private static BCLFeature registerLayer(String name, + StoneMaterial material, + float radius, + int minY, + int maxY, + int count) { + return registerLayer(name, material.stone, radius, minY, maxY, count); + } + + public static void addBiomeFeatures(ResourceLocation id, Holder biome) { + BiomeAPI.addBiomeFeature(biome, FLAVOLITE_LAYER); + BiomeAPI.addBiomeFeature(biome, THALLASIUM_ORE); + BiomeAPI.addBiomeFeature(biome, ENDER_ORE); + BiomeAPI.addBiomeFeature(biome, CRASHED_SHIP); + + BCLBiome bclbiome = BiomeAPI.getBiome(id); + BCLFeature feature = getBiomeStructures(bclbiome); + if (feature != null) { + BiomeAPI.addBiomeFeature(biome, feature); + } + + if (id.getNamespace().equals(BetterEnd.MOD_ID)) { + return; + } + + boolean hasCaves = bclbiome.getCustomData("has_caves", true) && !(bclbiome instanceof EndCaveBiome); + //TODO: 1.19 Test Cave generation + if (hasCaves && !BiomeAPI.wasRegisteredAsEndVoidBiome(id) /*!BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(id)*/) { + if (Configs.BIOME_CONFIG.getBoolean(id, "hasCaves", true)) { + BiomeAPI.addBiomeFeature(biome, ROUND_CAVE); + BiomeAPI.addBiomeFeature(biome, TUNEL_CAVE); + } + } + } + + private static BCLFeature getBiomeStructures(BCLBiome biome) { + String ns = biome.getID().getNamespace(); + String nm = biome.getID().getPath(); + ResourceLocation id = new ResourceLocation(ns, nm + "_structures"); + + if (BuiltinRegistries.PLACED_FEATURE.containsKey(id)) { + PlacedFeature placed = BuiltinRegistries.PLACED_FEATURE.get(id); + Feature feature = Registry.FEATURE.get(id); + return BCLFeatureBuilder + .start(id, feature) + .decoration(Decoration.SURFACE_STRUCTURES) + .modifier(placed.placement()) + .build(placed.feature().value().config()); + } + + String path = "/data/" + ns + "/structures/biome/" + nm + "/"; + InputStream inputstream = EndFeatures.class.getResourceAsStream(path + "structures.json"); + if (inputstream != null) { + JsonObject obj = JsonFactory.getJsonObject(inputstream); + JsonArray structures = obj.getAsJsonArray("structures"); + if (structures != null) { + List list = Lists.newArrayList(); + structures.forEach((entry) -> { + JsonObject e = entry.getAsJsonObject(); + String structure = path + e.get("nbt").getAsString() + ".nbt"; + TerrainMerge terrainMerge = TerrainMerge.getFromString(e.get("terrainMerge").getAsString()); + int offsetY = e.get("offsetY").getAsInt(); + list.add(new StructureInfo(structure, offsetY, terrainMerge)); + }); + if (!list.isEmpty()) { + return BCLCommonFeatures.makeChancedFeature( + new ResourceLocation(ns, nm + "_structures"), + Decoration.SURFACE_STRUCTURES, + new BuildingListFeature(list, Blocks.END_STONE.defaultBlockState()), + 10 + ); + } + } + } + return null; + } + + public static BCLBiomeBuilder addDefaultFeatures(BCLBiomeBuilder builder, boolean hasCaves) { + builder.feature(FLAVOLITE_LAYER); + builder.feature(THALLASIUM_ORE); + builder.feature(ENDER_ORE); + builder.feature(CRASHED_SHIP); + + if (hasCaves) { + builder.feature(ROUND_CAVE); + builder.feature(TUNEL_CAVE); + } + + return builder; + } + + public static void register() { + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndItems.java b/src/main/java/org/betterx/betterend/registry/EndItems.java new file mode 100644 index 00000000..61161963 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndItems.java @@ -0,0 +1,268 @@ +package org.betterx.betterend.registry; + +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.food.Foods; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.TieredItem; +import net.minecraft.world.item.Tiers; + +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; + +import org.betterx.bclib.items.BaseArmorItem; +import org.betterx.bclib.items.ModelProviderItem; +import org.betterx.bclib.items.tool.BaseAxeItem; +import org.betterx.bclib.items.tool.BaseHoeItem; +import org.betterx.bclib.items.tool.BaseShovelItem; +import org.betterx.bclib.items.tool.BaseSwordItem; +import org.betterx.bclib.registry.BaseRegistry; +import org.betterx.bclib.registry.ItemRegistry; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.config.Configs; +import org.betterx.betterend.item.*; +import org.betterx.betterend.item.material.EndArmorMaterial; +import org.betterx.betterend.item.material.EndToolMaterial; +import org.betterx.betterend.item.tool.EndHammerItem; +import org.betterx.betterend.item.tool.EndPickaxe; +import org.betterx.betterend.tab.CreativeTabs; + +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class EndItems { + private static final ItemRegistry REGISTRY = new ItemRegistry(CreativeTabs.TAB_ITEMS, Configs.ITEM_CONFIG); + + // Materials // + public final static Item ENDER_DUST = registerEndItem("ender_dust"); + public final static Item ENDER_SHARD = registerEndItem("ender_shard"); + public final static Item AETERNIUM_INGOT = registerEndItem("aeternium_ingot", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_FORGED_PLATE = registerEndItem("aeternium_forged_plate", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item END_LILY_LEAF = registerEndItem("end_lily_leaf"); + public final static Item END_LILY_LEAF_DRIED = registerEndItem("end_lily_leaf_dried"); + public final static Item CRYSTAL_SHARDS = registerEndItem("crystal_shards"); + public final static Item RAW_AMBER = registerEndItem("raw_amber"); + public final static Item AMBER_GEM = registerEndItem("amber_gem"); + public final static Item GLOWING_BULB = registerEndItem("glowing_bulb"); + public final static Item CRYSTALLINE_SULPHUR = registerEndItem("crystalline_sulphur"); + public final static Item HYDRALUX_PETAL = registerEndItem("hydralux_petal"); + public final static Item GELATINE = registerEndItem("gelatine"); + public static final Item ETERNAL_CRYSTAL = registerEndItem("eternal_crystal", new EternalCrystalItem()); + public final static Item ENCHANTED_PETAL = registerEndItem("enchanted_petal", new EnchantedItem(HYDRALUX_PETAL)); + public final static Item LEATHER_STRIPE = registerEndItem("leather_stripe"); + public final static Item LEATHER_WRAPPED_STICK = registerEndItem("leather_wrapped_stick"); + public final static Item SILK_FIBER = registerEndItem("silk_fiber"); + public final static Item LUMECORN_ROD = registerEndItem("lumecorn_rod"); + public final static Item SILK_MOTH_MATRIX = registerEndItem("silk_moth_matrix"); + public final static Item ENCHANTED_MEMBRANE = registerEndItem( + "enchanted_membrane", + new EnchantedItem(Items.PHANTOM_MEMBRANE) + ); + + // Music Discs + public final static Item MUSIC_DISC_STRANGE_AND_ALIEN = registerEndDisc( + "music_disc_strange_and_alien", + 0, + EndSounds.RECORD_STRANGE_AND_ALIEN + ); + public final static Item MUSIC_DISC_GRASPING_AT_STARS = registerEndDisc( + "music_disc_grasping_at_stars", + 0, + EndSounds.RECORD_GRASPING_AT_STARS + ); + public final static Item MUSIC_DISC_ENDSEEKER = registerEndDisc( + "music_disc_endseeker", + 0, + EndSounds.RECORD_ENDSEEKER + ); + public final static Item MUSIC_DISC_EO_DRACONA = registerEndDisc( + "music_disc_eo_dracona", + 0, + EndSounds.RECORD_EO_DRACONA + ); + + // Armor // + public static final Item AETERNIUM_HELMET = registerEndItem("aeternium_helmet", + new BaseArmorItem(EndArmorMaterial.AETERNIUM, + EquipmentSlot.HEAD, + makeEndItemSettings().fireResistant())); + public static final Item AETERNIUM_CHESTPLATE = registerEndItem("aeternium_chestplate", + new BaseArmorItem(EndArmorMaterial.AETERNIUM, + EquipmentSlot.CHEST, + makeEndItemSettings().fireResistant())); + public static final Item AETERNIUM_LEGGINGS = registerEndItem("aeternium_leggings", + new BaseArmorItem(EndArmorMaterial.AETERNIUM, + EquipmentSlot.LEGS, + makeEndItemSettings().fireResistant())); + public static final Item AETERNIUM_BOOTS = registerEndItem("aeternium_boots", + new BaseArmorItem(EndArmorMaterial.AETERNIUM, + EquipmentSlot.FEET, + makeEndItemSettings().fireResistant())); + public static final Item CRYSTALITE_HELMET = registerEndItem("crystalite_helmet", new CrystaliteHelmet()); + public static final Item CRYSTALITE_CHESTPLATE = registerEndItem("crystalite_chestplate", + new CrystaliteChestplate()); + public static final Item CRYSTALITE_LEGGINGS = registerEndItem("crystalite_leggings", new CrystaliteLeggings()); + public static final Item CRYSTALITE_BOOTS = registerEndItem("crystalite_boots", new CrystaliteBoots()); + public static final Item ARMORED_ELYTRA = registerEndItem("elytra_armored", + new ArmoredElytra("elytra_armored", + EndArmorMaterial.AETERNIUM, + Items.PHANTOM_MEMBRANE, + 900, + 0.975D, + true)); + public static final Item CRYSTALITE_ELYTRA = registerEndItem("elytra_crystalite", new CrystaliteElytra(650, 0.99D)); + + // Tools // + public static final TieredItem AETERNIUM_SHOVEL = registerEndTool("aeternium_shovel", new BaseShovelItem( + EndToolMaterial.AETERNIUM, 1.5F, -3.0F, makeEndItemSettings().fireResistant())); + public static final TieredItem AETERNIUM_SWORD = registerEndTool("aeternium_sword", + new BaseSwordItem(EndToolMaterial.AETERNIUM, + 3, + -2.4F, + makeEndItemSettings().fireResistant())); + public static final TieredItem AETERNIUM_PICKAXE = registerEndTool("aeternium_pickaxe", + new EndPickaxe(EndToolMaterial.AETERNIUM, + 1, + -2.8F, + makeEndItemSettings().fireResistant())); + public static final TieredItem AETERNIUM_AXE = registerEndTool("aeternium_axe", + new BaseAxeItem(EndToolMaterial.AETERNIUM, + 5.0F, + -3.0F, + makeEndItemSettings().fireResistant())); + public static final TieredItem AETERNIUM_HOE = registerEndTool("aeternium_hoe", + new BaseHoeItem(EndToolMaterial.AETERNIUM, + -3, + 0.0F, + makeEndItemSettings().fireResistant())); + public static final TieredItem AETERNIUM_HAMMER = registerEndTool("aeternium_hammer", + new EndHammerItem(EndToolMaterial.AETERNIUM, + 6.0F, + -3.0F, + 0.3D, + makeEndItemSettings().fireResistant())); + + // Toolparts // + public final static Item AETERNIUM_SHOVEL_HEAD = registerEndItem("aeternium_shovel_head", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_PICKAXE_HEAD = registerEndItem("aeternium_pickaxe_head", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_AXE_HEAD = registerEndItem("aeternium_axe_head", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_HOE_HEAD = registerEndItem("aeternium_hoe_head", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_HAMMER_HEAD = registerEndItem("aeternium_hammer_head", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_SWORD_BLADE = registerEndItem("aeternium_sword_blade", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + public final static Item AETERNIUM_SWORD_HANDLE = registerEndItem("aeternium_sword_handle", + new ModelProviderItem(makeEndItemSettings().fireResistant())); + + // ITEM_HAMMERS // + public static final TieredItem IRON_HAMMER = registerEndTool("iron_hammer", + new EndHammerItem(Tiers.IRON, + 5.0F, + -3.2F, + 0.2D, + makeEndItemSettings())); + public static final TieredItem GOLDEN_HAMMER = registerEndTool("golden_hammer", + new EndHammerItem(Tiers.GOLD, + 4.5F, + -3.4F, + 0.3D, + makeEndItemSettings())); + public static final TieredItem DIAMOND_HAMMER = registerEndTool("diamond_hammer", + new EndHammerItem(Tiers.DIAMOND, + 5.5F, + -3.1F, + 0.2D, + makeEndItemSettings())); + public static final TieredItem NETHERITE_HAMMER = registerEndTool("netherite_hammer", + new EndHammerItem(Tiers.NETHERITE, + 5.0F, + -3.0F, + 0.2D, + makeEndItemSettings().fireResistant())); + + // Food // + public final static Item SHADOW_BERRY_RAW = registerEndFood("shadow_berry_raw", 4, 0.5F); + public final static Item SHADOW_BERRY_COOKED = registerEndFood("shadow_berry_cooked", 6, 0.7F); + public final static Item END_FISH_RAW = registerEndFood("end_fish_raw", Foods.SALMON); + public final static Item END_FISH_COOKED = registerEndFood("end_fish_cooked", Foods.COOKED_SALMON); + public final static Item BUCKET_END_FISH = registerEndItem("bucket_end_fish", + new EndBucketItem(EndEntities.END_FISH)); + public final static Item BUCKET_CUBOZOA = registerEndItem("bucket_cubozoa", new EndBucketItem(EndEntities.CUBOZOA)); + public final static Item SWEET_BERRY_JELLY = registerEndFood("sweet_berry_jelly", 8, 0.7F); + public final static Item SHADOW_BERRY_JELLY = registerEndFood("shadow_berry_jelly", + 6, + 0.8F, + new MobEffectInstance(MobEffects.NIGHT_VISION, 400)); + public final static Item BLOSSOM_BERRY_JELLY = registerEndFood("blossom_berry_jelly", 8, 0.7F); + public final static Item BLOSSOM_BERRY = registerEndFood("blossom_berry", Foods.APPLE); + public final static Item AMBER_ROOT_RAW = registerEndFood("amber_root_raw", 2, 0.8F); + public final static Item CHORUS_MUSHROOM_RAW = registerEndFood("chorus_mushroom_raw", 3, 0.5F); + public final static Item CHORUS_MUSHROOM_COOKED = registerEndFood("chorus_mushroom_cooked", Foods.MUSHROOM_STEW); + public final static Item BOLUX_MUSHROOM_COOKED = registerEndFood("bolux_mushroom_cooked", Foods.MUSHROOM_STEW); + public final static Item CAVE_PUMPKIN_PIE = registerEndFood("cave_pumpkin_pie", Foods.PUMPKIN_PIE); + + // Drinks // + public final static Item UMBRELLA_CLUSTER_JUICE = registerEndDrink("umbrella_cluster_juice", 5, 0.7F); + + public static List getModItems() { + return BaseRegistry.getModItems(BetterEnd.MOD_ID); + } + + public static Item registerEndDisc(String name, int power, SoundEvent sound) { + return getItemRegistry().registerDisc(BetterEnd.makeID(name), power, sound); + } + + public static Item registerEndItem(String name) { + return getItemRegistry().register(BetterEnd.makeID(name)); + } + + public static Item registerEndItem(String name, Item item) { + if (item instanceof EndArmorItem) { + return getItemRegistry().register(BetterEnd.makeID(name), item, "armour"); + } + return getItemRegistry().register(BetterEnd.makeID(name), item); + } + + public static TieredItem registerEndTool(String name, TieredItem item) { + if (!Configs.ITEM_CONFIG.getBoolean("tools", name, true)) { + return item; + } + return (TieredItem) getItemRegistry().registerTool(BetterEnd.makeID(name), item); + } + + public static Item registerEndEgg(String name, EntityType type, int background, int dots) { + return getItemRegistry().registerEgg(BetterEnd.makeID(name), type, background, dots); + } + + public static Item registerEndFood(String name, int hunger, float saturation, MobEffectInstance... effects) { + return getItemRegistry().registerFood(BetterEnd.makeID(name), hunger, saturation, effects); + } + + public static Item registerEndFood(String name, FoodProperties foodComponent) { + return getItemRegistry().registerFood(BetterEnd.makeID(name), foodComponent); + } + + public static Item registerEndDrink(String name, int hunger, float saturation) { + return getItemRegistry().registerDrink(BetterEnd.makeID(name), hunger, saturation); + } + + public static FabricItemSettings makeEndItemSettings() { + return getItemRegistry().makeItemSettings(); + } + + @NotNull + public static ItemRegistry getItemRegistry() { + return REGISTRY; + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndModelProviders.java b/src/main/java/org/betterx/betterend/registry/EndModelProviders.java new file mode 100644 index 00000000..bc300b1b --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndModelProviders.java @@ -0,0 +1,18 @@ +package org.betterx.betterend.registry; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.betterend.item.model.CrystaliteArmorProvider; +import shadow.fabric.api.client.rendering.v1.ArmorRenderingRegistry; + +@Environment(EnvType.CLIENT) +public class EndModelProviders { + + public final static CrystaliteArmorProvider CRYSTALITE_PROVIDER = new CrystaliteArmorProvider(); + + public final static void register() { + ArmorRenderingRegistry.registerModel(CRYSTALITE_PROVIDER, CRYSTALITE_PROVIDER.getRenderedItems()); + ArmorRenderingRegistry.registerTexture(CRYSTALITE_PROVIDER, CRYSTALITE_PROVIDER.getRenderedItems()); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndParticles.java b/src/main/java/org/betterx/betterend/registry/EndParticles.java new file mode 100644 index 00000000..ecae72c1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndParticles.java @@ -0,0 +1,57 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.particles.SimpleParticleType; + +import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; +import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.particle.*; + +public class EndParticles { + public static final SimpleParticleType GLOWING_SPHERE = register("glowing_sphere"); + public static final SimpleParticleType PORTAL_SPHERE = register("portal_sphere"); + public static final ParticleType INFUSION = register( + "infusion", + FabricParticleTypes.complex(InfusionParticleType.PARAMETERS_FACTORY) + ); + public static final SimpleParticleType SULPHUR_PARTICLE = register("sulphur_particle"); + public static final SimpleParticleType GEYSER_PARTICLE = registerFar("geyser_particle"); + public static final SimpleParticleType SNOWFLAKE = register("snowflake"); + public static final SimpleParticleType AMBER_SPHERE = register("amber_sphere"); + public static final SimpleParticleType BLACK_SPORE = register("black_spore"); + public static final SimpleParticleType TENANEA_PETAL = register("tenanea_petal"); + public static final SimpleParticleType JUNGLE_SPORE = register("jungle_spore"); + public static final SimpleParticleType FIREFLY = register("firefly"); + public static final SimpleParticleType SMARAGDANT = register("smaragdant_particle"); + + public static void register() { + ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); + ParticleFactoryRegistry.getInstance().register(PORTAL_SPHERE, PaticlePortalSphere.FactoryPortalSphere::new); + ParticleFactoryRegistry.getInstance().register(INFUSION, InfusionParticle.InfusionFactory::new); + ParticleFactoryRegistry.getInstance().register(SULPHUR_PARTICLE, ParticleSulphur.FactorySulphur::new); + ParticleFactoryRegistry.getInstance().register(GEYSER_PARTICLE, ParticleGeyser.FactoryGeyser::new); + ParticleFactoryRegistry.getInstance().register(SNOWFLAKE, ParticleSnowflake.FactorySnowflake::new); + ParticleFactoryRegistry.getInstance().register(AMBER_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); + ParticleFactoryRegistry.getInstance().register(BLACK_SPORE, ParticleBlackSpore.FactoryBlackSpore::new); + ParticleFactoryRegistry.getInstance().register(TENANEA_PETAL, ParticleTenaneaPetal.FactoryTenaneaPetal::new); + ParticleFactoryRegistry.getInstance().register(JUNGLE_SPORE, ParticleJungleSpore.FactoryJungleSpore::new); + ParticleFactoryRegistry.getInstance().register(FIREFLY, FireflyParticle.FireflyParticleFactory::new); + ParticleFactoryRegistry.getInstance().register(SMARAGDANT, SmaragdantParticle.SmaragdantParticleFactory::new); + } + + private static SimpleParticleType register(String name) { + return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple()); + } + + private static SimpleParticleType registerFar(String name) { + return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple(true)); + } + + private static ParticleType register(String name, ParticleType type) { + return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), type); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndPortals.java b/src/main/java/org/betterx/betterend/registry/EndPortals.java new file mode 100644 index 00000000..fe5529e0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndPortals.java @@ -0,0 +1,162 @@ +package org.betterx.betterend.registry; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; + +import net.fabricmc.loader.api.FabricLoader; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.betterx.bclib.util.ColorUtil; +import org.betterx.bclib.util.JsonFactory; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; + +import java.io.File; + +public class EndPortals { + + public final static ResourceLocation OVERWORLD_ID = Level.OVERWORLD.location(); + + private static PortalInfo[] portals; + + public static void loadPortals() { + File file = new File(FabricLoader.getInstance().getConfigDir().toString(), "betterend/portals.json"); + JsonObject json; + if (!file.exists()) { + file.getParentFile().mkdirs(); + json = makeDefault(file); + } else { + json = JsonFactory.getJsonObject(file); + } + if (!json.has("portals") || !json.get("portals").isJsonArray()) { + json = makeDefault(file); + } + JsonArray array = json.get("portals").getAsJsonArray(); + if (array.size() == 0) { + json = makeDefault(file); + array = json.get("portals").getAsJsonArray(); + } + portals = new PortalInfo[array.size()]; + for (int i = 0; i < portals.length; i++) { + portals[i] = new PortalInfo(array.get(i).getAsJsonObject()); + } + } + + public static int getCount() { + return MHelper.max(portals.length - 1, 1); + } + + public static ServerLevel getWorld(MinecraftServer server, int portalId) { + if (portalId < 0 || portalId >= portals.length) { + return server.overworld(); + } + return portals[portalId].getWorld(server); + } + + public static ResourceLocation getWorldId(int portalId) { + if (portalId < 0 || portalId >= portals.length) { + return OVERWORLD_ID; + } + return portals[portalId].dimension; + } + + public static int getPortalIdByItem(ResourceLocation item) { + for (int i = 0; i < portals.length; i++) { + if (portals[i].item.equals(item)) { + return i; + } + } + return 0; + } + + public static int getPortalIdByWorld(ResourceLocation world) { + for (int i = 0; i < portals.length; i++) { + if (portals[i].dimension.equals(world)) { + return i; + } + } + return 0; + } + + public static int getColor(int state) { + return portals[state].color; + } + + public static boolean isAvailableItem(ResourceLocation item) { + for (PortalInfo portal : portals) { + if (portal.item.equals(item)) { + return true; + } + } + return false; + } + + private static JsonObject makeDefault(File file) { + JsonObject jsonObject = new JsonObject(); + JsonFactory.storeJson(file, jsonObject); + JsonArray array = new JsonArray(); + jsonObject.add("portals", array); + array.add(makeDefault().toJson()); + JsonFactory.storeJson(file, jsonObject); + return jsonObject; + } + + private static PortalInfo makeDefault() { + return new PortalInfo( + new ResourceLocation("minecraft:overworld"), + BetterEnd.makeID("eternal_crystal"), + 255, + 255, + 255 + ); + } + + private static class PortalInfo { + private final ResourceLocation dimension; + private final ResourceLocation item; + private final int color; + private ServerLevel world; + + PortalInfo(JsonObject obj) { + this( + new ResourceLocation(JsonFactory.getString(obj, "dimension", "minecraft:overworld")), + new ResourceLocation(JsonFactory.getString(obj, "item", "betterend:eternal_crystal")), + JsonFactory.getInt(obj, "colorRed", 255), + JsonFactory.getInt(obj, "colorGreen", 255), + JsonFactory.getInt(obj, "colorBlue", 255) + ); + } + + PortalInfo(ResourceLocation dimension, ResourceLocation item, int r, int g, int b) { + this.dimension = dimension; + this.item = item; + this.color = ColorUtil.color(r, g, b); + } + + ServerLevel getWorld(MinecraftServer server) { + if (world != null) { + return world; + } + for (ServerLevel world : server.getAllLevels()) { + if (world.dimension().location().equals(dimension)) { + this.world = world; + return world; + } + } + return server.overworld(); + } + + JsonObject toJson() { + JsonObject obj = new JsonObject(); + obj.addProperty("dimension", dimension.toString()); + obj.addProperty("item", item.toString()); + obj.addProperty("colorRed", (color >> 16) & 255); + obj.addProperty("colorGreen", (color >> 8) & 255); + obj.addProperty("colorBlue", color & 255); + return obj; + } + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndScreens.java b/src/main/java/org/betterx/betterend/registry/EndScreens.java new file mode 100644 index 00000000..2b39b155 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndScreens.java @@ -0,0 +1,12 @@ +package org.betterx.betterend.registry; + +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; + +import org.betterx.betterend.client.gui.EndStoneSmelterScreen; +import org.betterx.betterend.client.gui.EndStoneSmelterScreenHandler; + +public class EndScreens { + public static void register() { + ScreenRegistry.register(EndStoneSmelterScreenHandler.HANDLER_TYPE, EndStoneSmelterScreen::new); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndSounds.java b/src/main/java/org/betterx/betterend/registry/EndSounds.java new file mode 100644 index 00000000..8649130c --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndSounds.java @@ -0,0 +1,49 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.sounds.SoundEvent; + +import org.betterx.betterend.BetterEnd; + +public class EndSounds { + // Music + public static final SoundEvent MUSIC_FOREST = register("music", "forest"); + public static final SoundEvent MUSIC_WATER = register("music", "water"); + public static final SoundEvent MUSIC_DARK = register("music", "dark"); + public static final SoundEvent MUSIC_OPENSPACE = register("music", "openspace"); + public static final SoundEvent MUSIC_CAVES = register("music", "caves"); + + // Ambient + public static final SoundEvent AMBIENT_FOGGY_MUSHROOMLAND = register("ambient", "foggy_mushroomland"); + public static final SoundEvent AMBIENT_CHORUS_FOREST = register("ambient", "chorus_forest"); + public static final SoundEvent AMBIENT_MEGALAKE = register("ambient", "megalake"); + public static final SoundEvent AMBIENT_DUST_WASTELANDS = register("ambient", "dust_wastelands"); + public static final SoundEvent AMBIENT_MEGALAKE_GROVE = register("ambient", "megalake_grove"); + public static final SoundEvent AMBIENT_BLOSSOMING_SPIRES = register("ambient", "blossoming_spires"); + public static final SoundEvent AMBIENT_SULPHUR_SPRINGS = register("ambient", "sulphur_springs"); + public static final SoundEvent AMBIENT_UMBRELLA_JUNGLE = register("ambient", "umbrella_jungle"); + public static final SoundEvent AMBIENT_GLOWING_GRASSLANDS = register("ambient", "glowing_grasslands"); + public static final SoundEvent AMBIENT_CAVES = register("ambient", "caves"); + public static final SoundEvent AMBIENT_AMBER_LAND = register("ambient", "amber_land"); + public static final SoundEvent UMBRA_VALLEY = register("ambient", "umbra_valley"); + + // Entity + public static final SoundEvent ENTITY_DRAGONFLY = register("entity", "dragonfly"); + public static final SoundEvent ENTITY_SHADOW_WALKER = register("entity", "shadow_walker"); + public static final SoundEvent ENTITY_SHADOW_WALKER_DAMAGE = register("entity", "shadow_walker_damage"); + public static final SoundEvent ENTITY_SHADOW_WALKER_DEATH = register("entity", "shadow_walker_death"); + + // Records + public static final SoundEvent RECORD_STRANGE_AND_ALIEN = register("record", "strange_and_alien"); + public static final SoundEvent RECORD_GRASPING_AT_STARS = register("record", "grasping_at_stars"); + public static final SoundEvent RECORD_ENDSEEKER = register("record", "endseeker"); + public static final SoundEvent RECORD_EO_DRACONA = register("record", "eo_dracona"); + + public static void register() { + } + + private static SoundEvent register(String type, String id) { + id = "betterend." + type + "." + id; + return Registry.register(Registry.SOUND_EVENT, id, new SoundEvent(BetterEnd.makeID(id))); + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndStructures.java b/src/main/java/org/betterx/betterend/registry/EndStructures.java new file mode 100644 index 00000000..f75141d1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndStructures.java @@ -0,0 +1,87 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; + +import org.betterx.bclib.api.tag.TagAPI; +import org.betterx.bclib.world.structures.BCLStructure; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.world.structures.features.*; +import org.betterx.betterend.world.structures.piece.*; + +public class EndStructures { + public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new); + public static final StructurePieceType MOUNTAIN_PIECE = register("mountain_piece", CrystalMountainPiece::new); + public static final StructurePieceType CAVE_PIECE = register("cave_piece", CavePiece::new); + public static final StructurePieceType LAKE_PIECE = register("lake_piece", LakePiece::new); + public static final StructurePieceType PAINTED_MOUNTAIN_PIECE = register("painted_mountain_piece", + PaintedMountainPiece::new); + public static final StructurePieceType NBT_PIECE = register("nbt_piece", NBTPiece::new); + + public static final BCLStructure GIANT_MOSSY_GLOWSHROOM = new BCLStructure<>( + BetterEnd.makeID("giant_mossy_glowshroom"), + GiantMossyGlowshroomStructure::new, + Decoration.SURFACE_STRUCTURES, + 16, + 8 + ); + public static final BCLStructure MEGALAKE = new BCLStructure<>( + BetterEnd.makeID("megalake"), + MegaLakeStructure::new, + Decoration.RAW_GENERATION, + 4, + 1 + ); + public static final BCLStructure MEGALAKE_SMALL = new BCLStructure<>( + BetterEnd.makeID("megalake_small"), + MegaLakeSmallStructure::new, + Decoration.RAW_GENERATION, + 4, + 1 + ); + public static final BCLStructure MOUNTAIN = new BCLStructure<>( + BetterEnd.makeID("mountain"), + MountainStructure::new, + Decoration.RAW_GENERATION, + 3, + 2 + ); + public static final BCLStructure PAINTED_MOUNTAIN = new BCLStructure<>( + BetterEnd.makeID("painted_mountain"), + PaintedMountainStructure::new, + Decoration.RAW_GENERATION, + 3, + 2 + ); + public static final BCLStructure ETERNAL_PORTAL = new BCLStructure<>( + BetterEnd.makeID("eternal_portal"), + EternalPortalStructure::new, + Decoration.SURFACE_STRUCTURES, + 16, + 6 + ); + public static final BCLStructure GIANT_ICE_STAR = new BCLStructure<>( + BetterEnd.makeID("giant_ice_star"), + GiantIceStarStructure::new, + Decoration.SURFACE_STRUCTURES, + 16, + 8 + ); + + public static void register() { + } + + private static StructurePieceType register(String id, StructurePieceType pieceType) { + return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType); + } + + public static void addBiomeStructures(ResourceLocation biomeID, Holder biome) { + if (!biomeID.getPath().contains("mountain") && !biomeID.getPath().contains("lake")) { + TagAPI.addBiomeTag(ETERNAL_PORTAL.biomeTag, biome.value()); + } + } +} diff --git a/src/main/java/org/betterx/betterend/registry/EndTags.java b/src/main/java/org/betterx/betterend/registry/EndTags.java new file mode 100644 index 00000000..e9f5a30a --- /dev/null +++ b/src/main/java/org/betterx/betterend/registry/EndTags.java @@ -0,0 +1,149 @@ +package org.betterx.betterend.registry; + +import net.minecraft.core.Registry; +import net.minecraft.tags.TagKey; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; +import net.minecraft.world.level.material.Material; + +import net.fabricmc.fabric.mixin.object.builder.AbstractBlockAccessor; +import net.fabricmc.fabric.mixin.object.builder.AbstractBlockSettingsAccessor; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.BonemealAPI; +import org.betterx.bclib.api.ComposterAPI; +import org.betterx.bclib.api.tag.*; +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.bclib.blocks.SimpleLeavesBlock; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.basis.EndTerrainBlock; +import org.betterx.betterend.blocks.basis.PedestalBlock; +import org.betterx.betterend.item.tool.EndHammerItem; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.List; + +public class EndTags { + // Table with common (c) tags: + // https://fabricmc.net/wiki/tutorial:tags + + // Block Tags + public static final TagKey PEDESTALS = TagAPI.makeBlockTag(BetterEnd.MOD_ID, "pedestal"); + + // Item Tags + public static final TagKey ALLOYING_IRON = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_iron"); + public static final TagKey ALLOYING_GOLD = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_gold"); + public static final TagKey ALLOYING_COPPER = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_copper"); + + public static void register() { + addEndGround(EndBlocks.THALLASIUM.ore); + addEndGround(EndBlocks.ENDSTONE_DUST); + addEndGround(EndBlocks.AMBER_ORE); + + EndBlocks.getModBlocks().forEach(block -> { + Properties properties = ((AbstractBlockAccessor) block).getSettings(); + Material material = ((AbstractBlockSettingsAccessor) properties).getMaterial(); + final Item item = block.asItem(); + + if (material.equals(Material.STONE) || material.equals(Material.METAL) || material.equals(Material.HEAVY_METAL)) { + TagAPI.addBlockTag(NamedMineableTags.PICKAXE, block); + } else if (material.equals(Material.WOOD)) { + TagAPI.addBlockTag(NamedMineableTags.AXE, block); + } else if (material.equals(Material.LEAVES) || material.equals(Material.PLANT) || material.equals(Material.WATER_PLANT) || material.equals( + Material.SPONGE)) { + TagAPI.addBlockTag(NamedMineableTags.HOE, block); + } else if (material.equals(Material.SAND)) { + TagAPI.addBlockTag(NamedMineableTags.SHOVEL, block); + } + + if (block instanceof EndTerrainBlock) { + addEndGround(block); + TagAPI.addBlockTag(NamedBlockTags.NYLIUM, block); + BonemealAPI.addSpreadableBlock(block, Blocks.END_STONE); + } else if (block instanceof LeavesBlock || block instanceof SimpleLeavesBlock) { + TagAPI.addBlockTag(NamedBlockTags.LEAVES, block); + ComposterAPI.allowCompost(0.3f, item); + } else if (block instanceof BaseVineBlock) { + TagAPI.addBlockTag(NamedBlockTags.CLIMBABLE, block); + } else if (block instanceof PedestalBlock) { + TagAPI.addBlockTag(PEDESTALS, block); + } + + Material mat = block.defaultBlockState().getMaterial(); + if (mat.equals(Material.PLANT) || mat.equals(Material.REPLACEABLE_PLANT)) { + ComposterAPI.allowCompost(0.1F, item); + } + }); + addEndGround(EndBlocks.CAVE_MOSS); + TagAPI.addBlockTag(NamedBlockTags.NYLIUM, EndBlocks.CAVE_MOSS); + BonemealAPI.addSpreadableBlock(EndBlocks.CAVE_MOSS, Blocks.END_STONE); + BonemealAPI.addSpreadableBlock(EndBlocks.MOSSY_OBSIDIAN, Blocks.OBSIDIAN); + BonemealAPI.addSpreadableBlock(EndBlocks.MOSSY_DRAGON_BONE, EndBlocks.DRAGON_BONE_BLOCK); + + List ITEM_HAMMERS = Lists.newArrayList(); + EndItems.getModItems().forEach(item -> { + if (item.isEdible()) { + FoodProperties food = item.getFoodProperties(); + if (food != null) { + float compost = food.getNutrition() * food.getSaturationModifier() * 0.18F; + ComposterAPI.allowCompost(compost, item); + } + } + if (item instanceof EndHammerItem) { + ITEM_HAMMERS.add(item); + } + }); + + TagAPI.addBlockTag( + CommonBlockTags.END_STONES, + EndBlocks.ENDER_ORE, + EndBlocks.BRIMSTONE + ); + TagAPI.addBlockTag(CommonBlockTags.END_STONES, EndBlocks.BRIMSTONE); + TagAPI.addBlockTag(NamedBlockTags.ANVIL, EndBlocks.AETERNIUM_ANVIL); + TagAPI.addBlockTag(NamedBlockTags.BEACON_BASE_BLOCKS, EndBlocks.AETERNIUM_BLOCK); + TagAPI.addItemTag(NamedItemTags.BEACON_PAYMENT_ITEMS, EndItems.AETERNIUM_INGOT); + TagAPI.addBlockTag( + CommonBlockTags.DRAGON_IMMUNE, + EndBlocks.ENDER_ORE, + EndBlocks.ETERNAL_PEDESTAL, + EndBlocks.FLAVOLITE_RUNED_ETERNAL, + EndBlocks.FLAVOLITE_RUNED + ); + TagAPI.addItemTag(CommonItemTags.IRON_INGOTS, EndBlocks.THALLASIUM.ingot); + + TagAPI.addItemTag(ALLOYING_IRON, Items.IRON_ORE, Items.DEEPSLATE_IRON_ORE, Items.RAW_IRON); + TagAPI.addItemTag(ALLOYING_GOLD, Items.GOLD_ORE, Items.DEEPSLATE_GOLD_ORE, Items.RAW_GOLD); + TagAPI.addItemTag(ALLOYING_COPPER, Items.COPPER_ORE, Items.DEEPSLATE_COPPER_ORE, Items.RAW_COPPER); + } + + public static void addEndGround(Block bl) { + TagAPI.addBlockTag(CommonBlockTags.END_STONES, bl); + } + + public static void addBiomeSurfaceToEndGroup(EndBiome b) { + addEndGround(b.getTopMaterial().getBlock()); + addEndGround(b.getAltTopMaterial().getBlock()); + addEndGround(b.getUnderMaterial().getBlock()); + } + + // TODO make getter for biome top blocks + public static void addTerrainTags(Registry biomeRegistry) { + /*biomeRegistry.forEach((biome) -> { + if (biome.getBiomeCategory() == BiomeCategory.THEEND) { + SurfaceBuilderConfiguration config = biome.getGenerationSettings().getSurfaceBuilderConfig(); + Block under = config.getUnderMaterial().getBlock(); + Block surface = config.getTopMaterial().getBlock(); + TagAPI.addTag(CommonBlockTags.GEN_END_STONES, under, surface); + TagAPI.addTag(CommonBlockTags.END_STONES, surface); + } + }); + TagAPI.BLOCK_END_STONES.getValues().forEach(TagAPI::addEndGround);*/ + } +} diff --git a/src/main/java/org/betterx/betterend/rituals/EternalRitual.java b/src/main/java/org/betterx/betterend/rituals/EternalRitual.java new file mode 100644 index 00000000..dae79f4b --- /dev/null +++ b/src/main/java/org/betterx/betterend/rituals/EternalRitual.java @@ -0,0 +1,773 @@ +package org.betterx.betterend.rituals; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.blocks.EndPortalBlock; +import org.betterx.betterend.blocks.RunedFlavolite; +import org.betterx.betterend.blocks.entities.EternalPedestalEntity; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndPortals; + +import java.awt.*; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; + +public class EternalRitual { + private final static Set STRUCTURE_MAP = Sets.newHashSet( + new Point(-4, -5), + new Point(-4, 5), + new Point(-6, 0), + new Point(4, -5), + new Point(4, 5), + new Point(6, 0) + ); + private final static Set FRAME_MAP = Sets.newHashSet( + new Point(0, 0), + new Point(0, 6), + new Point(1, 0), + new Point(1, 6), + new Point(2, 1), + new Point(2, 5), + new Point(3, 2), + new Point(3, 3), + new Point(3, 4) + ); + private final static Set PORTAL_MAP = Sets.newHashSet( + new Point(0, 0), + new Point(0, 1), + new Point(0, 2), + new Point(0, 3), + new Point(0, 4), + new Point(1, 0), + new Point(1, 1), + new Point(1, 2), + new Point(1, 3), + new Point(1, 4), + new Point(2, 1), + new Point(2, 2), + new Point(2, 3) + ); + private final static Set BASE_MAP = Sets.newHashSet( + new Point(3, 0), + new Point(2, 0), + new Point(2, 1), + new Point(1, 1), + new Point(1, 2), + new Point(0, 1), + new Point(0, 2) + ); + + private final static Block BASE = EndBlocks.FLAVOLITE.tiles; + private final static Block PEDESTAL = EndBlocks.ETERNAL_PEDESTAL; + private final static Block FRAME = EndBlocks.FLAVOLITE_RUNED_ETERNAL; + private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK; + private final static BooleanProperty ACTIVE = BlockProperties.ACTIVE; + + public final static int SEARCH_RADIUS = calculateSearchSteps(48); + + private Level world; + private Direction.Axis axis; + private ResourceLocation targetWorldId; + private BlockPos center; + private BlockPos exit; + private boolean active = false; + + public EternalRitual(Level world) { + this.world = world; + } + + public EternalRitual(Level world, BlockPos initial) { + this(world); + this.configure(initial); + } + + public void setWorld(Level world) { + this.world = world; + } + + @Nullable + public ResourceLocation getTargetWorldId() { + return targetWorldId; + } + + private boolean isInvalid() { + return world == null || world.isClientSide() || center == null || axis == null; + } + + public void checkStructure() { + if (isInvalid()) return; + Direction moveX, moveY; + if (Direction.Axis.X == axis) { + moveX = Direction.EAST; + moveY = Direction.NORTH; + } else { + moveX = Direction.SOUTH; + moveY = Direction.EAST; + } + boolean valid = checkFrame(world, center.below()); + Item item = null; + for (Point pos : STRUCTURE_MAP) { + BlockPos.MutableBlockPos checkPos = center.mutable(); + checkPos.move(moveX, pos.x).move(moveY, pos.y); + valid &= isActive(checkPos); + if (valid) { + EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(checkPos); + if (pedestal != null) { + Item pItem = pedestal.getItem(0).getItem(); + if (item == null) { + item = pItem; + } else if (!item.equals(pItem)) { + valid = false; + } + } + } + } + if (valid && item != null) { + activatePortal(item); + } + } + + private boolean checkFrame(Level world, BlockPos framePos) { + Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; + boolean valid = true; + for (Point point : FRAME_MAP) { + BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + BlockState state = world.getBlockState(pos); + valid &= state.getBlock() instanceof RunedFlavolite; + pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + state = world.getBlockState(pos); + valid &= state.getBlock() instanceof RunedFlavolite; + } + return valid; + } + + public boolean isActive() { + return active; + } + + private void activatePortal(Item keyItem) { + if (active) return; + ResourceLocation itemId = Registry.ITEM.getKey(keyItem); + int portalId = EndPortals.getPortalIdByItem(itemId); + Level targetWorld = getTargetWorld(portalId); + ResourceLocation worldId = targetWorld.dimension().location(); + try { + if (exit == null) { + initPortal(worldId, portalId); + } else { + if (!worldId.equals(targetWorldId)) { + initPortal(worldId, portalId); + } else if (!checkFrame(targetWorld, exit.below())) { + Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; + generatePortal(targetWorld, exit, portalAxis, portalId); + } + activatePortal(targetWorld, exit, portalId); + } + activatePortal(world, center, portalId); + doEffects((ServerLevel) world, center); + active = true; + } catch (Exception ex) { + BetterEnd.LOGGER.error("Create End portals error.", ex); + removePortal(targetWorld, exit); + removePortal(world, center); + active = false; + } + } + + private void initPortal(ResourceLocation worldId, int portalId) { + targetWorldId = worldId; + exit = findPortalPos(portalId); + } + + private void doEffects(ServerLevel serverWorld, BlockPos center) { + Direction moveX, moveY; + if (Direction.Axis.X == axis) { + moveX = Direction.EAST; + moveY = Direction.NORTH; + } else { + moveX = Direction.SOUTH; + moveY = Direction.EAST; + } + for (Point pos : STRUCTURE_MAP) { + BlockPos.MutableBlockPos p = center.mutable(); + p.move(moveX, pos.x).move(moveY, pos.y); + serverWorld.sendParticles( + ParticleTypes.PORTAL, + p.getX() + 0.5, + p.getY() + 1.5, + p.getZ() + 0.5, + 20, + 0, + 0, + 0, + 1 + ); + serverWorld.sendParticles( + ParticleTypes.REVERSE_PORTAL, + p.getX() + 0.5, + p.getY() + 1.5, + p.getZ() + 0.5, + 20, + 0, + 0, + 0, + 0.3 + ); + } + serverWorld.playSound(null, center, SoundEvents.END_PORTAL_SPAWN, SoundSource.NEUTRAL, 16, 1); + } + + private void activatePortal(Level world, BlockPos center, int portalId) { + BlockPos framePos = center.below(); + Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; + BlockState frame = FRAME.defaultBlockState().setValue(ACTIVE, true); + FRAME_MAP.forEach(point -> { + BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + BlockState state = world.getBlockState(pos); + if (state.hasProperty(ACTIVE) && !state.getValue(ACTIVE)) { + world.setBlockAndUpdate(pos, frame); + } + pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + state = world.getBlockState(pos); + if (state.hasProperty(ACTIVE) && !state.getValue(ACTIVE)) { + world.setBlockAndUpdate(pos, frame); + } + }); + Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X; + BlockState portal = PORTAL.defaultBlockState() + .setValue(EndPortalBlock.AXIS, portalAxis) + .setValue(EndPortalBlock.PORTAL, portalId); + ParticleOptions effect = new BlockParticleOption(ParticleTypes.BLOCK, portal); + ServerLevel serverWorld = (ServerLevel) world; + + PORTAL_MAP.forEach(point -> { + BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + if (!world.getBlockState(pos).is(PORTAL)) { + world.setBlockAndUpdate(pos, portal); + serverWorld.sendParticles( + effect, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + 10, + 0.5, + 0.5, + 0.5, + 0.1 + ); + serverWorld.sendParticles( + ParticleTypes.REVERSE_PORTAL, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + 10, + 0.5, + 0.5, + 0.5, + 0.3 + ); + } + pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + if (!world.getBlockState(pos).is(PORTAL)) { + world.setBlockAndUpdate(pos, portal); + serverWorld.sendParticles( + effect, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + 10, + 0.5, + 0.5, + 0.5, + 0.1 + ); + serverWorld.sendParticles( + ParticleTypes.REVERSE_PORTAL, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + 10, + 0.5, + 0.5, + 0.5, + 0.3 + ); + } + }); + } + + public void disablePortal(int state) { + if (!active || isInvalid()) return; + removePortal(getTargetWorld(state), exit); + removePortal(world, center); + } + + private void removePortal(Level world, BlockPos center) { + BlockPos framePos = center.below(); + Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; + FRAME_MAP.forEach(point -> { + BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + BlockState state = world.getBlockState(pos); + if (state.is(FRAME) && state.getValue(ACTIVE)) { + world.setBlockAndUpdate(pos, state.setValue(ACTIVE, false)); + } + pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + state = world.getBlockState(pos); + if (state.is(FRAME) && state.getValue(ACTIVE)) { + world.setBlockAndUpdate(pos, state.setValue(ACTIVE, false)); + } + }); + PORTAL_MAP.forEach(point -> { + BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + if (world.getBlockState(pos).is(PORTAL)) { + world.removeBlock(pos, false); + } + pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + if (world.getBlockState(pos).is(PORTAL)) { + world.removeBlock(pos, false); + } + }); + this.active = false; + } + + @Nullable + private BlockPos findFrame(Level world, BlockPos.MutableBlockPos startPos) { + List foundPos = findAllBlockPos( + world, + startPos, + (SEARCH_RADIUS >> 4) + 1, + FRAME, + blockState -> blockState.is(FRAME) && !blockState.getValue(ACTIVE) + ); + for (BlockPos.MutableBlockPos testPos : foundPos) { + if (checkFrame(world, testPos)) { + return testPos; + } + } + return null; + } + + private BlockPos findPortalPos(int portalId) { + MinecraftServer server = world.getServer(); + ServerLevel targetWorld = (ServerLevel) getTargetWorld(portalId); + Registry registry = Objects.requireNonNull(server) + .registryAccess() + .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + double multiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale(); + BlockPos.MutableBlockPos basePos = center.mutable() + .set(center.getX() / multiplier, + center.getY(), + center.getZ() / multiplier + ); + BlockPos framePos = findFrame(targetWorld, basePos.mutable()); + if (framePos != null) { + return framePos.above(); + } + Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; + int worldCeil = targetWorld.getHeight() - 1; + if (checkIsAreaValid(targetWorld, basePos, portalAxis)) { + generatePortal(targetWorld, basePos, portalAxis, portalId); + return basePos.immutable(); + } else { + Direction direction = Direction.EAST; + BlockPos.MutableBlockPos checkPos = basePos.mutable(); + int radius = (int) ((SEARCH_RADIUS / multiplier) + 1); + for (int step = 1; step < radius; step++) { + for (int i = 0; i < (step >> 1); i++) { + ChunkAccess chunk = targetWorld.getChunk(checkPos); + if (chunk != null) { + int surfaceY = chunk.getHeight( + Heightmap.Types.WORLD_SURFACE, + checkPos.getX() & 15, + checkPos.getZ() & 15 + ); + int motionY = chunk.getHeight( + Heightmap.Types.MOTION_BLOCKING, + checkPos.getX() & 15, + checkPos.getZ() & 15 + ); + int ceil = Math.min(Math.max(surfaceY, motionY) + 1, worldCeil); + if (ceil < 5) continue; + checkPos.setY(ceil); + while (checkPos.getY() >= 5) { + if (checkIsAreaValid(targetWorld, checkPos, portalAxis)) { + generatePortal(targetWorld, checkPos, portalAxis, portalId); + return checkPos.immutable(); + } + checkPos.move(Direction.DOWN); + } + } + checkPos.move(direction); + } + direction = direction.getClockWise(); + } + } + if (targetWorld.dimension() == Level.END) { + net.minecraft.data.worldgen.features.EndFeatures.END_ISLAND.value().place( + targetWorld, + targetWorld.getChunkSource().getGenerator(), + new LegacyRandomSource(basePos.asLong()), + basePos.below() + ); + } else if (targetWorld.dimension() == Level.OVERWORLD) { + basePos.setY(targetWorld.getChunk(basePos) + .getHeight(Heightmap.Types.WORLD_SURFACE, basePos.getX(), basePos.getZ()) + 1); + } + EndFeatures.BIOME_ISLAND + .getPlacedFeature() + .value() + .place(targetWorld, + targetWorld.getChunkSource().getGenerator(), + new LegacyRandomSource(basePos.asLong()), + basePos.below() + ); + generatePortal(targetWorld, basePos, portalAxis, portalId); + return basePos.immutable(); + } + + private Level getTargetWorld(int state) { + if (world.dimension() == Level.END) { + return EndPortals.getWorld(world.getServer(), state); + } + return Objects.requireNonNull(world.getServer()).getLevel(Level.END); + } + + private boolean checkIsAreaValid(Level world, BlockPos pos, Direction.Axis axis) { + if (pos.getY() >= world.getHeight() - 1) return false; + if (!isBaseValid(world, pos, axis)) return false; + return EternalRitual.checkArea(world, pos, axis); + } + + private boolean isBaseValid(Level world, BlockPos pos, Direction.Axis axis) { + boolean solid = true; + if (axis.equals(Direction.Axis.X)) { + pos = pos.below().offset(0, 0, -3); + for (int i = 0; i < 7; i++) { + BlockPos checkPos = pos.offset(0, 0, i); + BlockState state = world.getBlockState(checkPos); + solid &= validBlock(world, checkPos, state); + } + } else { + pos = pos.below().offset(-3, 0, 0); + for (int i = 0; i < 7; i++) { + BlockPos checkPos = pos.offset(i, 0, 0); + BlockState state = world.getBlockState(checkPos); + solid &= validBlock(world, checkPos, state); + } + } + return solid; + } + + private boolean validBlock(Level world, BlockPos pos, BlockState state) { + return state.isRedstoneConductor(world, pos) && state.isCollisionShapeFullBlock(world, pos); + } + + public void configure(BlockPos initial) { + BlockPos checkPos = initial.east(12); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.X; + this.center = initial.east(6); + return; + } + checkPos = initial.west(12); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.X; + this.center = initial.west(6); + return; + } + checkPos = initial.south(12); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.Z; + this.center = initial.south(6); + return; + } + checkPos = initial.north(12); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.Z; + this.center = initial.north(6); + return; + } + checkPos = initial.north(10); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.X; + checkPos = checkPos.east(8); + if (this.hasPedestal(checkPos)) { + this.center = initial.north(5).east(4); + } else { + this.center = initial.north(5).west(4); + } + return; + } + checkPos = initial.south(10); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.X; + checkPos = checkPos.east(8); + if (this.hasPedestal(checkPos)) { + this.center = initial.south(5).east(4); + } else { + this.center = initial.south(5).west(4); + } + return; + } + checkPos = initial.east(10); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.Z; + checkPos = checkPos.south(8); + if (this.hasPedestal(checkPos)) { + this.center = initial.east(5).south(4); + } else { + this.center = initial.east(5).north(4); + } + return; + } + checkPos = initial.west(10); + if (this.hasPedestal(checkPos)) { + this.axis = Direction.Axis.Z; + checkPos = checkPos.south(8); + if (this.hasPedestal(checkPos)) { + this.center = initial.west(5).south(4); + } else { + this.center = initial.west(5).north(4); + } + } + } + + private boolean hasPedestal(BlockPos pos) { + return world.getBlockState(pos).is(PEDESTAL); + } + + private boolean isActive(BlockPos pos) { + BlockState state = world.getBlockState(pos); + if (state.is(PEDESTAL)) { + EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(pos); + if (pedestal != null) { + if (!pedestal.hasRitual()) { + pedestal.linkRitual(this); + } else { + EternalRitual ritual = pedestal.getRitual(); + if (!ritual.equals(this)) { + pedestal.linkRitual(this); + } + } + } + return state.getValue(ACTIVE); + } + return false; + } + + public CompoundTag toTag(CompoundTag tag) { + tag.put("center", NbtUtils.writeBlockPos(center)); + tag.putString("axis", axis.getName()); + tag.putBoolean("active", active); + if (targetWorldId != null) { + tag.putString("key_item", targetWorldId.toString()); + } + if (exit != null) { + tag.put("exit", NbtUtils.writeBlockPos(exit)); + } + return tag; + } + + public void fromTag(CompoundTag tag) { + axis = Direction.Axis.byName(tag.getString("axis")); + center = NbtUtils.readBlockPos(tag.getCompound("center")); + active = tag.getBoolean("active"); + if (tag.contains("exit")) { + exit = NbtUtils.readBlockPos(tag.getCompound("exit")); + } + if (tag.contains("key_item")) { + targetWorldId = new ResourceLocation(tag.getString("key_item")); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EternalRitual ritual = (EternalRitual) o; + return world.equals(ritual.world) && Objects.equals(center, ritual.center) && Objects.equals(exit, ritual.exit); + } + + public static void generatePortal(Level world, BlockPos center, Direction.Axis axis, int portalId) { + BlockPos framePos = center.below(); + Direction moveDir = Direction.Axis.X == axis ? Direction.EAST : Direction.NORTH; + BlockState frame = FRAME.defaultBlockState().setValue(ACTIVE, true); + FRAME_MAP.forEach(point -> { + BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + world.setBlockAndUpdate(pos, frame); + pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + world.setBlockAndUpdate(pos, frame); + }); + BlockState portal = PORTAL.defaultBlockState() + .setValue(EndPortalBlock.AXIS, axis) + .setValue(EndPortalBlock.PORTAL, portalId); + PORTAL_MAP.forEach(point -> { + BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + world.setBlockAndUpdate(pos, portal); + pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + world.setBlockAndUpdate(pos, portal); + }); + generateBase(world, framePos, moveDir); + } + + private static void generateBase(Level world, BlockPos center, Direction moveX) { + BlockState base = BASE.defaultBlockState(); + Direction moveY = moveX.getClockWise(); + BASE_MAP.forEach(point -> { + BlockPos pos = center.mutable().move(moveX, point.x).move(moveY, point.y); + world.setBlockAndUpdate(pos, base); + pos = center.mutable().move(moveX, -point.x).move(moveY, point.y); + world.setBlockAndUpdate(pos, base); + pos = center.mutable().move(moveX, point.x).move(moveY, -point.y); + world.setBlockAndUpdate(pos, base); + pos = center.mutable().move(moveX, -point.x).move(moveY, -point.y); + world.setBlockAndUpdate(pos, base); + }); + } + + public static boolean checkArea(Level world, BlockPos center, Direction.Axis axis) { + Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; + for (BlockPos checkPos : BlockPos.betweenClosed( + center.relative(moveDir.getClockWise()), + center.relative(moveDir.getCounterClockWise()) + )) { + for (Point point : PORTAL_MAP) { + BlockPos pos = checkPos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); + BlockState state = world.getBlockState(pos); + if (isStateInvalid(state)) return false; + pos = checkPos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); + state = world.getBlockState(pos); + if (isStateInvalid(state)) return false; + } + } + return true; + } + + private static boolean isStateInvalid(BlockState state) { + if (!state.getFluidState().isEmpty()) return true; + Material material = state.getMaterial(); + return !material.isReplaceable() && !material.equals(Material.PLANT); + } + + /** + * @param world World for search + * @param checkPos Start search position + * @param radius Search radius + * @param searchBlock Target block + * @param condition Predicate for test block states in the chunk section + * @return Position of the first found block or null. + */ + @Nullable + public static BlockPos.MutableBlockPos findBlockPos(Level world, + BlockPos.MutableBlockPos checkPos, + int radius, + Block searchBlock, + Predicate condition) { + Direction moveDirection = Direction.EAST; + for (int step = 1; step < radius; step++) { + for (int i = 0; i < (step >> 1); i++) { + ChunkAccess chunk = world.getChunk(checkPos); + if (!(chunk instanceof LevelChunk) || ((LevelChunk) chunk).isEmpty()) continue; + for (LevelChunkSection section : chunk.getSections()) { + if (section == null || !section.getStates().maybeHas(condition)) continue; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockState checkState = section.getBlockState(x, y, z); + if (checkState.is(searchBlock)) { + int worldX = (chunk.getPos().x << 4) + x; + int worldY = section.bottomBlockY() + y; + int worldZ = (chunk.getPos().z << 4) + z; + checkPos.set(worldX, worldY, worldZ); + return checkPos; + } + } + } + } + } + checkPos.move(moveDirection, 16); + } + moveDirection = moveDirection.getClockWise(); + } + return null; + } + + /** + * @param world World for search + * @param checkPos Start search position + * @param radius Search radius + * @param searchBlock Target block + * @param condition Predicate for test block states in the chunk section + * @return List of positions of the all found blocks or empty list. + */ + public static List findAllBlockPos(Level world, + BlockPos.MutableBlockPos checkPos, + int radius, + Block searchBlock, + Predicate condition) { + List posFound = Lists.newArrayList(); + Direction moveDirection = Direction.EAST; + for (int step = 1; step < radius; step++) { + for (int i = 0; i < (step >> 1); i++) { + ChunkAccess chunk = world.getChunk(checkPos); + if (!(chunk instanceof LevelChunk) || ((LevelChunk) chunk).isEmpty()) continue; + for (LevelChunkSection section : chunk.getSections()) { + if (section == null || !section.getStates().maybeHas(condition)) continue; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockState checkState = section.getBlockState(x, y, z); + if (checkState.is(searchBlock)) { + int worldX = (chunk.getPos().x << 4) + x; + int worldY = section.bottomBlockY() + y; + int worldZ = (chunk.getPos().z << 4) + z; + checkPos.set(worldX, worldY, worldZ); + posFound.add(checkPos.mutable()); + } + } + } + } + } + checkPos.move(moveDirection, 16); + } + moveDirection = moveDirection.getClockWise(); + } + return posFound; + } + + public static int calculateSearchSteps(int radius) { + return radius * 4 - 1; + } +} diff --git a/src/main/java/org/betterx/betterend/rituals/InfusionRitual.java b/src/main/java/org/betterx/betterend/rituals/InfusionRitual.java new file mode 100644 index 00000000..c1d193cf --- /dev/null +++ b/src/main/java/org/betterx/betterend/rituals/InfusionRitual.java @@ -0,0 +1,255 @@ +package org.betterx.betterend.rituals; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +import org.betterx.betterend.blocks.entities.InfusionPedestalEntity; +import org.betterx.betterend.blocks.entities.PedestalBlockEntity; +import org.betterx.betterend.particle.InfusionParticleType; +import org.betterx.betterend.recipe.builders.InfusionRecipe; + +import java.awt.*; +import java.util.Arrays; +import java.util.Objects; + +public class InfusionRitual implements Container { + private static final Point[] PEDESTALS_MAP = new Point[]{ + new Point(0, 3), + new Point(2, 2), + new Point(3, 0), + new Point(2, -2), + new Point(0, -3), + new Point(-2, -2), + new Point(-3, 0), + new Point(-2, 2) + }; + + private Level world; + private BlockPos worldPos; + private InfusionRecipe activeRecipe; + private boolean isDirty = false; + private boolean hasRecipe = false; + private int progress = 0; + private int time = 0; + + private final PedestalBlockEntity[] catalysts = new PedestalBlockEntity[8]; + private final InfusionPedestalEntity input; + + public InfusionRitual(InfusionPedestalEntity pedestal, Level world, BlockPos pos) { + this.input = pedestal; + this.world = world; + this.worldPos = pos; + configure(); + } + + public void configure() { + if (world == null || worldPos == null) return; + for (int i = 0; i < catalysts.length; i++) { + Point point = PEDESTALS_MAP[i]; + MutableBlockPos checkPos = worldPos.mutable().move(Direction.EAST, point.x).move(Direction.NORTH, point.y); + BlockEntity catalystEntity = world.getBlockEntity(checkPos); + if (catalystEntity instanceof PedestalBlockEntity) { + catalysts[i] = (PedestalBlockEntity) catalystEntity; + } else { + catalysts[i] = null; + } + } + } + + public boolean checkRecipe() { + if (!isValid()) return false; + InfusionRecipe recipe = world.getRecipeManager().getRecipeFor(InfusionRecipe.TYPE, this, world).orElse(null); + if (hasRecipe()) { + if (recipe == null) { + reset(); + return false; + } else if (activeRecipe == null || recipe.getInfusionTime() != time) { + updateRecipe(recipe); + } + return true; + } + if (recipe != null) { + updateRecipe(recipe); + return true; + } + return false; + } + + private void updateRecipe(InfusionRecipe recipe) { + activeRecipe = recipe; + hasRecipe = true; + resetTimer(); + setChanged(); + } + + private void resetTimer() { + time = activeRecipe != null ? activeRecipe.getInfusionTime() : 0; + progress = 0; + } + + public void reset() { + activeRecipe = null; + hasRecipe = false; + resetTimer(); + setChanged(); + } + + public void tick() { + if (isDirty) { + configure(); + isDirty = false; + } + if (!checkRecipe()) return; + progress++; + if (progress == time) { + clearContent(); + input.setItem(0, activeRecipe.assemble(this)); + reset(); + } else if (world instanceof ServerLevel) { + ServerLevel serverLevel = (ServerLevel) world; + BlockPos target = worldPos.above(); + double tx = target.getX() + 0.5; + double ty = target.getY() + 0.5; + double tz = target.getZ() + 0.5; + for (PedestalBlockEntity catalyst : catalysts) { + ItemStack stack = catalyst.getItem(0); + if (!stack.isEmpty()) { + BlockPos start = catalyst.getBlockPos(); + double sx = start.getX() + 0.5; + double sy = start.getY() + 1.25; + double sz = start.getZ() + 0.5; + serverLevel.sendParticles( + new InfusionParticleType(stack), + sx, + sy, + sz, + 0, + tx - sx, + ty - sy, + tz - sz, + 0.5 + ); + } + } + } + + } + + @Override + public boolean canPlaceItem(int slot, ItemStack stack) { + return isValid(); + } + + public boolean isValid() { + if (world == null || worldPos == null || input == null) return false; + return Arrays.stream(catalysts).noneMatch(Objects::isNull); + } + + public boolean hasRecipe() { + return hasRecipe; + } + + public void setLocation(Level world, BlockPos pos) { + this.world = world; + this.worldPos = pos; + this.isDirty = true; + } + + @Override + public void clearContent() { + if (!isValid()) return; + input.clearContent(); + Arrays.stream(catalysts).forEach(PedestalBlockEntity::clearContent); + } + + @Override + public int getContainerSize() { + return 9; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public ItemStack getItem(int slot) { + if (slot > 8) return ItemStack.EMPTY; + if (slot == 0) { + return input.getItem(0); + } else { + return catalysts[slot - 1].getItem(0); + } + } + + @Override + public ItemStack removeItem(int slot, int amount) { + return removeItemNoUpdate(slot); + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + if (slot > 8) return ItemStack.EMPTY; + if (slot == 0) { + return input.removeItemNoUpdate(0); + } else { + return catalysts[slot - 1].removeItemNoUpdate(0); + } + } + + @Override + public void setItem(int slot, ItemStack stack) { + if (slot > 8) return; + if (slot == 0) { + input.setItem(0, stack); + } else { + catalysts[slot - 1].setItem(0, stack); + } + } + + @Override + public void setChanged() { + if (isValid()) { + input.setChanged(); + Arrays.stream(catalysts).forEach(PedestalBlockEntity::setChanged); + } + } + + public void setDirty() { + this.isDirty = true; + } + + @Override + public boolean stillValid(Player player) { + return true; + } + + public void fromTag(CompoundTag tag) { + if (tag.contains("recipe")) { + hasRecipe = tag.getBoolean("recipe"); + progress = tag.getInt("progress"); + time = tag.getInt("time"); + } + } + + public CompoundTag toTag(CompoundTag tag) { + if (hasRecipe()) { + tag.putBoolean("recipe", hasRecipe); + tag.putInt("progress", progress); + tag.putInt("time", time); + } + return tag; + } + + public static Point[] getMap() { + return PEDESTALS_MAP; + } +} diff --git a/src/main/java/org/betterx/betterend/tab/CreativeTabs.java b/src/main/java/org/betterx/betterend/tab/CreativeTabs.java new file mode 100644 index 00000000..ae79e8ad --- /dev/null +++ b/src/main/java/org/betterx/betterend/tab/CreativeTabs.java @@ -0,0 +1,36 @@ +package org.betterx.betterend.tab; + +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; + +import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; + +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +import java.util.stream.Collectors; + +public class CreativeTabs { + public static final CreativeModeTab TAB_BLOCKS; + public static final CreativeModeTab TAB_ITEMS; + + static { + TAB_BLOCKS = FabricItemGroupBuilder + .create(BetterEnd.makeID("end_blocks")) + .icon(() -> new ItemStack(EndBlocks.END_MYCELIUM)) + .appendItems(stacks -> stacks.addAll(EndBlocks.getModBlockItems() + .stream() + .map(ItemStack::new) + .collect(Collectors.toList()))) + .build(); + TAB_ITEMS = FabricItemGroupBuilder + .create(BetterEnd.makeID("end_items")) + .icon(() -> new ItemStack(EndItems.ETERNAL_CRYSTAL)) + .appendItems(stacks -> stacks.addAll(EndItems.getModItems() + .stream() + .map(ItemStack::new) + .collect(Collectors.toList()))) + .build(); + } +} diff --git a/src/main/java/org/betterx/betterend/util/BlockFixer.java b/src/main/java/org/betterx/betterend/util/BlockFixer.java new file mode 100644 index 00000000..939c8606 --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/BlockFixer.java @@ -0,0 +1,229 @@ +package org.betterx.betterend.util; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.FallingBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.dimension.DimensionType; + +import com.google.common.collect.Sets; +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.bclib.blocks.StalactiteBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.BlueVineBlock; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.Set; +import java.util.stream.IntStream; + +public class BlockFixer { + private static final BlockState AIR = Blocks.AIR.defaultBlockState(); + private static final BlockState WATER = Blocks.WATER.defaultBlockState(); + + public static void fixBlocks(LevelAccessor level, BlockPos start, BlockPos end) { + final Registry registry = level.registryAccess() + .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + final ResourceLocation dimKey = registry.getKey(level.dimensionType()); + if (dimKey != null && "world_blender".equals(dimKey.getNamespace())) { + return; + } + final Set doubleCheck = Sets.newConcurrentHashSet(); + final int dx = end.getX() - start.getX() + 1; + final int dz = end.getZ() - start.getZ() + 1; + final int count = dx * dz; + final int minY = Math.max(start.getY(), level.getMinBuildHeight()); + final int maxY = Math.min(end.getY(), level.getMaxBuildHeight()); + IntStream.range(0, count).parallel().forEach(index -> { + MutableBlockPos POS = new MutableBlockPos(); + POS.setX((index % dx) + start.getX()); + POS.setZ((index / dx) + start.getZ()); + BlockState state; + for (int y = minY; y <= maxY; y++) { + POS.setY(y); + state = level.getBlockState(POS); + + if (state.getBlock() instanceof FurBlock) { + doubleCheck.add(POS.immutable()); + } + // Liquids + else if (!state.getFluidState().isEmpty()) { + if (!state.canSurvive(level, POS)) { + setWithoutUpdate(level, POS, WATER); + POS.setY(POS.getY() - 1); + state = level.getBlockState(POS); + while (!state.canSurvive(level, POS)) { + state = state.getFluidState().isEmpty() ? AIR : WATER; + setWithoutUpdate(level, POS, state); + POS.setY(POS.getY() - 1); + state = level.getBlockState(POS); + } + } + POS.setY(y - 1); + if (level.isEmptyBlock(POS)) { + POS.setY(y); + while (!level.getFluidState(POS).isEmpty()) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() + 1); + } + continue; + } + for (Direction dir : BlocksHelper.HORIZONTAL) { + if (level.isEmptyBlock(POS.relative(dir))) { + try { + level.scheduleTick(POS, state.getFluidState().getType(), 0); + } catch (Exception e) { + } + break; + } + } + } else if (state.is(EndBlocks.SMARAGDANT_CRYSTAL)) { + POS.setY(POS.getY() - 1); + if (level.isEmptyBlock(POS)) { + POS.setY(POS.getY() + 1); + while (state.is(EndBlocks.SMARAGDANT_CRYSTAL)) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() + 1); + state = level.getBlockState(POS); + } + } + } else if (state.getBlock() instanceof StalactiteBlock) { + if (!state.canSurvive(level, POS)) { + if (level.getBlockState(POS.above()).getBlock() instanceof StalactiteBlock) { + while (state.getBlock() instanceof StalactiteBlock) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() + 1); + state = level.getBlockState(POS); + } + } else { + while (state.getBlock() instanceof StalactiteBlock) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() - 1); + state = level.getBlockState(POS); + } + } + } + } else if (state.is(EndBlocks.CAVE_PUMPKIN)) { + if (!level.getBlockState(POS.above()).is(EndBlocks.CAVE_PUMPKIN_SEED)) { + setWithoutUpdate(level, POS, AIR); + } + } else if (!state.canSurvive(level, POS)) { + // Chorus + if (state.is(Blocks.CHORUS_PLANT)) { + Set ends = Sets.newHashSet(); + Set add = Sets.newHashSet(); + ends.add(POS.immutable()); + + for (int i = 0; i < 64 && !ends.isEmpty(); i++) { + ends.forEach((pos) -> { + setWithoutUpdate(level, pos, AIR); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos p = pos.relative(dir); + BlockState st = level.getBlockState(p); + if ((st.is(Blocks.CHORUS_PLANT) || st.is(Blocks.CHORUS_FLOWER)) && !st.canSurvive( + level, + p + )) { + add.add(p); + } + } + BlockPos p = pos.above(); + BlockState st = level.getBlockState(p); + if ((st.is(Blocks.CHORUS_PLANT) || st.is(Blocks.CHORUS_FLOWER)) && !st.canSurvive( + level, + p + )) { + add.add(p); + } + }); + ends.clear(); + ends.addAll(add); + add.clear(); + } + } + // Vines + else if (state.getBlock() instanceof BaseVineBlock) { + while (level.getBlockState(POS).getBlock() instanceof BaseVineBlock) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() - 1); + } + } + // Falling blocks + else if (state.getBlock() instanceof FallingBlock) { + BlockState falling = state; + + POS.setY(POS.getY() - 1); + state = level.getBlockState(POS); + + int ray = BlocksHelper.downRayRep(level, POS.immutable(), 64); + if (ray > 32) { + setWithoutUpdate(level, POS, Blocks.END_STONE.defaultBlockState()); + if (level.getRandom().nextBoolean()) { + POS.setY(POS.getY() - 1); + state = level.getBlockState(POS); + setWithoutUpdate(level, POS, Blocks.END_STONE.defaultBlockState()); + } + } else { + POS.setY(y); + BlockState replacement = AIR; + for (Direction dir : BlocksHelper.HORIZONTAL) { + state = level.getBlockState(POS.relative(dir)); + if (!state.getFluidState().isEmpty()) { + replacement = state; + break; + } + } + setWithoutUpdate(level, POS, replacement); + POS.setY(y - ray); + setWithoutUpdate(level, POS, falling); + } + } + // Blocks without support + else { + // Blue Vine + if (state.getBlock() instanceof BlueVineBlock) { + while (state.is(EndBlocks.BLUE_VINE) || state.is(EndBlocks.BLUE_VINE_LANTERN) || state.is( + EndBlocks.BLUE_VINE_FUR)) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() + 1); + state = level.getBlockState(POS); + } + } + // Double plants + if (state.getBlock() instanceof BaseDoublePlantBlock) { + setWithoutUpdate(level, POS, AIR); + POS.setY(POS.getY() + 1); + setWithoutUpdate(level, POS, AIR); + } + // Other blocks + else { + setWithoutUpdate(level, POS, getAirOrFluid(state)); + } + } + } + } + }); + + doubleCheck.forEach((pos) -> { + if (!level.getBlockState(pos).canSurvive(level, pos)) { + setWithoutUpdate(level, pos, AIR); + } + }); + } + + private static BlockState getAirOrFluid(BlockState state) { + return state.getFluidState().isEmpty() ? AIR : state.getFluidState().createLegacyBlock(); + } + + private static void setWithoutUpdate(LevelAccessor world, BlockPos pos, BlockState state) { + synchronized (world) { + BlocksHelper.setWithoutUpdate(world, pos, state); + } + } +} diff --git a/src/main/java/org/betterx/betterend/util/BonemealPlants.java b/src/main/java/org/betterx/betterend/util/BonemealPlants.java new file mode 100644 index 00000000..2964a846 --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/BonemealPlants.java @@ -0,0 +1,122 @@ +package org.betterx.betterend.util; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.BonemealAPI; +import org.betterx.betterend.blocks.basis.EndTerrainBlock; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; + +public class BonemealPlants { + public static void init() { + BonemealAPI.addLandGrass(EndBlocks.CREEPING_MOSS, EndBlocks.END_MOSS); + BonemealAPI.addLandGrass(EndBlocks.UMBRELLA_MOSS, EndBlocks.END_MOSS); + BonemealAPI.addLandGrass(EndBlocks.CREEPING_MOSS, EndBlocks.END_MYCELIUM); + BonemealAPI.addLandGrass(EndBlocks.UMBRELLA_MOSS, EndBlocks.END_MYCELIUM); + + BonemealAPI.addLandGrass(EndBlocks.CAVE_GRASS, EndBlocks.CAVE_MOSS); + BonemealAPI.addLandGrass(EndBlocks.CHORUS_GRASS, EndBlocks.CHORUS_NYLIUM); + BonemealAPI.addLandGrass(EndBlocks.CRYSTAL_GRASS, EndBlocks.CRYSTAL_MOSS); + BonemealAPI.addLandGrass(EndBlocks.SHADOW_PLANT, EndBlocks.SHADOW_GRASS); + BonemealAPI.addLandGrass(EndBlocks.BUSHY_GRASS, EndBlocks.PINK_MOSS); + BonemealAPI.addLandGrass(EndBlocks.AMBER_GRASS, EndBlocks.AMBER_MOSS); + + BonemealAPI.addLandGrass(EndBlocks.JUNGLE_GRASS, EndBlocks.JUNGLE_MOSS); + BonemealAPI.addLandGrass(EndBlocks.TWISTED_UMBRELLA_MOSS, EndBlocks.JUNGLE_MOSS); + BonemealAPI.addLandGrass(EndBlocks.SMALL_JELLYSHROOM, EndBlocks.JUNGLE_MOSS, 0.1F); + + BonemealAPI.addLandGrass( + EndBiomes.GLOWING_GRASSLANDS.getID(), + EndBlocks.BLOOMING_COOKSONIA, + EndBlocks.END_MOSS + ); + BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.VAIOLUSH_FERN, EndBlocks.END_MOSS); + BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.FRACTURN, EndBlocks.END_MOSS); + BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.SALTEAGO, EndBlocks.END_MOSS); + + BonemealAPI.addLandGrass( + EndBiomes.GLOWING_GRASSLANDS.getID(), + EndBlocks.CREEPING_MOSS, + EndBlocks.END_MOSS, + 0.1F + ); + BonemealAPI.addLandGrass( + EndBiomes.GLOWING_GRASSLANDS.getID(), + EndBlocks.UMBRELLA_MOSS, + EndBlocks.END_MOSS, + 0.1F + ); + BonemealAPI.addLandGrass( + EndBiomes.GLOWING_GRASSLANDS.getID(), + EndBlocks.TWISTED_UMBRELLA_MOSS, + EndBlocks.END_MOSS, + 0.1F + ); + + BonemealAPI.addLandGrass(EndBlocks.ORANGO, EndBlocks.RUTISCUS); + BonemealAPI.addLandGrass(EndBlocks.AERIDIUM, EndBlocks.RUTISCUS, 0.2F); + BonemealAPI.addLandGrass(EndBlocks.LUTEBUS, EndBlocks.RUTISCUS, 0.2F); + BonemealAPI.addLandGrass(EndBlocks.LAMELLARIUM, EndBlocks.RUTISCUS); + + BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.AERIDIUM, EndBlocks.RUTISCUS, 0.2F); + BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.LAMELLARIUM, EndBlocks.RUTISCUS); + BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.BOLUX_MUSHROOM, EndBlocks.RUTISCUS, 0.05F); + + BonemealAPI.addLandGrass( + EndBlocks.GLOBULAGUS, + EndBlocks.SANGNUM, + EndBlocks.MOSSY_OBSIDIAN, + EndBlocks.MOSSY_DRAGON_BONE + ); + BonemealAPI.addLandGrass( + EndBlocks.CLAWFERN, + EndBlocks.SANGNUM, + EndBlocks.MOSSY_OBSIDIAN, + EndBlocks.MOSSY_DRAGON_BONE + ); + BonemealAPI.addLandGrass(EndBlocks.SANGNUM, EndBlocks.SMALL_AMARANITA_MUSHROOM, 0.1F); + BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_OBSIDIAN, 0.1F); + BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_DRAGON_BONE, 0.1F); + + BonemealAPI.addLandGrass(EndBlocks.GLOBULAGUS, EndBlocks.MOSSY_DRAGON_BONE); + BonemealAPI.addLandGrass(EndBlocks.CLAWFERN, EndBlocks.MOSSY_DRAGON_BONE); + BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_DRAGON_BONE, 0.1F); + + BonemealAPI.addLandGrass(EndBlocks.GLOBULAGUS, EndBlocks.MOSSY_OBSIDIAN); + BonemealAPI.addLandGrass(EndBlocks.CLAWFERN, EndBlocks.MOSSY_OBSIDIAN); + BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_OBSIDIAN, 0.1F); + + Block[] charnias = new Block[]{ + EndBlocks.CHARNIA_CYAN, + EndBlocks.CHARNIA_GREEN, + EndBlocks.CHARNIA_ORANGE, + EndBlocks.CHARNIA_LIGHT_BLUE, + EndBlocks.CHARNIA_PURPLE, + EndBlocks.CHARNIA_RED + }; + List terrain = Lists.newArrayList(); + EndBlocks.getModBlocks().forEach(block -> { + if (block instanceof EndTerrainBlock) { + terrain.add(block); + } + }); + terrain.add(Blocks.END_STONE); + terrain.add(EndBlocks.ENDSTONE_DUST); + terrain.add(EndBlocks.CAVE_MOSS); + terrain.add(EndBlocks.SULPHURIC_ROCK.stone); + terrain.add(EndBlocks.VIOLECITE.stone); + terrain.add(EndBlocks.FLAVOLITE.stone); + terrain.add(EndBlocks.AZURE_JADESTONE.stone); + terrain.add(EndBlocks.VIRID_JADESTONE.stone); + terrain.add(EndBlocks.SANDY_JADESTONE.stone); + terrain.add(EndBlocks.BRIMSTONE); + Block[] terrainBlocks = terrain.toArray(new Block[terrain.size()]); + for (Block charnia : charnias) { + BonemealAPI.addWaterGrass(charnia, terrainBlocks); + } + } +} diff --git a/src/main/java/org/betterx/betterend/util/GlobalState.java b/src/main/java/org/betterx/betterend/util/GlobalState.java new file mode 100644 index 00000000..49650746 --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/GlobalState.java @@ -0,0 +1,13 @@ +package org.betterx.betterend.util; + +import net.minecraft.core.BlockPos.MutableBlockPos; + +public class GlobalState { + private static final ThreadLocal STATE = ThreadLocal.withInitial(() -> new GlobalState()); + + public static GlobalState stateForThread() { + return STATE.get(); + } + + public final MutableBlockPos POS = new MutableBlockPos(); +} diff --git a/src/main/java/org/betterx/betterend/util/LangUtil.java b/src/main/java/org/betterx/betterend/util/LangUtil.java new file mode 100644 index 00000000..1a0f5d41 --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/LangUtil.java @@ -0,0 +1,40 @@ +package org.betterx.betterend.util; + +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + + +public class LangUtil { + public final static String CONFIG_ELEMENT = "configuration"; + + private String element; + + public LangUtil(String element) { + this.element = element; + } + + public void setElement(String key) { + this.element = key; + } + + public String getString(String key) { + return getString(element, key); + } + + public MutableComponent getText(String key) { + return getText(element, key); + } + + public static String translate(String key) { + return I18n.get(key); + } + + public static String getString(String element, String key) { + return translate(String.format("%s.%s", element, key)); + } + + public static MutableComponent getText(String element, String key) { + return Component.translatable(getString(element, key)); + } +} diff --git a/src/main/java/org/betterx/betterend/util/LootTableUtil.java b/src/main/java/org/betterx/betterend/util/LootTableUtil.java new file mode 100644 index 00000000..63a7f3bd --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/LootTableUtil.java @@ -0,0 +1,153 @@ +package org.betterx.betterend.util; + +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceCondition; +import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; +import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; + +import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder; +import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder; +import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.complexmaterials.WoodenComplexMaterial; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndItems; + +public class LootTableUtil { + private static final ResourceLocation END_CITY_TREASURE_ID = new ResourceLocation("chests/end_city_treasure"); + private static final ResourceLocation COMMON = BetterEnd.makeID("chests/common"); + private static final ResourceLocation FOGGY_MUSHROOMLAND = BetterEnd.makeID("chests/foggy_mushroomland"); + private static final ResourceLocation CHORUS_FOREST = BetterEnd.makeID("chests/chorus_forest"); + private static final ResourceLocation SHADOW_FOREST = BetterEnd.makeID("chests/shadow_forest"); + private static final ResourceLocation LANTERN_WOODS = BetterEnd.makeID("chests/lantern_woods"); + private static final ResourceLocation UMBRELLA_JUNGLE = BetterEnd.makeID("chests/umbrella_jungle"); + + public static void init() { + LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, table, setter) -> { + if (END_CITY_TREASURE_ID.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(ConstantValue.exactly(1)); + builder.withCondition(LootItemRandomChanceCondition.randomChance(0.2f).build()); + builder.withEntry(LootItem.lootTableItem(Items.GHAST_TEAR).build()); + table.withPool(builder); + + builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(0, 3)); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_STRANGE_AND_ALIEN).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_GRASPING_AT_STARS).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_ENDSEEKER).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_EO_DRACONA).build()); + table.withPool(builder); + } else if (id.getNamespace().equals(BetterEnd.MOD_ID)) { + addCommonItems(table); + if (FOGGY_MUSHROOMLAND.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.MOSSY_GLOWSHROOM.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)) + .build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.MOSSY_GLOWSHROOM_SAPLING).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.BLUE_VINE_SEED).build()); + table.withPool(builder); + } else if (CHORUS_FOREST.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.PYTHADENDRON.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)) + .build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.PYTHADENDRON_SAPLING).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.CHORUS_MUSHROOM).build()); + table.withPool(builder); + } else if (SHADOW_FOREST.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.DRAGON_TREE.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)) + .build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.DRAGON_TREE_SAPLING).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.SHADOW_BERRY).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.SHADOW_BERRY_RAW).build()); + table.withPool(builder); + } else if (LANTERN_WOODS.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.LUCERNIA.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)) + .build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.LUCERNIA_SAPLING).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.BOLUX_MUSHROOM).build()); + table.withPool(builder); + } else if (UMBRELLA_JUNGLE.equals(id)) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.UMBRELLA_TREE.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)) + .build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.UMBRELLA_TREE_SAPLING).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.SMALL_JELLYSHROOM).build()); + table.withPool(builder); + } + } + }); + } + + public static ResourceLocation getTable(Holder biome) { + BCLBiome bclBiome = BiomeAPI.getBiome(biome.value()); + if (bclBiome == EndBiomes.FOGGY_MUSHROOMLAND) { + return FOGGY_MUSHROOMLAND; + } else if (bclBiome == EndBiomes.CHORUS_FOREST) { + return CHORUS_FOREST; + } else if (bclBiome == EndBiomes.SHADOW_FOREST) { + return SHADOW_FOREST; + } else if (bclBiome == EndBiomes.LANTERN_WOODS) { + return LANTERN_WOODS; + } else if (bclBiome == EndBiomes.UMBRELLA_JUNGLE) { + return UMBRELLA_JUNGLE; + } + return COMMON; + } + + private static void addCommonItems(FabricLootSupplierBuilder table) { + FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(0, 2)); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_STRANGE_AND_ALIEN).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_GRASPING_AT_STARS).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_ENDSEEKER).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_EO_DRACONA).build()); + table.withPool(builder); + + builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(4, 8)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.ingot).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.rawOre).build()); + builder.withEntry(LootItem.lootTableItem(Items.ENDER_PEARL).build()); + table.withPool(builder); + + builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(2, 4)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.TERMINITE.ingot).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.ENDER_SHARD).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.AURORA_CRYSTAL).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.axe).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.pickaxe).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.hoe).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.sword).build()); + builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.shovel).build()); + builder.withEntry(LootItem.lootTableItem(Items.ENDER_EYE).build()); + builder.withEntry(LootItem.lootTableItem(Blocks.OBSIDIAN).build()); + table.withPool(builder); + + builder = FabricLootPoolBuilder.builder(); + builder.setRolls(UniformGenerator.between(0, 4)); + builder.withEntry(LootItem.lootTableItem(EndBlocks.FLAVOLITE_RUNED).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.AETERNIUM_INGOT).build()); + builder.withEntry(LootItem.lootTableItem(EndItems.AMBER_GEM).build()); + builder.withEntry(LootItem.lootTableItem(Items.END_CRYSTAL).build()); + builder.withEntry(LootItem.lootTableItem(Items.GHAST_TEAR).build()); + table.withPool(builder); + } +} diff --git a/src/main/java/org/betterx/betterend/util/StructureErode.java b/src/main/java/org/betterx/betterend/util/StructureErode.java new file mode 100644 index 00000000..f12f35d2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/util/StructureErode.java @@ -0,0 +1,277 @@ +package org.betterx.betterend.util; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Sets; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; + +import java.util.Set; + +public class StructureErode { + private static final Direction[] DIR = BlocksHelper.makeHorizontal(); + + public static void erode(WorldGenLevel world, BoundingBox bounds, int iterations, RandomSource random) { + MutableBlockPos mut = new MutableBlockPos(); + boolean canDestruct = true; + for (int i = 0; i < iterations; i++) { + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + boolean ignore = ignore(state, world, mut); + if (canDestruct && BlocksHelper.isInvulnerable( + state, + world, + mut + ) && random.nextInt(8) == 0 && world.isEmptyBlock( + mut.below(2))) { + int r = MHelper.randRange(1, 4, random); + int cx = mut.getX(); + int cy = mut.getY(); + int cz = mut.getZ(); + int x1 = cx - r; + int y1 = cy - r; + int z1 = cz - r; + int x2 = cx + r; + int y2 = cy + r; + int z2 = cz + r; + for (int px = x1; px <= x2; px++) { + int dx = px - cx; + dx *= dx; + mut.setX(px); + for (int py = y1; py <= y2; py++) { + int dy = py - cy; + dy *= dy; + mut.setY(py); + for (int pz = z1; pz <= z2; pz++) { + int dz = pz - cz; + dz *= dz; + mut.setZ(pz); + if (dx + dy + dz <= r && BlocksHelper.isInvulnerable( + world.getBlockState(mut), + world, + mut + )) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + mut.setX(cx); + mut.setY(cy); + mut.setZ(cz); + canDestruct = false; + continue; + } else if (ignore) { + continue; + } + if (!state.isAir() && random.nextBoolean()) { + MHelper.shuffle(DIR, random); + for (Direction dir : DIR) { + if (world.isEmptyBlock(mut.relative(dir)) && world.isEmptyBlock(mut.below() + .relative(dir))) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + mut.move(dir).move(Direction.DOWN); + for (int py = mut.getY(); y >= bounds.minY() - 10; y--) { + mut.setY(py - 1); + if (!world.isEmptyBlock(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + break; + } else if (random.nextInt(8) == 0 && !BlocksHelper.isInvulnerable( + world.getBlockState(mut.above()), + world, + mut + )) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + } + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && world.isEmptyBlock(mut.below())) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + for (int py = mut.getY(); py >= bounds.minY() - 10; py--) { + mut.setY(py - 1); + if (!world.isEmptyBlock(mut)) { + mut.setY(py); + BlocksHelper.setWithoutUpdate(world, mut, state); + break; + } + } + } + } + } + } + } + + public static void erodeIntense(WorldGenLevel world, BoundingBox bounds, RandomSource random) { + MutableBlockPos mut = new MutableBlockPos(); + MutableBlockPos mut2 = new MutableBlockPos(); + int minY = bounds.minY() - 10; + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut)) { + if (random.nextInt(6) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + if (random.nextBoolean()) { + int px = MHelper.floor(random.nextGaussian() * 2 + x + 0.5); + int pz = MHelper.floor(random.nextGaussian() * 2 + z + 0.5); + mut2.set(px, y, pz); + while (world.getBlockState(mut2).getMaterial().isReplaceable() && mut2.getY() > minY) { + mut2.setY(mut2.getY() - 1); + } + if (!world.getBlockState(mut2).isAir() && state.canSurvive(world, mut2)) { + mut2.setY(mut2.getY() + 1); + BlocksHelper.setWithoutUpdate(world, mut2, state); + } + } + } else if (random.nextInt(8) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + } + } + } + } + } + + drop(world, bounds); + } + + private static void drop(WorldGenLevel world, BoundingBox bounds) { + MutableBlockPos mut = new MutableBlockPos(); + + Set blocks = Sets.newHashSet(); + Set edge = Sets.newHashSet(); + Set add = Sets.newHashSet(); + + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.minY(); y <= bounds.maxY(); y++) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && isTerrainNear(world, mut)) { + edge.add(mut.immutable()); + } + } + } + } + + if (edge.isEmpty()) { + return; + } + + while (!edge.isEmpty()) { + for (BlockPos center : edge) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + BlockState state = world.getBlockState(center); + if (state.isCollisionShapeFullBlock(world, center)) { + mut.set(center).move(dir); + if (bounds.isInside(mut)) { + state = world.getBlockState(mut); + if (!ignore(state, world, mut) && !blocks.contains(mut)) { + add.add(mut.immutable()); + } + } + } + } + } + + blocks.addAll(edge); + edge.clear(); + edge.addAll(add); + add.clear(); + } + + int minY = bounds.minY() - 10; + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + for (int y = bounds.minY(); y <= bounds.maxY(); y++) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (!ignore(state, world, mut) && !blocks.contains(mut)) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); + while (world.getBlockState(mut).getMaterial().isReplaceable() && mut.getY() > minY) { + mut.setY(mut.getY() - 1); + } + if (mut.getY() > minY) { + mut.setY(mut.getY() + 1); + BlocksHelper.setWithoutUpdate(world, mut, state); + } + } + } + } + } + } + + private static boolean ignore(BlockState state, WorldGenLevel world, BlockPos pos) { + if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(BlockTags.NYLIUM)) { + return true; + } + return !state.getMaterial().equals(Material.STONE) || BlocksHelper.isInvulnerable(state, world, pos); + } + + private static boolean isTerrainNear(WorldGenLevel world, BlockPos pos) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (world.getBlockState(pos.relative(dir)).is(CommonBlockTags.GEN_END_STONES)) { + return true; + } + } + return false; + } + + public static void cover(WorldGenLevel world, BoundingBox bounds, RandomSource random, BlockState defaultBlock) { + MutableBlockPos mut = new MutableBlockPos(); + for (int x = bounds.minX(); x <= bounds.maxX(); x++) { + mut.setX(x); + for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { + mut.setZ(z); + BlockState top = BiomeAPI.findTopMaterial(world.getBiome(mut)).orElse(defaultBlock); + for (int y = bounds.maxY(); y >= bounds.minY(); y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (state.is(CommonBlockTags.END_STONES) && !world.getBlockState(mut.above()) + .getMaterial() + .isSolidBlocking()) { + BlocksHelper.setWithoutUpdate(world, mut, top); + } + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/EndBiome.java b/src/main/java/org/betterx/betterend/world/biome/EndBiome.java new file mode 100644 index 00000000..fcd0dd14 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/EndBiome.java @@ -0,0 +1,182 @@ +package org.betterx.betterend.world.biome; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.surface.SurfaceRuleBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.registry.EndTags; + +public class EndBiome extends BCLBiome implements SurfaceMaterialProvider { + public static class DefaultSurfaceMaterialProvider implements SurfaceMaterialProvider { + public static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); + + @Override + public BlockState getTopMaterial() { + return getUnderMaterial(); + } + + @Override + public BlockState getAltTopMaterial() { + return getTopMaterial(); + } + + @Override + public BlockState getUnderMaterial() { + return END_STONE; + } + + @Override + public boolean generateFloorRule() { + return true; + } + + @Override + public SurfaceRuleBuilder surface() { + SurfaceRuleBuilder builder = SurfaceRuleBuilder.start(); + + if (generateFloorRule() && getTopMaterial() != getUnderMaterial()) { + if (getTopMaterial() != getAltTopMaterial()) { + builder.floor(getTopMaterial()); + } else { + builder.chancedFloor(getTopMaterial(), getAltTopMaterial()); + } + } + return builder.filler(getUnderMaterial()); + } + } + + public abstract static class Config { + public static final SurfaceMaterialProvider DEFAULT_MATERIAL = new DefaultSurfaceMaterialProvider(); + + protected static final SurfaceRules.RuleSource END_STONE = SurfaceRules.state(DefaultSurfaceMaterialProvider.END_STONE); + protected static final SurfaceRules.RuleSource END_MOSS = SurfaceRules.state(EndBlocks.END_MOSS.defaultBlockState()); + protected static final SurfaceRules.RuleSource ENDSTONE_DUST = SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()); + protected static final SurfaceRules.RuleSource END_MYCELIUM = SurfaceRules.state(EndBlocks.END_MYCELIUM.defaultBlockState()); + protected static final SurfaceRules.RuleSource FLAVOLITE = SurfaceRules.state(EndBlocks.FLAVOLITE.stone.defaultBlockState()); + protected static final SurfaceRules.RuleSource SULPHURIC_ROCK = SurfaceRules.state(EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState()); + protected static final SurfaceRules.RuleSource BRIMSTONE = SurfaceRules.state(EndBlocks.BRIMSTONE.defaultBlockState()); + protected static final SurfaceRules.RuleSource PALLIDIUM_FULL = SurfaceRules.state(EndBlocks.PALLIDIUM_FULL.defaultBlockState()); + protected static final SurfaceRules.RuleSource PALLIDIUM_HEAVY = SurfaceRules.state(EndBlocks.PALLIDIUM_HEAVY.defaultBlockState()); + protected static final SurfaceRules.RuleSource PALLIDIUM_THIN = SurfaceRules.state(EndBlocks.PALLIDIUM_THIN.defaultBlockState()); + protected static final SurfaceRules.RuleSource PALLIDIUM_TINY = SurfaceRules.state(EndBlocks.PALLIDIUM_TINY.defaultBlockState()); + protected static final SurfaceRules.RuleSource UMBRALITH = SurfaceRules.state(EndBlocks.UMBRALITH.stone.defaultBlockState()); + + public final ResourceLocation ID; + + protected Config(String name) { + this.ID = BetterEnd.makeID(name); + } + + protected abstract void addCustomBuildData(BCLBiomeBuilder builder); + + public BiomeSupplier getSupplier() { + return EndBiome::new; + } + + protected boolean hasCaves() { + return true; + } + + protected SurfaceMaterialProvider surfaceMaterial() { + return DEFAULT_MATERIAL; + } + } + + public EndBiome(ResourceLocation biomeID, Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + } + + public static EndBiome create(Config biomeConfig) { + BCLBiomeBuilder builder = BCLBiomeBuilder + .start(biomeConfig.ID) + .music(SoundEvents.MUSIC_END) + .waterColor(4159204) + .waterFogColor(329011) + .fogColor(0xA080A0) + .skyColor(0) + .mood(EndSounds.AMBIENT_DUST_WASTELANDS) + .temperature(0.5f) + .wetness(0.5f) + .precipitation(Biome.Precipitation.NONE) + .surface(biomeConfig.surfaceMaterial().surface().build()); + + biomeConfig.addCustomBuildData(builder); + EndFeatures.addDefaultFeatures(builder, biomeConfig.hasCaves()); + + + EndBiome biome = builder.build(biomeConfig.getSupplier()); + biome.addCustomData("has_caves", biomeConfig.hasCaves()); + biome.setSurfaceMaterial(biomeConfig.surfaceMaterial()); + + EndTags.addBiomeSurfaceToEndGroup(biome); + return biome; + } + + + private SurfaceMaterialProvider surfMatProv = Config.DEFAULT_MATERIAL; + + private void setSurfaceMaterial(SurfaceMaterialProvider prov) { + surfMatProv = prov; + } + + @Override + public BlockState getTopMaterial() { + return surfMatProv.getTopMaterial(); + } + + @Override + public BlockState getUnderMaterial() { + return surfMatProv.getUnderMaterial(); + } + + @Override + public BlockState getAltTopMaterial() { + return surfMatProv.getAltTopMaterial(); + } + + @Override + public boolean generateFloorRule() { + return surfMatProv.generateFloorRule(); + } + + @Override + public SurfaceRuleBuilder surface() { + return surfMatProv.surface(); + } + + public static BlockState findTopMaterial(BCLBiome biome) { + return BiomeAPI.findTopMaterial(biome).orElse(EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); + } + + public static BlockState findTopMaterial(Biome biome) { + return findTopMaterial(BiomeAPI.getBiome(biome)); + } + + public static BlockState findTopMaterial(WorldGenLevel world, BlockPos pos) { + return findTopMaterial(BiomeAPI.getBiome(world.getBiome(pos))); + } + + public static BlockState findUnderMaterial(BCLBiome biome) { + return BiomeAPI.findUnderMaterial(biome).orElse(EndBiome.Config.DEFAULT_MATERIAL.getUnderMaterial()); + } + + public static BlockState findUnderMaterial(WorldGenLevel world, BlockPos pos) { + return findUnderMaterial(BiomeAPI.getBiome(world.getBiome(pos))); + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/air/BiomeIceStarfield.java b/src/main/java/org/betterx/betterend/world/biome/air/BiomeIceStarfield.java new file mode 100644 index 00000000..413a0f6e --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/air/BiomeIceStarfield.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.world.biome.air; + +import net.minecraft.world.entity.EntityType; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.biome.EndBiome; + +public class BiomeIceStarfield extends EndBiome.Config { + public BiomeIceStarfield() { + super("ice_starfield"); + } + + @Override + protected boolean hasCaves() { + return false; + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder.structure(EndStructures.GIANT_ICE_STAR) + .fogColor(224, 245, 254) + .temperature(0F) + .fogDensity(2.2F) + .foliageColor(193, 244, 244) + .genChance(0.25F) + .particles(EndParticles.SNOWFLAKE, 0.002F) + .feature(EndFeatures.ICE_STAR) + .feature(EndFeatures.ICE_STAR_SMALL) + .spawn(EntityType.ENDERMAN, 20, 1, 4); + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/EmptyAuroraCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/EmptyAuroraCaveBiome.java new file mode 100644 index 00000000..bcb13196 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/EmptyAuroraCaveBiome.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.resources.ResourceLocation; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.world.biome.EndBiome; + +public class EmptyAuroraCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1); + + this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); + } + + @Override + public float getFloorDensity() { + return 0.01F; + } + + @Override + public float getCeilDensity() { + return 0.1F; + } + } + + public EmptyAuroraCaveBiome() { + super("empty_aurora_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogColor(150, 30, 68) + .fogDensity(2.0F) + .plantsColor(108, 25, 46) + .waterAndFogColor(186, 77, 237) + .particles(EndParticles.GLOWING_SPHERE, 0.001F); + } + + @Override + public BiomeSupplier getSupplier() { + return EmptyAuroraCaveBiome.Biome::new; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/EmptyEndCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/EmptyEndCaveBiome.java new file mode 100644 index 00000000..bdaee224 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/EmptyEndCaveBiome.java @@ -0,0 +1,45 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.resources.ResourceLocation; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.world.biome.EndBiome; + +public class EmptyEndCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE, 1); + this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); + } + + @Override + public float getFloorDensity() { + return 0.1F; + } + + @Override + public float getCeilDensity() { + return 0.1F; + } + } + + public EmptyEndCaveBiome() { + super("empty_end_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogDensity(2.0F); + } + + @Override + public BiomeSupplier getSupplier() { + return Biome::new; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java new file mode 100644 index 00000000..48754cb2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.resources.ResourceLocation; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.world.biome.EndBiome; + +public class EmptySmaragdantCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1); + this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20); + + this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); + } + + @Override + public float getFloorDensity() { + return 0.1F; + } + + @Override + public float getCeilDensity() { + return 0.1F; + } + } + + public EmptySmaragdantCaveBiome() { + super("empty_smaragdant_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogColor(0, 253, 182) + .fogDensity(2.0F) + .plantsColor(0, 131, 145) + .waterAndFogColor(31, 167, 212) + .particles(EndParticles.SMARAGDANT, 0.001F); + } + + @Override + public BiomeSupplier getSupplier() { + return EmptySmaragdantCaveBiome.Biome::new; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/EndCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/EndCaveBiome.java new file mode 100644 index 00000000..1d9d6bed --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/EndCaveBiome.java @@ -0,0 +1,95 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.feature.Feature; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.features.BCLCommonFeatures; +import org.betterx.bclib.util.WeightedList; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.bclib.world.features.BCLFeature; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.features.terrain.caves.CaveChunkPopulatorFeature; + +public class EndCaveBiome extends EndBiome { + public static abstract class Config extends EndBiome.Config { + protected Config(String name) { + super(name); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + BCLFeature feature = BCLCommonFeatures.makeChunkFeature( + BetterEnd.makeID(ID.getPath() + "_cave_populator"), + GenerationStep.Decoration.RAW_GENERATION, + new CaveChunkPopulatorFeature(() -> (EndCaveBiome) BiomeAPI.getBiome(ID)) + ); + + builder.feature(feature) + .music(EndSounds.MUSIC_CAVES) + .loop(EndSounds.AMBIENT_CAVES); + } + + @Override + protected boolean hasCaves() { + return false; + } + + @Override + public BiomeSupplier getSupplier() { + return EndCaveBiome::new; + } + } + + private final WeightedList> floorFeatures = new WeightedList>(); + private final WeightedList> ceilFeatures = new WeightedList>(); + + public EndCaveBiome(ResourceLocation biomeID, Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + } + + public void addFloorFeature(Feature feature, float weight) { + floorFeatures.add(feature, weight); + } + + public void addCeilFeature(Feature feature, float weight) { + ceilFeatures.add(feature, weight); + } + + public Feature getFloorFeature(RandomSource random) { + return floorFeatures.isEmpty() ? null : floorFeatures.get(random); + } + + public Feature getCeilFeature(RandomSource random) { + return ceilFeatures.isEmpty() ? null : ceilFeatures.get(random); + } + + public float getFloorDensity() { + return 0; + } + + public float getCeilDensity() { + return 0; + } + + public BlockState getCeil(BlockPos pos) { + return null; + } + + public BlockState getWall(BlockPos pos) { + return null; + } + + public static EndCaveBiome create(EndBiome.Config biomeConfig) { + return (EndCaveBiome) EndBiome.create(biomeConfig); + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/JadeCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/JadeCaveBiome.java new file mode 100644 index 00000000..8d99f6fd --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/JadeCaveBiome.java @@ -0,0 +1,55 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.world.biome.EndBiome; + +public class JadeCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + private static final OpenSimplexNoise WALL_NOISE = new OpenSimplexNoise("jade_cave".hashCode()); + private static final OpenSimplexNoise DEPTH_NOISE = new OpenSimplexNoise("depth_noise".hashCode()); + private static final BlockState[] JADE = new BlockState[3]; + + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + JADE[0] = EndBlocks.VIRID_JADESTONE.stone.defaultBlockState(); + JADE[1] = EndBlocks.AZURE_JADESTONE.stone.defaultBlockState(); + JADE[2] = EndBlocks.SANDY_JADESTONE.stone.defaultBlockState(); + } + + @Override + public BlockState getWall(BlockPos pos) { + double depth = DEPTH_NOISE.eval(pos.getX() * 0.02, pos.getZ() * 0.02) * 0.2 + 0.5; + int index = Mth.floor((pos.getY() + WALL_NOISE.eval(pos.getX() * 0.2, + pos.getZ() * 0.2) * 1.5) * depth + 0.5); + index = Mth.abs(index) % 3; + return JADE[index]; + } + } + + public JadeCaveBiome() { + super("jade_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogColor(118, 150, 112) + .fogDensity(2.0F) + .waterAndFogColor(95, 223, 255); + } + + @Override + public BiomeSupplier getSupplier() { + return JadeCaveBiome.Biome::new; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/LushAuroraCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/LushAuroraCaveBiome.java new file mode 100644 index 00000000..e8caa985 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/LushAuroraCaveBiome.java @@ -0,0 +1,80 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.world.biome.EndBiome; + +public class LushAuroraCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1); + this.addFloorFeature(EndFeatures.CAVE_BUSH, 5); + this.addFloorFeature(EndFeatures.CAVE_GRASS, 40); + this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE_CAVEMOSS, 5); + + this.addCeilFeature(EndFeatures.CAVE_BUSH, 1); + this.addCeilFeature(EndFeatures.CAVE_PUMPKIN, 1); + this.addCeilFeature(EndFeatures.RUBINEA, 3); + this.addCeilFeature(EndFeatures.MAGNULA, 1); + this.addCeilFeature(EndFeatures.END_STONE_STALACTITE_CAVEMOSS, 10); + } + + @Override + public float getFloorDensity() { + return 0.2F; + } + + @Override + public float getCeilDensity() { + return 0.1F; + } + + @Override + public BlockState getCeil(BlockPos pos) { + return EndBlocks.CAVE_MOSS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP); + } + } + + public LushAuroraCaveBiome() { + super("lush_aurora_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogColor(150, 30, 68) + .fogDensity(2.0F) + .plantsColor(108, 25, 46) + .waterAndFogColor(186, 77, 237) + .particles(EndParticles.GLOWING_SPHERE, 0.001F) + ; + } + + @Override + public BiomeSupplier getSupplier() { + return LushAuroraCaveBiome.Biome::new; + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.CAVE_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/cave/LushSmaragdantCaveBiome.java b/src/main/java/org/betterx/betterend/world/biome/cave/LushSmaragdantCaveBiome.java new file mode 100644 index 00000000..1eb1c016 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/cave/LushSmaragdantCaveBiome.java @@ -0,0 +1,65 @@ +package org.betterx.betterend.world.biome.cave; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.bclib.world.biomes.BCLBiomeSettings; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.world.biome.EndBiome; + +public class LushSmaragdantCaveBiome extends EndCaveBiome.Config { + public static class Biome extends EndCaveBiome { + public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { + super(biomeID, biome, settings); + + this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1); + this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20); + + this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); + } + + @Override + public float getFloorDensity() { + return 0.1F; + } + + @Override + public float getCeilDensity() { + return 0.1F; + } + } + + public LushSmaragdantCaveBiome() { + super("lush_smaragdant_cave"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + super.addCustomBuildData(builder); + builder.fogColor(0, 253, 182) + .fogDensity(2.0F) + .plantsColor(0, 131, 145) + .waterAndFogColor(31, 167, 212) + .particles(EndParticles.SMARAGDANT, 0.001F); + } + + @Override + public BiomeSupplier getSupplier() { + return LushSmaragdantCaveBiome.Biome::new; + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.CAVE_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/AmberLandBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/AmberLandBiome.java new file mode 100644 index 00000000..9cc186e1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/AmberLandBiome.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.biome.EndBiome; + +public class AmberLandBiome extends EndBiome.Config { + public AmberLandBiome() { + super("amber_land"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(255, 184, 71) + .fogDensity(2.0F) + .plantsColor(219, 115, 38) + .waterAndFogColor(145, 108, 72) + .music(EndSounds.MUSIC_FOREST) + .loop(EndSounds.AMBIENT_AMBER_LAND) + .particles(EndParticles.AMBER_SPHERE, 0.001F) + .feature(EndFeatures.AMBER_ORE) + .feature(EndFeatures.END_LAKE_RARE) + .feature(EndFeatures.HELIX_TREE) + .feature(EndFeatures.LANCELEAF) + .feature(EndFeatures.GLOW_PILLAR) + .feature(EndFeatures.AMBER_GRASS) + .feature(EndFeatures.AMBER_ROOT) + .feature(EndFeatures.BULB_MOSS) + .feature(EndFeatures.BULB_MOSS_WOOD) + .feature(EndFeatures.CHARNIA_ORANGE) + .feature(EndFeatures.CHARNIA_RED) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 4) + .spawn(EndEntities.END_SLIME, 30, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.AMBER_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/BlossomingSpiresBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/BlossomingSpiresBiome.java new file mode 100644 index 00000000..9b1aaf05 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/BlossomingSpiresBiome.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class BlossomingSpiresBiome extends EndBiome.Config { + public BlossomingSpiresBiome() { + super("blossoming_spires"); + } + + @Override + protected boolean hasCaves() { + return false; + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(241, 146, 229) + .fogDensity(1.7F) + .plantsColor(122, 45, 122) + .music(EndSounds.MUSIC_FOREST) + .loop(EndSounds.AMBIENT_BLOSSOMING_SPIRES) + .feature(EndFeatures.SPIRE) + .feature(EndFeatures.FLOATING_SPIRE) + .feature(EndFeatures.TENANEA) + .feature(EndFeatures.TENANEA_BUSH) + .feature(EndFeatures.BULB_VINE) + .feature(EndFeatures.BUSHY_GRASS) + .feature(EndFeatures.BUSHY_GRASS_WG) + .feature(EndFeatures.BLOSSOM_BERRY) + .feature(EndFeatures.TWISTED_MOSS) + .feature(EndFeatures.TWISTED_MOSS_WOOD) + .feature(EndFeatures.SILK_MOTH_NEST) + .spawn(EntityType.ENDERMAN, 50, 1, 4) + .spawn(EndEntities.SILK_MOTH, 5, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.PINK_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/ChorusForestBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/ChorusForestBiome.java new file mode 100644 index 00000000..4642efd1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/ChorusForestBiome.java @@ -0,0 +1,59 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.data.worldgen.placement.EndPlacements; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class ChorusForestBiome extends EndBiome.Config { + public ChorusForestBiome() { + super("chorus_forest"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(87, 26, 87) + .fogDensity(1.5F) + .plantsColor(122, 45, 122) + .waterAndFogColor(73, 30, 73) + .particles(ParticleTypes.PORTAL, 0.01F) + .loop(EndSounds.AMBIENT_CHORUS_FOREST) + .music(EndSounds.MUSIC_DARK) + .feature(EndFeatures.VIOLECITE_LAYER) + .feature(EndFeatures.END_LAKE_RARE) + .feature(EndFeatures.PYTHADENDRON_TREE) + .feature(EndFeatures.PYTHADENDRON_BUSH) + .feature(EndFeatures.PURPLE_POLYPORE) + .feature(Decoration.VEGETAL_DECORATION, EndPlacements.CHORUS_PLANT) + .feature(EndFeatures.CHORUS_GRASS) + .feature(EndFeatures.CHORUS_MUSHROOM) + .feature(EndFeatures.TAIL_MOSS) + .feature(EndFeatures.TAIL_MOSS_WOOD) + .feature(EndFeatures.CHARNIA_PURPLE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EndEntities.END_SLIME, 5, 1, 2) + .spawn(EntityType.ENDERMAN, 50, 1, 4); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.CHORUS_NYLIUM.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/CrystalMountainsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/CrystalMountainsBiome.java new file mode 100644 index 00000000..b7eff3bb --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/CrystalMountainsBiome.java @@ -0,0 +1,38 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.biome.EndBiome; + +public class CrystalMountainsBiome extends EndBiome.Config { + public CrystalMountainsBiome() { + super("crystal_mountains"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .structure(EndStructures.MOUNTAIN) + .plantsColor(255, 133, 211) + .music(EndSounds.MUSIC_OPENSPACE) + .feature(EndFeatures.CRYSTAL_GRASS) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.CRYSTAL_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/DragonGraveyardsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/DragonGraveyardsBiome.java new file mode 100644 index 00000000..65270b9c --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/DragonGraveyardsBiome.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class DragonGraveyardsBiome extends EndBiome.Config { + public DragonGraveyardsBiome() { + super("dragon_graveyards"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .genChance(0.1f) + .fogColor(244, 46, 79) + .fogDensity(1.3F) + .particles(EndParticles.FIREFLY, 0.0007F) + .music(EndSounds.MUSIC_OPENSPACE) + .loop(EndSounds.AMBIENT_GLOWING_GRASSLANDS) + .waterAndFogColor(203, 59, 167) + .plantsColor(244, 46, 79) + .feature(EndFeatures.OBSIDIAN_PILLAR_BASEMENT) + .feature(EndFeatures.DRAGON_BONE_BLOCK_ORE) + .feature(EndFeatures.FALLEN_PILLAR) + .feature(EndFeatures.OBSIDIAN_BOULDER) + .feature(EndFeatures.GIGANTIC_AMARANITA) + .feature(EndFeatures.LARGE_AMARANITA) + .feature(EndFeatures.SMALL_AMARANITA) + .feature(EndFeatures.GLOBULAGUS) + .feature(EndFeatures.CLAWFERN) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.SANGNUM.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/DryShrublandBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/DryShrublandBiome.java new file mode 100644 index 00000000..dc21fb39 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/DryShrublandBiome.java @@ -0,0 +1,45 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class DryShrublandBiome extends EndBiome.Config { + public DryShrublandBiome() { + super("dry_shrubland"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(132, 35, 13) + .fogDensity(1.2F) + .waterAndFogColor(113, 88, 53) + .plantsColor(237, 122, 66) + .music(EndSounds.MUSIC_OPENSPACE) + .feature(EndFeatures.LUCERNIA_BUSH_RARE) + .feature(EndFeatures.ORANGO) + .feature(EndFeatures.AERIDIUM) + .feature(EndFeatures.LUTEBUS) + .feature(EndFeatures.LAMELLARIUM) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.RUTISCUS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/DustWastelandsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/DustWastelandsBiome.java new file mode 100644 index 00000000..e9668e75 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/DustWastelandsBiome.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.placement.CaveSurface; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.surface.SurfaceRuleBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class DustWastelandsBiome extends EndBiome.Config { + public DustWastelandsBiome() { + super("dust_wastelands"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(226, 239, 168) + .fogDensity(2) + .waterAndFogColor(192, 180, 131) + .terrainHeight(1.5F) + .particles(ParticleTypes.WHITE_ASH, 0.01F) + .loop(EndSounds.AMBIENT_DUST_WASTELANDS) + .music(EndSounds.MUSIC_OPENSPACE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + + @Override + public SurfaceRuleBuilder surface() { + return super + .surface() + .ceil(Blocks.END_STONE.defaultBlockState()) + .rule(4, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), + SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()) + )); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/FoggyMushroomlandBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/FoggyMushroomlandBiome.java new file mode 100644 index 00000000..fefe07a3 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/FoggyMushroomlandBiome.java @@ -0,0 +1,66 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.biome.EndBiome; + +public class FoggyMushroomlandBiome extends EndBiome.Config { + public FoggyMushroomlandBiome() { + super("foggy_mushroomland"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .structure(EndStructures.GIANT_MOSSY_GLOWSHROOM) + .plantsColor(73, 210, 209) + .fogColor(41, 122, 173) + .fogDensity(3) + .waterAndFogColor(119, 227, 250) + .particles(EndParticles.GLOWING_SPHERE, 0.001F) + .loop(EndSounds.AMBIENT_FOGGY_MUSHROOMLAND) + .music(EndSounds.MUSIC_FOREST) + .feature(EndFeatures.END_LAKE) + .feature(EndFeatures.MOSSY_GLOWSHROOM) + .feature(EndFeatures.BLUE_VINE) + .feature(EndFeatures.UMBRELLA_MOSS) + .feature(EndFeatures.CREEPING_MOSS) + .feature(EndFeatures.DENSE_VINE) + //.feature(EndFeatures.PEARLBERRY) + .feature(EndFeatures.CYAN_MOSS) + .feature(EndFeatures.CYAN_MOSS_WOOD) + .feature(EndFeatures.END_LILY) + .feature(EndFeatures.BUBBLE_CORAL) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_LIGHT_BLUE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EndEntities.DRAGONFLY, 80, 2, 5) + .spawn(EndEntities.END_FISH, 20, 2, 5) + .spawn(EndEntities.CUBOZOA, 10, 3, 8) + .spawn(EndEntities.END_SLIME, 10, 1, 2) + .spawn(EntityType.ENDERMAN, 10, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.END_MOSS.defaultBlockState(); + } + + @Override + public BlockState getAltTopMaterial() { + return EndBlocks.END_MYCELIUM.defaultBlockState(); + } + }; + + + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/GlowingGrasslandsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/GlowingGrasslandsBiome.java new file mode 100644 index 00000000..f190fffd --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/GlowingGrasslandsBiome.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class GlowingGrasslandsBiome extends EndBiome.Config { + public GlowingGrasslandsBiome() { + super("glowing_grasslands"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(99, 228, 247) + .fogDensity(1.3F) + .particles(EndParticles.FIREFLY, 0.001F) + .music(EndSounds.MUSIC_OPENSPACE) + .loop(EndSounds.AMBIENT_GLOWING_GRASSLANDS) + .waterAndFogColor(92, 250, 230) + .plantsColor(73, 210, 209) + .feature(EndFeatures.END_LAKE_RARE) + .feature(EndFeatures.LUMECORN) + .feature(EndFeatures.BLOOMING_COOKSONIA) + .feature(EndFeatures.SALTEAGO) + .feature(EndFeatures.VAIOLUSH_FERN) + .feature(EndFeatures.FRACTURN) + .feature(EndFeatures.UMBRELLA_MOSS_RARE) + .feature(EndFeatures.CREEPING_MOSS_RARE) + .feature(EndFeatures.TWISTED_UMBRELLA_MOSS_RARE) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_GREEN) + .feature(EndFeatures.CHARNIA_LIGHT_BLUE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.END_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/LanternWoodsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/LanternWoodsBiome.java new file mode 100644 index 00000000..5ec0ae02 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/LanternWoodsBiome.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class LanternWoodsBiome extends EndBiome.Config { + public LanternWoodsBiome() { + super("lantern_woods"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(189, 82, 70) + .fogDensity(1.1F) + .waterAndFogColor(171, 234, 226) + .plantsColor(254, 85, 57) + .music(EndSounds.MUSIC_FOREST) + .particles(EndParticles.GLOWING_SPHERE, 0.001F) + .feature(EndFeatures.END_LAKE_NORMAL) + .feature(EndFeatures.FLAMAEA) + .feature(EndFeatures.LUCERNIA) + .feature(EndFeatures.LUCERNIA_BUSH) + .feature(EndFeatures.FILALUX) + .feature(EndFeatures.AERIDIUM) + .feature(EndFeatures.LAMELLARIUM) + .feature(EndFeatures.BOLUX_MUSHROOM) + .feature(EndFeatures.AURANT_POLYPORE) + .feature(EndFeatures.POND_ANEMONE) + .feature(EndFeatures.CHARNIA_ORANGE) + .feature(EndFeatures.CHARNIA_RED) + .feature(EndFeatures.RUSCUS) + .feature(EndFeatures.RUSCUS_WOOD) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.RUTISCUS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/MegalakeBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/MegalakeBiome.java new file mode 100644 index 00000000..eb0ee1ba --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/MegalakeBiome.java @@ -0,0 +1,59 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.biome.EndBiome; + +public class MegalakeBiome extends EndBiome.Config { + public MegalakeBiome() { + super("megalake"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .structure(EndStructures.MEGALAKE) + .plantsColor(73, 210, 209) + .fogColor(178, 209, 248) + .waterAndFogColor(96, 163, 255) + .fogDensity(1.75F) + .music(EndSounds.MUSIC_WATER) + .loop(EndSounds.AMBIENT_MEGALAKE) + .terrainHeight(0F) + .feature(EndFeatures.END_LOTUS) + .feature(EndFeatures.END_LOTUS_LEAF) + .feature(EndFeatures.BUBBLE_CORAL_RARE) + .feature(EndFeatures.END_LILY_RARE) + .feature(EndFeatures.UMBRELLA_MOSS) + .feature(EndFeatures.CREEPING_MOSS) + //.feature(EndFeatures.PEARLBERRY) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_LIGHT_BLUE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .feature(EndFeatures.MENGER_SPONGE) + .spawn(EndEntities.DRAGONFLY, 50, 1, 3) + .spawn(EndEntities.END_FISH, 50, 3, 8) + .spawn(EndEntities.CUBOZOA, 50, 3, 8) + .spawn(EndEntities.END_SLIME, 5, 1, 2) + .spawn(EntityType.ENDERMAN, 10, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.END_MOSS.defaultBlockState(); + } + + @Override + public BlockState getAltTopMaterial() { + return EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/MegalakeGroveBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/MegalakeGroveBiome.java new file mode 100644 index 00000000..e4b5e414 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/MegalakeGroveBiome.java @@ -0,0 +1,56 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.biome.EndBiome; + +public class MegalakeGroveBiome extends EndBiome.Config { + public MegalakeGroveBiome() { + super("megalake_grove"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .structure(EndStructures.MEGALAKE_SMALL) + .plantsColor(73, 210, 209) + .fogColor(178, 209, 248) + .waterAndFogColor(96, 163, 255) + .fogDensity(2.0F) + .particles(EndParticles.GLOWING_SPHERE, 0.001F) + .music(EndSounds.MUSIC_WATER) + .loop(EndSounds.AMBIENT_MEGALAKE_GROVE) + .terrainHeight(0F) + .feature(EndFeatures.LACUGROVE) + .feature(EndFeatures.END_LOTUS) + .feature(EndFeatures.END_LOTUS_LEAF) + .feature(EndFeatures.BUBBLE_CORAL_RARE) + .feature(EndFeatures.END_LILY_RARE) + .feature(EndFeatures.UMBRELLA_MOSS) + //.feature(EndFeatures.PEARLBERRY) + .feature(EndFeatures.CREEPING_MOSS) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_LIGHT_BLUE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .feature(EndFeatures.MENGER_SPONGE) + .spawn(EndEntities.DRAGONFLY, 20, 1, 3) + .spawn(EndEntities.END_FISH, 20, 3, 8) + .spawn(EndEntities.CUBOZOA, 50, 3, 8) + .spawn(EndEntities.END_SLIME, 5, 1, 2) + .spawn(EntityType.ENDERMAN, 10, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.END_MOSS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/NeonOasisBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/NeonOasisBiome.java new file mode 100644 index 00000000..73e05514 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/NeonOasisBiome.java @@ -0,0 +1,82 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +import net.minecraft.world.level.levelgen.placement.CaveSurface; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.surface.SurfaceRuleBuilder; +import org.betterx.bclib.api.surface.rules.SwitchRuleSource; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.surface.SplitNoiseCondition; + +import java.util.List; + +public class NeonOasisBiome extends EndBiome.Config { + public NeonOasisBiome() { + super("neon_oasis"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .genChance(0.5F) + .fogColor(226, 239, 168) + .fogDensity(2) + .waterAndFogColor(106, 238, 215) + .particles(ParticleTypes.WHITE_ASH, 0.01F) + .loop(EndSounds.AMBIENT_DUST_WASTELANDS) + .music(EndSounds.MUSIC_OPENSPACE) + .feature(EndFeatures.DESERT_LAKE) + .feature(EndFeatures.NEON_CACTUS) + .feature(EndFeatures.UMBRELLA_MOSS) + .feature(EndFeatures.CREEPING_MOSS) + .feature(EndFeatures.CHARNIA_GREEN) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_RED) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + + @Override + public BlockState getAltTopMaterial() { + return EndBlocks.END_MOSS.defaultBlockState(); + } + + @Override + public SurfaceRuleBuilder surface() { + RuleSource surfaceBlockRule = new SwitchRuleSource( + new SplitNoiseCondition(), + List.of( + SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()), + SurfaceRules.state(EndBlocks.END_MOSS.defaultBlockState()) + ) + ); + return super + .surface() + .ceil(Blocks.END_STONE.defaultBlockState()) + .rule(1, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, surfaceBlockRule)) + .rule(4, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), + SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()) + )); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/PaintedMountainsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/PaintedMountainsBiome.java new file mode 100644 index 00000000..8814bcbe --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/PaintedMountainsBiome.java @@ -0,0 +1,41 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.biome.EndBiome; + +public class PaintedMountainsBiome extends EndBiome.Config { + public PaintedMountainsBiome() { + super("painted_mountains"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .structure(EndStructures.PAINTED_MOUNTAIN) + .fogColor(226, 239, 168) + .fogDensity(2) + .waterAndFogColor(192, 180, 131) + .music(EndSounds.MUSIC_OPENSPACE) + .loop(EndSounds.AMBIENT_DUST_WASTELANDS) + .particles(ParticleTypes.WHITE_ASH, 0.01F) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/ShadowForestBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/ShadowForestBiome.java new file mode 100644 index 00000000..9b3c3245 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/ShadowForestBiome.java @@ -0,0 +1,60 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndEntities; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class ShadowForestBiome extends EndBiome.Config { + public ShadowForestBiome() { + super("shadow_forest"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(0, 0, 0) + .fogDensity(2.5F) + .plantsColor(45, 45, 45) + .waterAndFogColor(42, 45, 80) + .particles(ParticleTypes.MYCELIUM, 0.01F) + .loop(EndSounds.AMBIENT_CHORUS_FOREST) + .music(EndSounds.MUSIC_DARK) + .feature(EndFeatures.VIOLECITE_LAYER) + .feature(EndFeatures.END_LAKE_RARE) + .feature(EndFeatures.DRAGON_TREE) + .feature(EndFeatures.DRAGON_TREE_BUSH) + .feature(EndFeatures.SHADOW_PLANT) + .feature(EndFeatures.MURKWEED) + .feature(EndFeatures.NEEDLEGRASS) + .feature(EndFeatures.SHADOW_BERRY) + .feature(EndFeatures.TWISTED_VINE) + .feature(EndFeatures.PURPLE_POLYPORE) + .feature(EndFeatures.TAIL_MOSS) + .feature(EndFeatures.TAIL_MOSS_WOOD) + .feature(EndFeatures.CHARNIA_PURPLE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EndEntities.SHADOW_WALKER, 80, 2, 4) + .spawn(EntityType.ENDERMAN, 40, 1, 4) + .spawn(EntityType.PHANTOM, 1, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.SHADOW_GRASS.defaultBlockState(); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/SulphurSpringsBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/SulphurSpringsBiome.java new file mode 100644 index 00000000..2de0aaf2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/SulphurSpringsBiome.java @@ -0,0 +1,92 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +import net.minecraft.world.level.levelgen.placement.CaveSurface; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.surface.SurfaceRuleBuilder; +import org.betterx.bclib.api.surface.rules.SwitchRuleSource; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.*; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.surface.SulphuricSurfaceNoiseCondition; + +import java.util.List; + +public class SulphurSpringsBiome extends EndBiome.Config { + public SulphurSpringsBiome() { + super("sulphur_springs"); + } + + @Override + protected boolean hasCaves() { + return false; + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .music(EndSounds.MUSIC_OPENSPACE) + .loop(EndSounds.AMBIENT_SULPHUR_SPRINGS) + .waterColor(25, 90, 157) + .waterFogColor(30, 65, 61) + .fogColor(207, 194, 62) + .fogDensity(1.5F) + .terrainHeight(0F) + .particles(EndParticles.SULPHUR_PARTICLE, 0.001F) + .feature(EndFeatures.GEYSER) + .feature(EndFeatures.SURFACE_VENT) + .feature(EndFeatures.SULPHURIC_LAKE) + .feature(EndFeatures.SULPHURIC_CAVE) + .feature(EndFeatures.HYDRALUX) + .feature(EndFeatures.CHARNIA_GREEN) + .feature(EndFeatures.CHARNIA_ORANGE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .spawn(EndEntities.END_FISH, 50, 3, 8) + .spawn(EndEntities.CUBOZOA, 50, 3, 8) + .spawn(EntityType.ENDERMAN, 50, 1, 4); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.FLAVOLITE.stone.defaultBlockState(); + } + + @Override + public BlockState getAltTopMaterial() { + return Blocks.END_STONE.defaultBlockState(); + } + + @Override + public boolean generateFloorRule() { + return false; + } + + @Override + public SurfaceRuleBuilder surface() { + RuleSource surfaceBlockRule = new SwitchRuleSource( + new SulphuricSurfaceNoiseCondition(), + List.of( + SurfaceRules.state(surfaceMaterial().getAltTopMaterial()), + SurfaceRules.state(surfaceMaterial().getTopMaterial()), + SULPHURIC_ROCK, + BRIMSTONE + ) + ); + return super + .surface() + .rule(2, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, surfaceBlockRule)) + .rule(2, + SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), + surfaceBlockRule)); + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/UmbraValleyBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/UmbraValleyBiome.java new file mode 100644 index 00000000..af5f9997 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/UmbraValleyBiome.java @@ -0,0 +1,93 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.api.surface.SurfaceRuleBuilder; +import org.betterx.bclib.api.surface.rules.SwitchRuleSource; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.surface.UmbraSurfaceNoiseCondition; + +import java.util.List; + +public class UmbraValleyBiome extends EndBiome.Config { + private static final Block[] SURFACE_BLOCKS = new Block[]{ + EndBlocks.PALLIDIUM_FULL, + EndBlocks.PALLIDIUM_HEAVY, + EndBlocks.PALLIDIUM_THIN, + EndBlocks.PALLIDIUM_TINY, + EndBlocks.UMBRALITH.stone + }; + + public UmbraValleyBiome() { + super("umbra_valley"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(100, 100, 100) + .plantsColor(172, 189, 190) + .waterAndFogColor(69, 104, 134) + .particles(EndParticles.AMBER_SPHERE, 0.0001F) + .loop(EndSounds.UMBRA_VALLEY) + .music(EndSounds.MUSIC_DARK) + .feature(EndFeatures.UMBRALITH_ARCH) + .feature(EndFeatures.THIN_UMBRALITH_ARCH) + .feature(EndFeatures.INFLEXIA) + .feature(EndFeatures.FLAMMALIX); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.UMBRALITH.stone.defaultBlockState(); + } + + @Override + public BlockState getUnderMaterial() { + return EndBlocks.UMBRALITH.stone.defaultBlockState(); + } + + @Override + public BlockState getAltTopMaterial() { + return EndBlocks.PALLIDIUM_FULL.defaultBlockState(); + } + + @Override + public boolean generateFloorRule() { + return false; + } + + @Override + public SurfaceRuleBuilder surface() { + return super.surface() + .rule(2, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, + new SwitchRuleSource( + new UmbraSurfaceNoiseCondition(), + List.of( + SurfaceRules.state(surfaceMaterial().getAltTopMaterial()), + PALLIDIUM_HEAVY, + PALLIDIUM_THIN, + PALLIDIUM_TINY, + SurfaceRules.state(surfaceMaterial().getTopMaterial()) + ) + ) + )); + } + }; + } + + public static Block getSurface(int x, int z) { + return SURFACE_BLOCKS[UmbraSurfaceNoiseCondition.getDepth(x, z)]; + } +} diff --git a/src/main/java/org/betterx/betterend/world/biome/land/UmbrellaJungleBiome.java b/src/main/java/org/betterx/betterend/world/biome/land/UmbrellaJungleBiome.java new file mode 100644 index 00000000..ce37c3c9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/biome/land/UmbrellaJungleBiome.java @@ -0,0 +1,60 @@ +package org.betterx.betterend.world.biome.land; + +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.api.biomes.BCLBiomeBuilder; +import org.betterx.bclib.interfaces.SurfaceMaterialProvider; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.registry.EndParticles; +import org.betterx.betterend.registry.EndSounds; +import org.betterx.betterend.world.biome.EndBiome; + +public class UmbrellaJungleBiome extends EndBiome.Config { + public UmbrellaJungleBiome() { + super("umbrella_jungle"); + } + + @Override + protected void addCustomBuildData(BCLBiomeBuilder builder) { + builder + .fogColor(87, 223, 221) + .waterAndFogColor(119, 198, 253) + .foliageColor(27, 183, 194) + .fogDensity(2.3F) + .particles(EndParticles.JUNGLE_SPORE, 0.001F) + .music(EndSounds.MUSIC_FOREST) + .loop(EndSounds.AMBIENT_UMBRELLA_JUNGLE) + .feature(EndFeatures.END_LAKE) + .feature(EndFeatures.UMBRELLA_TREE) + .feature(EndFeatures.JELLYSHROOM) + .feature(EndFeatures.TWISTED_UMBRELLA_MOSS) + .feature(EndFeatures.SMALL_JELLYSHROOM_FLOOR) + .feature(EndFeatures.JUNGLE_GRASS) + .feature(EndFeatures.CYAN_MOSS) + .feature(EndFeatures.CYAN_MOSS_WOOD) + .feature(EndFeatures.JUNGLE_FERN_WOOD) + .feature(EndFeatures.SMALL_JELLYSHROOM_WALL) + .feature(EndFeatures.SMALL_JELLYSHROOM_WOOD) + .feature(EndFeatures.SMALL_JELLYSHROOM_CEIL) + .feature(EndFeatures.JUNGLE_VINE) + .feature(EndFeatures.CHARNIA_CYAN) + .feature(EndFeatures.CHARNIA_GREEN) + .feature(EndFeatures.CHARNIA_LIGHT_BLUE) + .feature(EndFeatures.CHARNIA_RED_RARE) + .structure(BiomeTags.HAS_END_CITY) + .spawn(EntityType.ENDERMAN, 50, 1, 2); + } + + @Override + protected SurfaceMaterialProvider surfaceMaterial() { + return new EndBiome.DefaultSurfaceMaterialProvider() { + @Override + public BlockState getTopMaterial() { + return EndBlocks.JUNGLE_MOSS.defaultBlockState(); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/world/features/BiomeIslandFeature.java b/src/main/java/org/betterx/betterend/world/features/BiomeIslandFeature.java new file mode 100644 index 00000000..42aebbe0 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/BiomeIslandFeature.java @@ -0,0 +1,73 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.world.biome.EndBiome; + +public class BiomeIslandFeature extends DefaultFeature { + private static final MutableBlockPos CENTER = new MutableBlockPos(); + private static final SDF ISLAND; + + private static OpenSimplexNoise simplexNoise = new OpenSimplexNoise(412L); + private static BlockState topBlock = Blocks.GRASS_BLOCK.defaultBlockState(); + private static BlockState underBlock = Blocks.DIRT.defaultBlockState(); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + //Holder biome = world.getBiome(pos); + int dist = BlocksHelper.downRay(world, pos, 10) + 1; + BlockPos surfacePos = new BlockPos(pos.getX(), pos.getY() - dist, pos.getZ()); + BlockState topMaterial = EndBiome.findTopMaterial(world, surfacePos); + + if (BlocksHelper.isFluid(topMaterial)) { + topBlock = Blocks.GRAVEL.defaultBlockState(); + underBlock = Blocks.STONE.defaultBlockState(); + } else { + underBlock = EndBiome.findUnderMaterial(world, surfacePos); + } + + simplexNoise = new OpenSimplexNoise(world.getSeed()); + CENTER.set(pos); + ISLAND.fillRecursive(world, pos.below()); + return true; + } + + private static SDF createSDFIsland() { + SDF sdfCone = new SDFCappedCone().setRadius1(0).setRadius2(6).setHeight(4).setBlock(pos -> { + if (pos.getY() > CENTER.getY()) return AIR; + if (pos.getY() == CENTER.getY()) return topBlock; + return underBlock; + }); + sdfCone = new SDFTranslate().setTranslate(0, -2, 0).setSource(sdfCone); + sdfCone = new SDFDisplacement().setFunction(pos -> { + float deltaX = Math.abs(pos.x()); + float deltaY = Math.abs(pos.y()); + float deltaZ = Math.abs(pos.z()); + if (deltaY < 2.0f && (deltaX < 3.0f || deltaZ < 3.0F)) return 0.0f; + return (float) simplexNoise.eval(CENTER.getX() + pos.x(), CENTER.getY() + pos.y(), CENTER.getZ() + pos.z()); + }) + .setSource(sdfCone) + .setReplaceFunction(state -> BlocksHelper.isFluid(state) || state.getMaterial() + .isReplaceable()); + return sdfCone; + } + + static { + ISLAND = createSDFIsland(); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/BlueVineFeature.java b/src/main/java/org/betterx/betterend/world/features/BlueVineFeature.java new file mode 100644 index 00000000..a17f1105 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/BlueVineFeature.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class BlueVineFeature extends ScatterFeature { + private boolean small; + + public BlueVineFeature() { + super(5); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + float d = MHelper.length( + center.getX() - blockPos.getX(), + center.getZ() - blockPos.getZ() + ) / radius * 0.6F + random.nextFloat() * 0.4F; + small = d > 0.5F; + return EndBlocks.BLUE_VINE_SEED.canSurvive(AIR, world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + if (small) { + BlocksHelper.setWithoutUpdate( + world, + blockPos, + EndBlocks.BLUE_VINE_SEED.defaultBlockState().setValue(EndPlantWithAgeBlock.AGE, random.nextInt(4)) + ); + } else { + EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.BLUE_VINE_SEED); + seed.growAdult(world, random, blockPos); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/BuildingListFeature.java b/src/main/java/org/betterx/betterend/world/features/BuildingListFeature.java new file mode 100644 index 00000000..73695463 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/BuildingListFeature.java @@ -0,0 +1,68 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +import org.betterx.bclib.world.features.ListFeature; +import org.betterx.betterend.util.LootTableUtil; + +import java.util.List; +import org.jetbrains.annotations.Nullable; + +public class BuildingListFeature extends ListFeature { + public BuildingListFeature(List list, BlockState defaultBlock) { + super(list, defaultBlock); + } + + @Override + protected void addStructureData(StructurePlaceSettings data) { + super.addStructureData(data); + data.addProcessor(new ChestProcessor()); + } + + class ChestProcessor extends StructureProcessor { + @Nullable + @Override + public StructureTemplate.StructureBlockInfo processBlock(LevelReader levelReader, + BlockPos blockPos, + BlockPos blockPos2, + StructureBlockInfo structureBlockInfo, + StructureBlockInfo structureBlockInfo2, + StructurePlaceSettings structurePlaceSettings) { + BlockState blockState = structureBlockInfo2.state; + if (blockState.getBlock() instanceof ChestBlock) { + RandomSource random = structurePlaceSettings.getRandom(structureBlockInfo2.pos); + BlockPos chestPos = structureBlockInfo2.pos; + ChestBlock chestBlock = (ChestBlock) blockState.getBlock(); + BlockEntity entity = chestBlock.newBlockEntity(chestPos, blockState); + levelReader.getChunk(chestPos).setBlockEntity(entity); + RandomizableContainerBlockEntity chestEntity = (RandomizableContainerBlockEntity) entity; + Holder biome = levelReader.getNoiseBiome( + chestPos.getX() >> 2, + chestPos.getY() >> 2, + chestPos.getZ() >> 2 + ); + chestEntity.setLootTable(LootTableUtil.getTable(biome), random.nextLong()); + chestEntity.setChanged(); + } + return structureBlockInfo2; + } + + @Override + protected StructureProcessorType getType() { + return StructureProcessorType.NOP; + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/CavePumpkinFeature.java b/src/main/java/org/betterx/betterend/world/features/CavePumpkinFeature.java new file mode 100644 index 00000000..ac6e0924 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/CavePumpkinFeature.java @@ -0,0 +1,43 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.EndBlockProperties; +import org.betterx.betterend.registry.EndBlocks; + +public class CavePumpkinFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.above()) + .is(CommonBlockTags.GEN_END_STONES) || !world.isEmptyBlock(pos) || !world.isEmptyBlock( + pos.below())) { + return false; + } + + int age = random.nextInt(4); + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.CAVE_PUMPKIN_SEED.defaultBlockState().setValue(EndBlockProperties.AGE, age) + ); + if (age > 1) { + BlocksHelper.setWithoutUpdate( + world, + pos.below(), + EndBlocks.CAVE_PUMPKIN.defaultBlockState().setValue(EndBlockProperties.SMALL, age < 3) + ); + } + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/CharniaFeature.java b/src/main/java/org/betterx/betterend/world/features/CharniaFeature.java new file mode 100644 index 00000000..c6abdbf4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/CharniaFeature.java @@ -0,0 +1,14 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.world.level.block.Block; + +public class CharniaFeature extends UnderwaterPlantFeature { + public CharniaFeature(Block plant) { + super(plant, 6); + } + + @Override + protected int getChance() { + return 3; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/CrashedShipFeature.java b/src/main/java/org/betterx/betterend/world/features/CrashedShipFeature.java new file mode 100644 index 00000000..0e05a2c2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/CrashedShipFeature.java @@ -0,0 +1,148 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.templatesystem.*; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.StructureHelper; +import org.betterx.bclib.world.features.NBTFeature; +import org.betterx.betterend.util.BlockFixer; +import org.betterx.betterend.util.StructureErode; +import org.betterx.betterend.world.biome.EndBiome; + +public class CrashedShipFeature extends NBTFeature { + private static final StructureProcessor REPLACER; + private static final String STRUCTURE_PATH = "/data/minecraft/structures/end_city/ship.nbt"; + private StructureTemplate structure; + + public CrashedShipFeature() { + super(EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); + } + + @Override + protected StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, RandomSource random) { + if (structure == null) { + structure = world.getLevel().getStructureManager().getOrCreate(new ResourceLocation("end_city/ship")); + if (structure == null) { + structure = StructureHelper.readStructure(STRUCTURE_PATH); + } + } + return structure; + } + + @Override + protected boolean canSpawn(WorldGenLevel world, BlockPos pos, RandomSource random) { + long x = pos.getX() >> 4; + long z = pos.getX() >> 4; + if (x * x + z * z < 3600) { + return false; + } + return pos.getY() > 5 && world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES); + } + + @Override + protected Rotation getRotation(WorldGenLevel world, BlockPos pos, RandomSource random) { + return Rotation.getRandom(random); + } + + @Override + protected Mirror getMirror(WorldGenLevel world, BlockPos pos, RandomSource random) { + return Mirror.values()[random.nextInt(3)]; + } + + @Override + protected int getYOffset(StructureTemplate structure, WorldGenLevel world, BlockPos pos, RandomSource random) { + int min = structure.getSize().getY() >> 3; + int max = structure.getSize().getY() >> 2; + return -MHelper.randRange(min, max, random); + } + + @Override + protected TerrainMerge getTerrainMerge(WorldGenLevel world, BlockPos pos, RandomSource random) { + return TerrainMerge.NONE; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + center = new BlockPos(((center.getX() >> 4) << 4) | 8, 128, ((center.getZ() >> 4) << 4) | 8); + center = getGround(world, center); + BoundingBox bounds = makeBox(center); + + if (!canSpawn(world, center, random)) { + return false; + } + + StructureTemplate structure = getStructure(world, center, random); + Rotation rotation = getRotation(world, center, random); + Mirror mirror = getMirror(world, center, random); + BlockPos offset = StructureTemplate.transform( + new BlockPos(structure.getSize()), + mirror, + rotation, + BlockPos.ZERO + ); + center = center.offset(0, getYOffset(structure, world, center, random) + 0.5, 0); + StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror); + center = center.offset(-offset.getX() * 0.5, 0, -offset.getZ() * 0.5); + + BoundingBox structB = structure.getBoundingBox(placementData, center); + bounds = StructureHelper.intersectBoxes(bounds, structB); + + addStructureData(placementData); + structure.placeInWorld(world, center, center, placementData.setBoundingBox(bounds), random, 2); + + StructureErode.erodeIntense(world, bounds, random); + BlockFixer.fixBlocks( + world, + new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()), + new BlockPos(bounds.maxX(), bounds.maxY(), bounds.maxZ()) + ); + + return true; + } + + @Override + protected void addStructureData(StructurePlaceSettings data) { + data.addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(REPLACER).setIgnoreEntities(true); + } + + static { + REPLACER = new StructureProcessor() { + @Override + public StructureBlockInfo processBlock(LevelReader worldView, + BlockPos pos, + BlockPos blockPos, + StructureBlockInfo structureBlockInfo, + StructureBlockInfo structureBlockInfo2, + StructurePlaceSettings structurePlacementData) { + BlockState state = structureBlockInfo2.state; + if (state.is(Blocks.SPAWNER) || state.getMaterial().equals(Material.WOOL)) { + return new StructureBlockInfo(structureBlockInfo2.pos, AIR, null); + } + return structureBlockInfo2; + } + + @Override + protected StructureProcessorType getType() { + return StructureProcessorType.NOP; + } + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/DoublePlantFeature.java b/src/main/java/org/betterx/betterend/world/features/DoublePlantFeature.java new file mode 100644 index 00000000..99dbe579 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/DoublePlantFeature.java @@ -0,0 +1,49 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; + +public class DoublePlantFeature extends ScatterFeature { + private final Block smallPlant; + private final Block largePlant; + private Block plant; + + public DoublePlantFeature(Block smallPlant, Block largePlant, int radius) { + super(radius); + this.smallPlant = smallPlant; + this.largePlant = largePlant; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + float d = MHelper.length( + center.getX() - blockPos.getX(), + center.getZ() - blockPos.getZ() + ) / radius * 0.6F + random.nextFloat() * 0.4F; + plant = d < 0.5F ? largePlant : smallPlant; + return plant.canSurvive(plant.defaultBlockState(), world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + if (plant instanceof BaseDoublePlantBlock) { + int rot = random.nextInt(4); + BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); + BlocksHelper.setWithoutUpdate(world, blockPos, state); + BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); + } else { + BlocksHelper.setWithoutUpdate(world, blockPos, plant); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/EndLilyFeature.java b/src/main/java/org/betterx/betterend/world/features/EndLilyFeature.java new file mode 100644 index 00000000..e4e7f7ac --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/EndLilyFeature.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.betterend.blocks.EndLilySeedBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLilyFeature extends UnderwaterPlantScatter { + public EndLilyFeature(int radius) { + super(radius); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + EndLilySeedBlock seed = (EndLilySeedBlock) EndBlocks.END_LILY_SEED; + seed.grow(world, random, blockPos); + } + + @Override + protected int getChance() { + return 15; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/EndLotusFeature.java b/src/main/java/org/betterx/betterend/world/features/EndLotusFeature.java new file mode 100644 index 00000000..b4e62509 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/EndLotusFeature.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.betterend.blocks.EndLotusSeedBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLotusFeature extends UnderwaterPlantScatter { + public EndLotusFeature(int radius) { + super(radius); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + EndLotusSeedBlock seed = (EndLotusSeedBlock) EndBlocks.END_LOTUS_SEED; + seed.grow(world, random, blockPos); + } + + @Override + protected int getChance() { + return 15; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/EndLotusLeafFeature.java b/src/main/java/org/betterx/betterend/world/features/EndLotusLeafFeature.java new file mode 100644 index 00000000..4e98e0cf --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/EndLotusLeafFeature.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.EndLotusLeafBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class EndLotusLeafFeature extends ScatterFeature { + public EndLotusLeafFeature(int radius) { + super(radius); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + if (canGenerate(world, blockPos)) { + generateLeaf(world, blockPos); + } + } + + @Override + protected int getChance() { + return 15; + } + + @Override + protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { + return getPosOnSurface(world, pos); + } + + private void generateLeaf(WorldGenLevel world, BlockPos pos) { + MutableBlockPos p = new MutableBlockPos(); + BlockState leaf = EndBlocks.END_LOTUS_LEAF.defaultBlockState(); + BlocksHelper.setWithoutUpdate(world, pos, leaf.setValue(EndLotusLeafBlock.SHAPE, TripleShape.BOTTOM)); + for (Direction move : BlocksHelper.HORIZONTAL) { + BlocksHelper.setWithoutUpdate( + world, + p.set(pos).move(move), + leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, move) + .setValue(EndLotusLeafBlock.SHAPE, TripleShape.MIDDLE) + ); + } + for (int i = 0; i < 4; i++) { + Direction d1 = BlocksHelper.HORIZONTAL[i]; + Direction d2 = BlocksHelper.HORIZONTAL[(i + 1) & 3]; + BlocksHelper.setWithoutUpdate( + world, + p.set(pos).move(d1).move(d2), + leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, d1) + .setValue(EndLotusLeafBlock.SHAPE, TripleShape.TOP) + ); + } + } + + private boolean canGenerate(WorldGenLevel world, BlockPos pos) { + MutableBlockPos p = new MutableBlockPos(); + p.setY(pos.getY()); + int count = 0; + for (int x = -1; x < 2; x++) { + p.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + p.setZ(pos.getZ() + z); + if (world.isEmptyBlock(p) && world.getBlockState(p.below()).is(Blocks.WATER)) count++; + } + } + return count == 9; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return world.isEmptyBlock(blockPos) && world.getBlockState(blockPos.below()).is(Blocks.WATER); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/FilaluxFeature.java b/src/main/java/org/betterx/betterend/world/features/FilaluxFeature.java new file mode 100644 index 00000000..088fac9a --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/FilaluxFeature.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; + +public class FilaluxFeature extends SkyScatterFeature { + public FilaluxFeature() { + super(10); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + BlockState vine = EndBlocks.FILALUX.defaultBlockState(); + BlockState wings = EndBlocks.FILALUX_WINGS.defaultBlockState(); + BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.FILALUX_LANTERN); + BlocksHelper.setWithoutUpdate( + world, + blockPos.above(), + wings.setValue(BlockStateProperties.FACING, Direction.UP) + ); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlocksHelper.setWithoutUpdate( + world, + blockPos.relative(dir), + wings.setValue(BlockStateProperties.FACING, dir) + ); + } + int length = MHelper.randRange(1, 3, random); + for (int i = 1; i <= length; i++) { + TripleShape shape = length > 1 ? TripleShape.TOP : TripleShape.BOTTOM; + if (i > 1) { + shape = i == length ? TripleShape.BOTTOM : TripleShape.MIDDLE; + } + BlocksHelper.setWithoutUpdate(world, blockPos.below(i), vine.setValue(BlockProperties.TRIPLE_SHAPE, shape)); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/FullHeightScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/FullHeightScatterFeature.java new file mode 100644 index 00000000..fcc50b6d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/FullHeightScatterFeature.java @@ -0,0 +1,63 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.util.GlobalState; + +public abstract class FullHeightScatterFeature extends DefaultFeature { + private final int radius; + + public FullHeightScatterFeature(int radius) { + this.radius = radius; + } + + public abstract boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius); + + public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + final RandomSource random = featureConfig.random(); + final BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, center.getX(), center.getZ()); + int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); + for (int y = maxY; y > minY; y--) { + POS.set(center.getX(), y, center.getZ()); + if (world.getBlockState(POS).isAir() && !world.getBlockState(POS.below()).isAir()) { + float r = MHelper.randRange(radius * 0.5F, radius, random); + int count = MHelper.floor(r * r * MHelper.randRange(1.5F, 3F, random)); + for (int i = 0; i < count; i++) { + float pr = r * (float) Math.sqrt(random.nextFloat()); + float theta = random.nextFloat() * MHelper.PI2; + float x = pr * (float) Math.cos(theta); + float z = pr * (float) Math.sin(theta); + + POS.set(center.getX() + x, y + 5, center.getZ() + z); + int down = BlocksHelper.downRay(world, POS, 16); + if (down > 10) continue; + POS.setY(POS.getY() - down); + + if (canGenerate(world, random, center, POS, r)) { + generate(world, random, POS); + } + } + } + } + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/GlowPillarFeature.java b/src/main/java/org/betterx/betterend/world/features/GlowPillarFeature.java new file mode 100644 index 00000000..99b7bf54 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/GlowPillarFeature.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class GlowPillarFeature extends ScatterFeature { + public GlowPillarFeature() { + super(9); + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return EndBlocks.GLOWING_PILLAR_SEED.canSurvive(AIR, world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.GLOWING_PILLAR_SEED); + seed.growAdult(world, random, blockPos); + } + + @Override + protected int getChance() { + return 10; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/HydraluxFeature.java b/src/main/java/org/betterx/betterend/world/features/HydraluxFeature.java new file mode 100644 index 00000000..0b6a7be5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/HydraluxFeature.java @@ -0,0 +1,25 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.betterend.blocks.HydraluxSaplingBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class HydraluxFeature extends UnderwaterPlantScatter { + public HydraluxFeature(int radius) { + super(radius); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + HydraluxSaplingBlock seed = (HydraluxSaplingBlock) EndBlocks.HYDRALUX_SAPLING; + seed.grow(world, random, blockPos); + } + + @Override + protected int getChance() { + return 15; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/InvertedScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/InvertedScatterFeature.java new file mode 100644 index 00000000..dd8a704a --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/InvertedScatterFeature.java @@ -0,0 +1,63 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.util.GlobalState; + +public abstract class InvertedScatterFeature extends DefaultFeature { + private final int radius; + + public InvertedScatterFeature(int radius) { + this.radius = radius; + } + + public abstract boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius); + + public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + final RandomSource random = featureConfig.random(); + final BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); + int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); + for (int y = maxY; y > minY; y--) { + POS.set(center.getX(), y, center.getZ()); + if (world.getBlockState(POS).isAir() && !world.getBlockState(POS.above()).isAir()) { + float r = MHelper.randRange(radius * 0.5F, radius, random); + int count = MHelper.floor(r * r * MHelper.randRange(0.5F, 1.5F, random)); + for (int i = 0; i < count; i++) { + float pr = r * (float) Math.sqrt(random.nextFloat()); + float theta = random.nextFloat() * MHelper.PI2; + float x = pr * (float) Math.cos(theta); + float z = pr * (float) Math.sin(theta); + + POS.set(center.getX() + x, center.getY() - 7, center.getZ() + z); + int up = BlocksHelper.upRay(world, POS, 16); + if (up > 14) continue; + POS.setY(POS.getY() + up); + + if (canGenerate(world, random, center, POS, r)) { + generate(world, random, POS); + } + } + } + } + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/LanceleafFeature.java b/src/main/java/org/betterx/betterend/world/features/LanceleafFeature.java new file mode 100644 index 00000000..8de229be --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/LanceleafFeature.java @@ -0,0 +1,34 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class LanceleafFeature extends ScatterFeature { + public LanceleafFeature() { + super(7); + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return EndBlocks.LANCELEAF_SEED.canSurvive(AIR, world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.LANCELEAF_SEED); + seed.growAdult(world, random, blockPos); + } + + @Override + protected int getChance() { + return 5; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/MengerSpongeFeature.java b/src/main/java/org/betterx/betterend/world/features/MengerSpongeFeature.java new file mode 100644 index 00000000..39b84c9e --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/MengerSpongeFeature.java @@ -0,0 +1,42 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.function.Function; + +public class MengerSpongeFeature extends UnderwaterPlantScatter { + private static final Function REPLACE; + + public MengerSpongeFeature(int radius) { + super(radius); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.MENGER_SPONGE_WET); + if (random.nextBoolean()) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + BlockPos pos = blockPos.relative(dir); + if (REPLACE.apply(world.getBlockState(pos))) { + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.MENGER_SPONGE_WET); + } + } + } + } + + static { + REPLACE = (state) -> { + if (state.is(EndBlocks.END_LOTUS_STEM)) { + return false; + } + return !state.getFluidState().isEmpty() || state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/NeonCactusFeature.java b/src/main/java/org/betterx/betterend/world/features/NeonCactusFeature.java new file mode 100644 index 00000000..e989fb31 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/NeonCactusFeature.java @@ -0,0 +1,30 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.NeonCactusPlantBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class NeonCactusFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + BlockState ground = world.getBlockState(pos.below()); + if (!ground.is(EndBlocks.ENDSTONE_DUST) && !ground.is(EndBlocks.END_MOSS)) { + return false; + } + + NeonCactusPlantBlock cactus = ((NeonCactusPlantBlock) EndBlocks.NEON_CACTUS); + cactus.growPlant(world, pos, random); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/ScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/ScatterFeature.java new file mode 100644 index 00000000..e794d1e1 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/ScatterFeature.java @@ -0,0 +1,92 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.util.GlobalState; + +public abstract class ScatterFeature extends DefaultFeature { + private final int radius; + + public ScatterFeature(int radius) { + this.radius = radius; + } + + public abstract boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius); + + public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); + + protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { + return getPosOnSurfaceWG(world, pos); + } + + protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { + if (pos.getY() < 5) { + return false; + } else return world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES); + } + + protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { + int down = BlocksHelper.downRay(world, pos, 16); + if (down > Math.abs(getYOffset() * 2)) { + return false; + } + pos.setY(pos.getY() - down); + return true; + } + + protected int getYOffset() { + return 5; + } + + protected int getChance() { + return 1; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + final RandomSource random = featureConfig.random(); + BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + center = getCenterGround(world, center); + + if (!canSpawn(world, center)) { + return false; + } + + float r = MHelper.randRange(radius * 0.5F, radius, random); + int count = MHelper.floor(r * r * MHelper.randRange(1.5F, 3F, random)); + for (int i = 0; i < count; i++) { + float pr = r * (float) Math.sqrt(random.nextFloat()); + float theta = random.nextFloat() * MHelper.PI2; + float x = pr * (float) Math.cos(theta); + float z = pr * (float) Math.sin(theta); + + POS.set(center.getX() + x, center.getY() + getYOffset(), center.getZ() + z); + if (getGroundPlant(world, POS) && canGenerate( + world, + random, + center, + POS, + r + ) && (getChance() < 2 || random.nextInt(getChance()) == 0)) { + generate(world, random, POS); + } + } + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/SilkMothNestFeature.java b/src/main/java/org/betterx/betterend/world/features/SilkMothNestFeature.java new file mode 100644 index 00000000..01acd839 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/SilkMothNestFeature.java @@ -0,0 +1,67 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.util.GlobalState; + +public class SilkMothNestFeature extends DefaultFeature { + private boolean canGenerate(WorldGenLevel world, BlockPos pos) { + BlockState state = world.getBlockState(pos.above()); + if (state.is(BlockTags.LEAVES) || state.is(BlockTags.LOGS)) { + state = world.getBlockState(pos); + if ((state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) && world.isEmptyBlock(pos.below())) { + for (Direction dir : BlocksHelper.HORIZONTAL) { + return !world.getBlockState(pos.below().relative(dir)).getMaterial().blocksMotion(); + } + } + } + return false; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + final RandomSource random = featureConfig.random(); + final BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); + int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); + POS.set(center); + for (int y = maxY; y > minY; y--) { + POS.setY(y); + if (canGenerate(world, POS)) { + Direction dir = BlocksHelper.randomHorizontal(random); + BlocksHelper.setWithoutUpdate( + world, + POS, + EndBlocks.SILK_MOTH_NEST.defaultBlockState() + .setValue(BlockStateProperties.HORIZONTAL_FACING, dir) + .setValue(BlockProperties.ACTIVE, false) + ); + POS.setY(y - 1); + BlocksHelper.setWithoutUpdate( + world, + POS, + EndBlocks.SILK_MOTH_NEST.defaultBlockState() + .setValue(BlockStateProperties.HORIZONTAL_FACING, dir) + ); + return true; + } + } + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/SingleInvertedScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/SingleInvertedScatterFeature.java new file mode 100644 index 00000000..7ca36bf8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/SingleInvertedScatterFeature.java @@ -0,0 +1,46 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +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 org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.util.BlocksHelper; + +public class SingleInvertedScatterFeature extends InvertedScatterFeature { + private final Block block; + + public SingleInvertedScatterFeature(Block block, int radius) { + super(radius); + this.block = block; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + if (!world.isEmptyBlock(blockPos)) { + return false; + } + BlockState state = block.defaultBlockState(); + if (block instanceof BaseAttachedBlock) { + state = state.setValue(BlockStateProperties.FACING, Direction.DOWN); + } + return state.canSurvive(world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + BlockState state = block.defaultBlockState(); + if (block instanceof BaseAttachedBlock) { + state = state.setValue(BlockStateProperties.FACING, Direction.DOWN); + } + BlocksHelper.setWithoutUpdate(world, blockPos, state); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/SinglePlantFeature.java b/src/main/java/org/betterx/betterend/world/features/SinglePlantFeature.java new file mode 100644 index 00000000..0a99af26 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/SinglePlantFeature.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseCropBlock; +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock; + +public class SinglePlantFeature extends ScatterFeature { + private final Block plant; + private final boolean rawHeightmap; + private final int chance; + + public SinglePlantFeature(Block plant, int radius) { + this(plant, radius, true, 1); + } + + public SinglePlantFeature(Block plant, int radius, int chance) { + this(plant, radius, true, chance); + } + + public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap) { + this(plant, radius, rawHeightmap, 1); + } + + public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap, int chance) { + super(radius); + this.plant = plant; + this.rawHeightmap = rawHeightmap; + this.chance = chance; + } + + protected int getChance() { + return chance; + } + + @Override + protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { + return rawHeightmap ? getPosOnSurfaceWG(world, pos) : getPosOnSurface(world, pos); + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return plant.canSurvive(plant.defaultBlockState(), world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + if (plant instanceof BaseDoublePlantBlock) { + int rot = random.nextInt(4); + BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); + BlocksHelper.setWithoutUpdate(world, blockPos, state); + BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); + } else if (plant instanceof BaseCropBlock) { + BlockState state = plant.defaultBlockState().setValue(BaseCropBlock.AGE, 3); + BlocksHelper.setWithoutUpdate(world, blockPos, state); + } else if (plant instanceof EndPlantWithAgeBlock) { + int age = random.nextInt(4); + BlockState state = plant.defaultBlockState().setValue(EndPlantWithAgeBlock.AGE, age); + BlocksHelper.setWithoutUpdate(world, blockPos, state); + } else { + BlocksHelper.setWithoutUpdate(world, blockPos, plant); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/SkyScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/SkyScatterFeature.java new file mode 100644 index 00000000..ae04d069 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/SkyScatterFeature.java @@ -0,0 +1,58 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; + +public abstract class SkyScatterFeature extends ScatterFeature { + public SkyScatterFeature(int radius) { + super(radius); + } + + @Override + protected int getChance() { + return 10; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + if (!world.isEmptyBlock(blockPos)) { + return false; + } + + for (Direction dir : BlocksHelper.HORIZONTAL) { + if (!world.isEmptyBlock(blockPos.relative(dir))) { + return false; + } + } + + int maxD = getYOffset() + 2; + int maxV = getYOffset() - 2; + + return BlocksHelper.upRay(world, blockPos, maxD) > maxV && BlocksHelper.downRay(world, blockPos, maxD) > maxV; + } + + @Override + protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { + return true; + } + + @Override + protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { + return new BlockPos(pos.getX(), MHelper.randRange(32, 192, world.getRandom()), pos.getZ()); + } + + protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { + pos.setY(pos.getY() + MHelper.randRange(-getYOffset(), getYOffset(), world.getRandom())); + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantFeature.java b/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantFeature.java new file mode 100644 index 00000000..a14a0248 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantFeature.java @@ -0,0 +1,40 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseDoublePlantBlock; +import org.betterx.bclib.util.BlocksHelper; + +public class UnderwaterPlantFeature extends UnderwaterPlantScatter { + private final Block plant; + + public UnderwaterPlantFeature(Block plant, int radius) { + super(radius); + this.plant = plant; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return super.canSpawn(world, blockPos) && plant.canSurvive(plant.defaultBlockState(), world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + if (plant instanceof BaseDoublePlantBlock) { + int rot = random.nextInt(4); + BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); + BlocksHelper.setWithoutUpdate(world, blockPos, state); + BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); + } else { + BlocksHelper.setWithoutUpdate(world, blockPos, plant); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantScatter.java b/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantScatter.java new file mode 100644 index 00000000..4d312fa7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/UnderwaterPlantScatter.java @@ -0,0 +1,60 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; + +import org.betterx.betterend.util.GlobalState; + +public abstract class UnderwaterPlantScatter extends ScatterFeature { + public UnderwaterPlantScatter(int radius) { + super(radius); + } + + @Override + protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + POS.setX(pos.getX()); + POS.setZ(pos.getZ()); + POS.setY(0); + return getGround(world, POS).immutable(); + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + return world.getBlockState(blockPos).is(Blocks.WATER); + } + + @Override + protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { + return world.getBlockState(pos).is(Blocks.WATER); + } + + @Override + protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { + return getGround(world, pos).getY() < 128; + } + + @Override + protected int getYOffset() { + return -5; + } + + @Override + protected int getChance() { + return 5; + } + + private BlockPos getGround(WorldGenLevel world, MutableBlockPos pos) { + while (pos.getY() < 128 && world.getFluidState(pos).isEmpty()) { + pos.setY(pos.getY() + 1); + } + return pos; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/VineFeature.java b/src/main/java/org/betterx/betterend/world/features/VineFeature.java new file mode 100644 index 00000000..e726c240 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/VineFeature.java @@ -0,0 +1,73 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import org.betterx.bclib.blocks.BaseVineBlock; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; + +public class VineFeature extends InvertedScatterFeature { + private final Block vineBlock; + private final int maxLength; + private final boolean vine; + + public VineFeature(Block vineBlock, int maxLength) { + super(6); + this.vineBlock = vineBlock; + this.maxLength = maxLength; + this.vine = vineBlock instanceof BaseVineBlock; + } + + @Override + public boolean canGenerate(WorldGenLevel world, + RandomSource random, + BlockPos center, + BlockPos blockPos, + float radius) { + BlockState state = world.getBlockState(blockPos); + return state.getMaterial().isReplaceable() && canPlaceBlock(state, world, blockPos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { + int h = BlocksHelper.downRay(world, blockPos, random.nextInt(maxLength)) - 1; + if (h > 2) { + BlockState top = getTopState(); + BlockState middle = getMiggleState(); + BlockState bottom = getBottomState(); + BlocksHelper.setWithoutUpdate(world, blockPos, top); + for (int i = 1; i < h; i++) { + BlocksHelper.setWithoutUpdate(world, blockPos.below(i), middle); + } + BlocksHelper.setWithoutUpdate(world, blockPos.below(h), bottom); + } + } + + private boolean canPlaceBlock(BlockState state, WorldGenLevel world, BlockPos blockPos) { + if (vine) { + return ((BaseVineBlock) vineBlock).canGenerate(state, world, blockPos); + } else { + return vineBlock.canSurvive(state, world, blockPos); + } + } + + private BlockState getTopState() { + BlockState state = vineBlock.defaultBlockState(); + return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) : state; + } + + private BlockState getMiggleState() { + BlockState state = vineBlock.defaultBlockState(); + return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) : state; + } + + private BlockState getBottomState() { + BlockState state = vineBlock.defaultBlockState(); + return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM) : state; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/WallPlantFeature.java b/src/main/java/org/betterx/betterend/world/features/WallPlantFeature.java new file mode 100644 index 00000000..167d5142 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/WallPlantFeature.java @@ -0,0 +1,45 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +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 org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.blocks.BaseWallPlantBlock; +import org.betterx.bclib.util.BlocksHelper; + +public class WallPlantFeature extends WallScatterFeature { + private final Block block; + + public WallPlantFeature(Block block, int radius) { + super(radius); + this.block = block; + } + + @Override + public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { + if (block instanceof BaseWallPlantBlock) { + BlockState state = block.defaultBlockState().setValue(BaseWallPlantBlock.FACING, dir); + return block.canSurvive(state, world, pos); + } else if (block instanceof BaseAttachedBlock) { + BlockState state = block.defaultBlockState().setValue(BlockStateProperties.FACING, dir); + return block.canSurvive(state, world, pos); + } + return block.canSurvive(block.defaultBlockState(), world, pos); + } + + @Override + public void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { + BlockState state = block.defaultBlockState(); + if (block instanceof BaseWallPlantBlock) { + state = state.setValue(BaseWallPlantBlock.FACING, dir); + } else if (block instanceof BaseAttachedBlock) { + state = state.setValue(BlockStateProperties.FACING, dir); + } + BlocksHelper.setWithoutUpdate(world, pos, state); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/WallPlantOnLogFeature.java b/src/main/java/org/betterx/betterend/world/features/WallPlantOnLogFeature.java new file mode 100644 index 00000000..b9000ac9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/WallPlantOnLogFeature.java @@ -0,0 +1,22 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class WallPlantOnLogFeature extends WallPlantFeature { + public WallPlantOnLogFeature(Block block, int radius) { + super(block, radius); + } + + @Override + public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { + BlockPos blockPos = pos.relative(dir.getOpposite()); + BlockState blockState = world.getBlockState(blockPos); + return blockState.is(BlockTags.LOGS); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/WallScatterFeature.java b/src/main/java/org/betterx/betterend/world/features/WallScatterFeature.java new file mode 100644 index 00000000..1894a95f --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/WallScatterFeature.java @@ -0,0 +1,71 @@ +package org.betterx.betterend.world.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; + +public abstract class WallScatterFeature extends DefaultFeature { + private static final Direction[] DIR = BlocksHelper.makeHorizontal(); + private final int radius; + + public WallScatterFeature(int radius) { + this.radius = radius; + } + + public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir); + + public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos center = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); + int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); + if (maxY < 10 || maxY < minY) { + return false; + } + int py = MHelper.randRange(minY, maxY, random); + + MutableBlockPos mut = new MutableBlockPos(); + for (int x = -radius; x <= radius; x++) { + mut.setX(center.getX() + x); + for (int y = -radius; y <= radius; y++) { + mut.setY(py + y); + for (int z = -radius; z <= radius; z++) { + mut.setZ(center.getZ() + z); + if (random.nextInt(4) == 0 && world.isEmptyBlock(mut)) { + shuffle(random); + for (Direction dir : DIR) { + if (canGenerate(world, random, mut, dir)) { + generate(world, random, mut, dir); + break; + } + } + } + } + } + } + + return true; + } + + private void shuffle(RandomSource random) { + for (int i = 0; i < 4; i++) { + int j = random.nextInt(4); + Direction d = DIR[i]; + DIR[i] = DIR[j]; + DIR[j] = d; + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/bushes/BushFeature.java b/src/main/java/org/betterx/betterend/world/features/bushes/BushFeature.java new file mode 100644 index 00000000..7e273fd4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/bushes/BushFeature.java @@ -0,0 +1,99 @@ +package org.betterx.betterend.world.features.bushes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.function.Function; + +public class BushFeature extends DefaultFeature { + private static final Function REPLACE; + private final Block leaves; + private final Block stem; + + public BushFeature(Block leaves, Block stem) { + this.leaves = leaves; + this.stem = stem; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES) && !world.getBlockState(pos.above()) + .is(CommonBlockTags.END_STONES)) + return false; + + float radius = MHelper.randRange(1.8F, 3.5F, random); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); + SDF sphere = new SDFSphere().setRadius(radius).setBlock(this.leaves); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; + }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return MHelper.randRange(-2F, 2F, random); + }).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere) + .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); + sphere.setReplaceFunction(REPLACE); + sphere.addPostProcess((info) -> { + if (info.getState().getBlock() instanceof LeavesBlock) { + int distance = info.getPos().distManhattan(pos); + if (distance < 7) { + return info.getState().setValue(LeavesBlock.DISTANCE, distance); + } else { + return AIR; + } + } + return info.getState(); + }); + sphere.fillRecursive(world, pos); + BlocksHelper.setWithoutUpdate(world, pos, stem); + for (Direction d : Direction.values()) { + BlockPos p = pos.relative(d); + if (world.isEmptyBlock(p)) { + if (leaves instanceof LeavesBlock) { + BlocksHelper.setWithoutUpdate( + world, + p, + leaves.defaultBlockState().setValue(LeavesBlock.DISTANCE, 1) + ); + } else { + BlocksHelper.setWithoutUpdate(world, p, leaves.defaultBlockState()); + } + } + } + + return true; + } + + static { + REPLACE = (state) -> { + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/bushes/BushWithOuterFeature.java b/src/main/java/org/betterx/betterend/world/features/bushes/BushWithOuterFeature.java new file mode 100644 index 00000000..463650b7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/bushes/BushWithOuterFeature.java @@ -0,0 +1,116 @@ +package org.betterx.betterend.world.features.bushes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.function.Function; + +public class BushWithOuterFeature extends DefaultFeature { + private static final Direction[] DIRECTIONS = Direction.values(); + private static final Function REPLACE; + private final Block outer_leaves; + private final Block leaves; + private final Block stem; + + public BushWithOuterFeature(Block leaves, Block outer_leaves, Block stem) { + this.outer_leaves = outer_leaves; + this.leaves = leaves; + this.stem = stem; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES) && !world.getBlockState(pos.above()) + .is(CommonBlockTags.END_STONES)) + return false; + + float radius = MHelper.randRange(1.8F, 3.5F, random); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); + SDF sphere = new SDFSphere().setRadius(radius).setBlock(this.leaves); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; + }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return MHelper.randRange(-2F, 2F, random); + }).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere) + .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); + sphere.setReplaceFunction(REPLACE); + sphere.addPostProcess((info) -> { + if (info.getState().getBlock() instanceof LeavesBlock) { + int distance = info.getPos().distManhattan(pos); + if (distance < 7) { + return info.getState().setValue(LeavesBlock.DISTANCE, distance); + } else { + return AIR; + } + } + return info.getState(); + }).addPostProcess((info) -> { + if (info.getState().getBlock() instanceof LeavesBlock) { + MHelper.shuffle(DIRECTIONS, random); + for (Direction dir : DIRECTIONS) { + if (info.getState(dir).isAir()) { + info.setBlockPos( + info.getPos().relative(dir), + outer_leaves.defaultBlockState().setValue(BlockStateProperties.FACING, dir) + ); + } + } + } + return info.getState(); + }); + sphere.fillRecursive(world, pos); + BlocksHelper.setWithoutUpdate(world, pos, stem); + for (Direction d : Direction.values()) { + BlockPos p = pos.relative(d); + if (world.isEmptyBlock(p)) { + if (leaves instanceof LeavesBlock) { + BlocksHelper.setWithoutUpdate( + world, + p, + leaves.defaultBlockState().setValue(LeavesBlock.DISTANCE, 1) + ); + } else { + BlocksHelper.setWithoutUpdate(world, p, leaves.defaultBlockState()); + } + } + } + + return true; + } + + static { + REPLACE = (state) -> { + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/bushes/LargeAmaranitaFeature.java b/src/main/java/org/betterx/betterend/world/features/bushes/LargeAmaranitaFeature.java new file mode 100644 index 00000000..3ce4ca0f --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/bushes/LargeAmaranitaFeature.java @@ -0,0 +1,55 @@ +package org.betterx.betterend.world.features.bushes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; + +public class LargeAmaranitaFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + + MutableBlockPos mut = new MutableBlockPos().set(pos); + int height = MHelper.randRange(2, 3, random); + for (int i = 1; i < height; i++) { + mut.setY(mut.getY() + 1); + if (!world.isEmptyBlock(mut)) { + return false; + } + } + mut.set(pos); + + BlockState state = EndBlocks.LARGE_AMARANITA_MUSHROOM.defaultBlockState(); + BlocksHelper.setWithUpdate(world, mut, state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM)); + if (height > 2) { + BlocksHelper.setWithUpdate( + world, + mut.move(Direction.UP), + state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) + ); + } + BlocksHelper.setWithUpdate( + world, + mut.move(Direction.UP), + state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) + ); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/bushes/Lumecorn.java b/src/main/java/org/betterx/betterend/world/features/bushes/Lumecorn.java new file mode 100644 index 00000000..42d7d013 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/bushes/Lumecorn.java @@ -0,0 +1,82 @@ +package org.betterx.betterend.world.features.bushes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.EndBlockProperties.LumecornShape; +import org.betterx.betterend.blocks.LumecornBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class Lumecorn extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + + int height = MHelper.randRange(4, 7, random); + MutableBlockPos mut = new MutableBlockPos().set(pos); + for (int i = 1; i < height; i++) { + mut.move(Direction.UP); + if (!world.isEmptyBlock(mut)) { + return false; + } + } + mut.set(pos); + BlockState topMiddle = EndBlocks.LUMECORN.defaultBlockState() + .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_TOP_MIDDLE); + BlockState middle = EndBlocks.LUMECORN.defaultBlockState() + .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_MIDDLE); + BlockState bottom = EndBlocks.LUMECORN.defaultBlockState() + .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_BOTTOM); + BlockState top = EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_TOP); + if (height == 4) { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_SMALL) + ); + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), bottom); + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), topMiddle); + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), top); + return true; + } + if (random.nextBoolean()) { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_SMALL) + ); + } else { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_BIG) + ); + BlocksHelper.setWithoutUpdate( + world, + mut.move(Direction.UP), + EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.MIDDLE) + ); + height--; + } + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), bottom); + for (int i = 4; i < height; i++) { + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), middle); + } + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), topMiddle); + BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), top); + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/bushes/TenaneaBushFeature.java b/src/main/java/org/betterx/betterend/world/features/bushes/TenaneaBushFeature.java new file mode 100644 index 00000000..7bf5c419 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/bushes/TenaneaBushFeature.java @@ -0,0 +1,137 @@ +package org.betterx.betterend.world.features.bushes; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class TenaneaBushFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Direction[] DIRECTIONS = Direction.values(); + + public TenaneaBushFeature() { + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; + + float radius = MHelper.randRange(1.8F, 3.5F, random); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); + BlockState leaves = EndBlocks.TENANEA_LEAVES.defaultBlockState(); + SDF sphere = new SDFSphere().setRadius(radius).setBlock(leaves); + sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( + vec.x() * 0.2, + vec.y() * 0.2, + vec.z() * 0.2 + ) * 3).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-2F, 2F, random)).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere) + .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); + sphere.setReplaceFunction(REPLACE); + List support = Lists.newArrayList(); + sphere.addPostProcess((info) -> { + if (info.getState().getBlock() instanceof LeavesBlock) { + int distance = info.getPos().distManhattan(pos); + if (distance < 7) { + if (random.nextInt(4) == 0 && info.getStateDown().isAir()) { + BlockPos d = info.getPos().below(); + support.add(d); + } + + MHelper.shuffle(DIRECTIONS, random); + for (Direction d : DIRECTIONS) { + if (info.getState(d).isAir()) { + info.setBlockPos( + info.getPos().relative(d), + EndBlocks.TENANEA_OUTER_LEAVES.defaultBlockState().setValue(FurBlock.FACING, d) + ); + } + } + + return info.getState().setValue(LeavesBlock.DISTANCE, distance); + } else { + return AIR; + } + } + return info.getState(); + }); + sphere.fillRecursive(world, pos); + BlockState stem = EndBlocks.TENANEA.getBark().defaultBlockState(); + BlocksHelper.setWithoutUpdate(world, pos, stem); + for (Direction d : Direction.values()) { + BlockPos p = pos.relative(d); + if (world.isEmptyBlock(p)) { + BlocksHelper.setWithoutUpdate(world, p, leaves.setValue(LeavesBlock.DISTANCE, 1)); + } + } + + MutableBlockPos mut = new MutableBlockPos(); + BlockState top = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); + BlockState middle = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); + BlockState bottom = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); + support.forEach((bpos) -> { + BlockState state = world.getBlockState(bpos); + if (state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) { + int count = MHelper.randRange(3, 8, random); + mut.set(bpos); + if (world.getBlockState(mut.above()).is(EndBlocks.TENANEA_LEAVES)) { + BlocksHelper.setWithoutUpdate(world, mut, top); + for (int i = 1; i < count; i++) { + mut.setY(mut.getY() - 1); + if (world.isEmptyBlock(mut.below())) { + BlocksHelper.setWithoutUpdate(world, mut, middle); + } else { + break; + } + } + BlocksHelper.setWithoutUpdate(world, mut, bottom); + } + } + }); + + return true; + } + + static { + REPLACE = (state) -> { + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/ArchFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/ArchFeature.java new file mode 100644 index 00000000..75b2c796 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/ArchFeature.java @@ -0,0 +1,86 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.primitive.SDFTorus; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.List; +import java.util.function.Function; + +public class ArchFeature extends DefaultFeature { + private final Function surfaceFunction; + private final Block block; + + public ArchFeature(Block block, Function surfaceFunction) { + this.surfaceFunction = surfaceFunction; + this.block = block; + } + + @Override + public boolean place(FeaturePlaceContext featurePlaceContext) { + final WorldGenLevel world = featurePlaceContext.level(); + BlockPos origin = featurePlaceContext.origin(); + RandomSource random = featurePlaceContext.random(); + + BlockPos pos = getPosOnSurfaceWG( + world, + new BlockPos((origin.getX() & 0xFFFFFFF0) | 7, 0, (origin.getZ() & 0xFFFFFFF0) | 7) + ); + if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + float bigRadius = MHelper.randRange(10F, 20F, random); + float smallRadius = MHelper.randRange(3F, 7F, random); + if (smallRadius + bigRadius > 23) { + smallRadius = 23 - bigRadius; + } + SDF arch = new SDFTorus().setBigRadius(bigRadius).setSmallRadius(smallRadius).setBlock(block); + arch = new SDFRotation().setRotation(MHelper.randomHorizontal(random), (float) Math.PI * 0.5F).setSource(arch); + + final float smallRadiusF = smallRadius; + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + arch = new SDFDisplacement().setFunction((vec) -> { + return (float) (Math.abs(noise.eval(vec.x() * 0.1, + vec.y() * 0.1, + vec.z() * 0.1 + )) * 3F + Math.abs(noise.eval( + vec.x() * 0.3, + vec.y() * 0.3 + 100, + vec.z() * 0.3 + )) * 1.3F) - smallRadiusF * Math.abs(1 - vec.y() / bigRadius); + }).setSource(arch); + + List surface = Lists.newArrayList(); + arch.addPostProcess((info) -> { + if (info.getStateUp().isAir()) { + return surfaceFunction.apply(info.getPos()); + } + return info.getState(); + }); + + float side = (bigRadius + smallRadius + 3F) * 2; + if (side > 47) { + side = 47; + } + arch.fillArea(world, pos, AABB.ofSize(Vec3.atCenterOf(pos), side, side, side)); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/BigAuroraCrystalFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/BigAuroraCrystalFeature.java new file mode 100644 index 00000000..19ef0ff8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/BigAuroraCrystalFeature.java @@ -0,0 +1,54 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.primitive.SDFHexPrism; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; + +public class BigAuroraCrystalFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int maxY = pos.getY() + BlocksHelper.upRay(world, pos, 16); + int minY = pos.getY() - BlocksHelper.downRay(world, pos, 16); + + if (maxY - minY < 10) { + return false; + } + + int y = MHelper.randRange(minY, maxY, random); + pos = new BlockPos(pos.getX(), y, pos.getZ()); + + int height = MHelper.randRange(5, 25, random); + SDF prism = new SDFHexPrism().setHeight(height) + .setRadius(MHelper.randRange(1.7F, 3F, random)) + .setBlock(EndBlocks.AURORA_CRYSTAL); + Vector3f vec = MHelper.randomHorizontal(random); + prism = new SDFRotation().setRotation(vec, random.nextFloat()).setSource(prism); + prism.setReplaceFunction((bState) -> { + return bState.getMaterial() + .isReplaceable() || bState.is(CommonBlockTags.GEN_END_STONES) || bState.getMaterial() + .equals(Material.PLANT) || bState + .getMaterial() + .equals(Material.LEAVES); + }); + prism.fillRecursive(world, pos); + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.AURORA_CRYSTAL); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/DesertLakeFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/DesertLakeFeature.java new file mode 100644 index 00000000..93f89680 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/DesertLakeFeature.java @@ -0,0 +1,242 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.util.BlockFixer; +import org.betterx.betterend.util.GlobalState; +import org.betterx.betterend.world.biome.EndBiome; + +public class DesertLakeFeature extends DefaultFeature { + private static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + + final RandomSource random = featureConfig.random(); + BlockPos blockPos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + double radius = MHelper.randRange(8.0, 15.0, random); + double depth = radius * 0.5 * MHelper.randRange(0.8, 1.2, random); + int dist = MHelper.floor(radius); + int dist2 = MHelper.floor(radius * 1.5); + int bott = MHelper.floor(depth); + blockPos = getPosOnSurfaceWG(world, blockPos); + + if (blockPos.getY() < 10) return false; + + int waterLevel = blockPos.getY(); + + BlockPos pos = getPosOnSurfaceRaycast(world, blockPos.north(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.south(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.east(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.west(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + BlockState state; + + int minX = blockPos.getX() - dist2; + int maxX = blockPos.getX() + dist2; + int minZ = blockPos.getZ() - dist2; + int maxZ = blockPos.getZ() + dist2; + int maskMinX = minX - 1; + int maskMinZ = minZ - 1; + + boolean[][] mask = new boolean[maxX - minX + 3][maxZ - minZ + 3]; + for (int x = minX; x <= maxX; x++) { + POS.setX(x); + int mx = x - maskMinX; + for (int z = minZ; z <= maxZ; z++) { + POS.setZ(z); + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + for (int y = waterLevel + 1; y <= waterLevel + 20; y++) { + POS.setY(y); + FluidState fluid = world.getFluidState(POS); + if (!fluid.isEmpty()) { + for (int i = -1; i < 2; i++) { + int px = mx + i; + for (int j = -1; j < 2; j++) { + int pz = mz + j; + mask[px][pz] = true; + } + } + break; + } + } + } + } + } + + for (int x = minX; x <= maxX; x++) { + POS.setX(x); + int x2 = x - blockPos.getX(); + x2 *= x2; + int mx = x - maskMinX; + for (int z = minZ; z <= maxZ; z++) { + POS.setZ(z); + int z2 = z - blockPos.getZ(); + z2 *= z2; + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + double size = 1; + for (int y = blockPos.getY(); y <= blockPos.getY() + 20; y++) { + POS.setY(y); + double add = y - blockPos.getY(); + if (add > 5) { + size *= 0.8; + add = 5; + } + double r = (add * 1.8 + radius * (NOISE.eval( + x * 0.2, + y * 0.2, + z * 0.2 + ) * 0.25 + 0.75)) - 1.0 / size; + if (r > 0) { + r *= r; + if (x2 + z2 <= r) { + state = world.getBlockState(POS); + if (state.is(CommonBlockTags.GEN_END_STONES)) { + BlocksHelper.setWithoutUpdate(world, POS, AIR); + } + pos = POS.below(); + if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { + state = EndBiome.findTopMaterial(world, + pos); //world.getBiome(pos).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + if (y > waterLevel + 1) BlocksHelper.setWithoutUpdate(world, pos, state); + else if (y > waterLevel) + BlocksHelper.setWithoutUpdate( + world, + pos, + random.nextBoolean() + ? state + : EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + else + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + } + } + } else { + break; + } + } + } + } + } + + double aspect = (radius / depth); + + for (int x = blockPos.getX() - dist; x <= blockPos.getX() + dist; x++) { + POS.setX(x); + int x2 = x - blockPos.getX(); + x2 *= x2; + int mx = x - maskMinX; + for (int z = blockPos.getZ() - dist; z <= blockPos.getZ() + dist; z++) { + POS.setZ(z); + int z2 = z - blockPos.getZ(); + z2 *= z2; + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + for (int y = blockPos.getY() - bott; y < blockPos.getY(); y++) { + POS.setY(y); + double y2 = (double) (y - blockPos.getY()) * aspect; + y2 *= y2; + double r = radius * (NOISE.eval(x * 0.2, y * 0.2, z * 0.2) * 0.25 + 0.75); + double rb = r * 1.2; + r *= r; + rb *= rb; + if (y2 + x2 + z2 <= r) { + state = world.getBlockState(POS); + if (canReplace(state)) { + state = world.getBlockState(POS.above()); + state = canReplace(state) ? (y < waterLevel ? WATER : AIR) : state; + BlocksHelper.setWithoutUpdate(world, POS, state); + } + pos = POS.below(); + if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.ENDSTONE_DUST.defaultBlockState()); + } + pos = POS.above(); + while (canReplace(state = world.getBlockState(pos)) && !state.isAir() && state.getFluidState() + .isEmpty()) { + BlocksHelper.setWithoutUpdate(world, pos, pos.getY() < waterLevel ? WATER : AIR); + pos = pos.above(); + } + } + // Make border + else if (y2 + x2 + z2 <= rb) { + state = world.getBlockState(POS); + if (state.is(CommonBlockTags.GEN_END_STONES) && world.isEmptyBlock(POS.above())) { + BlocksHelper.setWithoutUpdate(world, POS, EndBlocks.END_MOSS); + } else if (y < waterLevel) { + if (world.isEmptyBlock(POS.above())) { + state = EndBiome.findTopMaterial(world, + pos); //world.getBiome(POS).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + BlocksHelper.setWithoutUpdate( + world, + POS, + random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); + } else { + BlocksHelper.setWithoutUpdate( + world, + POS, + EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); + } + } + } + } + } + } + } + + BlockFixer.fixBlocks( + world, + new BlockPos(minX - 2, waterLevel - 2, minZ - 2), + new BlockPos(maxX + 2, blockPos.getY() + 20, maxZ + 2) + ); + + return true; + } + + private boolean canReplace(BlockState state) { + return state.getMaterial() + .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.ENDSTONE_DUST) || state.getMaterial() + .equals( + Material.PLANT) || state + .getMaterial() + .equals(Material.WATER_PLANT); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/EndLakeFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/EndLakeFeature.java new file mode 100644 index 00000000..9e957148 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/EndLakeFeature.java @@ -0,0 +1,238 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.util.BlockFixer; +import org.betterx.betterend.util.GlobalState; +import org.betterx.betterend.world.biome.EndBiome; + +public class EndLakeFeature extends DefaultFeature { + private static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); + + public EndLakeFeature() { + + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final MutableBlockPos POS = GlobalState.stateForThread().POS; + final RandomSource random = featureConfig.random(); + BlockPos blockPos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + double radius = MHelper.randRange(10.0, 20.0, random); + double depth = radius * 0.5 * MHelper.randRange(0.8, 1.2, random); + int dist = MHelper.floor(radius); + int dist2 = MHelper.floor(radius * 1.5); + int bott = MHelper.floor(depth); + blockPos = getPosOnSurfaceWG(world, blockPos); + + if (blockPos.getY() < 10) return false; + + int waterLevel = blockPos.getY(); + + BlockPos pos = getPosOnSurfaceRaycast(world, blockPos.north(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.south(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.east(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + + pos = getPosOnSurfaceRaycast(world, blockPos.west(dist).above(10), 20); + if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; + waterLevel = MHelper.min(pos.getY(), waterLevel); + BlockState state; + + int minX = blockPos.getX() - dist2; + int maxX = blockPos.getX() + dist2; + int minZ = blockPos.getZ() - dist2; + int maxZ = blockPos.getZ() + dist2; + int maskMinX = minX - 1; + int maskMinZ = minZ - 1; + + boolean[][] mask = new boolean[maxX - minX + 3][maxZ - minZ + 3]; + for (int x = minX; x <= maxX; x++) { + POS.setX(x); + int mx = x - maskMinX; + for (int z = minZ; z <= maxZ; z++) { + POS.setZ(z); + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + for (int y = waterLevel + 1; y <= waterLevel + 20; y++) { + POS.setY(y); + FluidState fluid = world.getFluidState(POS); + if (!fluid.isEmpty()) { + for (int i = -1; i < 2; i++) { + int px = mx + i; + for (int j = -1; j < 2; j++) { + int pz = mz + j; + mask[px][pz] = true; + } + } + break; + } + } + } + } + } + + for (int x = minX; x <= maxX; x++) { + POS.setX(x); + int x2 = x - blockPos.getX(); + x2 *= x2; + int mx = x - maskMinX; + for (int z = minZ; z <= maxZ; z++) { + POS.setZ(z); + int z2 = z - blockPos.getZ(); + z2 *= z2; + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + double size = 1; + for (int y = blockPos.getY(); y <= blockPos.getY() + 20; y++) { + POS.setY(y); + double add = y - blockPos.getY(); + if (add > 5) { + size *= 0.8; + add = 5; + } + double r = (add * 1.8 + radius * (NOISE.eval( + x * 0.2, + y * 0.2, + z * 0.2 + ) * 0.25 + 0.75)) - 1.0 / size; + if (r > 0) { + r *= r; + if (x2 + z2 <= r) { + state = world.getBlockState(POS); + if (state.is(CommonBlockTags.GEN_END_STONES)) { + BlocksHelper.setWithoutUpdate(world, POS, AIR); + } + pos = POS.below(); + if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { + state = EndBiome.findTopMaterial(world, pos); + if (y > waterLevel + 1) BlocksHelper.setWithoutUpdate(world, pos, state); + else if (y > waterLevel) + BlocksHelper.setWithoutUpdate( + world, + pos, + random.nextBoolean() + ? state + : EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + else + BlocksHelper.setWithoutUpdate( + world, + pos, + EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + } + } + } else { + break; + } + } + } + } + } + + double aspect = (radius / depth); + + for (int x = blockPos.getX() - dist; x <= blockPos.getX() + dist; x++) { + POS.setX(x); + int x2 = x - blockPos.getX(); + x2 *= x2; + int mx = x - maskMinX; + for (int z = blockPos.getZ() - dist; z <= blockPos.getZ() + dist; z++) { + POS.setZ(z); + int z2 = z - blockPos.getZ(); + z2 *= z2; + int mz = z - maskMinZ; + if (!mask[mx][mz]) { + for (int y = blockPos.getY() - bott; y < blockPos.getY(); y++) { + POS.setY(y); + double y2 = (double) (y - blockPos.getY()) * aspect; + y2 *= y2; + double r = radius * (NOISE.eval(x * 0.2, y * 0.2, z * 0.2) * 0.25 + 0.75); + double rb = r * 1.2; + r *= r; + rb *= rb; + if (y2 + x2 + z2 <= r) { + state = world.getBlockState(POS); + if (canReplace(state)) { + state = world.getBlockState(POS.above()); + state = canReplace(state) ? (y < waterLevel ? WATER : AIR) : state; + BlocksHelper.setWithoutUpdate(world, POS, state); + } + pos = POS.below(); + if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.ENDSTONE_DUST.defaultBlockState()); + } + pos = POS.above(); + while (canReplace(state = world.getBlockState(pos)) && !state.isAir() && state.getFluidState() + .isEmpty()) { + BlocksHelper.setWithoutUpdate(world, pos, pos.getY() < waterLevel ? WATER : AIR); + pos = pos.above(); + } + } + // Make border + else if (y < waterLevel && y2 + x2 + z2 <= rb) { + if (world.isEmptyBlock(POS.above())) { + state = EndBiome.findTopMaterial(world, pos); +// state = world.getBiome(POS) +// .getGenerationSettings() +// .getSurfaceBuilderConfig() +// .getTopMaterial(); + BlocksHelper.setWithoutUpdate( + world, + POS, + random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() + ); + BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); + } else { + BlocksHelper.setWithoutUpdate(world, POS, EndBlocks.ENDSTONE_DUST.defaultBlockState()); + BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); + } + } + } + } + } + } + + BlockFixer.fixBlocks( + world, + new BlockPos(minX - 2, waterLevel - 2, minZ - 2), + new BlockPos(maxX + 2, blockPos.getY() + 20, maxZ + 2) + ); + + return true; + } + + private boolean canReplace(BlockState state) { + return state.getMaterial() + .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.ENDSTONE_DUST) || state.getMaterial() + .equals( + Material.PLANT) || state + .getMaterial() + .equals(Material.WATER_PLANT); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/FallenPillarFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/FallenPillarFeature.java new file mode 100644 index 00000000..8ca5c0c2 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/FallenPillarFeature.java @@ -0,0 +1,67 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +public class FallenPillarFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + pos = getPosOnSurface( + world, + new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) + ); + if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + float height = MHelper.randRange(20F, 40F, random); + float radius = MHelper.randRange(2F, 4F, random); + SDF pillar = new SDFCappedCone().setRadius1(radius) + .setRadius2(radius) + .setHeight(height * 0.5F) + .setBlock(Blocks.OBSIDIAN); + pillar = new SDFTranslate().setTranslate(0, radius * 0.5F - 2, 0).setSource(pillar); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + pillar = new SDFDisplacement().setFunction((vec) -> { + return (float) (noise.eval(vec.x() * 0.3, vec.y() * 0.3, vec.z() * 0.3) * 0.5F); + }).setSource(pillar); + Vector3f vec = MHelper.randomHorizontal(random); + float angle = (float) random.nextGaussian() * 0.05F + (float) Math.PI; + pillar = new SDFRotation().setRotation(vec, angle).setSource(pillar); + + BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); + pillar.addPostProcess((info) -> { + if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { + return mossy; + } + return info.getState(); + }).setReplaceFunction((state) -> { + return state.getMaterial() + .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() + .equals(Material.PLANT); + }).fillRecursive(world, pos); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/FloatingSpireFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/FloatingSpireFeature.java new file mode 100644 index 00000000..c8e8995e --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/FloatingSpireFeature.java @@ -0,0 +1,97 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.List; +import java.util.Optional; + +public class FloatingSpireFeature extends SpireFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); + int minY = getYOnSurface(world, pos.getX(), pos.getZ()); + int y = minY > 57 ? MHelper.floor(MHelper.randRange(minY, minY * 2, random) * 0.5F + 32) : MHelper.randRange( + 64, + 192, + random + ); + pos = new BlockPos(pos.getX(), y, pos.getZ()); + + SDF sdf = new SDFSphere().setRadius(MHelper.randRange(2, 3, random)).setBlock(Blocks.END_STONE); + int count = MHelper.randRange(3, 5, random); + + for (int i = 0; i < count; i++) { + float rMin = (i * 1.3F) + 2.5F; + sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); + } + for (int i = count - 1; i > 0; i--) { + float rMin = (i * 1.3F) + 2.5F; + sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); + } + + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + sdf = new SDFDisplacement().setFunction((vec) -> { + return (float) (Math.abs(noise.eval( + vec.x() * 0.1, + vec.y() * 0.1, + vec.z() * 0.1 + )) * 3F + Math.abs(noise.eval(vec.x() * 0.3, + vec.y() * 0.3 + 100, + vec.z() * 0.3)) * 1.3F); + }).setSource(sdf); + final BlockPos center = pos; + List support = Lists.newArrayList(); + sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { + if (info.getStateUp().isAir()) { + if (random.nextInt(16) == 0) { + support.add(info.getPos().above()); + } + return EndBiome.findTopMaterial(world, + info.getPos());//world.getBiome(info.getPos()).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + } else if (info.getState(Direction.UP, 3).isAir()) { + return EndBiome.findUnderMaterial(world, info.getPos()); +// return world.getBiome(info.getPos()) +// .getGenerationSettings() +// .getSurfaceBuilderConfig() +// .getUnderMaterial(); + } + return info.getState(); + }); + sdf.fillRecursive(world, center); + + support.forEach((bpos) -> { + if (BiomeAPI.getFromBiome(world.getBiome(bpos)) == EndBiomes.BLOSSOMING_SPIRES) { + EndFeatures.TENANEA_BUSH.getFeature() + .place(new FeaturePlaceContext<>(Optional.empty(), + world, + chunkGenerator, + random, + bpos, + null)); + } + }); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/GeyserFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/GeyserFeature.java new file mode 100644 index 00000000..2ea9830b --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/GeyserFeature.java @@ -0,0 +1,292 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.sdf.primitive.SDFFlatland; +import org.betterx.bclib.sdf.primitive.SDFPrimitive; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.HydrothermalVentBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.util.BlockFixer; + +import java.util.Optional; +import java.util.function.Function; + +public class GeyserFeature extends DefaultFeature { + protected static final Function REPLACE1; + protected static final Function REPLACE2; + private static final Function IGNORE; + private static final Direction[] HORIZONTAL = BlocksHelper.makeHorizontal(); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final WorldGenLevel world = featureConfig.level(); + final BlockPos pos = getPosOnSurfaceWG(world, featureConfig.origin()); + final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); + + if (pos.getY() < 10) { + return false; + } + + MutableBlockPos bpos = new MutableBlockPos().set(pos); + bpos.setY(bpos.getY() - 1); + BlockState state = world.getBlockState(bpos); + while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + + if (pos.getY() - bpos.getY() < 25) { + return false; + } + + int halfHeight = MHelper.randRange(10, 20, random); + float radius1 = halfHeight * 0.5F; + float radius2 = halfHeight * 0.1F + 0.5F; + SDF sdf = new SDFCappedCone().setHeight(halfHeight) + .setRadius1(radius1) + .setRadius2(radius2) + .setBlock(EndBlocks.SULPHURIC_ROCK.stone); + sdf = new SDFTranslate().setTranslate(0, halfHeight - 3, 0).setSource(sdf); + + int count = halfHeight; + for (int i = 0; i < count; i++) { + int py = i << 1; + float delta = (float) i / (float) (count - 1); + float radius = Mth.lerp(delta, radius1, radius2) * 1.3F; + + SDF bowl = new SDFCappedCone().setHeight(radius) + .setRadius1(0) + .setRadius2(radius) + .setBlock(EndBlocks.SULPHURIC_ROCK.stone); + + SDF brimstone = new SDFCappedCone().setHeight(radius) + .setRadius1(0) + .setRadius2(radius) + .setBlock(EndBlocks.BRIMSTONE); + brimstone = new SDFTranslate().setTranslate(0, 2F, 0).setSource(brimstone); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(brimstone); + bowl = new SDFUnion().setSourceA(brimstone).setSourceB(bowl); + + SDF water = new SDFCappedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(Blocks.WATER); + water = new SDFTranslate().setTranslate(0, 4, 0).setSource(water); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(water); + bowl = new SDFUnion().setSourceA(water).setSourceB(bowl); + + final OpenSimplexNoise noise1 = new OpenSimplexNoise(random.nextLong()); + final OpenSimplexNoise noise2 = new OpenSimplexNoise(random.nextLong()); + + bowl = new SDFCoordModify().setFunction((vec) -> { + float dx = (float) noise1.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); + float dz = (float) noise2.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); + vec.set(vec.x() + dx, vec.y(), vec.z() + dz); + }).setSource(bowl); + + SDF cut = new SDFFlatland().setBlock(Blocks.AIR); + cut = new SDFInvert().setSource(cut); + cut = new SDFTranslate().setTranslate(0, radius - 2, 0).setSource(cut); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(cut); + + bowl = new SDFTranslate().setTranslate(radius, py - radius, 0).setSource(bowl); + bowl = new SDFRotation().setRotation(Vector3f.YP, i * 4F).setSource(bowl); + sdf = new SDFUnion().setSourceA(sdf).setSourceB(bowl); + } + sdf.setReplaceFunction(REPLACE2).fillRecursive(world, pos); + + radius2 = radius2 * 0.5F; + if (radius2 < 0.7F) { + radius2 = 0.7F; + } + final OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + + SDFPrimitive obj1; + SDFPrimitive obj2; + + obj1 = new SDFCappedCone().setHeight(halfHeight + 5).setRadius1(radius1 * 0.5F).setRadius2(radius2); + sdf = new SDFTranslate().setTranslate(0, halfHeight - 13, 0).setSource(obj1); + sdf = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.3F, vec.y() * 0.3F, vec.z() * 0.3F) * 0.5F; + }).setSource(sdf); + + obj2 = new SDFSphere().setRadius(radius1); + SDF cave = new SDFScale3D().setScale(1.5F, 1, 1.5F).setSource(obj2); + cave = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.1F, vec.y() * 0.1F, vec.z() * 0.1F) * 2F; + }).setSource(cave); + cave = new SDFTranslate().setTranslate(0, -halfHeight - 10, 0).setSource(cave); + + sdf = new SDFSmoothUnion().setRadius(5).setSourceA(cave).setSourceB(sdf); + + obj1.setBlock(WATER); + obj2.setBlock(WATER); + sdf.setReplaceFunction(REPLACE2); + sdf.fillRecursive(world, pos); + + obj1.setBlock(EndBlocks.BRIMSTONE); + obj2.setBlock(EndBlocks.BRIMSTONE); + new SDFDisplacement().setFunction((vec) -> { + return -2F; + }).setSource(sdf).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); + + obj1.setBlock(EndBlocks.SULPHURIC_ROCK.stone); + obj2.setBlock(EndBlocks.SULPHURIC_ROCK.stone); + new SDFDisplacement().setFunction((vec) -> { + return -4F; + }).setSource(cave).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); + + obj1.setBlock(Blocks.END_STONE); + obj2.setBlock(Blocks.END_STONE); + new SDFDisplacement().setFunction((vec) -> { + return -6F; + }).setSource(cave).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); + + BlocksHelper.setWithoutUpdate(world, pos, WATER); + MutableBlockPos mut = new MutableBlockPos().set(pos); + count = getYOnSurface(world, pos.getX(), pos.getZ()) - pos.getY(); + for (int i = 0; i < count; i++) { + BlocksHelper.setWithoutUpdate(world, mut, WATER); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlocksHelper.setWithoutUpdate(world, mut.relative(dir), WATER); + } + mut.setY(mut.getY() + 1); + } + + for (int i = 0; i < 150; i++) { + mut.set(pos) + .move(MHelper.floor(random.nextGaussian() * 4 + 0.5), + -halfHeight - 10, + MHelper.floor(random.nextGaussian() * 4 + 0.5) + ); + float distRaw = MHelper.length(mut.getX() - pos.getX(), mut.getZ() - pos.getZ()); + int dist = MHelper.floor(6 - distRaw) + random.nextInt(2); + if (dist >= 0) { + state = world.getBlockState(mut); + while (!state.getFluidState().isEmpty() || state.getMaterial().equals(Material.WATER_PLANT)) { + mut.setY(mut.getY() - 1); + state = world.getBlockState(mut); + } + if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()) + .is(EndBlocks.HYDROTHERMAL_VENT)) { + for (int j = 0; j <= dist; j++) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); + MHelper.shuffle(HORIZONTAL, random); + for (Direction dir : HORIZONTAL) { + BlockPos p = mut.relative(dir); + if (random.nextBoolean() && world.getBlockState(p).is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate( + world, + p, + EndBlocks.TUBE_WORM.defaultBlockState() + .setValue(HorizontalDirectionalBlock.FACING, dir) + ); + } + } + mut.setY(mut.getY() + 1); + } + state = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() + .setValue(HydrothermalVentBlock.ACTIVATED, distRaw < 2); + BlocksHelper.setWithoutUpdate(world, mut, state); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + while (state.is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + } + } + } + } + + for (int i = 0; i < 10; i++) { + mut.set(pos) + .move(MHelper.floor(random.nextGaussian() * 0.7 + 0.5), + -halfHeight - 10, + MHelper.floor(random.nextGaussian() * 0.7 + 0.5) + ); + float distRaw = MHelper.length(mut.getX() - pos.getX(), mut.getZ() - pos.getZ()); + int dist = MHelper.floor(6 - distRaw) + random.nextInt(2); + if (dist >= 0) { + state = world.getBlockState(mut); + while (state.is(Blocks.WATER)) { + mut.setY(mut.getY() - 1); + state = world.getBlockState(mut); + } + if (state.is(CommonBlockTags.GEN_END_STONES)) { + for (int j = 0; j <= dist; j++) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); + mut.setY(mut.getY() + 1); + } + state = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() + .setValue(HydrothermalVentBlock.ACTIVATED, distRaw < 2); + BlocksHelper.setWithoutUpdate(world, mut, state); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + while (state.is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + } + } + } + } + + EndFeatures.SULPHURIC_LAKE.getFeature() + .place(new FeaturePlaceContext<>(Optional.empty(), + world, + chunkGenerator, + random, + pos, + null)); + + double distance = radius1 * 1.7; + BlockPos start = pos.offset(-distance, -halfHeight - 15 - distance, -distance); + BlockPos end = pos.offset(distance, -halfHeight - 5 + distance, distance); + BlockFixer.fixBlocks(world, start, end); + + return true; + } + + static { + REPLACE1 = (state) -> { + return state.isAir() || (state.is(CommonBlockTags.GEN_END_STONES)); + }; + + REPLACE2 = (state) -> { + if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.HYDROTHERMAL_VENT) || state.is(EndBlocks.SULPHUR_CRYSTAL)) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = (state) -> { + return state.is(Blocks.WATER) || state.is(Blocks.CAVE_AIR) || state.is(EndBlocks.SULPHURIC_ROCK.stone) || state + .is(EndBlocks.BRIMSTONE); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/IceStarFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/IceStarFeature.java new file mode 100644 index 00000000..4c5e9e6c --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/IceStarFeature.java @@ -0,0 +1,114 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.operator.SDFUnion; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.ArrayList; +import java.util.List; + +public class IceStarFeature extends DefaultFeature { + private final float minSize; + private final float maxSize; + private final int minCount; + private final int maxCount; + + public IceStarFeature(float minSize, float maxSize, int minCount, int maxCount) { + this.minSize = minSize; + this.maxSize = maxSize; + this.minCount = minCount; + this.maxCount = maxCount; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + float size = MHelper.randRange(minSize, maxSize, random); + int count = MHelper.randRange(minCount, maxCount, random); + List points = getFibonacciPoints(count); + SDF sdf = null; + SDF spike = new SDFCappedCone().setRadius1(3 + (size - 5) * 0.2F) + .setRadius2(0) + .setHeight(size) + .setBlock(EndBlocks.DENSE_SNOW); + spike = new SDFTranslate().setTranslate(0, size - 0.5F, 0).setSource(spike); + for (Vector3f point : points) { + SDF rotated = spike; + point = MHelper.normalize(point); + float angle = MHelper.angle(Vector3f.YP, point); + if (angle > 0.01F && angle < 3.14F) { + Vector3f axis = MHelper.normalize(MHelper.cross(Vector3f.YP, point)); + rotated = new SDFRotation().setRotation(axis, angle).setSource(spike); + } else if (angle > 1) { + rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(spike); + } + sdf = (sdf == null) ? rotated : new SDFUnion().setSourceA(sdf).setSourceB(rotated); + } + + int x1 = (pos.getX() >> 4) << 4; + int z1 = (pos.getZ() >> 4) << 4; + pos = new BlockPos(x1 + random.nextInt(16), MHelper.randRange(32, 128, random), z1 + random.nextInt(16)); + + final float ancientRadius = size * 0.7F; + final float denseRadius = size * 0.9F; + final float iceRadius = size < 7 ? size * 5 : size * 1.3F; + final float randScale = size * 0.3F; + + final BlockPos center = pos; + final BlockState ice = EndBlocks.EMERALD_ICE.defaultBlockState(); + final BlockState dense = EndBlocks.DENSE_EMERALD_ICE.defaultBlockState(); + final BlockState ancient = EndBlocks.ANCIENT_EMERALD_ICE.defaultBlockState(); + final SDF sdfCopy = sdf; + + sdf.addPostProcess((info) -> { + BlockPos bpos = info.getPos(); + float px = bpos.getX() - center.getX(); + float py = bpos.getY() - center.getY(); + float pz = bpos.getZ() - center.getZ(); + float distance = MHelper.length(px, py, pz) + sdfCopy.getDistance( + px, + py, + pz + ) * 0.4F + random.nextFloat() * randScale; + if (distance < ancientRadius) { + return ancient; + } else if (distance < denseRadius) { + return dense; + } else if (distance < iceRadius) { + return ice; + } + return info.getState(); + }).fillRecursive(world, pos); + + return true; + } + + private List getFibonacciPoints(int count) { + float max = count - 1; + List result = new ArrayList(count); + for (int i = 0; i < count; i++) { + float y = 1F - (i / max) * 2F; + float radius = (float) Math.sqrt(1F - y * y); + float theta = MHelper.PHI * i; + float x = (float) Math.cos(theta) * radius; + float z = (float) Math.sin(theta) * radius; + result.add(new Vector3f(x, y, z)); + } + return result; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianBoulderFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianBoulderFeature.java new file mode 100644 index 00000000..a11239f8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianBoulderFeature.java @@ -0,0 +1,76 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +public class ObsidianBoulderFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + pos = getPosOnSurface( + world, + new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) + ); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { + return false; + } + + int count = MHelper.randRange(1, 5, random); + for (int i = 0; i < count; i++) { + BlockPos p = getPosOnSurface( + world, + new BlockPos(pos.getX() + random.nextInt(16) - 8, pos.getY(), pos.getZ() + random.nextInt(16) - 8) + ); + makeBoulder(world, p, random); + } + + return true; + } + + private void makeBoulder(WorldGenLevel world, BlockPos pos, RandomSource random) { + if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { + return; + } + + float radius = MHelper.randRange(1F, 5F, random); + SDF sphere = new SDFSphere().setRadius(radius).setBlock(Blocks.OBSIDIAN); + float sx = MHelper.randRange(0.7F, 1.3F, random); + float sy = MHelper.randRange(0.7F, 1.3F, random); + float sz = MHelper.randRange(0.7F, 1.3F, random); + sphere = new SDFScale3D().setScale(sx, sy, sz).setSource(sphere); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) (noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 1.5F); + }).setSource(sphere); + + BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); + sphere.addPostProcess((info) -> { + if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { + return mossy; + } + return info.getState(); + }).setReplaceFunction((state) -> { + return state.getMaterial() + .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() + .equals(Material.PLANT); + }).fillRecursive(world, pos); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianPillarBasementFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianPillarBasementFeature.java new file mode 100644 index 00000000..4f34e587 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/ObsidianPillarBasementFeature.java @@ -0,0 +1,74 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.sdf.primitive.SDFFlatland; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +public class ObsidianPillarBasementFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + pos = getPosOnSurface( + world, + new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) + ); + if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + float height = MHelper.randRange(10F, 35F, random); + float radius = MHelper.randRange(2F, 5F, random); + SDF pillar = new SDFCappedCone().setRadius1(radius) + .setRadius2(radius) + .setHeight(height * 0.5F) + .setBlock(Blocks.OBSIDIAN); + pillar = new SDFTranslate().setTranslate(0, height * 0.5F - 3, 0).setSource(pillar); + SDF cut = new SDFFlatland().setBlock(Blocks.OBSIDIAN); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + cut = new SDFDisplacement().setFunction((vec) -> { + return (float) (noise.eval(vec.x() * 0.2, vec.z() * 0.2) * 3); + }).setSource(cut); + Vector3f vec = MHelper.randomHorizontal(random); + float angle = random.nextFloat() * 0.5F + (float) Math.PI; + cut = new SDFRotation().setRotation(vec, angle).setSource(cut); + cut = new SDFTranslate().setTranslate(0, height * 0.7F - 3, 0).setSource(cut); + pillar = new SDFSubtraction().setSourceA(pillar).setSourceB(cut); + vec = MHelper.randomHorizontal(random); + angle = random.nextFloat() * 0.2F; + pillar = new SDFRotation().setRotation(vec, angle).setSource(pillar); + BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); + pillar.addPostProcess((info) -> { + if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { + return mossy; + } + return info.getState(); + }).setReplaceFunction((state) -> { + return state.getMaterial() + .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() + .equals(Material.PLANT); + }).fillRecursive(world, pos); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/OreLayerFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/OreLayerFeature.java new file mode 100644 index 00000000..8bb7bb8d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/OreLayerFeature.java @@ -0,0 +1,76 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFCoordModify; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; + +public class OreLayerFeature extends DefaultFeature { + private static final SDFSphere SPHERE; + private static final SDFCoordModify NOISE; + private static final SDF FUNCTION; + + private final BlockState state; + private final float radius; + private final int minY; + private final int maxY; + private OpenSimplexNoise noise; + + public OreLayerFeature(BlockState state, float radius, int minY, int maxY) { + this.state = state; + this.radius = radius; + this.minY = minY; + this.maxY = maxY; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + float radius = this.radius * 0.5F; + int r = MHelper.floor(radius + 1); + int posX = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getX(); + int posZ = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getZ(); + int posY = MHelper.randRange(minY, maxY, random); + + if (noise == null) { + noise = new OpenSimplexNoise(world.getSeed()); + } + + SPHERE.setRadius(radius).setBlock(state); + NOISE.setFunction((vec) -> { + double x = (vec.x() + pos.getX()) * 0.1; + double z = (vec.z() + pos.getZ()) * 0.1; + double offset = noise.eval(x, z); + vec.set(vec.x(), vec.y() + (float) offset * 8, vec.z()); + }); + FUNCTION.fillRecursive(world, new BlockPos(posX, posY, posZ)); + return true; + } + + static { + SPHERE = new SDFSphere(); + NOISE = new SDFCoordModify(); + + SDF body = SPHERE; + body = new SDFScale3D().setScale(1, 0.2F, 1).setSource(body); + body = NOISE.setSource(body); + body.setReplaceFunction((state) -> { + return state.is(Blocks.END_STONE); + }); + + FUNCTION = body; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SingleBlockFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SingleBlockFeature.java new file mode 100644 index 00000000..dfda30fd --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SingleBlockFeature.java @@ -0,0 +1,41 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +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.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; + +public class SingleBlockFeature extends DefaultFeature { + private final Block block; + + public SingleBlockFeature(Block block) { + this.block = block; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + BlockState state = block.defaultBlockState(); + if (block.getStateDefinition().getProperty("waterlogged") != null) { + boolean waterlogged = !world.getFluidState(pos).isEmpty(); + state = state.setValue(BlockStateProperties.WATERLOGGED, waterlogged); + } + BlocksHelper.setWithoutUpdate(world, pos, state); + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SmaragdantCrystalFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SmaragdantCrystalFeature.java new file mode 100644 index 00000000..d5e0fe31 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SmaragdantCrystalFeature.java @@ -0,0 +1,63 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; + +public class SmaragdantCrystalFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + MutableBlockPos mut = new MutableBlockPos(); + int count = MHelper.randRange(15, 30, random); + BlockState crystal = EndBlocks.SMARAGDANT_CRYSTAL.defaultBlockState(); + BlockState shard = EndBlocks.SMARAGDANT_CRYSTAL_SHARD.defaultBlockState(); + for (int i = 0; i < count; i++) { + mut.set(pos) + .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), 5, MHelper.floor(random.nextGaussian() * 2 + 0.5)); + int dist = MHelper.floor(1.5F - MHelper.length( + mut.getX() - pos.getX(), + mut.getZ() - pos.getZ() + )) + random.nextInt(3); + if (dist > 0) { + BlockState state = world.getBlockState(mut); + for (int n = 0; n < 10 && state.isAir(); n++) { + mut.setY(mut.getY() - 1); + state = world.getBlockState(mut); + } + if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()) + .is(crystal.getBlock())) { + for (int j = 0; j <= dist; j++) { + BlocksHelper.setWithoutUpdate(world, mut, crystal); + mut.setY(mut.getY() + 1); + } + boolean waterlogged = !world.getFluidState(mut).isEmpty(); + BlocksHelper.setWithoutUpdate( + world, + mut, + shard.setValue(BlockStateProperties.WATERLOGGED, waterlogged) + ); + } + } + } + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SpireFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SpireFeature.java new file mode 100644 index 00000000..37a8a30f --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SpireFeature.java @@ -0,0 +1,121 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFSmoothUnion; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.registry.EndFeatures; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class SpireFeature extends DefaultFeature { + protected static final Function REPLACE; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); + pos = getPosOnSurfaceWG(world, pos); + if (pos.getY() < 10 || !world.getBlockState(pos.below(3)) + .is(CommonBlockTags.GEN_END_STONES) || !world.getBlockState(pos.below(6)) + .is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + SDF sdf = new SDFSphere().setRadius(MHelper.randRange(2, 3, random)).setBlock(Blocks.END_STONE); + int count = MHelper.randRange(3, 7, random); + for (int i = 0; i < count; i++) { + float rMin = (i * 1.3F) + 2.5F; + sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); + } + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + sdf = new SDFDisplacement().setFunction((vec) -> { + return (float) (Math.abs(noise.eval( + vec.x() * 0.1, + vec.y() * 0.1, + vec.z() * 0.1 + )) * 3F + Math.abs(noise.eval(vec.x() * 0.3, + vec.y() * 0.3 + 100, + vec.z() * 0.3)) * 1.3F); + }).setSource(sdf); + final BlockPos center = pos; + List support = Lists.newArrayList(); + sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { + if (info.getStateUp().isAir()) { + if (random.nextInt(16) == 0) { + support.add(info.getPos().above()); + } + return EndBiome.findTopMaterial(world, info.getPos()); + //return world.getBiome(info.getPos()).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + } else if (info.getState(Direction.UP, 3).isAir()) { + return EndBiome.findUnderMaterial(world, info.getPos()); +// return world.getBiome(info.getPos()) +// .getGenerationSettings() +// .getSurfaceBuilderConfig() +// .getUnderMaterial(); + } + return info.getState(); + }).fillRecursive(world, center); + + support.forEach((bpos) -> { + if (BiomeAPI.getFromBiome(world.getBiome(bpos)) == EndBiomes.BLOSSOMING_SPIRES) { + EndFeatures.TENANEA_BUSH.getFeature() + .place(new FeaturePlaceContext<>(Optional.empty(), + world, + chunkGenerator, + random, + bpos, + null)); + } + }); + + return true; + } + + protected SDF addSegment(SDF sdf, float radius, RandomSource random) { + SDF sphere = new SDFSphere().setRadius(radius).setBlock(Blocks.END_STONE); + SDF offseted = new SDFTranslate().setTranslate(0, radius + random.nextFloat() * 0.25F * radius, 0) + .setSource(sdf); + return new SDFSmoothUnion().setRadius(radius * 0.5F).setSourceA(sphere).setSourceB(offseted); + } + + static { + REPLACE = (state) -> { + if (state.is(CommonBlockTags.END_STONES)) { + return true; + } + if (state.getBlock() instanceof LeavesBlock) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/StalactiteFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/StalactiteFeature.java new file mode 100644 index 00000000..d5a8f058 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/StalactiteFeature.java @@ -0,0 +1,84 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +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.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.StalactiteBlock; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; + +public class StalactiteFeature extends DefaultFeature { + private final boolean ceiling; + private final Block[] ground; + private final Block block; + + public StalactiteFeature(boolean ceiling, Block block, Block... ground) { + this.ceiling = ceiling; + this.ground = ground; + this.block = block; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!isGround(world.getBlockState(ceiling ? pos.above() : pos.below()).getBlock())) { + return false; + } + + MutableBlockPos mut = new MutableBlockPos().set(pos); + int height = random.nextInt(16); + int dir = ceiling ? -1 : 1; + boolean stalagnate = false; + + for (int i = 1; i <= height; i++) { + mut.setY(pos.getY() + i * dir); + BlockState state = world.getBlockState(mut); + if (!state.getMaterial().isReplaceable()) { + stalagnate = state.is(CommonBlockTags.GEN_END_STONES); + height = i; + break; + } + } + + if (!stalagnate && height > 7) { + height = random.nextInt(8); + } + + float center = height * 0.5F; + for (int i = 0; i < height; i++) { + mut.setY(pos.getY() + i * dir); + int size = stalagnate ? Mth.clamp((int) (Mth.abs(i - center) + 1), 1, 7) : height - i - 1; + boolean waterlogged = !world.getFluidState(mut).isEmpty(); + BlockState base = block.defaultBlockState() + .setValue(StalactiteBlock.SIZE, size) + .setValue(BlockStateProperties.WATERLOGGED, waterlogged); + BlockState state = stalagnate ? base.setValue( + StalactiteBlock.IS_FLOOR, + dir > 0 ? i < center : i > center + ) : base.setValue(StalactiteBlock.IS_FLOOR, dir > 0); + BlocksHelper.setWithoutUpdate(world, mut, state); + } + + return true; + } + + private boolean isGround(Block block) { + for (Block b : ground) { + if (b == block) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SulphurHillFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SulphurHillFeature.java new file mode 100644 index 00000000..e421a486 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SulphurHillFeature.java @@ -0,0 +1,96 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +public class SulphurHillFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + pos = getPosOnSurfaceWG(world, pos); + if (pos.getY() < 57 || pos.getY() > 70) { + return false; + } + + int count = MHelper.randRange(5, 13, random); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + for (int i = 0; i < count; i++) { + int dist = count - i; + int px = pos.getX() + MHelper.floor(random.nextGaussian() * dist * 0.6 + 0.5); + int pz = pos.getZ() + MHelper.floor(random.nextGaussian() * dist * 0.6 + 0.5); + int py = getYOnSurface(world, px, pz); + if (py > 56 && py - pos.getY() <= count) { + makeCircle(world, new BlockPos(px, py, pz), noise, random); + } + } + return true; + } + + private void makeCircle(WorldGenLevel world, BlockPos pos, OpenSimplexNoise noise, RandomSource random) { + int radius = MHelper.randRange(5, 9, random); + int min = -radius - 3; + int max = radius + 4; + MutableBlockPos mut = new MutableBlockPos(); + BlockState rock = EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState(); + BlockState brimstone = EndBlocks.BRIMSTONE.defaultBlockState().setValue(BlockProperties.ACTIVE, true); + for (int x = min; x < max; x++) { + int x2 = x * x; + int px = pos.getX() + x; + mut.setX(px); + for (int z = min; z < max; z++) { + int z2 = z * z; + int pz = pos.getZ() + z; + mut.setZ(pz); + double r1 = radius * (noise.eval(px * 0.1, pz * 0.1) * 0.2 + 0.8); + double r2 = r1 - 1.5; + double r3 = r1 - 3; + int d = x2 + z2; + mut.setY(pos.getY()); + BlockState state = world.getBlockState(mut); + if (state.getMaterial().isReplaceable() || state.is(EndBlocks.HYDROTHERMAL_VENT)) { + if (d < r2 * r2) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.WATER); + mut.move(Direction.DOWN); + if (d < r3 * r3) { + BlocksHelper.setWithoutUpdate(world, mut, Blocks.WATER); + mut.move(Direction.DOWN); + } + BlocksHelper.setWithoutUpdate(world, mut, brimstone); + mut.move(Direction.DOWN); + state = world.getBlockState(mut); + int maxIt = MHelper.floor(10 - Math.sqrt(d)) + random.nextInt(1); + for (int i = 0; i < maxIt && state.getMaterial().isReplaceable(); i++) { + BlocksHelper.setWithoutUpdate(world, mut, rock); + mut.move(Direction.DOWN); + } + } else if (d < r1 * r1) { + BlocksHelper.setWithoutUpdate(world, mut, brimstone); + mut.move(Direction.DOWN); + state = world.getBlockState(mut); + int maxIt = MHelper.floor(10 - Math.sqrt(d)) + random.nextInt(1); + for (int i = 0; i < maxIt && state.getMaterial().isReplaceable(); i++) { + BlocksHelper.setWithoutUpdate(world, mut, rock); + mut.move(Direction.DOWN); + } + } + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricCaveFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricCaveFeature.java new file mode 100644 index 00000000..96eb2b25 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricCaveFeature.java @@ -0,0 +1,222 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Sets; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.EndBlockProperties; +import org.betterx.betterend.blocks.SulphurCrystalBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.util.BlockFixer; + +import java.util.Set; + +public class SulphuricCaveFeature extends DefaultFeature { + private static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); + private static final BlockState WATER = Blocks.WATER.defaultBlockState(); + private static final Direction[] HORIZONTAL = BlocksHelper.makeHorizontal(); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + int radius = MHelper.randRange(10, 30, random); + + int top = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); + MutableBlockPos bpos = new MutableBlockPos(); + bpos.setX(pos.getX()); + bpos.setZ(pos.getZ()); + bpos.setY(top - 1); + + BlockState state = world.getBlockState(bpos); + while (!state.is(CommonBlockTags.GEN_END_STONES) && bpos.getY() > 5) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + if (bpos.getY() < 10) { + return false; + } + top = (int) (bpos.getY() - (radius * 1.3F + 5)); + + while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + int bottom = (int) (bpos.getY() + radius * 1.3F + 5); + + if (top <= bottom) { + return false; + } + + MutableBlockPos mut = new MutableBlockPos(); + pos = new BlockPos(pos.getX(), MHelper.randRange(bottom, top, random), pos.getZ()); + + OpenSimplexNoise noise = new OpenSimplexNoise(MHelper.getSeed(534, pos.getX(), pos.getZ())); + + int x1 = pos.getX() - radius - 5; + int z1 = pos.getZ() - radius - 5; + int x2 = pos.getX() + radius + 5; + int z2 = pos.getZ() + radius + 5; + int y1 = MHelper.floor(pos.getY() - (radius + 5) / 1.6); + int y2 = MHelper.floor(pos.getY() + (radius + 5) / 1.6); + + double hr = radius * 0.75; + double nr = radius * 0.25; + + Set brimstone = Sets.newHashSet(); + BlockState rock = EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState(); + int waterLevel = pos.getY() + MHelper.randRange(MHelper.floor(radius * 0.8), radius, random); + for (int x = x1; x <= x2; x++) { + int xsq = x - pos.getX(); + xsq *= xsq; + mut.setX(x); + for (int z = z1; z <= z2; z++) { + int zsq = z - pos.getZ(); + zsq *= zsq; + mut.setZ(z); + for (int y = y1; y <= y2; y++) { + int ysq = y - pos.getY(); + ysq *= 1.6; + ysq *= ysq; + mut.setY(y); + double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; + double r2 = r + 5; + double dist = xsq + ysq + zsq; + if (dist < r * r) { + state = world.getBlockState(mut); + if (isReplaceable(state)) { + BlocksHelper.setWithoutUpdate(world, mut, y < waterLevel ? WATER : CAVE_AIR); + } + } else if (dist < r2 * r2) { + state = world.getBlockState(mut); + if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(Blocks.AIR)) { + double v = noise.eval(x * 0.1, y * 0.1, z * 0.1) + noise.eval( + x * 0.03, + y * 0.03, + z * 0.03 + ) * 0.5; + if (v > 0.4) { + brimstone.add(mut.immutable()); + } else { + BlocksHelper.setWithoutUpdate(world, mut, rock); + } + } + } + } + } + } + brimstone.forEach((blockPos) -> { + placeBrimstone(world, blockPos, random); + }); + + if (random.nextInt(4) == 0) { + int count = MHelper.randRange(5, 20, random); + for (int i = 0; i < count; i++) { + mut.set(pos) + .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), + 0, + MHelper.floor(random.nextGaussian() * 2 + 0.5) + ); + int dist = MHelper.floor(3 - MHelper.length( + mut.getX() - pos.getX(), + mut.getZ() - pos.getZ() + )) + random.nextInt(2); + if (dist > 0) { + state = world.getBlockState(mut); + while (!state.getFluidState().isEmpty() || state.getMaterial().equals(Material.WATER_PLANT)) { + mut.setY(mut.getY() - 1); + state = world.getBlockState(mut); + } + if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()) + .is(EndBlocks.HYDROTHERMAL_VENT)) { + for (int j = 0; j <= dist; j++) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); + MHelper.shuffle(HORIZONTAL, random); + for (Direction dir : HORIZONTAL) { + BlockPos p = mut.relative(dir); + if (random.nextBoolean() && world.getBlockState(p).is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate( + world, + p, + EndBlocks.TUBE_WORM.defaultBlockState() + .setValue(HorizontalDirectionalBlock.FACING, dir) + ); + } + } + mut.setY(mut.getY() + 1); + } + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.HYDROTHERMAL_VENT); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + while (state.is(Blocks.WATER)) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); + world.scheduleTick(mut.immutable(), + EndBlocks.VENT_BUBBLE_COLUMN, + MHelper.randRange(8, 32, random)); + mut.setY(mut.getY() + 1); + state = world.getBlockState(mut); + } + } + } + } + } + + BlockFixer.fixBlocks(world, new BlockPos(x1, y1, z1), new BlockPos(x2, y2, z2)); + + return true; + } + + private boolean isReplaceable(BlockState state) { + return state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.HYDROTHERMAL_VENT) || state.is(EndBlocks.VENT_BUBBLE_COLUMN) || state + .is(EndBlocks.SULPHUR_CRYSTAL) || state.getMaterial().isReplaceable() || state.getMaterial() + .equals(Material.PLANT) || state + .getMaterial() + .equals(Material.WATER_PLANT) || state.getMaterial().equals(Material.LEAVES); + } + + private void placeBrimstone(WorldGenLevel world, BlockPos pos, RandomSource random) { + BlockState state = getBrimstone(world, pos); + BlocksHelper.setWithoutUpdate(world, pos, state); + if (state.getValue(EndBlockProperties.ACTIVE)) { + makeShards(world, pos, random); + } + } + + private BlockState getBrimstone(WorldGenLevel world, BlockPos pos) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (world.getBlockState(pos.relative(dir)).is(Blocks.WATER)) { + return EndBlocks.BRIMSTONE.defaultBlockState().setValue(EndBlockProperties.ACTIVE, true); + } + } + return EndBlocks.BRIMSTONE.defaultBlockState(); + } + + private void makeShards(WorldGenLevel world, BlockPos pos, RandomSource random) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + BlockPos side; + if (random.nextInt(16) == 0 && world.getBlockState((side = pos.relative(dir))).is(Blocks.WATER)) { + BlockState state = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() + .setValue(SulphurCrystalBlock.WATERLOGGED, true) + .setValue(SulphurCrystalBlock.FACING, dir) + .setValue(SulphurCrystalBlock.AGE, random.nextInt(3)); + BlocksHelper.setWithoutUpdate(world, side, state); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricLakeFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricLakeFeature.java new file mode 100644 index 00000000..0a0d0a51 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SulphuricLakeFeature.java @@ -0,0 +1,211 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Fluids; + +import com.google.common.collect.Sets; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.EndBlockProperties; +import org.betterx.betterend.blocks.SulphurCrystalBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.util.GlobalState; + +import java.util.Set; + +public class SulphuricLakeFeature extends DefaultFeature { + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + BlockPos blockPos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + blockPos = getPosOnSurfaceWG(world, blockPos); + + if (blockPos.getY() < 57) { + return false; + } + + final RandomSource random = featureConfig.random(); + final MutableBlockPos POS = GlobalState.stateForThread().POS; + double radius = MHelper.randRange(10.0, 20.0, random); + int dist2 = MHelper.floor(radius * 1.5); + + int minX = blockPos.getX() - dist2; + int maxX = blockPos.getX() + dist2; + int minZ = blockPos.getZ() - dist2; + int maxZ = blockPos.getZ() + dist2; + + Set brimstone = Sets.newHashSet(); + for (int x = minX; x <= maxX; x++) { + POS.setX(x); + int x2 = x - blockPos.getX(); + x2 *= x2; + for (int z = minZ; z <= maxZ; z++) { + POS.setZ(z); + int z2 = z - blockPos.getZ(); + z2 *= z2; + double r = radius * (NOISE.eval(x * 0.2, z * 0.2) * 0.25 + 0.75); + double r2 = r * 1.5; + r *= r; + r2 *= r2; + int dist = x2 + z2; + if (dist <= r) { + POS.setY(getYOnSurface(world, x, z) - 1); + if (world.getBlockState(POS).is(CommonBlockTags.GEN_END_STONES)) { + if (isBorder(world, POS)) { + if (random.nextInt(8) > 0) { + brimstone.add(POS.immutable()); + if (random.nextBoolean()) { + brimstone.add(POS.below()); + if (random.nextBoolean()) { + brimstone.add(POS.below(2)); + } + } + } else { + if (!isAbsoluteBorder(world, POS)) { + BlocksHelper.setWithoutUpdate(world, POS, Blocks.WATER); + //world.setBlock(blockPos, Blocks.WATER.defaultBlockState(), 2); + world.scheduleTick(POS, Fluids.WATER, 0); + brimstone.add(POS.below()); + if (random.nextBoolean()) { + brimstone.add(POS.below(2)); + if (random.nextBoolean()) { + brimstone.add(POS.below(3)); + } + } + } else { + brimstone.add(POS.immutable()); + if (random.nextBoolean()) { + brimstone.add(POS.below()); + } + } + } + } else { + BlocksHelper.setWithoutUpdate(world, POS, Blocks.WATER); + brimstone.remove(POS); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos offseted = POS.relative(dir); + if (world.getBlockState(offseted).is(CommonBlockTags.GEN_END_STONES)) { + brimstone.add(offseted); + } + } + if (isDeepWater(world, POS)) { + BlocksHelper.setWithoutUpdate(world, POS.move(Direction.DOWN), Blocks.WATER); + brimstone.remove(POS); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos offseted = POS.relative(dir); + if (world.getBlockState(offseted).is(CommonBlockTags.GEN_END_STONES)) { + brimstone.add(offseted); + } + } + } + brimstone.add(POS.below()); + if (random.nextBoolean()) { + brimstone.add(POS.below(2)); + if (random.nextBoolean()) { + brimstone.add(POS.below(3)); + } + } + } + } + } else if (dist < r2) { + POS.setY(getYOnSurface(world, x, z) - 1); + if (world.getBlockState(POS).is(CommonBlockTags.GEN_END_STONES)) { + brimstone.add(POS.immutable()); + if (random.nextBoolean()) { + brimstone.add(POS.below()); + if (random.nextBoolean()) { + brimstone.add(POS.below(2)); + } + } + } + } + } + } + + brimstone.forEach((bpos) -> { + placeBrimstone(world, bpos, random); + }); + + return true; + } + + private boolean isBorder(WorldGenLevel world, BlockPos pos) { + int y = pos.getY() + 1; + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (getYOnSurface(world, pos.getX() + dir.getStepX(), pos.getZ() + dir.getStepZ()) < y) { + return true; + } + } + return false; + } + + private boolean isAbsoluteBorder(WorldGenLevel world, BlockPos pos) { + int y = pos.getY() - 2; + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (getYOnSurface(world, pos.getX() + dir.getStepX() * 3, pos.getZ() + dir.getStepZ() * 3) < y) { + return true; + } + } + return false; + } + + private boolean isDeepWater(WorldGenLevel world, BlockPos pos) { + int y = pos.getY() + 1; + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (getYOnSurface(world, pos.getX() + dir.getStepX(), pos.getZ() + dir.getStepZ()) < y || getYOnSurface( + world, + pos.getX() + dir.getStepX() * 2, + pos.getZ() + dir.getStepZ() * 2 + ) < y || getYOnSurface( + world, + pos.getX() + dir.getStepX() * 3, + pos.getZ() + dir.getStepZ() * 3) < y) { + return false; + } + } + return true; + } + + private void placeBrimstone(WorldGenLevel world, BlockPos pos, RandomSource random) { + BlockState state = getBrimstone(world, pos); + BlocksHelper.setWithoutUpdate(world, pos, state); + if (state.getValue(EndBlockProperties.ACTIVE)) { + makeShards(world, pos, random); + } + } + + private BlockState getBrimstone(WorldGenLevel world, BlockPos pos) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (world.getBlockState(pos.relative(dir)).is(Blocks.WATER)) { + return EndBlocks.BRIMSTONE.defaultBlockState().setValue(EndBlockProperties.ACTIVE, true); + } + } + return EndBlocks.BRIMSTONE.defaultBlockState(); + } + + private void makeShards(WorldGenLevel world, BlockPos pos, RandomSource random) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + BlockPos side; + if (random.nextInt(16) == 0 && world.getBlockState((side = pos.relative(dir))).is(Blocks.WATER)) { + BlockState state = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() + .setValue(SulphurCrystalBlock.WATERLOGGED, true) + .setValue(SulphurCrystalBlock.FACING, dir) + .setValue(SulphurCrystalBlock.AGE, random.nextInt(3)); + BlocksHelper.setWithoutUpdate(world, side, state); + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/SurfaceVentFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/SurfaceVentFeature.java new file mode 100644 index 00000000..9d34bb63 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/SurfaceVentFeature.java @@ -0,0 +1,62 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.HydrothermalVentBlock; +import org.betterx.betterend.registry.EndBlocks; + +public class SurfaceVentFeature extends DefaultFeature { + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + pos = getPosOnSurface( + world, + new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) + ); + if (!world.getBlockState(pos.below(3)).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + MutableBlockPos mut = new MutableBlockPos(); + int count = MHelper.randRange(15, 30, random); + BlockState vent = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() + .setValue(HydrothermalVentBlock.WATERLOGGED, false); + for (int i = 0; i < count; i++) { + mut.set(pos) + .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), 5, MHelper.floor(random.nextGaussian() * 2 + 0.5)); + int dist = MHelper.floor(2 - MHelper.length( + mut.getX() - pos.getX(), + mut.getZ() - pos.getZ() + )) + random.nextInt(2); + if (dist > 0) { + BlockState state = world.getBlockState(mut); + for (int n = 0; n < 10 && state.isAir(); n++) { + mut.setY(mut.getY() - 1); + state = world.getBlockState(mut); + } + if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()) + .is(EndBlocks.HYDROTHERMAL_VENT)) { + for (int j = 0; j <= dist; j++) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); + mut.setY(mut.getY() + 1); + } + BlocksHelper.setWithoutUpdate(world, mut, vent); + } + } + } + + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/ThinArchFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/ThinArchFeature.java new file mode 100644 index 00000000..4a3fc821 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/ThinArchFeature.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.world.features.terrain; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFCoordModify; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.operator.SDFUnion; +import org.betterx.bclib.sdf.primitive.SDFTorus; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; + +public class ThinArchFeature extends DefaultFeature { + private final Block block; + + public ThinArchFeature(Block block) { + this.block = block; + } + + @Override + public boolean place(FeaturePlaceContext featurePlaceContext) { + final WorldGenLevel world = featurePlaceContext.level(); + BlockPos origin = featurePlaceContext.origin(); + RandomSource random = featurePlaceContext.random(); + + BlockPos pos = getPosOnSurfaceWG(world, + new BlockPos((origin.getX() & 0xFFFFFFF0) | 7, + 0, + (origin.getZ() & 0xFFFFFFF0) | 7)); + if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { + return false; + } + + SDF sdf = null; + float bigRadius = MHelper.randRange(15F, 20F, random); + float variation = bigRadius * 0.3F; + int count = MHelper.randRange(2, 4, random); + + for (int i = 0; i < count; i++) { + float smallRadius = MHelper.randRange(0.6F, 1.3F, random); + SDF arch = new SDFTorus().setBigRadius(bigRadius - random.nextFloat() * variation) + .setSmallRadius(smallRadius) + .setBlock(block); + float angle = (i - count * 0.5F) * 0.3F + random.nextFloat() * 0.05F + (float) Math.PI * 0.5F; + arch = new SDFRotation().setRotation(Vector3f.XP, angle).setSource(arch); + sdf = sdf == null ? arch : new SDFUnion().setSourceA(sdf).setSourceB(arch); + } + + sdf = new SDFRotation().setRotation(MHelper.randomHorizontal(random), random.nextFloat() * MHelper.PI2) + .setSource(sdf); + + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + sdf = new SDFCoordModify().setFunction(vec -> { + float dx = (float) noise.eval(vec.y() * 0.02, vec.z() * 0.02); + float dy = (float) noise.eval(vec.x() * 0.02, vec.z() * 0.02); + float dz = (float) noise.eval(vec.x() * 0.02, vec.y() * 0.02); + vec.add(dx * 10, dy * 10, dz * 10); + }).setSource(sdf); + sdf = new SDFDisplacement().setFunction(vec -> { + float offset = vec.y() / bigRadius - 0.5F; + return Mth.clamp(offset * 3, -10F, 0F); + }).setSource(sdf); + + float side = (bigRadius + 2.5F) * 2; + if (side > 47) { + side = 47; + } + sdf.fillArea(world, pos, AABB.ofSize(Vec3.atCenterOf(pos), side, side, side)); + return true; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java new file mode 100644 index 00000000..c035e9a5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java @@ -0,0 +1,149 @@ +package org.betterx.betterend.world.features.terrain.caves; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import com.google.common.collect.Sets; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.util.BlockFixer; +import org.betterx.betterend.world.biome.cave.EndCaveBiome; + +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; + +public class CaveChunkPopulatorFeature extends DefaultFeature { + private final Supplier supplier; + + public CaveChunkPopulatorFeature(Supplier biome) { + this.supplier = biome; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + Set floorPositions = Sets.newHashSet(); + Set ceilPositions = Sets.newHashSet(); + int sx = (pos.getX() >> 4) << 4; + int sz = (pos.getZ() >> 4) << 4; + MutableBlockPos min = new MutableBlockPos().set(pos); + MutableBlockPos max = new MutableBlockPos().set(pos); + fillSets(sx, sz, world.getChunk(pos), floorPositions, ceilPositions, min, max); + EndCaveBiome biome = supplier.get(); + BlockState surfaceBlock = Blocks.END_STONE.defaultBlockState(); //biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + placeFloor(world, biome, floorPositions, random, surfaceBlock); + placeCeil(world, biome, ceilPositions, random); + BlockFixer.fixBlocks(world, min, max); + return true; + } + + protected void fillSets(int sx, + int sz, + ChunkAccess chunk, + Set floorPositions, + Set ceilPositions, + MutableBlockPos min, + MutableBlockPos max) { + MutableBlockPos mut = new MutableBlockPos(); + MutableBlockPos mut2 = new MutableBlockPos(); + MutableBlockPos mut3 = new MutableBlockPos(); + for (int x = 0; x < 16; x++) { + mut.setX(x); + mut2.setX(x); + for (int z = 0; z < 16; z++) { + mut.setZ(z); + mut2.setZ(z); + mut2.setY(0); + for (int y = 1; y < chunk.getMaxBuildHeight(); y++) { + mut.setY(y); + BlockState top = chunk.getBlockState(mut); + BlockState bottom = chunk.getBlockState(mut2); + if (top.isAir() && (bottom.is(CommonBlockTags.GEN_END_STONES) || bottom.is(Blocks.STONE))) { + mut3.set(mut2).move(sx, 0, sz); + floorPositions.add(mut3.immutable()); + updateMin(mut3, min); + updateMax(mut3, max); + } else if (bottom.isAir() && (top.is(CommonBlockTags.GEN_END_STONES) || top.is(Blocks.STONE))) { + mut3.set(mut).move(sx, 0, sz); + ceilPositions.add(mut3.immutable()); + updateMin(mut3, min); + updateMax(mut3, max); + } + mut2.setY(y); + } + } + } + } + + private void updateMin(BlockPos pos, MutableBlockPos min) { + if (pos.getX() < min.getX()) { + min.setX(pos.getX()); + } + if (pos.getY() < min.getY()) { + min.setY(pos.getY()); + } + if (pos.getZ() < min.getZ()) { + min.setZ(pos.getZ()); + } + } + + private void updateMax(BlockPos pos, MutableBlockPos max) { + if (pos.getX() > max.getX()) { + max.setX(pos.getX()); + } + if (pos.getY() > max.getY()) { + max.setY(pos.getY()); + } + if (pos.getZ() > max.getZ()) { + max.setZ(pos.getZ()); + } + } + + protected void placeFloor(WorldGenLevel world, + EndCaveBiome biome, + Set floorPositions, + RandomSource random, + BlockState surfaceBlock) { + float density = biome.getFloorDensity(); + floorPositions.forEach((pos) -> { + BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getFloorFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); + } + } + }); + } + + protected void placeCeil(WorldGenLevel world, + EndCaveBiome biome, + Set ceilPositions, + RandomSource random) { + float density = biome.getCeilDensity(); + ceilPositions.forEach((pos) -> { + BlockState ceilBlock = biome.getCeil(pos); + if (ceilBlock != null) { + BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); + } + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getCeilFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); + } + } + }); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/caves/EndCaveFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/caves/EndCaveFeature.java new file mode 100644 index 00000000..1699e287 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/caves/EndCaveFeature.java @@ -0,0 +1,270 @@ +package org.betterx.betterend.world.features.terrain.caves; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.core.Vec3i; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.bclib.world.generator.BiomePicker; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.util.BlockFixer; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.biome.cave.EndCaveBiome; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public abstract class EndCaveFeature extends DefaultFeature { + protected static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); + protected static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); + protected static final BlockState WATER = Blocks.WATER.defaultBlockState(); + private static final Vec3i[] SPHERE; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 2500) { + return false; + } + + if (biomeMissingCaves(world, pos)) { + return false; + } + + int radius = MHelper.randRange(10, 30, random); + BlockPos center = findPos(world, pos, radius, random); + + if (center == null) { + return false; + } + + BiomePicker.ActualBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ()); + Set caveBlocks = generate(world, center, radius, random); + if (!caveBlocks.isEmpty()) { + if (biome != null) { + setBiomes(world, biome, caveBlocks); + Set floorPositions = Sets.newConcurrentHashSet(); + Set ceilPositions = Sets.newConcurrentHashSet(); + caveBlocks.parallelStream().forEach((bpos) -> { + if (world.getBlockState(bpos).getMaterial().isReplaceable()) { + BlockPos side = bpos.below(); + if (world.getBlockState(side).is(CommonBlockTags.GEN_END_STONES)) { + floorPositions.add(side); + } + side = bpos.above(); + if (world.getBlockState(side).is(CommonBlockTags.GEN_END_STONES)) { + ceilPositions.add(side); + } + } + }); + + BlockState surfaceBlock = EndBiome.findTopMaterial(biome.bclBiome); + placeFloor(world, (EndCaveBiome) biome.bclBiome, floorPositions, random, surfaceBlock); + placeCeil(world, (EndCaveBiome) biome.bclBiome, ceilPositions, random); + placeWalls(world, (EndCaveBiome) biome.bclBiome, caveBlocks, random); + } + fixBlocks(world, caveBlocks); + } + + return true; + } + + protected abstract Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random); + + protected void placeFloor(WorldGenLevel world, + EndCaveBiome biome, + Set floorPositions, + RandomSource random, + BlockState surfaceBlock) { + float density = biome.getFloorDensity(); + floorPositions.forEach((pos) -> { + if (!surfaceBlock.is(Blocks.END_STONE)) { + BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); + } + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getFloorFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); + } + } + }); + } + + protected void placeCeil(WorldGenLevel world, + EndCaveBiome biome, + Set ceilPositions, + RandomSource random) { + float density = biome.getCeilDensity(); + ceilPositions.forEach((pos) -> { + BlockState ceilBlock = biome.getCeil(pos); + if (ceilBlock != null) { + BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); + } + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getCeilFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); + } + } + }); + } + + protected void placeWalls(WorldGenLevel world, EndCaveBiome biome, Set positions, RandomSource random) { + Set placed = Sets.newHashSet(); + positions.forEach(pos -> { + if (random.nextInt(4) == 0 && hasOpenSide(pos, positions)) { + BlockState wallBlock = biome.getWall(pos); + if (wallBlock != null) { + for (Vec3i offset : SPHERE) { + BlockPos wallPos = pos.offset(offset); + if (!positions.contains(wallPos) && !placed.contains(wallPos) && world.getBlockState(wallPos) + .is(CommonBlockTags.GEN_END_STONES)) { + wallBlock = biome.getWall(wallPos); + BlocksHelper.setWithoutUpdate(world, wallPos, wallBlock); + placed.add(wallPos); + } + } + } + } + }); + } + + private boolean hasOpenSide(BlockPos pos, Set positions) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (!positions.contains(pos.relative(dir))) { + return true; + } + } + return false; + } + + protected void setBiomes(WorldGenLevel world, BiomePicker.ActualBiome biome, Set blocks) { + blocks.forEach((pos) -> setBiome(world, pos, biome)); + } + + protected void setBiome(WorldGenLevel world, BlockPos pos, BiomePicker.ActualBiome biome) { + BiomeAPI.setBiome(world, pos, biome.biome); + } + + private BlockPos findPos(WorldGenLevel world, BlockPos pos, int radius, RandomSource random) { + int top = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); + MutableBlockPos bpos = new MutableBlockPos(); + bpos.setX(pos.getX()); + bpos.setZ(pos.getZ()); + bpos.setY(top - 1); + + BlockState state = world.getBlockState(bpos); + while (!state.is(CommonBlockTags.GEN_END_STONES) && bpos.getY() > 5) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + if (bpos.getY() < 10) { + return null; + } + top = (int) (bpos.getY() - (radius * 1.3F + 5)); + + while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + int bottom = (int) (bpos.getY() + radius * 1.3F + 5); + + if (top <= bottom) { + return null; + } + + return new BlockPos(pos.getX(), MHelper.randRange(bottom, top, random), pos.getZ()); + } + + protected void fixBlocks(WorldGenLevel world, Set caveBlocks) { + BlockPos pos = caveBlocks.iterator().next(); + MutableBlockPos start = new MutableBlockPos().set(pos); + MutableBlockPos end = new MutableBlockPos().set(pos); + caveBlocks.forEach((bpos) -> { + if (bpos.getX() < start.getX()) { + start.setX(bpos.getX()); + } + if (bpos.getX() > end.getX()) { + end.setX(bpos.getX()); + } + + if (bpos.getY() < start.getY()) { + start.setY(bpos.getY()); + } + if (bpos.getY() > end.getY()) { + end.setY(bpos.getY()); + } + + if (bpos.getZ() < start.getZ()) { + start.setZ(bpos.getZ()); + } + if (bpos.getZ() > end.getZ()) { + end.setZ(bpos.getZ()); + } + }); + BlockFixer.fixBlocks(world, start.offset(-2, -2, -2), end.offset(2, 2, 2)); + } + + protected boolean isWaterNear(WorldGenLevel world, BlockPos pos) { + for (Direction dir : BlocksHelper.DIRECTIONS) { + if (!world.getFluidState(pos.relative(dir, 5)).isEmpty()) { + return true; + } + } + return false; + } + + protected boolean biomeMissingCaves(WorldGenLevel world, BlockPos pos) { + for (int x = -2; x < 3; x++) { + for (int z = -2; z < 3; z++) { + Holder biome = world.getBiome(pos.offset(x << 4, 0, z << 4)); + BCLBiome endBiome = BiomeAPI.getFromBiome(biome); + boolean hasCaves = endBiome.getCustomData("has_caves", true); + if (!hasCaves && BiomeAPI.wasRegisteredAsEndLandBiome(endBiome.getID())) { + return true; + } + } + } + return false; + } + + static { + List prePos = Lists.newArrayList(); + int radius = 5; + int r2 = radius * radius; + for (int x = -radius; x <= radius; x++) { + int x2 = x * x; + for (int y = -radius; y <= radius; y++) { + int y2 = y * y; + for (int z = -radius; z <= radius; z++) { + int z2 = z * z; + if (x2 + y2 + z2 < r2) { + prePos.add(new Vec3i(x, y, z)); + } + } + } + } + SPHERE = prePos.toArray(new Vec3i[]{}); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/caves/RoundCaveFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/caves/RoundCaveFeature.java new file mode 100644 index 00000000..59b22640 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/caves/RoundCaveFeature.java @@ -0,0 +1,83 @@ +package org.betterx.betterend.world.features.terrain.caves; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Sets; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.Set; +import java.util.stream.IntStream; + +public class RoundCaveFeature extends EndCaveFeature { + @Override + protected Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random) { + OpenSimplexNoise noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); + + int x1 = center.getX() - radius - 5; + int z1 = center.getZ() - radius - 5; + int x2 = center.getX() + radius + 5; + int z2 = center.getZ() + radius + 5; + int y1 = MHelper.floor(center.getY() - (radius + 5) / 1.6); + int y2 = MHelper.floor(center.getY() + (radius + 5) / 1.6); + + double hr = radius * 0.75; + double nr = radius * 0.25; + + int dx = x2 - x1 + 1; + int dz = z2 - z1 + 1; + int count = dx * dz; + Set blocks = Sets.newConcurrentHashSet(); + IntStream.range(0, count).parallel().forEach(index -> { + MutableBlockPos bpos = new MutableBlockPos(); + int x = (index % dx) + x1; + int z = (index / dx) + z1; + bpos.setX(x); + bpos.setZ(z); + int xsq = MHelper.sqr(x - center.getX()); + int zsq = MHelper.sqr(z - center.getZ()); + int dxz = xsq + zsq; + BlockState state; + for (int y = y1; y <= y2; y++) { + int ysq = (int) MHelper.sqr((y - center.getY()) * 1.6); + double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; + double dist = dxz + ysq; + if (dist < r * r) { + bpos.setY(y); + state = world.getBlockState(bpos); + if (isReplaceable(state) && !isWaterNear(world, bpos)) { + blocks.add(bpos.immutable()); + + while (state.getMaterial().equals(Material.LEAVES)) { + bpos.setY(bpos.getY() + 1); + state = world.getBlockState(bpos); + } + + bpos.setY(y - 1); + while (state.getMaterial().equals(Material.LEAVES)) { + bpos.setY(bpos.getY() - 1); + state = world.getBlockState(bpos); + } + } + } + } + }); + blocks.forEach(bpos -> BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR)); + + return blocks; + } + + private boolean isReplaceable(BlockState state) { + return state.is(CommonBlockTags.GEN_END_STONES) || + state.getMaterial().isReplaceable() || + state.getMaterial().equals(Material.PLANT) || + state.getMaterial().equals(Material.LEAVES); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/terrain/caves/TunelCaveFeature.java b/src/main/java/org/betterx/betterend/world/features/terrain/caves/TunelCaveFeature.java new file mode 100644 index 00000000..af3db9a8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/terrain/caves/TunelCaveFeature.java @@ -0,0 +1,250 @@ +package org.betterx.betterend.world.features.terrain.caves; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.bclib.world.generator.BiomePicker; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBiomes; +import org.betterx.betterend.world.biome.EndBiome; +import org.betterx.betterend.world.biome.cave.EndCaveBiome; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.IntStream; + +public class TunelCaveFeature extends EndCaveFeature { + private Set generate(WorldGenLevel world, BlockPos center, RandomSource random) { + int cx = center.getX() >> 4; + int cz = center.getZ() >> 4; + if ((long) cx * (long) cx + (long) cz + (long) cz < 256) { + return Sets.newHashSet(); + } + + int x1 = cx << 4; + int z1 = cz << 4; + int x2 = x1 + 16; + int z2 = z1 + 16; + + RandomSource rand = new LegacyRandomSource(world.getSeed()); + OpenSimplexNoise noiseH = new OpenSimplexNoise(rand.nextInt()); + OpenSimplexNoise noiseV = new OpenSimplexNoise(rand.nextInt()); + OpenSimplexNoise noiseD = new OpenSimplexNoise(rand.nextInt()); + + Set positions = Sets.newConcurrentHashSet(); + + float a = hasCaves(world, new BlockPos(x1, 0, z1)) ? 1F : 0F; + float b = hasCaves(world, new BlockPos(x2, 0, z1)) ? 1F : 0F; + float c = hasCaves(world, new BlockPos(x1, 0, z2)) ? 1F : 0F; + float d = hasCaves(world, new BlockPos(x2, 0, z2)) ? 1F : 0F; + + ChunkAccess chunk = world.getChunk(cx, cz); + IntStream.range(0, 256).parallel().forEach(index -> { + MutableBlockPos pos = new MutableBlockPos(); + int x = index & 15; + int z = index >> 4; + int wheight = chunk.getHeight(Types.WORLD_SURFACE_WG, x, z); + float dx = x / 16F; + float dz = z / 16F; + pos.setX(x + x1); + pos.setZ(z + z1); + float da = Mth.lerp(dx, a, b); + float db = Mth.lerp(dx, c, d); + float density = 1 - Mth.lerp(dz, da, db); + if (density < 0.5) { + for (int y = 0; y < wheight; y++) { + pos.setY(y); + float gradient = 1 - Mth.clamp((wheight - y) * 0.1F, 0F, 1F); + if (gradient > 0.5) { + break; + } + float val = Mth.abs((float) noiseH.eval(pos.getX() * 0.02, y * 0.01, pos.getZ() * 0.02)); + float vert = Mth.sin((y + (float) noiseV.eval( + pos.getX() * 0.01, + pos.getZ() * 0.01 + ) * 20) * 0.1F) * 0.9F; + float dist = (float) noiseD.eval(pos.getX() * 0.1, y * 0.1, pos.getZ() * 0.1) * 0.12F; + val = (val + vert * vert + dist) + density + gradient; + if (val < 0.15 && world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES) && noWaterNear(world, + pos)) { + positions.add(pos.immutable()); + } + } + } + }); + positions.forEach(bpos -> BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR)); + + return positions; + } + + private boolean noWaterNear(WorldGenLevel world, BlockPos pos) { + BlockPos above1 = pos.above(); + BlockPos above2 = pos.above(2); + if (!world.getFluidState(above1).isEmpty() || !world.getFluidState(above2).isEmpty()) { + return false; + } + for (Direction dir : BlocksHelper.HORIZONTAL) { + if (!world.getFluidState(above1.relative(dir)).isEmpty()) { + return false; + } + if (!world.getFluidState(above2.relative(dir)).isEmpty()) { + return false; + } + } + return true; + } + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 2500) { + return false; + } + + if (biomeMissingCaves(world, pos)) { + return false; + } + + Set caveBlocks = generate(world, pos, random); + if (caveBlocks.isEmpty()) { + return false; + } + + Map> floorSets = Maps.newHashMap(); + Map> ceilSets = Maps.newHashMap(); + MutableBlockPos mut = new MutableBlockPos(); + Set remove = Sets.newHashSet(); + caveBlocks.forEach((bpos) -> { + mut.set(bpos); + BiomePicker.ActualBiome bio = EndBiomes.getCaveBiome(bpos.getX(), bpos.getZ()); + int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ()); + if (mut.getY() >= height) { + remove.add(bpos); + } else if (world.getBlockState(mut).getMaterial().isReplaceable()) { + mut.setY(bpos.getY() - 1); + if (world.getBlockState(mut).is(CommonBlockTags.GEN_END_STONES)) { + Set floorPositions = floorSets.get(bio); + if (floorPositions == null) { + floorPositions = Sets.newHashSet(); + floorSets.put(bio, floorPositions); + } + floorPositions.add(mut.immutable()); + } + mut.setY(bpos.getY() + 1); + if (world.getBlockState(mut).is(CommonBlockTags.GEN_END_STONES)) { + Set ceilPositions = ceilSets.get(bio); + if (ceilPositions == null) { + ceilPositions = Sets.newHashSet(); + ceilSets.put(bio, ceilPositions); + } + ceilPositions.add(mut.immutable()); + } + setBiome(world, bpos, bio); + } + }); + caveBlocks.removeAll(remove); + + if (caveBlocks.isEmpty()) { + return true; + } + + floorSets.forEach((biome, floorPositions) -> { + BlockState surfaceBlock = EndBiome.findTopMaterial(biome.bclBiome); + placeFloor(world, (EndCaveBiome) biome.bclBiome, floorPositions, random, surfaceBlock); + }); + ceilSets.forEach((biome, ceilPositions) -> { + placeCeil(world, (EndCaveBiome) biome.bclBiome, ceilPositions, random); + }); + BiomePicker.ActualBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ()); + placeWalls(world, (EndCaveBiome) biome.bclBiome, caveBlocks, random); + fixBlocks(world, caveBlocks); + + return true; + } + + @Override + protected Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random) { + return null; + } + + @Override + protected void placeFloor(WorldGenLevel world, + EndCaveBiome biome, + Set floorPositions, + RandomSource random, + BlockState surfaceBlock) { + float density = biome.getFloorDensity() * 0.2F; + floorPositions.forEach((pos) -> { + if (!surfaceBlock.is(Blocks.END_STONE)) { + BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); + } + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getFloorFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); + } + } + }); + } + + @Override + protected void placeCeil(WorldGenLevel world, + EndCaveBiome biome, + Set ceilPositions, + RandomSource random) { + float density = biome.getCeilDensity() * 0.2F; + ceilPositions.forEach((pos) -> { + BlockState ceilBlock = biome.getCeil(pos); + if (ceilBlock != null) { + BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); + } + if (density > 0 && random.nextFloat() <= density) { + Feature feature = biome.getCeilFeature(random); + if (feature != null) { + feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); + } + } + }); + } + + protected boolean hasCaves(WorldGenLevel world, BlockPos pos) { + return hasCavesInBiome(world, pos.offset(-8, 0, -8)) && hasCavesInBiome( + world, + pos.offset(8, 0, -8) + ) && hasCavesInBiome(world, + pos.offset(-8, + 0, + 8)) && hasCavesInBiome( + world, + pos.offset(8, 0, 8)); + } + + protected boolean hasCavesInBiome(WorldGenLevel world, BlockPos pos) { + Holder biome = world.getBiome(pos); + BCLBiome endBiome = BiomeAPI.getFromBiome(biome); + return endBiome.getCustomData("has_caves", true); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/DragonTreeFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/DragonTreeFeature.java new file mode 100644 index 00000000..3ae94d5c --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/DragonTreeFeature.java @@ -0,0 +1,256 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class DragonTreeFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Function IGNORE; + private static final Function POST; + private static final List BRANCH; + private static final List SIDE1; + private static final List SIDE2; + private static final List ROOT; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + float size = MHelper.randRange(10, 25, random); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 6); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + + if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { + return false; + } + BlocksHelper.setWithoutUpdate(world, pos, AIR); + + Vector3f last = SplineHelper.getPos(spline, 3.5F); + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + float radius = size * MHelper.randRange(0.5F, 0.7F, random); + makeCap(world, pos.offset(last.x(), last.y(), last.z()), radius, random, noise); + + last = spline.get(0); + makeRoots(world, pos.offset(last.x(), last.y(), last.z()), radius, random); + + radius = MHelper.randRange(1.2F, 2.3F, random); + SDF function = SplineHelper.buildSDF(spline, radius, 1.2F, (bpos) -> { + return EndBlocks.DRAGON_TREE.getBark().defaultBlockState(); + }); + + function.setReplaceFunction(REPLACE); + function.addPostProcess(POST); + function.fillRecursiveIgnore(world, pos, IGNORE); + + return true; + } + + private void makeCap(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise) { + int count = (int) radius; + int offset = (int) (BRANCH.get(BRANCH.size() - 1).y() * radius); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(BRANCH); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); + + branch = SplineHelper.copySpline(SIDE1); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); + + branch = SplineHelper.copySpline(SIDE2); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); + } + leavesBall(world, pos.above(offset), radius * 1.15F + 2, random, noise); + } + + private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random) { + int count = (int) (radius * 1.5F); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(ROOT); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + Vector3f last = branch.get(branch.size() - 1); + if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { + SplineHelper.fillSpline(branch, + world, + EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), + pos, + REPLACE); + } + } + } + + private void leavesBall(WorldGenLevel world, + BlockPos pos, + float radius, + RandomSource random, + OpenSimplexNoise noise) { + SDF sphere = new SDFSphere().setRadius(radius) + .setBlock(EndBlocks.DRAGON_TREE_LEAVES.defaultBlockState() + .setValue(LeavesBlock.DISTANCE, 6)); + SDF sub = new SDFScale().setScale(5).setSource(sphere); + sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 1.5F; + }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return random.nextFloat() * 3F - 1.5F; + }).setSource(sphere); + MutableBlockPos mut = new MutableBlockPos(); + sphere.addPostProcess((info) -> { + if (random.nextInt(5) == 0) { + for (Direction dir : Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); + } + } + info.setState(EndBlocks.DRAGON_TREE.getBark().defaultBlockState()); + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); + + if (radius > 5) { + int count = (int) (radius * 2.5F); + for (int i = 0; i < count; i++) { + BlockPos p = pos.offset( + random.nextGaussian() * 1, + random.nextGaussian() * 1, + random.nextGaussian() * 1 + ); + boolean place = true; + for (Direction d : Direction.values()) { + BlockState state = world.getBlockState(p.relative(d)); + if (!EndBlocks.DRAGON_TREE.isTreeLog(state) && !state.is(EndBlocks.DRAGON_TREE_LEAVES)) { + place = false; + break; + } + } + if (place) { + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.DRAGON_TREE.getBark()); + } + } + } + + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.DRAGON_TREE.getBark()); + } + + static { + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (state.getBlock() == EndBlocks.DRAGON_TREE_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = (state) -> { + return EndBlocks.DRAGON_TREE.isTreeLog(state); + }; + + POST = (info) -> { + if (EndBlocks.DRAGON_TREE.isTreeLog(info.getStateUp()) && EndBlocks.DRAGON_TREE.isTreeLog(info.getStateDown())) { + return EndBlocks.DRAGON_TREE.getLog().defaultBlockState(); + } + return info.getState(); + }; + + BRANCH = Lists.newArrayList( + new Vector3f(0, 0, 0), + new Vector3f(0.1F, 0.3F, 0), + new Vector3f(0.4F, 0.6F, 0), + new Vector3f(0.8F, 0.8F, 0), + new Vector3f(1, 1, 0) + ); + SIDE1 = Lists.newArrayList(new Vector3f(0.4F, 0.6F, 0), new Vector3f(0.8F, 0.8F, 0), new Vector3f(1, 1, 0)); + SIDE2 = SplineHelper.copySpline(SIDE1); + + Vector3f offset1 = new Vector3f(-0.4F, -0.6F, 0); + Vector3f offset2 = new Vector3f(0.4F, 0.6F, 0); + + SplineHelper.offset(SIDE1, offset1); + SplineHelper.offset(SIDE2, offset1); + SplineHelper.rotateSpline(SIDE1, 0.5F); + SplineHelper.rotateSpline(SIDE2, -0.5F); + SplineHelper.offset(SIDE1, offset2); + SplineHelper.offset(SIDE2, offset2); + + ROOT = Lists.newArrayList( + new Vector3f(0F, 1F, 0), + new Vector3f(0.1F, 0.7F, 0), + new Vector3f(0.3F, 0.3F, 0), + new Vector3f(0.7F, 0.05F, 0), + new Vector3f(0.8F, -0.2F, 0) + ); + SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/GiganticAmaranitaFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/GiganticAmaranitaFeature.java new file mode 100644 index 00000000..f2b05412 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/GiganticAmaranitaFeature.java @@ -0,0 +1,379 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.blocks.BaseAttachedBlock; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class GiganticAmaranitaFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Function IGNORE; + private static final Function POST; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + float size = MHelper.randRange(5, 10, random); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 5); + SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); + + if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { + return false; + } + BlocksHelper.setWithoutUpdate(world, pos, AIR); + + float radius = size * 0.17F;// MHelper.randRange(0.8F, 1.2F, random); + SDF function = SplineHelper.buildSDF( + spline, + radius, + 0.2F, + (bpos) -> EndBlocks.AMARANITA_STEM.defaultBlockState() + ); + + Vector3f capPos = spline.get(spline.size() - 1); + makeHead(world, pos.offset(capPos.x() + 0.5F, capPos.y() + 1.5F, capPos.z() + 0.5F), Mth.floor(size / 1.6F)); + + function.setReplaceFunction(REPLACE); + function.addPostProcess(POST); + function.fillRecursiveIgnore(world, pos, IGNORE); + + for (int i = 0; i < 3; i++) { + List copy = SplineHelper.copySpline(spline); + SplineHelper.offsetParts(copy, random, 0.2F, 0, 0.2F); + SplineHelper.fillSplineForce(copy, world, EndBlocks.AMARANITA_HYPHAE.defaultBlockState(), pos, REPLACE); + } + + return true; + } + + private void makeHead(WorldGenLevel world, BlockPos pos, int radius) { + MutableBlockPos mut = new MutableBlockPos(); + if (radius < 2) { + for (int i = -1; i < 2; i++) { + mut.set(pos).move(Direction.NORTH, 2).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.SOUTH, 2).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.EAST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + for (int x = -1; x < 2; x++) { + for (int z = -1; z < 2; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.AMARANITA_FUR.defaultBlockState() + .setValue(BaseAttachedBlock.FACING, Direction.DOWN) + ); + } + } + } + } + + int h = radius + 1; + for (int y = 0; y < h; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -1; x < 2; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + mut.setY(pos.getY() + h + 1); + for (int x = -1; x < 2; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 2; z++) { + mut.setZ(pos.getZ() + z); + if ((x == 0 || z == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } else if (radius < 4) { + pos = pos.offset(-1, 0, -1); + for (int i = -2; i < 2; i++) { + mut.set(pos).move(Direction.NORTH, 2).move(Direction.WEST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.SOUTH, 3).move(Direction.WEST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + for (int x = -1; x < 3; x++) { + for (int z = -1; z < 3; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if ((x >> 1) == 0 || (z >> 1) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; + int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; + BlockPos offseted = mut.relative(axis, distance); + if (world.getBlockState(offseted).getMaterial().isReplaceable()) { + Direction dir = Direction.fromAxisAndDirection( + axis, + distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE + ); + BlocksHelper.setWithoutUpdate( + world, + offseted, + EndBlocks.AMARANITA_FUR.defaultBlockState() + .setValue(BaseAttachedBlock.FACING, dir) + ); + } + mut.move(Direction.DOWN); + } + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.AMARANITA_FUR.defaultBlockState() + .setValue(BaseAttachedBlock.FACING, Direction.DOWN) + ); + } + } + } + } + + int h = radius - 1; + for (int y = 0; y < h; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -1; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + mut.setY(pos.getY() + h + 1); + for (int x = -1; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -1; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (((x >> 1) == 0 || (z >> 1) == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } else { + for (int i = -2; i < 3; i++) { + mut.set(pos).move(Direction.NORTH, 3).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.NORTH); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.SOUTH, 3).move(Direction.EAST, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.SOUTH); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.EAST); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + + mut.set(pos).move(Direction.WEST, 3).move(Direction.NORTH, i); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.UP); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + mut.move(Direction.WEST); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + + for (int i = 0; i < 4; i++) { + mut.set(pos) + .move(Direction.UP) + .move(BlocksHelper.HORIZONTAL[i], 3) + .move(BlocksHelper.HORIZONTAL[(i + 1) & 3], 3); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); + } + } + + for (int x = -2; x < 3; x++) { + for (int z = -2; z < 3; z++) { + mut.set(pos).move(x, 0, z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + mut.move(Direction.DOWN); + if ((x / 2) == 0 || (z / 2) == 0) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); + Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; + int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; + BlockPos offseted = mut.relative(axis, distance); + if (world.getBlockState(offseted).getMaterial().isReplaceable()) { + Direction dir = Direction.fromAxisAndDirection( + axis, + distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE + ); + BlocksHelper.setWithoutUpdate( + world, + offseted, + EndBlocks.AMARANITA_FUR.defaultBlockState() + .setValue(BaseAttachedBlock.FACING, dir) + ); + } + mut.move(Direction.DOWN); + } + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate( + world, + mut, + EndBlocks.AMARANITA_FUR.defaultBlockState() + .setValue(BaseAttachedBlock.FACING, Direction.DOWN) + ); + } + } + } + } + + for (int y = 0; y < 3; y++) { + mut.setY(pos.getY() + y + 1); + for (int x = -2; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -2; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (world.getBlockState(mut).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + + int h = radius + 1; + for (int y = 4; y < h; y++) { + mut.setY(pos.getY() + y); + for (int x = -2; x < 3; x++) { + mut.setX(pos.getX() + x); + for (int z = -2; z < 3; z++) { + mut.setZ(pos.getZ() + z); + if (y < 6) { + if (((x / 2) == 0 || (z / 2) == 0) && world.getBlockState(mut) + .getMaterial() + .isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } else { + if ((x == 0 || z == 0) && (Math.abs(x) < 2 && Math.abs(z) < 2) && world.getBlockState(mut) + .getMaterial() + .isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); + } + } + } + } + } + } + } + + static { + REPLACE = (state) -> { + if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = EndBlocks.DRAGON_TREE::isTreeLog; + + POST = (info) -> { + if (!info.getStateUp().is(EndBlocks.AMARANITA_STEM) || !info.getStateDown().is(EndBlocks.AMARANITA_STEM)) { + return EndBlocks.AMARANITA_HYPHAE.defaultBlockState(); + } + return info.getState(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/HelixTreeFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/HelixTreeFeature.java new file mode 100644 index 00000000..7b701e24 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/HelixTreeFeature.java @@ -0,0 +1,206 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.phys.AABB; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.HelixTreeLeavesBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class HelixTreeFeature extends DefaultFeature { + private static final Function POST; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + BlocksHelper.setWithoutUpdate(world, pos, AIR); + + float angle = random.nextFloat() * MHelper.PI2; + float radiusRange = MHelper.randRange(4.5F, 6F, random); + float scale = MHelper.randRange(0.5F, 1F, random); + + float dx; + float dz; + List spline = new ArrayList(10); + for (int i = 0; i < 10; i++) { + float radius = (0.9F - i * 0.1F) * radiusRange; + dx = (float) Math.sin(i + angle) * radius; + dz = (float) Math.cos(i + angle) * radius; + spline.add(new Vector3f(dx, i * 2, dz)); + } + SDF sdf = SplineHelper.buildSDF(spline, 1.7F, 0.5F, (p) -> { + return EndBlocks.HELIX_TREE.getBark().defaultBlockState(); + }); + SDF rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(sdf); + sdf = new SDFUnion().setSourceA(rotated).setSourceB(sdf); + + Vector3f lastPoint = spline.get(spline.size() - 1); + List spline2 = SplineHelper.makeSpline(0, 0, 0, 0, 20, 0, 5); + SDF stem = SplineHelper.buildSDF(spline2, 1.0F, 0.5F, (p) -> { + return EndBlocks.HELIX_TREE.getBark().defaultBlockState(); + }); + stem = new SDFTranslate().setTranslate(lastPoint.x(), lastPoint.y(), lastPoint.z()).setSource(stem); + sdf = new SDFSmoothUnion().setRadius(3).setSourceA(sdf).setSourceB(stem); + + sdf = new SDFScale().setScale(scale).setSource(sdf); + dx = 30 * scale; + float dy1 = -20 * scale; + float dy2 = 100 * scale; + sdf.addPostProcess(POST).fillArea(world, pos, new AABB(pos.offset(-dx, dy1, -dx), pos.offset(dx, dy2, dx))); + SplineHelper.scale(spline, scale); + SplineHelper.fillSplineForce(spline, + world, + EndBlocks.HELIX_TREE.getBark().defaultBlockState(), + pos, + (state) -> { + return state.getMaterial().isReplaceable(); + }); + SplineHelper.rotateSpline(spline, (float) Math.PI); + SplineHelper.fillSplineForce(spline, + world, + EndBlocks.HELIX_TREE.getBark().defaultBlockState(), + pos, + (state) -> { + return state.getMaterial().isReplaceable(); + }); + SplineHelper.scale(spline2, scale); + BlockPos leafStart = pos.offset(lastPoint.x() + 0.5, lastPoint.y() + 0.5, lastPoint.z() + 0.5); + SplineHelper.fillSplineForce( + spline2, + world, + EndBlocks.HELIX_TREE.getLog().defaultBlockState(), + leafStart, + (state) -> { + return state.getMaterial().isReplaceable(); + } + ); + + spline.clear(); + float rad = MHelper.randRange(8F, 11F, random); + int count = MHelper.randRange(20, 30, random); + float scaleM = 20F / (float) count * scale * 1.75F; + float hscale = 20F / (float) count * 0.05F; + for (int i = 0; i <= count; i++) { + float radius = 1 - i * hscale; + radius = radius * radius * 2 - 1; + radius *= radius; + radius = (1 - radius) * rad * scale; + dx = (float) Math.sin(i * 0.45F + angle) * radius; + dz = (float) Math.cos(i * 0.45F + angle) * radius; + spline.add(new Vector3f(dx, i * scaleM, dz)); + } + + Vector3f start = new Vector3f(); + Vector3f end = new Vector3f(); + lastPoint = spline.get(0); + BlockState leaf = EndBlocks.HELIX_TREE_LEAVES.defaultBlockState(); + for (int i = 1; i < spline.size(); i++) { + Vector3f point = spline.get(i); + int minY = MHelper.floor(lastPoint.y()); + int maxY = MHelper.floor(point.y()); + float div = point.y() - lastPoint.y(); + for (float py = minY; py <= maxY; py += 0.2F) { + start.set(0, py, 0); + float delta = (py - minY) / div; + float px = Mth.lerp(delta, lastPoint.x(), point.x()); + float pz = Mth.lerp(delta, lastPoint.z(), point.z()); + end.set(px, py, pz); + fillLine(start, end, world, leaf, leafStart, i / 2 - 1); + float ax = Math.abs(px); + float az = Math.abs(pz); + if (ax > az) { + start.set(start.x(), start.y(), start.z() + az > 0 ? 1 : -1); + end.set(end.x(), end.y(), end.z() + az > 0 ? 1 : -1); + } else { + start.set(start.x() + ax > 0 ? 1 : -1, start.y(), start.z()); + end.set(end.x() + ax > 0 ? 1 : -1, end.y(), end.z()); + } + fillLine(start, end, world, leaf, leafStart, i / 2 - 1); + } + lastPoint = point; + } + + leaf = leaf.setValue(HelixTreeLeavesBlock.COLOR, 7); + leafStart = leafStart.offset(0, lastPoint.y(), 0); + if (world.getBlockState(leafStart).isAir()) { + BlocksHelper.setWithoutUpdate(world, leafStart, leaf); + leafStart = leafStart.above(); + if (world.getBlockState(leafStart).isAir()) { + BlocksHelper.setWithoutUpdate(world, leafStart, leaf); + leafStart = leafStart.above(); + if (world.getBlockState(leafStart).isAir()) { + BlocksHelper.setWithoutUpdate(world, leafStart, leaf); + } + } + } + + return true; + } + + private void fillLine(Vector3f start, + Vector3f end, + WorldGenLevel world, + BlockState state, + BlockPos pos, + int offset) { + float dx = end.x() - start.x(); + float dy = end.y() - start.y(); + float dz = end.z() - start.z(); + float max = MHelper.max(Math.abs(dx), Math.abs(dy), Math.abs(dz)); + int count = MHelper.floor(max + 1); + dx /= max; + dy /= max; + dz /= max; + float x = start.x(); + float y = start.y(); + float z = start.z(); + + MutableBlockPos bPos = new MutableBlockPos(); + for (int i = 0; i < count; i++) { + bPos.set(x + pos.getX(), y + pos.getY(), z + pos.getZ()); + int color = MHelper.floor((float) i / (float) count * 7F + 0.5F) + offset; + color = Mth.clamp(color, 0, 7); + if (world.getBlockState(bPos).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, bPos, state.setValue(HelixTreeLeavesBlock.COLOR, color)); + } + x += dx; + y += dy; + z += dz; + } + bPos.set(end.x() + pos.getX(), end.y() + pos.getY(), end.z() + pos.getZ()); + if (world.getBlockState(bPos).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, bPos, state.setValue(HelixTreeLeavesBlock.COLOR, 7)); + } + } + + static { + POST = (info) -> { + if (EndBlocks.HELIX_TREE.isTreeLog(info.getStateUp()) && EndBlocks.HELIX_TREE.isTreeLog(info.getStateDown())) { + return EndBlocks.HELIX_TREE.getLog().defaultBlockState(); + } + return info.getState(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/JellyshroomFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/JellyshroomFeature.java new file mode 100644 index 00000000..cf170c46 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/JellyshroomFeature.java @@ -0,0 +1,128 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.JellyshroomCapBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class JellyshroomFeature extends DefaultFeature { + private static final Function REPLACE; + private static final List ROOT; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + BlockState bark = EndBlocks.JELLYSHROOM.getBark().defaultBlockState(); + BlockState membrane = EndBlocks.JELLYSHROOM_CAP_PURPLE.defaultBlockState(); + + int height = MHelper.randRange(5, 8, random); + float radius = height * MHelper.randRange(0.15F, 0.25F, random); + List spline = SplineHelper.makeSpline(0, -1, 0, 0, height, 0, 3); + SplineHelper.offsetParts(spline, random, 0.5F, 0, 0.5F); + SDF sdf = SplineHelper.buildSDF(spline, radius, 0.8F, (bpos) -> { + return bark; + }); + + radius = height * MHelper.randRange(0.7F, 0.9F, random); + if (radius < 1.5F) { + radius = 1.5F; + } + final float membraneRadius = radius; + SDF cap = makeCap(membraneRadius, random, membrane); + final Vector3f last = spline.get(spline.size() - 1); + cap = new SDFTranslate().setTranslate(last.x(), last.y(), last.z()).setSource(cap); + sdf = new SDFSmoothUnion().setRadius(3F).setSourceA(sdf).setSourceB(cap); + sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { + if (EndBlocks.JELLYSHROOM.isTreeLog(info.getState())) { + if (EndBlocks.JELLYSHROOM.isTreeLog(info.getStateUp()) && EndBlocks.JELLYSHROOM.isTreeLog(info.getStateDown())) { + return EndBlocks.JELLYSHROOM.getLog().defaultBlockState(); + } + } else if (info.getState().is(EndBlocks.JELLYSHROOM_CAP_PURPLE)) { + float dx = info.getPos().getX() - pos.getX() - last.x(); + float dz = info.getPos().getZ() - pos.getZ() - last.z(); + float distance = MHelper.length(dx, dz) / membraneRadius * 7F; + int color = Mth.clamp(MHelper.floor(distance), 0, 7); + return info.getState().setValue(JellyshroomCapBlock.COLOR, color); + } + return info.getState(); + }).fillRecursive(world, pos); + radius = height * 0.5F; + makeRoots(world, pos.offset(0, 2, 0), radius, random, bark); + + return true; + } + + private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, BlockState wood) { + int count = (int) (radius * 3.5F); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(ROOT); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + Vector3f last = branch.get(branch.size() - 1); + if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { + SplineHelper.fillSpline(branch, world, wood, pos, REPLACE); + } + } + } + + private SDF makeCap(float radius, RandomSource random, BlockState cap) { + SDF sphere = new SDFSphere().setRadius(radius).setBlock(cap); + SDF sub = new SDFTranslate().setTranslate(0, -4, 0).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFTranslate().setTranslate(0, 1 - radius * 0.5F, 0).setSource(sphere); + + float angle = random.nextFloat() * MHelper.PI2; + int count = (int) MHelper.randRange(radius * 0.5F, radius, random); + if (count < 3) { + count = 3; + } + sphere = new SDFFlatWave().setAngle(angle).setRaysCount(count).setIntensity(0.2F).setSource(sphere); + + return sphere; + } + + static { + ROOT = Lists.newArrayList( + new Vector3f(0.1F, 0.70F, 0), + new Vector3f(0.3F, 0.30F, 0), + new Vector3f(0.7F, 0.05F, 0), + new Vector3f(0.8F, -0.20F, 0) + ); + SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); + + REPLACE = (state) -> { + if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/LacugroveFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/LacugroveFeature.java new file mode 100644 index 00000000..7dced7f4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/LacugroveFeature.java @@ -0,0 +1,223 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class LacugroveFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Function IGNORE; + private static final Function POST; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + float size = MHelper.randRange(15, 25, random); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 6); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + + if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { + return false; + } + + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + + float radius = MHelper.randRange(6F, 8F, random); + radius *= (size - 15F) / 20F + 1F; + Vector3f center = spline.get(4); + leavesBall(world, pos.offset(center.x(), center.y(), center.z()), radius, random, noise); + + radius = MHelper.randRange(1.2F, 1.8F, random); + SDF function = SplineHelper.buildSDF(spline, radius, 0.7F, (bpos) -> { + return EndBlocks.LACUGROVE.getBark().defaultBlockState(); + }); + + function.setReplaceFunction(REPLACE); + function.addPostProcess(POST); + function.fillRecursive(world, pos); + + spline = spline.subList(4, 6); + SplineHelper.fillSpline(spline, world, EndBlocks.LACUGROVE.getBark().defaultBlockState(), pos, REPLACE); + + MutableBlockPos mut = new MutableBlockPos(); + int offset = random.nextInt(2); + for (int i = 0; i < 100; i++) { + double px = pos.getX() + MHelper.randRange(-5, 5, random); + double pz = pos.getZ() + MHelper.randRange(-5, 5, random); + mut.setX(MHelper.floor(px + 0.5)); + mut.setZ(MHelper.floor(pz + 0.5)); + if (((mut.getX() + mut.getZ() + offset) & 1) == 0) { + double distance = 3.5 - MHelper.length(px - pos.getX(), pz - pos.getZ()) * 0.5; + if (distance > 0) { + int minY = MHelper.floor(pos.getY() - distance * 0.5); + int maxY = MHelper.floor(pos.getY() + distance + random.nextDouble()); + boolean generate = false; + for (int y = minY; y < maxY; y++) { + mut.setY(y); + if (world.getBlockState(mut).is(CommonBlockTags.END_STONES)) { + generate = true; + break; + } + } + if (generate) { + int top = maxY - 1; + for (int y = top; y >= minY; y--) { + mut.setY(y); + BlockState state = world.getBlockState(mut); + if (state.getMaterial().isReplaceable() || state.getMaterial() + .equals(Material.PLANT) || state.is( + CommonBlockTags.END_STONES)) { + BlocksHelper.setWithoutUpdate( + world, + mut, + y == top ? EndBlocks.LACUGROVE.getBark() : EndBlocks.LACUGROVE.getLog() + ); + } else { + break; + } + } + } + } + } + } + + return true; + } + + private void leavesBall(WorldGenLevel world, + BlockPos pos, + float radius, + RandomSource random, + OpenSimplexNoise noise) { + SDF sphere = new SDFSphere().setRadius(radius) + .setBlock(EndBlocks.LACUGROVE_LEAVES.defaultBlockState() + .setValue(LeavesBlock.DISTANCE, 6)); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; + }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return random.nextFloat() * 3F - 1.5F; + }).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere) + .setSourceB(new SDFTranslate().setTranslate(0, -radius - 2, 0).setSource(sphere)); + MutableBlockPos mut = new MutableBlockPos(); + sphere.addPostProcess((info) -> { + if (random.nextInt(5) == 0) { + for (Direction dir : Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); + } + } + info.setState(EndBlocks.LACUGROVE.getBark().defaultBlockState()); + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); + + if (radius > 5) { + int count = (int) (radius * 2.5F); + for (int i = 0; i < count; i++) { + BlockPos p = pos.offset( + random.nextGaussian() * 1, + random.nextGaussian() * 1, + random.nextGaussian() * 1 + ); + boolean place = true; + for (Direction d : Direction.values()) { + BlockState state = world.getBlockState(p.relative(d)); + if (!EndBlocks.LACUGROVE.isTreeLog(state) && !state.is(EndBlocks.LACUGROVE_LEAVES)) { + place = false; + break; + } + } + if (place) { + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LACUGROVE.getBark()); + } + } + } + + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.LACUGROVE.getBark()); + } + + static { + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (EndBlocks.LACUGROVE.isTreeLog(state)) { + return true; + } + if (state.getBlock() == EndBlocks.LACUGROVE_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = (state) -> { + return EndBlocks.LACUGROVE.isTreeLog(state); + }; + + POST = (info) -> { + if (EndBlocks.LACUGROVE.isTreeLog(info.getStateUp()) && EndBlocks.LACUGROVE.isTreeLog(info.getStateDown())) { + return EndBlocks.LACUGROVE.getLog().defaultBlockState(); + } + return info.getState(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/LucerniaFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/LucerniaFeature.java new file mode 100644 index 00000000..c76db45a --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/LucerniaFeature.java @@ -0,0 +1,234 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class LucerniaFeature extends DefaultFeature { + private static final Direction[] DIRECTIONS = Direction.values(); + private static final Function REPLACE; + private static final Function IGNORE; + private static final List SPLINE; + private static final List ROOT; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + final NoneFeatureConfiguration config = featureConfig.config(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + float size = MHelper.randRange(12, 20, random); + int count = (int) (size * 0.3F); + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.scale(spline, size * MHelper.randRange(0.5F, 1F, random)); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SplineHelper.fillSpline(spline, world, EndBlocks.LUCERNIA.getBark().defaultBlockState(), pos, REPLACE); + Vector3f last = spline.get(spline.size() - 1); + float leavesRadius = (size * 0.13F + MHelper.randRange(0.8F, 1.5F, random)) * 1.4F; + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + leavesBall(world, pos.offset(last.x(), last.y(), last.z()), leavesRadius, random, noise, config != null); + } + + makeRoots(world, pos.offset(0, MHelper.randRange(3, 5, random), 0), size * 0.35F, random); + + return true; + } + + private void leavesBall(WorldGenLevel world, + BlockPos pos, + float radius, + RandomSource random, + OpenSimplexNoise noise, + boolean natural) { + SDF sphere = new SDFSphere().setRadius(radius) + .setBlock(EndBlocks.LUCERNIA_LEAVES.defaultBlockState() + .setValue(LeavesBlock.DISTANCE, 6)); + SDF sub = new SDFScale().setScale(5).setSource(sphere); + sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( + vec.x() * 0.2, + vec.y() * 0.2, + vec.z() * 0.2 + ) * 2F).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-1.5F, 1.5F, random)).setSource(sphere); + + MutableBlockPos mut = new MutableBlockPos(); + for (Direction d1 : BlocksHelper.HORIZONTAL) { + BlockPos p = mut.set(pos).move(Direction.UP).move(d1).immutable(); + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LUCERNIA.getBark().defaultBlockState()); + for (Direction d2 : BlocksHelper.HORIZONTAL) { + mut.set(p).move(Direction.UP).move(d2); + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LUCERNIA.getBark().defaultBlockState()); + } + } + + BlockState top = EndBlocks.FILALUX.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); + BlockState middle = EndBlocks.FILALUX.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); + BlockState bottom = EndBlocks.FILALUX.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); + BlockState outer = EndBlocks.LUCERNIA_OUTER_LEAVES.defaultBlockState(); + + List support = Lists.newArrayList(); + sphere.addPostProcess((info) -> { + if (natural && random.nextInt(6) == 0 && info.getStateDown().isAir()) { + BlockPos d = info.getPos().below(); + support.add(d); + } + if (random.nextInt(15) == 0) { + for (Direction dir : Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); + } + } + info.setState(EndBlocks.LUCERNIA.getBark().defaultBlockState()); + } + + MHelper.shuffle(DIRECTIONS, random); + for (Direction d : DIRECTIONS) { + if (info.getState(d).isAir()) { + info.setBlockPos(info.getPos().relative(d), outer.setValue(FurBlock.FACING, d)); + } + } + + if (EndBlocks.LUCERNIA.isTreeLog(info.getState())) { + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.LUCERNIA.getBark()); + + support.forEach((bpos) -> { + BlockState state = world.getBlockState(bpos); + if (state.isAir() || state.is(EndBlocks.LUCERNIA_OUTER_LEAVES)) { + int count = MHelper.randRange(3, 8, random); + mut.set(bpos); + if (world.getBlockState(mut.above()).is(EndBlocks.LUCERNIA_LEAVES)) { + BlocksHelper.setWithoutUpdate(world, mut, top); + for (int i = 1; i < count; i++) { + mut.setY(mut.getY() - 1); + if (world.isEmptyBlock(mut.below())) { + BlocksHelper.setWithoutUpdate(world, mut, middle); + } else { + break; + } + } + BlocksHelper.setWithoutUpdate(world, mut, bottom); + } + } + }); + } + + private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random) { + int count = (int) (radius * 1.5F); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(ROOT); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + Vector3f last = branch.get(branch.size() - 1); + if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { + SplineHelper.fillSplineForce(branch, + world, + EndBlocks.LUCERNIA.getBark().defaultBlockState(), + pos, + REPLACE); + } + } + } + + static { + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (state.getBlock() == EndBlocks.LUCERNIA_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = EndBlocks.LUCERNIA::isTreeLog; + + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); + + ROOT = Lists.newArrayList( + new Vector3f(0.1F, 0.70F, 0), + new Vector3f(0.3F, 0.30F, 0), + new Vector3f(0.7F, 0.05F, 0), + new Vector3f(0.8F, -0.20F, 0) + ); + SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/MossyGlowshroomFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/MossyGlowshroomFeature.java new file mode 100644 index 00000000..2d8d5c0d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/MossyGlowshroomFeature.java @@ -0,0 +1,173 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.sdf.primitive.SDFPrimitive; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.MossyGlowshroomCapBlock; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class MossyGlowshroomFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Vector3f CENTER = new Vector3f(); + private static final SDFBinary FUNCTION; + private static final SDFTranslate HEAD_POS; + private static final SDFFlatWave ROOTS_ROT; + + private static final SDFPrimitive CONE1; + private static final SDFPrimitive CONE2; + private static final SDFPrimitive CONE_GLOW; + private static final SDFPrimitive ROOTS; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos blockPos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + BlockState down = world.getBlockState(blockPos.below()); + if (!down.is(EndBlocks.END_MYCELIUM) && !down.is(EndBlocks.END_MOSS)) return false; + + CONE1.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); + CONE2.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); + CONE_GLOW.setBlock(EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE); + ROOTS.setBlock(EndBlocks.MOSSY_GLOWSHROOM.getBark()); + + float height = MHelper.randRange(10F, 25F, random); + int count = MHelper.floor(height / 4); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { + return EndBlocks.MOSSY_GLOWSHROOM.getLog().defaultBlockState(); + }); + Vector3f pos = spline.get(spline.size() - 1); + float scale = MHelper.randRange(0.75F, 1.1F, random); + + if (!SplineHelper.canGenerate(spline, scale, blockPos, world, REPLACE)) { + return false; + } + BlocksHelper.setWithoutUpdate(world, blockPos, AIR); + + CENTER.set(blockPos.getX(), 0, blockPos.getZ()); + HEAD_POS.setTranslate(pos.x(), pos.y(), pos.z()); + ROOTS_ROT.setAngle(random.nextFloat() * MHelper.PI2); + FUNCTION.setSourceA(sdf); + + new SDFScale().setScale(scale).setSource(FUNCTION).setReplaceFunction(REPLACE).addPostProcess((info) -> { + if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) { + if (random.nextBoolean() && info.getStateUp().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() + .setValue(MossyGlowshroomCapBlock.TRANSITION, true)); + return info.getState(); + } else if (!EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !EndBlocks.MOSSY_GLOWSHROOM.isTreeLog( + info.getStateDown())) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM.getBark().defaultBlockState()); + return info.getState(); + } + } else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { + if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() + .setValue(MossyGlowshroomCapBlock.TRANSITION, true)); + return info.getState(); + } + + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState()); + return info.getState(); + } else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { + for (Direction dir : BlocksHelper.HORIZONTAL) { + if (info.getState(dir) == AIR) { + info.setBlockPos( + info.getPos().relative(dir), + EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState().setValue(FurBlock.FACING, dir) + ); + } + } + + if (info.getStateDown().getBlock() != EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { + info.setBlockPos( + info.getPos().below(), + EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState().setValue(FurBlock.FACING, Direction.DOWN) + ); + } + } + return info.getState(); + }).fillRecursive(world, blockPos); + + return true; + } + + static { + SDFCappedCone cone1 = new SDFCappedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); + SDFCappedCone cone2 = new SDFCappedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); + SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); + SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0) + .setSource(new SDFScale().setScale(2).setSource(cone2)); + SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); + SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); + SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); + + CONE1 = cone1; + CONE2 = cone2; + + SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone); + innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone); + cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone); + + SDF glowCone = new SDFCappedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F); + CONE_GLOW = (SDFPrimitive) glowCone; + glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone); + glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3); + + cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone); + + OpenSimplexNoise noise = new OpenSimplexNoise(1234); + cones = new SDFCoordModify().setFunction((pos) -> { + float dist = MHelper.length(pos.x(), pos.z()); + float y = pos.y() + (float) noise.eval( + pos.x() * 0.1 + CENTER.x(), + pos.z() * 0.1 + CENTER.z() + ) * dist * 0.3F - dist * 0.15F; + pos.set(pos.x(), y, pos.z()); + }).setSource(cones); + + HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0) + .setSource(cones)); + + SDF roots = new SDFSphere().setRadius(4F); + ROOTS = (SDFPrimitive) roots; + roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots); + ROOTS_ROT = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots); + + FUNCTION = new SDFSmoothUnion().setRadius(4) + .setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(ROOTS_ROT)); + + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/PythadendronTreeFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/PythadendronTreeFeature.java new file mode 100644 index 00000000..d95274d7 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/PythadendronTreeFeature.java @@ -0,0 +1,222 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.PosInfo; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFDisplacement; +import org.betterx.bclib.sdf.operator.SDFScale3D; +import org.betterx.bclib.sdf.operator.SDFSubtraction; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class PythadendronTreeFeature extends DefaultFeature { + private static final Function REPLACE; + private static final Function IGNORE; + private static final Function POST; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (world.getBlockState(pos.below()).getBlock() != EndBlocks.CHORUS_NYLIUM) { + return false; + } + BlocksHelper.setWithoutUpdate(world, pos, AIR); + + float size = MHelper.randRange(10, 20, random); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 4); + SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); + Vector3f last = spline.get(spline.size() - 1); + + int depth = MHelper.floor((size - 10F) * 3F / 10F + 1F); + float bsize = (10F - (size - 10F)) / 10F + 1.5F; + branch( + last.x(), + last.y(), + last.z(), + size * bsize, + MHelper.randRange(0, MHelper.PI2, random), + random, + depth, + world, + pos + ); + + SDF function = SplineHelper.buildSDF(spline, 1.7F, 1.1F, (bpos) -> { + return EndBlocks.PYTHADENDRON.getBark().defaultBlockState(); + }); + function.setReplaceFunction(REPLACE); + function.addPostProcess(POST); + function.fillRecursive(world, pos); + + return true; + } + + private void branch(float x, + float y, + float z, + float size, + float angle, + RandomSource random, + int depth, + WorldGenLevel world, + BlockPos pos) { + if (depth == 0) return; + + float dx = (float) Math.cos(angle) * size * 0.15F; + float dz = (float) Math.sin(angle) * size * 0.15F; + + float x1 = x + dx; + float z1 = z + dz; + float x2 = x - dx; + float z2 = z - dz; + + List spline = SplineHelper.makeSpline(x, y, z, x1, y, z1, 5); + SplineHelper.powerOffset(spline, size * MHelper.randRange(1.0F, 2.0F, random), 4); + SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); + Vector3f pos1 = spline.get(spline.size() - 1); + + boolean s1 = SplineHelper.fillSpline( + spline, + world, + EndBlocks.PYTHADENDRON.getBark().defaultBlockState(), + pos, + REPLACE + ); + + spline = SplineHelper.makeSpline(x, y, z, x2, y, z2, 5); + SplineHelper.powerOffset(spline, size * MHelper.randRange(1.0F, 2.0F, random), 4); + SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); + Vector3f pos2 = spline.get(spline.size() - 1); + + boolean s2 = SplineHelper.fillSpline( + spline, + world, + EndBlocks.PYTHADENDRON.getBark().defaultBlockState(), + pos, + REPLACE + ); + + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); + if (depth < 3) { + if (s1) { + leavesBall(world, pos.offset(pos1.x(), pos1.y(), pos1.z()), random, noise); + } + if (s2) { + leavesBall(world, pos.offset(pos2.x(), pos2.y(), pos2.z()), random, noise); + } + } + + float size1 = size * MHelper.randRange(0.75F, 0.95F, random); + float size2 = size * MHelper.randRange(0.75F, 0.95F, random); + float angle1 = angle + (float) Math.PI * 0.5F + MHelper.randRange(-0.1F, 0.1F, random); + float angle2 = angle + (float) Math.PI * 0.5F + MHelper.randRange(-0.1F, 0.1F, random); + + if (s1) { + branch(pos1.x(), pos1.y(), pos1.z(), size1, angle1, random, depth - 1, world, pos); + } + if (s2) { + branch(pos2.x(), pos2.y(), pos2.z(), size2, angle2, random, depth - 1, world, pos); + } + } + + private void leavesBall(WorldGenLevel world, BlockPos pos, RandomSource random, OpenSimplexNoise noise) { + float radius = MHelper.randRange(4.5F, 6.5F, random); + + SDF sphere = new SDFSphere().setRadius(radius) + .setBlock(EndBlocks.PYTHADENDRON_LEAVES.defaultBlockState() + .setValue(LeavesBlock.DISTANCE, 6)); + sphere = new SDFScale3D().setScale(1, 0.6F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; + }).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> { + return random.nextFloat() * 3F - 1.5F; + }).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere) + .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); + MutableBlockPos mut = new MutableBlockPos(); + sphere.addPostProcess((info) -> { + if (random.nextInt(5) == 0) { + for (Direction dir : Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); + } + } + info.setState(EndBlocks.PYTHADENDRON.getBark().defaultBlockState()); + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); + } + + static { + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (state.getBlock() == EndBlocks.PYTHADENDRON_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = (state) -> { + return EndBlocks.PYTHADENDRON.isTreeLog(state); + }; + + POST = (info) -> { + if (EndBlocks.PYTHADENDRON.isTreeLog(info.getStateUp()) && EndBlocks.PYTHADENDRON.isTreeLog(info.getStateDown())) { + return EndBlocks.PYTHADENDRON.getLog().defaultBlockState(); + } + return info.getState(); + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/TenaneaFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/TenaneaFeature.java new file mode 100644 index 00000000..6a51b08d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/TenaneaFeature.java @@ -0,0 +1,201 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.blocks.BlockProperties; +import org.betterx.bclib.blocks.BlockProperties.TripleShape; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class TenaneaFeature extends DefaultFeature { + private static final Direction[] DIRECTIONS = Direction.values(); + private static final Function REPLACE; + private static final Function IGNORE; + private static final List SPLINE; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + float size = MHelper.randRange(7, 10, random); + int count = (int) (size * 0.45F); + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.scale(spline, size + MHelper.randRange(0, size * 0.5F, random)); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SplineHelper.fillSpline(spline, world, EndBlocks.TENANEA.getBark().defaultBlockState(), pos, REPLACE); + Vector3f last = spline.get(spline.size() - 1); + float leavesRadius = (size * 0.3F + MHelper.randRange(0.8F, 1.5F, random)) * 1.4F; + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + leavesBall(world, pos.offset(last.x(), last.y(), last.z()), leavesRadius, random, noise); + } + + return true; + } + + private void leavesBall(WorldGenLevel world, + BlockPos pos, + float radius, + RandomSource random, + OpenSimplexNoise noise) { + SDF sphere = new SDFSphere().setRadius(radius) + .setBlock(EndBlocks.TENANEA_LEAVES.defaultBlockState() + .setValue(LeavesBlock.DISTANCE, 6)); + SDF sub = new SDFScale().setScale(5).setSource(sphere); + sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( + vec.x() * 0.2, + vec.y() * 0.2, + vec.z() * 0.2 + ) * 2F).setSource(sphere); + sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-1.5F, 1.5F, random)).setSource(sphere); + + MutableBlockPos mut = new MutableBlockPos(); + for (Direction d1 : BlocksHelper.HORIZONTAL) { + BlockPos p = mut.set(pos).move(Direction.UP).move(d1).immutable(); + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.TENANEA.getBark().defaultBlockState()); + for (Direction d2 : BlocksHelper.HORIZONTAL) { + mut.set(p).move(Direction.UP).move(d2); + BlocksHelper.setWithoutUpdate(world, p, EndBlocks.TENANEA.getBark().defaultBlockState()); + } + } + + BlockState top = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); + BlockState middle = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); + BlockState bottom = EndBlocks.TENANEA_FLOWERS.defaultBlockState() + .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); + BlockState outer = EndBlocks.TENANEA_OUTER_LEAVES.defaultBlockState(); + + List support = Lists.newArrayList(); + sphere.addPostProcess((info) -> { + if (random.nextInt(6) == 0 && info.getStateDown().isAir()) { + BlockPos d = info.getPos().below(); + support.add(d); + } + if (random.nextInt(5) == 0) { + for (Direction dir : Direction.values()) { + BlockState state = info.getState(dir, 2); + if (state.isAir()) { + return info.getState(); + } + } + info.setState(EndBlocks.TENANEA.getBark().defaultBlockState()); + } + + MHelper.shuffle(DIRECTIONS, random); + for (Direction d : DIRECTIONS) { + if (info.getState(d).isAir()) { + info.setBlockPos(info.getPos().relative(d), outer.setValue(FurBlock.FACING, d)); + } + } + + if (EndBlocks.TENANEA.isTreeLog(info.getState())) { + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.getValue(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + return info.getState(); + }); + sphere.fillRecursiveIgnore(world, pos, IGNORE); + BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.TENANEA.getBark()); + + support.forEach((bpos) -> { + BlockState state = world.getBlockState(bpos); + if (state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) { + int count = MHelper.randRange(3, 8, random); + mut.set(bpos); + if (world.getBlockState(mut.above()).is(EndBlocks.TENANEA_LEAVES)) { + BlocksHelper.setWithoutUpdate(world, mut, top); + for (int i = 1; i < count; i++) { + mut.setY(mut.getY() - 1); + if (world.isEmptyBlock(mut.below())) { + BlocksHelper.setWithoutUpdate(world, mut, middle); + } else { + break; + } + } + BlocksHelper.setWithoutUpdate(world, mut, bottom); + } + } + }); + } + + static { + REPLACE = (state) -> { + /*if (state.is(CommonBlockTags.END_STONES)) { + return true; + }*/ + if (state.getBlock() == EndBlocks.TENANEA_LEAVES) { + return true; + } + if (state.getMaterial().equals(Material.PLANT)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + + IGNORE = EndBlocks.TENANEA::isTreeLog; + + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); + } +} diff --git a/src/main/java/org/betterx/betterend/world/features/trees/UmbrellaTreeFeature.java b/src/main/java/org/betterx/betterend/world/features/trees/UmbrellaTreeFeature.java new file mode 100644 index 00000000..c6270895 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/features/trees/UmbrellaTreeFeature.java @@ -0,0 +1,247 @@ +package org.betterx.betterend.world.features.trees; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; +import net.minecraft.world.level.material.Material; + +import com.google.common.collect.Lists; +import com.mojang.math.Vector3f; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.bclib.world.features.DefaultFeature; +import org.betterx.betterend.blocks.UmbrellaTreeClusterBlock; +import org.betterx.betterend.blocks.UmbrellaTreeMembraneBlock; +import org.betterx.betterend.registry.EndBlocks; + +import java.util.List; +import java.util.function.Function; + +public class UmbrellaTreeFeature extends DefaultFeature { + private static final Function REPLACE; + private static final List SPLINE; + private static final List ROOT; + + @Override + public boolean place(FeaturePlaceContext featureConfig) { + final RandomSource random = featureConfig.random(); + final BlockPos pos = featureConfig.origin(); + final WorldGenLevel world = featureConfig.level(); + final NoneFeatureConfiguration config = featureConfig.config(); + if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; + + BlockState wood = EndBlocks.UMBRELLA_TREE.getBark().defaultBlockState(); + BlockState membrane = EndBlocks.UMBRELLA_TREE_MEMBRANE.defaultBlockState() + .setValue(UmbrellaTreeMembraneBlock.COLOR, 1); + BlockState center = EndBlocks.UMBRELLA_TREE_MEMBRANE.defaultBlockState() + .setValue(UmbrellaTreeMembraneBlock.COLOR, 0); + BlockState fruit = EndBlocks.UMBRELLA_TREE_CLUSTER.defaultBlockState() + .setValue(UmbrellaTreeClusterBlock.NATURAL, true); + + float size = MHelper.randRange(10, 20, random); + int count = (int) (size * 0.15F); + float var = MHelper.PI2 / (float) (count * 3); + float start = MHelper.randRange(0, MHelper.PI2, random); + SDF sdf = null; + List
centers = Lists.newArrayList(); + + float scale = 1; + if (config != null) { + scale = MHelper.randRange(1F, 1.7F, random); + } + + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; + List spline = SplineHelper.copySpline(SPLINE); + float sizeXZ = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.7F; + SplineHelper.scale(spline, sizeXZ, sizeXZ * MHelper.randRange(1F, 2F, random), sizeXZ); + // SplineHelper.offset(spline, new Vector3f((20 - size) * 0.2F, 0, 0)); + SplineHelper.rotateSpline(spline, angle); + SplineHelper.offsetParts(spline, random, 0.5F, 0, 0.5F); + + if (SplineHelper.canGenerate(spline, pos, world, REPLACE)) { + float rScale = (scale - 1) * 0.4F + 1; + SDF branch = SplineHelper.buildSDF(spline, 1.2F * rScale, 0.8F * rScale, (bpos) -> { + return wood; + }); + + Vector3f vec = spline.get(spline.size() - 1); + float radius = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.4F; + + sdf = (sdf == null) ? branch : new SDFUnion().setSourceA(sdf).setSourceB(branch); + SDF mem = makeMembrane(world, radius, random, membrane, center); + + float px = MHelper.floor(vec.x()) + 0.5F; + float py = MHelper.floor(vec.y()) + 0.5F; + float pz = MHelper.floor(vec.z()) + 0.5F; + mem = new SDFTranslate().setTranslate(px, py, pz).setSource(mem); + sdf = new SDFSmoothUnion().setRadius(2).setSourceA(sdf).setSourceB(mem); + centers.add(new Center( + pos.getX() + (double) (px * scale), + pos.getY() + (double) (py * scale), + pos.getZ() + (double) (pz * scale), + radius * scale + )); + + vec = spline.get(0); + } + } + + if (sdf == null) { + return false; + } + + if (scale > 1) { + sdf = new SDFScale().setScale(scale).setSource(sdf); + } + + sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { + if (EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateUp()) && EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateDown())) { + return EndBlocks.UMBRELLA_TREE.getLog().defaultBlockState(); + } else if (info.getState().equals(membrane)) { + Center min = centers.get(0); + double d = Double.MAX_VALUE; + BlockPos bpos = info.getPos(); + for (Center c : centers) { + double d2 = c.distance(bpos.getX(), bpos.getZ()); + if (d2 < d) { + d = d2; + min = c; + } + } + int color = MHelper.floor(d / min.radius * 7); + color = Mth.clamp(color, 1, 7); + return info.getState().setValue(UmbrellaTreeMembraneBlock.COLOR, color); + } + return info.getState(); + }).fillRecursive(world, pos); + makeRoots(world, pos, (size * 0.5F + 3) * scale, random, wood); + + for (Center c : centers) { + if (!world.getBlockState(new BlockPos(c.px, c.py, c.pz)).isAir()) { + count = MHelper.floor(MHelper.randRange(5F, 10F, random) * scale); + float startAngle = random.nextFloat() * MHelper.PI2; + for (int i = 0; i < count; i++) { + float angle = (float) i / count * MHelper.PI2 + startAngle; + float dist = MHelper.randRange(1.5F, 2.5F, random) * scale; + double px = c.px + Math.sin(angle) * dist; + double pz = c.pz + Math.cos(angle) * dist; + makeFruits(world, px, c.py - 1, pz, fruit, scale); + } + } + } + + return true; + } + + private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, BlockState wood) { + int count = (int) (radius * 1.5F); + for (int i = 0; i < count; i++) { + float angle = (float) i / (float) count * MHelper.PI2; + float scale = radius * MHelper.randRange(0.85F, 1.15F, random); + + List branch = SplineHelper.copySpline(ROOT); + SplineHelper.rotateSpline(branch, angle); + SplineHelper.scale(branch, scale); + Vector3f last = branch.get(branch.size() - 1); + if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { + SplineHelper.fillSplineForce(branch, world, wood, pos, REPLACE); + } + } + } + + private SDF makeMembrane(WorldGenLevel world, + float radius, + RandomSource random, + BlockState membrane, + BlockState center) { + SDF sphere = new SDFSphere().setRadius(radius).setBlock(membrane); + SDF sub = new SDFTranslate().setTranslate(0, -4, 0).setSource(sphere); + sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); + sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); + sphere = new SDFTranslate().setTranslate(0, 1 - radius * 0.5F, 0).setSource(sphere); + + float angle = random.nextFloat() * MHelper.PI2; + int count = (int) MHelper.randRange(radius, radius * 2, random); + if (count < 5) { + count = 5; + } + sphere = new SDFFlatWave().setAngle(angle).setRaysCount(count).setIntensity(0.6F).setSource(sphere); + + SDF cent = new SDFSphere().setRadius(2.5F).setBlock(center); + sphere = new SDFUnion().setSourceA(sphere).setSourceB(cent); + + return sphere; + } + + private void makeFruits(WorldGenLevel world, double px, double py, double pz, BlockState fruit, float scale) { + MutableBlockPos mut = new MutableBlockPos().set(px, py, pz); + for (int i = 0; i < 8; i++) { + mut.move(Direction.DOWN); + if (world.isEmptyBlock(mut)) { + BlockState state = world.getBlockState(mut.above()); + if (state.is(EndBlocks.UMBRELLA_TREE_MEMBRANE) && state.getValue(UmbrellaTreeMembraneBlock.COLOR) < 2) { + BlocksHelper.setWithoutUpdate(world, mut, fruit); + } + break; + } + } + } + + static { + SPLINE = Lists.newArrayList( + new Vector3f(0.00F, 0.00F, 0.00F), + new Vector3f(0.10F, 0.35F, 0.00F), + new Vector3f(0.20F, 0.50F, 0.00F), + new Vector3f(0.30F, 0.55F, 0.00F), + new Vector3f(0.42F, 0.70F, 0.00F), + new Vector3f(0.50F, 1.00F, 0.00F) + ); + + ROOT = Lists.newArrayList( + new Vector3f(0.1F, 0.70F, 0), + new Vector3f(0.3F, 0.30F, 0), + new Vector3f(0.7F, 0.05F, 0), + new Vector3f(0.8F, -0.20F, 0) + ); + SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); + + REPLACE = (state) -> { + if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT) || state.is( + EndBlocks.UMBRELLA_TREE_MEMBRANE)) { + return true; + } + return state.getMaterial().isReplaceable(); + }; + } + + private class Center { + final double px; + final double py; + final double pz; + final float radius; + + Center(double x, double y, double z, float radius) { + this.px = x; + this.py = y; + this.pz = z; + this.radius = radius; + } + + double distance(float x, float z) { + return MHelper.length(px - x, pz - z); + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/generator/BiomeType.java b/src/main/java/org/betterx/betterend/world/generator/BiomeType.java new file mode 100644 index 00000000..c6a3ded5 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/BiomeType.java @@ -0,0 +1,5 @@ +package org.betterx.betterend.world.generator; + +public enum BiomeType { + LAND, VOID +} diff --git a/src/main/java/org/betterx/betterend/world/generator/GeneratorOptions.java b/src/main/java/org/betterx/betterend/world/generator/GeneratorOptions.java new file mode 100644 index 00000000..a2ce7bb4 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/GeneratorOptions.java @@ -0,0 +1,153 @@ +package org.betterx.betterend.world.generator; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; + +import org.betterx.betterend.config.Configs; + +public class GeneratorOptions { + private static int biomeSizeCaves; + private static boolean hasPortal; + private static boolean hasPillars; + private static boolean hasDragonFights; + private static boolean changeChorusPlant; + private static boolean newGenerator; + private static boolean generateCentralIsland; + private static boolean generateObsidianPlatform; + private static int endCityFailChance; + public static LayerOptions bigOptions; + public static LayerOptions mediumOptions; + public static LayerOptions smallOptions; + private static boolean changeSpawn; + private static BlockPos spawn; + private static boolean replacePortal; + private static boolean replacePillars; + private static int islandDistChunk; + private static boolean directSpikeHeight; + private static int circleRadius = 1000; + private static int circleRadiusSqr; + + public static void init() { + biomeSizeCaves = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeCaves", 32); + hasPortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "hasPortal", true); + hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true); + hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true); + changeChorusPlant = Configs.GENERATOR_CONFIG.getBoolean("chorusPlant", "changeChorusPlant", true); + newGenerator = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "useNewGenerator", true); + generateCentralIsland = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "generateCentralIsland", true); + endCityFailChance = Configs.GENERATOR_CONFIG.getInt("customGenerator", "endCityFailChance", 5); + generateObsidianPlatform = Configs.GENERATOR_CONFIG.getBooleanRoot("generateObsidianPlatform", true); + bigOptions = new LayerOptions( + "customGenerator.layers.bigIslands", + Configs.GENERATOR_CONFIG, + 300, + 200, + 70, + 10, + false + ); + mediumOptions = new LayerOptions( + "customGenerator.layers.mediumIslands", + Configs.GENERATOR_CONFIG, + 150, + 100, + 70, + 20, + true + ); + smallOptions = new LayerOptions( + "customGenerator.layers.smallIslands", + Configs.GENERATOR_CONFIG, + 60, + 50, + 70, + 30, + false + ); + changeSpawn = Configs.GENERATOR_CONFIG.getBoolean("spawn", "changeSpawn", false); + spawn = new BlockPos( + Configs.GENERATOR_CONFIG.getInt("spawn.point", "x", 20), + Configs.GENERATOR_CONFIG.getInt("spawn.point", "y", 65), + Configs.GENERATOR_CONFIG.getInt("spawn.point", "z", 0) + ); + replacePortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "customEndPortal", true); + replacePillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "customObsidianSpikes", true); + circleRadius = Configs.GENERATOR_CONFIG.getInt("customGenerator", "voidRingSize", 1000); + circleRadiusSqr = circleRadius * circleRadius; + islandDistChunk = (circleRadius >> 3); // Twice bigger than normal + } + + public static int getBiomeSizeCaves() { + return Mth.clamp(biomeSizeCaves, 1, 8192); + } + + public static boolean hasPortal() { + return hasPortal; + } + + public static boolean hasPillars() { + return hasPillars; + } + + public static boolean hasDragonFights() { + return hasDragonFights; + } + + public static boolean changeChorusPlant() { + return changeChorusPlant; + } + + public static boolean useNewGenerator() { + return newGenerator; + } + + public static boolean hasCentralIsland() { + return generateCentralIsland; + } + + public static boolean generateObsidianPlatform() { + return generateObsidianPlatform; + } + + public static int getEndCityFailChance() { + return endCityFailChance; + } + + public static boolean changeSpawn() { + return changeSpawn; + } + + public static BlockPos getSpawn() { + return spawn; + } + + public static boolean replacePortal() { + return replacePortal; + } + + public static boolean replacePillars() { + return replacePillars; + } + + public static int getIslandDistBlock() { + return circleRadius; + } + + public static int getIslandDistBlockSqr() { + return circleRadiusSqr; + } + + public static int getIslandDistChunk() { + return islandDistChunk; + } + + public static void setDirectSpikeHeight() { + directSpikeHeight = true; + } + + public static boolean isDirectSpikeHeight() { + boolean height = directSpikeHeight; + directSpikeHeight = false; + return height; + } +} diff --git a/src/main/java/org/betterx/betterend/world/generator/IslandLayer.java b/src/main/java/org/betterx/betterend/world/generator/IslandLayer.java new file mode 100644 index 00000000..847af6e9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/IslandLayer.java @@ -0,0 +1,192 @@ +package org.betterx.betterend.world.generator; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.LegacyRandomSource; + +import com.google.common.collect.Maps; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFRadialNoiseMap; +import org.betterx.bclib.sdf.operator.SDFScale; +import org.betterx.bclib.sdf.operator.SDFSmoothUnion; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class IslandLayer { + private static final RandomSource RANDOM = new LegacyRandomSource(MHelper.RANDOM.nextLong()); + private final SDFRadialNoiseMap noise; + private final SDF island; + + private final List positions = new ArrayList(9); + private final Map islands = Maps.newHashMap(); + private final OpenSimplexNoise density; + private final int seed; + private int lastX = Integer.MIN_VALUE; + private int lastZ = Integer.MIN_VALUE; + private final LayerOptions options; + + public IslandLayer(int seed, LayerOptions options) { + this.density = new OpenSimplexNoise(seed); + this.options = options; + this.seed = seed; + + SDF cone1 = makeCone(0, 0.4F, 0.2F, -0.3F); + SDF cone2 = makeCone(0.4F, 0.5F, 0.1F, -0.1F); + SDF cone3 = makeCone(0.5F, 0.45F, 0.03F, 0.0F); + SDF cone4 = makeCone(0.45F, 0, 0.02F, 0.03F); + + SDF coneBottom = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone1).setSourceB(cone2); + SDF coneTop = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone3).setSourceB(cone4); + noise = (SDFRadialNoiseMap) new SDFRadialNoiseMap().setSeed(seed) + .setRadius(0.5F) + .setIntensity(0.2F) + .setSource(coneTop); + island = new SDFSmoothUnion().setRadius(0.01F).setSourceA(noise).setSourceB(coneBottom); + } + + private int getSeed(int x, int z) { + int h = seed + x * 374761393 + z * 668265263; + h = (h ^ (h >> 13)) * 1274126177; + return h ^ (h >> 16); + } + + public void updatePositions(double x, double z) { + int ix = MHelper.floor(x / options.distance); + int iz = MHelper.floor(z / options.distance); + + if (lastX != ix || lastZ != iz) { + lastX = ix; + lastZ = iz; + positions.clear(); + for (int pox = -1; pox < 2; pox++) { + int px = pox + ix; + long px2 = px; + for (int poz = -1; poz < 2; poz++) { + int pz = poz + iz; + long pz2 = pz; + if (px2 * px2 + pz2 * pz2 > options.centerDist) { + RANDOM.setSeed(getSeed(px, pz)); + double posX = (px + RANDOM.nextFloat()) * options.distance; + double posY = MHelper.randRange(options.minY, options.maxY, RANDOM); + double posZ = (pz + RANDOM.nextFloat()) * options.distance; + if (density.eval(posX * 0.01, posZ * 0.01) > options.coverage) { + positions.add(new BlockPos(posX, posY, posZ)); + } + } + } + } + } + + if (GeneratorOptions.hasCentralIsland() && Math.abs(ix) < GeneratorOptions.getIslandDistChunk() && Math.abs(iz) < GeneratorOptions + .getIslandDistChunk()) { + int count = positions.size(); + for (int n = 0; n < count; n++) { + BlockPos pos = positions.get(n); + long d = (long) pos.getX() * (long) pos.getX() + (long) pos.getZ() * (long) pos.getZ(); + if (d < GeneratorOptions.getIslandDistBlockSqr()) { + positions.remove(n); + count--; + n--; + } + } + if (options.hasCentralIsland) { + positions.add(new BlockPos(0, 64, 0)); + } + } + } + + private SDF getIsland(BlockPos pos) { + SDF island = islands.get(pos); + if (island == null) { + if (pos.getX() == 0 && pos.getZ() == 0) { + island = new SDFScale().setScale(1.3F).setSource(this.island); + } else { + RANDOM.setSeed(getSeed(pos.getX(), pos.getZ())); + island = new SDFScale().setScale(RANDOM.nextFloat() + 0.5F).setSource(this.island); + } + islands.put(pos, island); + } + noise.setOffset(pos.getX(), pos.getZ()); + return island; + } + + private float getRelativeDistance(SDF sdf, BlockPos center, double px, double py, double pz) { + float x = (float) (px - center.getX()) / options.scale; + float y = (float) (py - center.getY()) / options.scale; + float z = (float) (pz - center.getZ()) / options.scale; + return sdf.getDistance(x, y, z); + } + + private float calculateSDF(double x, double y, double z) { + float distance = 10; + for (BlockPos pos : positions) { + SDF island = getIsland(pos); + float dist = getRelativeDistance(island, pos, x, y, z); + distance = MHelper.min(distance, dist); + } + return distance; + } + + public float getDensity(double x, double y, double z) { + return -calculateSDF(x, y, z); + } + + public float getDensity(double x, double y, double z, float height) { + noise.setIntensity(height); + noise.setRadius(0.5F / (1 + height)); + return -calculateSDF(x, y, z); + } + + public void clearCache() { + if (islands.size() > 128) { + islands.clear(); + } + } + + private static SDF makeCone(float radiusBottom, float radiusTop, float height, float minY) { + float hh = height * 0.5F; + SDF sdf = new SDFCappedCone().setHeight(hh).setRadius1(radiusBottom).setRadius2(radiusTop); + return new SDFTranslate().setTranslate(0, minY + hh, 0).setSource(sdf); + } + + /*private static NativeImage loadMap(String path) { + InputStream stream = IslandLayer.class.getResourceAsStream(path); + if (stream != null) { + try { + NativeImage map = NativeImage.read(stream); + stream.close(); + return map; + } + catch (IOException e) { + BetterEnd.LOGGER.warning(e.getMessage()); + } + } + return null; + }*/ + + /*static { + NativeImage map = loadMap("/assets/" + BetterEnd.MOD_ID + "/textures/heightmaps/mountain_1.png"); + + SDF cone1 = makeCone(0, 0.4F, 0.2F, -0.3F); + SDF cone2 = makeCone(0.4F, 0.5F, 0.1F, -0.1F); + SDF cone3 = makeCone(0.5F, 0.45F, 0.03F, 0.0F); + SDF cone4 = makeCone(0.45F, 0, 0.02F, 0.03F); + + SDF coneBottom = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone1).setSourceB(cone2); + SDF coneTop = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone3).setSourceB(cone4); + + SDF map1 = new SDFHeightmap().setMap(map).setIntensity(0.3F).setSource(coneTop); + NOISE = (SDFRadialNoiseMap) new SDFRadialNoiseMap().setSource(coneTop); + + ISLAND = new SDF[] { + new SDFSmoothUnion().setRadius(0.01F).setSourceA(coneTop).setSourceB(coneBottom), + new SDFSmoothUnion().setRadius(0.01F).setSourceA(map1).setSourceB(coneBottom) + }; + }*/ +} diff --git a/src/main/java/org/betterx/betterend/world/generator/LayerOptions.java b/src/main/java/org/betterx/betterend/world/generator/LayerOptions.java new file mode 100644 index 00000000..e87687bd --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/LayerOptions.java @@ -0,0 +1,55 @@ +package org.betterx.betterend.world.generator; + +import net.minecraft.util.Mth; + +import org.betterx.bclib.config.PathConfig; + +public class LayerOptions { + public final float distance; + public final float scale; + public final float coverage; + public final int center; + public final int heightVariation; + public final int minY; + public final int maxY; + public final long centerDist; + public final boolean hasCentralIsland; + + public LayerOptions(String name, + PathConfig config, + float distance, + float scale, + int center, + int heightVariation, + boolean hasCentral) { + this.distance = clampDistance(config.getFloat(name, "distance[1-8192]", distance)); + this.scale = clampScale(config.getFloat(name, "scale[0.1-1024]", scale)); + this.center = clampCenter(config.getInt(name, "averageHeight[0-255]", center)); + this.heightVariation = clampVariation(config.getInt(name, "heightVariation[0-255]", heightVariation)); + this.coverage = clampCoverage(config.getFloat(name, "coverage[0-1]", 0.5F)); + this.minY = this.center - this.heightVariation; + this.maxY = this.center + this.heightVariation; + this.centerDist = Mth.floor(1000 / this.distance); + this.hasCentralIsland = config.getBoolean(name, "hasCentralIsland", hasCentral); + } + + private float clampDistance(float value) { + return Mth.clamp(value, 1, 8192); + } + + private float clampScale(float value) { + return Mth.clamp(value, 0.1F, 1024); + } + + private float clampCoverage(float value) { + return 0.9999F - Mth.clamp(value, 0, 1) * 2; + } + + private int clampCenter(int value) { + return Mth.clamp(value, 0, 255); + } + + private int clampVariation(int value) { + return Mth.clamp(value, 0, 255); + } +} diff --git a/src/main/java/org/betterx/betterend/world/generator/TerrainBoolCache.java b/src/main/java/org/betterx/betterend/world/generator/TerrainBoolCache.java new file mode 100644 index 00000000..d9407e12 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/TerrainBoolCache.java @@ -0,0 +1,21 @@ +package org.betterx.betterend.world.generator; + +public class TerrainBoolCache { + private final byte[] data = new byte[16384]; + + public static int scaleCoordinate(int value) { + return value >> 7; + } + + private int getIndex(int x, int z) { + return x << 7 | z; + } + + public void setData(int x, int z, byte value) { + data[getIndex(x & 127, z & 127)] = value; + } + + public byte getData(int x, int z) { + return data[getIndex(x & 127, z & 127)]; + } +} diff --git a/src/main/java/org/betterx/betterend/world/generator/TerrainGenerator.java b/src/main/java/org/betterx/betterend/world/generator/TerrainGenerator.java new file mode 100644 index 00000000..4b20bb8e --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/generator/TerrainGenerator.java @@ -0,0 +1,197 @@ +package org.betterx.betterend.world.generator; + +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.biome.Climate.Sampler; +import net.minecraft.world.level.levelgen.LegacyRandomSource; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.world.biomes.BCLBiome; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.awt.*; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; + +public class TerrainGenerator { + private static final Map TERRAIN_BOOL_CACHE_MAP = Maps.newHashMap(); + private static final ReentrantLock LOCKER = new ReentrantLock(); + private static final Point POS = new Point(); + private static final double SCALE_XZ = 8.0; + private static final double SCALE_Y = 4.0; + private static final float[] COEF; + private static final Point[] OFFS; + + private static IslandLayer largeIslands; + private static IslandLayer mediumIslands; + private static IslandLayer smallIslands; + private static OpenSimplexNoise noise1; + private static OpenSimplexNoise noise2; + private static BiomeSource biomeSource; + private static Sampler sampler; + + public static void initNoise(long seed, BiomeSource biomeSource, Sampler sampler) { + RandomSource random = new LegacyRandomSource(seed); + largeIslands = new IslandLayer(random.nextInt(), GeneratorOptions.bigOptions); + mediumIslands = new IslandLayer(random.nextInt(), GeneratorOptions.mediumOptions); + smallIslands = new IslandLayer(random.nextInt(), GeneratorOptions.smallOptions); + noise1 = new OpenSimplexNoise(random.nextInt()); + noise2 = new OpenSimplexNoise(random.nextInt()); + TERRAIN_BOOL_CACHE_MAP.clear(); + TerrainGenerator.biomeSource = biomeSource; + TerrainGenerator.sampler = sampler; + } + + public static void fillTerrainDensity(double[] buffer, int posX, int posZ, int scaleXZ, int scaleY) { + LOCKER.lock(); + + largeIslands.clearCache(); + mediumIslands.clearCache(); + smallIslands.clearCache(); + + int x = Mth.floor(posX / scaleXZ); + int z = Mth.floor(posZ / scaleXZ); + double distortion1 = noise1.eval(x * 0.1, z * 0.1) * 20 + noise2.eval( + x * 0.2, + z * 0.2 + ) * 10 + noise1.eval(x * 0.4, z * 0.4) * 5; + double distortion2 = noise2.eval(x * 0.1, z * 0.1) * 20 + noise1.eval( + x * 0.2, + z * 0.2 + ) * 10 + noise2.eval(x * 0.4, z * 0.4) * 5; + double px = (double) x * scaleXZ + distortion1; + double pz = (double) z * scaleXZ + distortion2; + + largeIslands.updatePositions(px, pz); + mediumIslands.updatePositions(px, pz); + smallIslands.updatePositions(px, pz); + + float height = getAverageDepth(x << 1, z << 1) * 0.5F; + + for (int y = 0; y < buffer.length; y++) { + double py = (double) y * scaleY; + float dist = largeIslands.getDensity(px, py, pz, height); + dist = dist > 1 ? dist : MHelper.max(dist, mediumIslands.getDensity(px, py, pz, height)); + dist = dist > 1 ? dist : MHelper.max(dist, smallIslands.getDensity(px, py, pz, height)); + if (dist > -0.5F) { + dist += noise1.eval(px * 0.01, py * 0.01, pz * 0.01) * 0.02 + 0.02; + dist += noise2.eval(px * 0.05, py * 0.05, pz * 0.05) * 0.01 + 0.01; + dist += noise1.eval(px * 0.1, py * 0.1, pz * 0.1) * 0.005 + 0.005; + } + if (py > 100) { + dist = (float) Mth.lerp((py - 100) / 27F, dist, -1); + } + buffer[y] = dist; + } + + LOCKER.unlock(); + } + + private static float getAverageDepth(int x, int z) { + if (biomeSource == null) { + return 0; + } + if (getBiome(biomeSource, x, z).getTerrainHeight() < 0.1F) { + return 0F; + } + float depth = 0F; + for (int i = 0; i < OFFS.length; i++) { + int px = x + OFFS[i].x; + int pz = z + OFFS[i].y; + depth += getBiome(biomeSource, px, pz).getTerrainHeight() * COEF[i]; + } + return depth; + } + + private static BCLBiome getBiome(BiomeSource biomeSource, int x, int z) { + return BiomeAPI.getBiome(biomeSource.getNoiseBiome(x, 0, z, sampler)); + } + + static { + float sum = 0; + List coef = Lists.newArrayList(); + List pos = Lists.newArrayList(); + for (int x = -3; x <= 3; x++) { + for (int z = -3; z <= 3; z++) { + float dist = MHelper.length(x, z) / 3F; + if (dist <= 1) { + sum += dist; + coef.add(dist); + pos.add(new Point(x, z)); + } + } + } + OFFS = pos.toArray(new Point[]{}); + COEF = new float[coef.size()]; + for (int i = 0; i < COEF.length; i++) { + COEF[i] = coef.get(i) / sum; + } + } + + public static Boolean isLand(int x, int z) { + int sectionX = TerrainBoolCache.scaleCoordinate(x); + int sectionZ = TerrainBoolCache.scaleCoordinate(z); + + LOCKER.lock(); + POS.setLocation(sectionX, sectionZ); + + TerrainBoolCache section = TERRAIN_BOOL_CACHE_MAP.get(POS); + if (section == null) { + if (TERRAIN_BOOL_CACHE_MAP.size() > 64) { + TERRAIN_BOOL_CACHE_MAP.clear(); + } + section = new TerrainBoolCache(); + TERRAIN_BOOL_CACHE_MAP.put(new Point(POS.x, POS.y), section); + } + byte value = section.getData(x, z); + if (value > 0) { + LOCKER.unlock(); + return value > 1; + } + + double px = (x >> 1) + 0.5; + double pz = (z >> 1) + 0.5; + + double distortion1 = noise1.eval(px * 0.1, pz * 0.1) * 20 + noise2.eval(px * 0.2, pz * 0.2) * 10 + noise1.eval( + px * 0.4, + pz * 0.4 + ) * 5; + double distortion2 = noise2.eval(px * 0.1, pz * 0.1) * 20 + noise1.eval(px * 0.2, pz * 0.2) * 10 + noise2.eval( + px * 0.4, + pz * 0.4 + ) * 5; + px = px * SCALE_XZ + distortion1; + pz = pz * SCALE_XZ + distortion2; + + largeIslands.updatePositions(px, pz); + mediumIslands.updatePositions(px, pz); + smallIslands.updatePositions(px, pz); + + boolean result = false; + for (int y = 0; y < 32; y++) { + double py = (double) y * SCALE_Y; + float dist = largeIslands.getDensity(px, py, pz); + dist = dist > 1 ? dist : MHelper.max(dist, mediumIslands.getDensity(px, py, pz)); + dist = dist > 1 ? dist : MHelper.max(dist, smallIslands.getDensity(px, py, pz)); + if (dist > -0.5F) { + dist += noise1.eval(px * 0.01, py * 0.01, pz * 0.01) * 0.02 + 0.02; + dist += noise2.eval(px * 0.05, py * 0.05, pz * 0.05) * 0.01 + 0.01; + dist += noise1.eval(px * 0.1, py * 0.1, pz * 0.1) * 0.005 + 0.005; + } + if (dist > -0.01) { + result = true; + break; + } + } + + section.setData(x, z, (byte) (result ? 2 : 1)); + LOCKER.unlock(); + + return result; + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/EternalPortalStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/EternalPortalStructure.java new file mode 100644 index 00000000..2322e56d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/EternalPortalStructure.java @@ -0,0 +1,78 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import org.betterx.bclib.util.StructureHelper; +import org.betterx.bclib.world.structures.BCLStructure; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.NBTPiece; + +import java.util.Optional; + +public class EternalPortalStructure extends FeatureBaseStructure { + private static final ResourceLocation STRUCTURE_ID = BetterEnd.makeID("portal/eternal_portal"); + private static final StructureTemplate STRUCTURE = StructureHelper.readStructure(STRUCTURE_ID); + + public EternalPortalStructure(StructureSettings s) { + super(s); + } + + @Override + public Optional findGenerationPoint(GenerationContext context) { + if (!BCLStructure.isValidBiome(context)) return Optional.empty(); + + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + + long x = (long) chunkPos.x * (long) chunkPos.x; + long z = (long) chunkPos.z * (long) chunkPos.z; + if (x + z < 1024L) { + return Optional.empty(); + } + if (chunkGenerator.getBaseHeight( + chunkPos.getBlockX(8), + chunkPos.getBlockZ(8), + Heightmap.Types.WORLD_SURFACE_WG, + levelHeightAccessor, + context.randomState() + ) < 5) { + return Optional.empty(); + } + return super.findGenerationPoint(context); + } + + @Override + public StructureType type() { + return EndStructures.ETERNAL_PORTAL.structureType; + } + + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + int x = chunkPos.getBlockX(8); + int z = chunkPos.getBlockZ(8); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, context.randomState()); + structurePiecesBuilder.addPiece(new NBTPiece( + STRUCTURE_ID, + STRUCTURE, + new BlockPos(x, y - 4, z), + random.nextInt(5), + true, + random + )); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/FeatureBaseStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/FeatureBaseStructure.java new file mode 100644 index 00000000..243ece65 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/FeatureBaseStructure.java @@ -0,0 +1,93 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.world.structures.BCLStructure; + +import java.util.Optional; + +public abstract class FeatureBaseStructure extends Structure { + protected static final BlockState AIR = Blocks.AIR.defaultBlockState(); + + public FeatureBaseStructure(Structure.StructureSettings structureSettings) { + super(structureSettings); + } + + @Override + public Optional findGenerationPoint(GenerationContext context) { + BlockPos pos = getGenerationHeight(context.chunkPos(), + context.chunkGenerator(), + context.heightAccessor(), + context.randomState()); + if (pos.getZ() >= 20 && BCLStructure.isValidBiome(context)) { + return Optional.of(new Structure.GenerationStub(pos, (structurePiecesBuilder) -> { + generatePieces(structurePiecesBuilder, context); + })); + } + return Optional.empty(); + } + + protected Holder getNoiseBiome(ChunkGenerator cg, RandomState rState, int i, int j, int k) { + return cg.getBiomeSource().getNoiseBiome(i, j, k, rState.sampler()); + } + + protected abstract void generatePieces(StructurePiecesBuilder structurePiecesBuilder, + Structure.GenerationContext context); + + private static BlockPos getGenerationHeight(ChunkPos chunkPos, + ChunkGenerator chunkGenerator, + LevelHeightAccessor levelHeightAccessor, + RandomState rState) { + LegacyRandomSource random = new LegacyRandomSource(chunkPos.x + chunkPos.z * 10387313); + Rotation blockRotation = Rotation.getRandom(random); + + int i = 5; + int j = 5; + if (blockRotation == Rotation.CLOCKWISE_90) { + i = -5; + } else if (blockRotation == Rotation.CLOCKWISE_180) { + i = -5; + j = -5; + } else if (blockRotation == Rotation.COUNTERCLOCKWISE_90) { + j = -5; + } + + int k = chunkPos.getBlockX(7); + int l = chunkPos.getBlockZ(7); + int m = chunkGenerator.getFirstOccupiedHeight(k, + l, + Heightmap.Types.WORLD_SURFACE_WG, + levelHeightAccessor, + rState); + int n = chunkGenerator.getFirstOccupiedHeight(k, + l + j, + Heightmap.Types.WORLD_SURFACE_WG, + levelHeightAccessor, + rState); + int o = chunkGenerator.getFirstOccupiedHeight(k + i, + l, + Heightmap.Types.WORLD_SURFACE_WG, + levelHeightAccessor, + rState); + int p = chunkGenerator.getFirstOccupiedHeight( + k + i, + l + j, + Heightmap.Types.WORLD_SURFACE_WG, + levelHeightAccessor, rState + ); + return new BlockPos(k, l, Math.min(Math.min(m, n), Math.min(o, p))); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/GiantIceStarStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/GiantIceStarStructure.java new file mode 100644 index 00000000..a078b62d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/GiantIceStarStructure.java @@ -0,0 +1,126 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.SDFRotation; +import org.betterx.bclib.sdf.operator.SDFTranslate; +import org.betterx.bclib.sdf.operator.SDFUnion; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.VoxelPiece; + +import java.util.ArrayList; +import java.util.List; + +public class GiantIceStarStructure extends SDFStructureFeature { + private static final float minSize = 20; + private static final float maxSize = 35; + private static final int minCount = 25; + private static final int maxCount = 40; + + public GiantIceStarStructure(StructureSettings s) { + super(s); + } + + @Override + public StructureType type() { + return EndStructures.GIANT_ICE_STAR.structureType; + } + + protected static SDF getSDF(BlockPos pos, RandomSource random) { + float size = MHelper.randRange(minSize, maxSize, random); + int count = MHelper.randRange(minCount, maxCount, random); + List points = getFibonacciPoints(count); + SDF sdf = null; + SDF spike = new SDFCappedCone().setRadius1(3 + (size - 5) * 0.2F) + .setRadius2(0) + .setHeight(size) + .setBlock(EndBlocks.DENSE_SNOW); + spike = new SDFTranslate().setTranslate(0, size - 0.5F, 0).setSource(spike); + for (Vector3f point : points) { + SDF rotated = spike; + point = MHelper.normalize(point); + float angle = MHelper.angle(Vector3f.YP, point); + if (angle > 0.01F && angle < 3.14F) { + Vector3f axis = MHelper.normalize(MHelper.cross(Vector3f.YP, point)); + rotated = new SDFRotation().setRotation(axis, angle).setSource(spike); + } else if (angle > 1) { + rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(spike); + } + sdf = (sdf == null) ? rotated : new SDFUnion().setSourceA(sdf).setSourceB(rotated); + } + + final float ancientRadius = size * 0.7F; + final float denseRadius = size * 0.9F; + final float iceRadius = size < 7 ? size * 5 : size * 1.3F; + final float randScale = size * 0.3F; + + final BlockPos center = pos; + final BlockState ice = EndBlocks.EMERALD_ICE.defaultBlockState(); + final BlockState dense = EndBlocks.DENSE_EMERALD_ICE.defaultBlockState(); + final BlockState ancient = EndBlocks.ANCIENT_EMERALD_ICE.defaultBlockState(); + final SDF sdfCopy = sdf; + + return sdf.addPostProcess((info) -> { + BlockPos bpos = info.getPos(); + float px = bpos.getX() - center.getX(); + float py = bpos.getY() - center.getY(); + float pz = bpos.getZ() - center.getZ(); + float distance = MHelper.length(px, py, pz) + sdfCopy.getDistance( + px, + py, + pz + ) * 0.4F + random.nextFloat() * randScale; + if (distance < ancientRadius) { + return ancient; + } else if (distance < denseRadius) { + return dense; + } else if (distance < iceRadius) { + return ice; + } + return info.getState(); + }); + } + + private static List getFibonacciPoints(int count) { + float max = count - 1; + List result = new ArrayList(count); + for (int i = 0; i < count; i++) { + float y = 1F - (i / max) * 2F; + float radius = (float) Math.sqrt(1F - y * y); + float theta = MHelper.PHI * i; + float x = (float) Math.cos(theta) * radius; + float z = (float) Math.sin(theta) * radius; + result.add(new Vector3f(x, y, z)); + } + return result; + } + + public void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + BlockPos start = new BlockPos(x, MHelper.randRange(32, 128, random), z); + VoxelPiece piece = new VoxelPiece((world) -> { + getSDF(start, random).fillRecursive(world, start); + }, random.nextInt()); + structurePiecesBuilder.addPiece(piece); + + //this.calculateBoundingBox(); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/GiantMossyGlowshroomStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/GiantMossyGlowshroomStructure.java new file mode 100644 index 00000000..11fa46ba --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/GiantMossyGlowshroomStructure.java @@ -0,0 +1,156 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import com.mojang.math.Vector3f; +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.sdf.operator.*; +import org.betterx.bclib.sdf.primitive.SDFCappedCone; +import org.betterx.bclib.sdf.primitive.SDFPrimitive; +import org.betterx.bclib.sdf.primitive.SDFSphere; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.SplineHelper; +import org.betterx.betterend.blocks.MossyGlowshroomCapBlock; +import org.betterx.betterend.blocks.basis.FurBlock; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndStructures; + +import java.util.List; + +public class GiantMossyGlowshroomStructure extends SDFStructureFeature { + public GiantMossyGlowshroomStructure(StructureSettings s) { + super(s); + } + + + @Override + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + SDFStructureFeature.generatePieces(structurePiecesBuilder, context, GiantMossyGlowshroomStructure::getSDF); + } + + protected static SDF getSDF(BlockPos center, RandomSource random) { + SDFCappedCone cone1 = new SDFCappedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); + SDFCappedCone cone2 = new SDFCappedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); + SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); + SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0) + .setSource(new SDFScale().setScale(2).setSource(cone2)); + SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); + SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); + SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); + + SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone); + innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone); + cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone); + + SDF glowCone = new SDFCappedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F); + SDFPrimitive priGlowCone = (SDFPrimitive) glowCone; + glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone); + glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3); + + cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone); + + OpenSimplexNoise noise = new OpenSimplexNoise(1234); + cones = new SDFCoordModify().setFunction((pos) -> { + float dist = MHelper.length(pos.x(), pos.z()); + float y = pos.y() + (float) noise.eval( + pos.x() * 0.1 + center.getX(), + pos.z() * 0.1 + center.getZ() + ) * dist * 0.3F - dist * 0.15F; + pos.set(pos.x(), y, pos.z()); + }).setSource(cones); + + SDFTranslate HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0) + .setSource(cones)); + + SDF roots = new SDFSphere().setRadius(4F); + SDFPrimitive primRoots = (SDFPrimitive) roots; + roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots); + SDFFlatWave rotRoots = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots); + + SDFBinary function = new SDFSmoothUnion().setRadius(4) + .setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(rotRoots)); + + cone1.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); + cone2.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); + priGlowCone.setBlock(EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE); + primRoots.setBlock(EndBlocks.MOSSY_GLOWSHROOM.getBark()); + + float height = MHelper.randRange(10F, 25F, random); + int count = MHelper.floor(height / 4); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { + return EndBlocks.MOSSY_GLOWSHROOM.getLog().defaultBlockState(); + }); + Vector3f pos = spline.get(spline.size() - 1); + float scale = MHelper.randRange(2F, 3.5F, random); + + HEAD_POS.setTranslate(pos.x(), pos.y(), pos.z()); + rotRoots.setAngle(random.nextFloat() * MHelper.PI2); + function.setSourceA(sdf); + + return new SDFRound().setRadius(1.5F) + .setSource(new SDFScale().setScale(scale).setSource(function)) + .addPostProcess((info) -> { + if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) { + if (random.nextBoolean() && info.getStateUp() + .getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() + .setValue( + MossyGlowshroomCapBlock.TRANSITION, + true + )); + return info.getState(); + } else if (!EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !EndBlocks.MOSSY_GLOWSHROOM + .isTreeLog(info.getStateDown())) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM.getBark().defaultBlockState()); + return info.getState(); + } + } else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { + if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) { + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() + .setValue( + MossyGlowshroomCapBlock.TRANSITION, + true + )); + return info.getState(); + } + + info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState()); + return info.getState(); + } else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { + for (Direction dir : BlocksHelper.HORIZONTAL) { + if (info.getState(dir) == AIR) { + info.setBlockPos( + info.getPos().relative(dir), + EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState() + .setValue(FurBlock.FACING, dir) + ); + } + } + + if (info.getStateDown().getBlock() != EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { + info.setBlockPos( + info.getPos().below(), + EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState() + .setValue(FurBlock.FACING, + Direction.DOWN) + ); + } + } + return info.getState(); + }); + } + + + @Override + public StructureType type() { + return EndStructures.GIANT_MOSSY_GLOWSHROOM.structureType; + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeSmallStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeSmallStructure.java new file mode 100644 index 00000000..583ab4fd --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeSmallStructure.java @@ -0,0 +1,51 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.LakePiece; + +public class MegaLakeSmallStructure extends FeatureBaseStructure { + public MegaLakeSmallStructure(StructureSettings s) { + super(s); + } + + @Override + public StructureType type() { + return EndStructures.MEGALAKE_SMALL.structureType; + } + + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + final RandomState rState = context.randomState(); + + + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); + + Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); + if (y > 5) { + float radius = MHelper.randRange(20, 40, random); + float depth = MHelper.randRange(5, 10, random); + LakePiece piece = new LakePiece(new BlockPos(x, y, z), radius, depth, random, biome); + structurePiecesBuilder.addPiece(piece); + } + + //this.calculateBoundingBox(); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeStructure.java new file mode 100644 index 00000000..89e81af6 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/MegaLakeStructure.java @@ -0,0 +1,54 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.LakePiece; + +public class MegaLakeStructure extends FeatureBaseStructure { + + + public MegaLakeStructure(Structure.StructureSettings structureSettings) { + super(structureSettings); + } + + @Override + public StructureType type() { + return EndStructures.MEGALAKE.structureType; + } + + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, Structure.GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final RandomState rState = context.randomState(); + + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); + + if (y > 5) { + Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); + + float radius = MHelper.randRange(32, 64, random); + float depth = MHelper.randRange(7, 15, random); + LakePiece piece = new LakePiece(new BlockPos(x, y, z), radius, depth, random, biome); + structurePiecesBuilder.addPiece(piece); + } + } + +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/MountainStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/MountainStructure.java new file mode 100644 index 00000000..209a4f9c --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/MountainStructure.java @@ -0,0 +1,57 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.CrystalMountainPiece; + +public class MountainStructure extends FeatureBaseStructure { + + public MountainStructure(StructureSettings s) { + super(s); + } + + @Override + public StructureType type() { + return EndStructures.MOUNTAIN.structureType; + } + + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + final RandomState rState = context.randomState(); + + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); + if (y > 5) { + Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); + float radius = MHelper.randRange(50, 100, random); + float height = radius * MHelper.randRange(0.8F, 1.2F, random); + CrystalMountainPiece piece = new CrystalMountainPiece( + new BlockPos(x, y, z), + radius, + height, + random, + biome + ); + structurePiecesBuilder.addPiece(piece); + } + + //this.calculateBoundingBox(); + } +} + diff --git a/src/main/java/org/betterx/betterend/world/structures/features/PaintedMountainStructure.java b/src/main/java/org/betterx/betterend/world/structures/features/PaintedMountainStructure.java new file mode 100644 index 00000000..442df363 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/PaintedMountainStructure.java @@ -0,0 +1,72 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.structures.piece.PaintedMountainPiece; + +public class PaintedMountainStructure extends FeatureBaseStructure { + private static final BlockState[] VARIANTS; + + public PaintedMountainStructure(StructureSettings s) { + super(s); + } + + @Override + public StructureType type() { + return EndStructures.PAINTED_MOUNTAIN.structureType; + } + + protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + final RandomState rState = context.randomState(); + + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); + if (y > 50) { + Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); + float radius = MHelper.randRange(50, 100, random); + float height = radius * MHelper.randRange(0.4F, 0.6F, random); + int count = MHelper.floor(height * MHelper.randRange(0.1F, 0.35F, random) + 1); + BlockState[] slises = new BlockState[count]; + for (int i = 0; i < count; i++) { + slises[i] = VARIANTS[random.nextInt(VARIANTS.length)]; + } + structurePiecesBuilder.addPiece(new PaintedMountainPiece(new BlockPos(x, y, z), + radius, + height, + random, + biome, + slises)); + } + + //this.calculateBoundingBox(); + } + + + static { + VARIANTS = new BlockState[]{ + Blocks.END_STONE.defaultBlockState(), + EndBlocks.FLAVOLITE.stone.defaultBlockState(), + EndBlocks.VIOLECITE.stone.defaultBlockState(), + }; + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/features/SDFStructureFeature.java b/src/main/java/org/betterx/betterend/world/structures/features/SDFStructureFeature.java new file mode 100644 index 00000000..71c856a9 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/features/SDFStructureFeature.java @@ -0,0 +1,43 @@ +package org.betterx.betterend.world.structures.features; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; + +import org.betterx.bclib.sdf.SDF; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.world.structures.piece.VoxelPiece; + +import java.util.function.BiFunction; + +public abstract class SDFStructureFeature extends FeatureBaseStructure { + public SDFStructureFeature(StructureSettings s) { + super(s); + } + + public static void generatePieces(StructurePiecesBuilder structurePiecesBuilder, + GenerationContext context, + BiFunction sdf) { + final RandomSource random = context.random(); + final ChunkPos chunkPos = context.chunkPos(); + final ChunkGenerator chunkGenerator = context.chunkGenerator(); + final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); + int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); + int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); + int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, context.randomState()); + if (y > 5) { + BlockPos start = new BlockPos(x, y, z); + VoxelPiece piece = new VoxelPiece((world) -> { + sdf.apply(start, random).fillRecursive(world, start); + }, random.nextInt()); + + structurePiecesBuilder.addPiece(piece); + } + + //this.calculateBoundingBox(); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/BasePiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/BasePiece.java new file mode 100644 index 00000000..04534aab --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/BasePiece.java @@ -0,0 +1,29 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.StructurePiece; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; + +public abstract class BasePiece extends StructurePiece { + protected BasePiece(StructurePieceType type, int i, BoundingBox boundingBox) { + super(type, i, boundingBox); + } + + protected BasePiece(StructurePieceType type, CompoundTag tag) { + super(type, tag); + fromNbt(tag); + } + + protected abstract void fromNbt(CompoundTag tag); + + protected void addAdditionalSaveData(CompoundTag tag) { + } + + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext structurePieceSerializationContext, + CompoundTag compoundTag) { + addAdditionalSaveData(compoundTag); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/CavePiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/CavePiece.java new file mode 100644 index 00000000..72c976ee --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/CavePiece.java @@ -0,0 +1,114 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.util.GlobalState; + +public class CavePiece extends BasePiece { + private OpenSimplexNoise noise; + private BlockPos center; + private float radius; + + public CavePiece(BlockPos center, float radius, int id) { + super(EndStructures.CAVE_PIECE, id, null); + this.center = center; + this.radius = radius; + this.noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); + makeBoundingBox(); + } + + public CavePiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.CAVE_PIECE, tag); + makeBoundingBox(); + } + + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + int x1 = MHelper.max(this.boundingBox.minX(), blockBox.minX()); + int z1 = MHelper.max(this.boundingBox.minZ(), blockBox.minZ()); + int x2 = MHelper.min(this.boundingBox.maxX(), blockBox.maxX()); + int z2 = MHelper.min(this.boundingBox.maxZ(), blockBox.maxZ()); + int y1 = this.boundingBox.minY(); + int y2 = this.boundingBox.maxY(); + + double hr = radius * 0.75; + double nr = radius * 0.25; + final MutableBlockPos pos = GlobalState.stateForThread().POS; + for (int x = x1; x <= x2; x++) { + int xsq = x - center.getX(); + xsq *= xsq; + pos.setX(x); + for (int z = z1; z <= z2; z++) { + int zsq = z - center.getZ(); + zsq *= zsq; + pos.setZ(z); + for (int y = y1; y <= y2; y++) { + int ysq = y - center.getY(); + ysq *= 1.6; + ysq *= ysq; + pos.setY(y); + double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; + double r2 = r - 4.5; + double dist = xsq + ysq + zsq; + if (dist < r2 * r2) { + if (world.getBlockState(pos).is(CommonBlockTags.END_STONES)) { + BlocksHelper.setWithoutUpdate(world, pos, CAVE_AIR); + } + } else if (dist < r * r) { + if (world.getBlockState(pos).getMaterial().isReplaceable()) { + BlocksHelper.setWithoutUpdate(world, pos, Blocks.END_STONE); + } + } + } + } + } + + return; + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + tag.put("center", NbtUtils.writeBlockPos(center)); + tag.putFloat("radius", radius); + } + + @Override + protected void fromNbt(CompoundTag tag) { + center = NbtUtils.readBlockPos(tag.getCompound("center")); + radius = tag.getFloat("radius"); + noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); + } + + private void makeBoundingBox() { + int minX = MHelper.floor(center.getX() - radius); + int minY = MHelper.floor(center.getY() - radius); + int minZ = MHelper.floor(center.getZ() - radius); + int maxX = MHelper.floor(center.getX() + radius + 1); + int maxY = MHelper.floor(center.getY() + radius + 1); + int maxZ = MHelper.floor(center.getZ() + radius + 1); + this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/CrystalMountainPiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/CrystalMountainPiece.java new file mode 100644 index 00000000..7c36c729 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/CrystalMountainPiece.java @@ -0,0 +1,184 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Holder; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.util.GlobalState; +import org.betterx.betterend.world.biome.EndBiome; + +public class CrystalMountainPiece extends MountainPiece { + private BlockState top; + + public CrystalMountainPiece(BlockPos center, float radius, float height, RandomSource random, Holder biome) { + super(EndStructures.MOUNTAIN_PIECE, center, radius, height, random, biome); + top = EndBiome.findTopMaterial(biome.value()); //biome.getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + } + + public CrystalMountainPiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.MOUNTAIN_PIECE, tag); + } + + @Override + protected void fromNbt(CompoundTag tag) { + super.fromNbt(tag); + top = EndBiome.findTopMaterial(BiomeAPI.getBiome(biomeID)); //BiomeAPI.getBiome(biomeID).getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + } + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + int sx = chunkPos.getMinBlockX(); + int sz = chunkPos.getMinBlockZ(); + final MutableBlockPos pos = GlobalState.stateForThread().POS; + ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); + Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); + Heightmap map2 = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE_WG); + for (int x = 0; x < 16; x++) { + int px = x + sx; + int px2 = px - center.getX(); + px2 *= px2; + pos.setX(x); + for (int z = 0; z < 16; z++) { + int pz = z + sz; + int pz2 = pz - center.getZ(); + pz2 *= pz2; + float dist = px2 + pz2; + if (dist < r2) { + pos.setZ(z); + dist = 1 - (float) Math.pow(dist / r2, 0.3); + int minY = map.getFirstAvailable(x, z); + if (minY < 10) { + continue; + } + pos.setY(minY); + while (!chunk.getBlockState(pos) + .is(CommonBlockTags.GEN_END_STONES) && pos.getY() > 56 && !chunk.getBlockState( + pos.below()).is(Blocks.CAVE_AIR)) { + pos.setY(pos.getY() - 1); + } + minY = pos.getY(); + minY = Math.max(minY, map2.getFirstAvailable(x, z)); + if (minY > center.getY() - 8) { + float maxY = dist * height * getHeightClamp(world, 12, px, pz); + if (maxY > 0) { + maxY *= (float) noise1.eval(px * 0.05, pz * 0.05) * 0.3F + 0.7F; + maxY *= (float) noise1.eval(px * 0.1, pz * 0.1) * 0.1F + 0.8F; + maxY += center.getY(); + int maxYI = (int) (maxY); + int cover = maxYI - 1; + boolean needCover = (noise1.eval(px * 0.1, pz * 0.1) + MHelper.randRange( + -0.4, + 0.4, + random + ) - (center.getY() + 14) * 0.1) > 0; + for (int y = minY - 1; y < maxYI; y++) { + pos.setY(y); + chunk.setBlockState( + pos, + needCover && y == cover ? top : Blocks.END_STONE.defaultBlockState(), + false + ); + } + } + } + } + } + } + + map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); + + // Big crystals + int count = (map.getFirstAvailable(8, 8) - (center.getY() + 24)) / 7; + count = Mth.clamp(count, 0, 8); + for (int i = 0; i < count; i++) { + int radius = MHelper.randRange(2, 3, random); + float fill = MHelper.randRange(0F, 1F, random); + int x = MHelper.randRange(radius, 15 - radius, random); + int z = MHelper.randRange(radius, 15 - radius, random); + int y = map.getFirstAvailable(x, z); + if (y > 80) { + pos.set(x, y, z); + if (chunk.getBlockState(pos.below()).is(Blocks.END_STONE)) { + int height = MHelper.floor(radius * MHelper.randRange(1.5F, 3F, random) + (y - 80) * 0.3F); + crystal(chunk, pos, radius, height, fill, random); + } + } + } + + // Small crystals + count = (map.getFirstAvailable(8, 8) - (center.getY() + 24)) / 2; + count = Mth.clamp(count, 4, 8); + for (int i = 0; i < count; i++) { + int radius = MHelper.randRange(1, 2, random); + float fill = random.nextBoolean() ? 0 : 1; + int x = MHelper.randRange(radius, 15 - radius, random); + int z = MHelper.randRange(radius, 15 - radius, random); + int y = map.getFirstAvailable(x, z); + if (y > 80) { + pos.set(x, y, z); + if (chunk.getBlockState(pos.below()).getBlock() == Blocks.END_STONE) { + int height = MHelper.floor(radius * MHelper.randRange(1.5F, 3F, random) + (y - 80) * 0.3F); + crystal(chunk, pos, radius, height, fill, random); + } + } + } + } + + private void crystal(ChunkAccess chunk, BlockPos pos, int radius, int height, float fill, RandomSource random) { + MutableBlockPos mut = new MutableBlockPos(); + int max = MHelper.floor(fill * radius + radius + 0.5F); + height += pos.getY(); + Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); + int coefX = MHelper.randRange(-1, 1, random); + int coefZ = MHelper.randRange(-1, 1, random); + for (int x = -radius; x <= radius; x++) { + mut.setX(x + pos.getX()); + if (mut.getX() >= 0 && mut.getX() < 16) { + int ax = Math.abs(x); + for (int z = -radius; z <= radius; z++) { + mut.setZ(z + pos.getZ()); + if (mut.getZ() >= 0 && mut.getZ() < 16) { + int az = Math.abs(z); + if (ax + az < max) { + int minY = map.getFirstAvailable(mut.getX(), mut.getZ()) - MHelper.randRange(3, 7, random); + if (pos.getY() - minY > 8) { + minY = pos.getY() - 8; + } + int h = coefX * x + coefZ * z + height; + for (int y = minY; y < h; y++) { + mut.setY(y); + chunk.setBlockState(mut, EndBlocks.AURORA_CRYSTAL.defaultBlockState(), false); + } + } + } + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/LakePiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/LakePiece.java new file mode 100644 index 00000000..49a97d48 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/LakePiece.java @@ -0,0 +1,283 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +import net.minecraft.world.level.material.FluidState; + +import com.google.common.collect.Maps; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.api.tag.CommonBlockTags; +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; +import org.betterx.betterend.registry.EndBlocks; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.world.biome.EndBiome; + +import java.util.Map; + +public class LakePiece extends BasePiece { + private static final BlockState ENDSTONE = Blocks.END_STONE.defaultBlockState(); + private static final BlockState WATER = Blocks.WATER.defaultBlockState(); + private final Map heightmap = Maps.newHashMap(); + private OpenSimplexNoise noise; + private BlockPos center; + private float radius; + private float aspect; + private float depth; + private int seed; + + private ResourceLocation biomeID; + + public LakePiece(BlockPos center, float radius, float depth, RandomSource random, Holder biome) { + super(EndStructures.LAKE_PIECE, random.nextInt(), null); + this.center = center; + this.radius = radius; + this.depth = depth; + this.seed = random.nextInt(); + this.noise = new OpenSimplexNoise(this.seed); + this.aspect = radius / depth; + this.biomeID = BiomeAPI.getBiomeID(biome.value()); + makeBoundingBox(); + } + + public LakePiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.LAKE_PIECE, tag); + makeBoundingBox(); + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + tag.put("center", NbtUtils.writeBlockPos(center)); + tag.putFloat("radius", radius); + tag.putFloat("depth", depth); + tag.putInt("seed", seed); + tag.putString("biome", biomeID.toString()); + } + + @Override + protected void fromNbt(CompoundTag tag) { + center = NbtUtils.readBlockPos(tag.getCompound("center")); + radius = tag.getFloat("radius"); + depth = tag.getFloat("depth"); + seed = tag.getInt("seed"); + noise = new OpenSimplexNoise(seed); + aspect = radius / depth; + biomeID = new ResourceLocation(tag.getString("biome")); + } + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + int minY = this.boundingBox.minY(); + int maxY = this.boundingBox.maxY(); + int sx = SectionPos.sectionToBlockCoord(chunkPos.x); + int sz = SectionPos.sectionToBlockCoord(chunkPos.z); + MutableBlockPos mut = new MutableBlockPos(); + ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); + for (int x = 0; x < 16; x++) { + mut.setX(x); + int wx = x | sx; + double nx = wx * 0.1; + int x2 = wx - center.getX(); + for (int z = 0; z < 16; z++) { + mut.setZ(z); + int wz = z | sz; + double nz = wz * 0.1; + int z2 = wz - center.getZ(); + float clamp = getHeightClamp(world, 8, wx, wz); + if (clamp < 0.01) continue; + + double n = noise.eval(nx, nz) * 1.5 + 1.5; + double x3 = MHelper.sqr(x2 + noise.eval(nx, nz, 100) * 10); + double z3 = MHelper.sqr(z2 + noise.eval(nx, nz, -100) * 10); + + for (int y = maxY; y >= minY; y--) { + mut.setY((int) (y + n)); + double y2 = MHelper.sqr((y - center.getY()) * aspect); + double r2 = radius * clamp; + double r3 = r2 + 8; + r2 *= r2; + r3 = r3 * r3 + 100; + double dist = x3 + y2 + z3; + if (dist < r2) { + BlockState state = chunk.getBlockState(mut); + if (state.is(CommonBlockTags.GEN_END_STONES) || state.isAir()) { + state = mut.getY() < center.getY() ? WATER : CAVE_AIR; + chunk.setBlockState(mut, state, false); + } + } else if (dist <= r3 && mut.getY() < center.getY()) { + BlockState state = chunk.getBlockState(mut); + BlockPos worldPos = mut.offset(sx, 0, sz); + if (!state.isCollisionShapeFullBlock(world, worldPos) && !state.isRedstoneConductor( + world, + worldPos + )) { + state = chunk.getBlockState(mut.above()); + if (state.isAir()) { + state = random.nextBoolean() ? ENDSTONE : EndBiome.findTopMaterial(world, worldPos); + } else { + state = state.getFluidState().isEmpty() + ? ENDSTONE + : EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + chunk.setBlockState(mut, state, false); + } + } + } + } + } + fixWater(world, chunk, mut, random, sx, sz); + } + + private void fixWater(WorldGenLevel world, + ChunkAccess chunk, + MutableBlockPos mut, + RandomSource random, + int sx, + int sz) { + int minY = this.boundingBox.minY(); + int maxY = this.boundingBox.maxY(); + for (int x = 0; x < 16; x++) { + mut.setX(x); + for (int z = 0; z < 16; z++) { + mut.setZ(z); + for (int y = minY; y <= maxY; y++) { + mut.setY(y); + FluidState state = chunk.getFluidState(mut); + if (!state.isEmpty()) { + mut.setY(y - 1); + if (chunk.getBlockState(mut).isAir()) { + mut.setY(y + 1); + + BlockState bState = chunk.getBlockState(mut); + if (bState.isAir()) { + bState = random.nextBoolean() + ? ENDSTONE + : EndBiome.findTopMaterial(world, mut.offset(sx, 0, sz)); + } else { + bState = bState.getFluidState().isEmpty() + ? ENDSTONE + : EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + + mut.setY(y); + + makeEndstonePillar(chunk, mut, bState); + } else if (x > 1 && x < 15 && z > 1 && z < 15) { + mut.setY(y); + for (Direction dir : BlocksHelper.HORIZONTAL) { + BlockPos wPos = mut.offset(dir.getStepX(), 0, dir.getStepZ()); + if (chunk.getBlockState(wPos).isAir()) { + mut.setY(y + 1); + BlockState bState = chunk.getBlockState(mut); + if (bState.isAir()) { + bState = random.nextBoolean() + ? ENDSTONE + : EndBiome.findTopMaterial(world, mut.offset(sx, 0, sz)); + } else { + bState = bState.getFluidState().isEmpty() + ? ENDSTONE + : EndBlocks.ENDSTONE_DUST.defaultBlockState(); + } + mut.setY(y); + makeEndstonePillar(chunk, mut, bState); + break; + } + } + } else if (chunk.getBlockState(mut.move(Direction.UP)).isAir()) { + chunk.markPosForPostprocessing(mut.move(Direction.DOWN).immutable()); + } + } else if (chunk.getBlockState(mut).isRandomlyTicking()) { + chunk.markPosForPostprocessing(mut.immutable()); + } + } + } + } + } + + private void makeEndstonePillar(ChunkAccess chunk, MutableBlockPos mut, BlockState terrain) { + chunk.setBlockState(mut, terrain, false); + mut.setY(mut.getY() - 1); + while (!chunk.getFluidState(mut).isEmpty()) { + chunk.setBlockState(mut, ENDSTONE, false); + mut.setY(mut.getY() - 1); + } + } + + private int getHeight(WorldGenLevel world, BlockPos pos) { + int p = ((pos.getX() & 2047) << 11) | (pos.getZ() & 2047); + int h = heightmap.getOrDefault(p, Byte.MIN_VALUE); + if (h > Byte.MIN_VALUE) { + return h; + } + + if (!BiomeAPI.getBiomeID(world.getBiome(pos)).equals(biomeID)) { + heightmap.put(p, (byte) 0); + return 0; + } + + h = world.getHeight(Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); + h = Mth.abs(h - center.getY()); + h = h < 8 ? 1 : 0; + + heightmap.put(p, (byte) h); + return h; + } + + private float getHeightClamp(WorldGenLevel world, int radius, int posX, int posZ) { + MutableBlockPos mut = new MutableBlockPos(); + int r2 = radius * radius; + float height = 0; + float max = 0; + for (int x = -radius; x <= radius; x++) { + mut.setX(posX + x); + int x2 = x * x; + for (int z = -radius; z <= radius; z++) { + mut.setZ(posZ + z); + int z2 = z * z; + if (x2 + z2 < r2) { + float mult = 1 - (float) Math.sqrt(x2 + z2) / radius; + max += mult; + height += getHeight(world, mut) * mult; + } + } + } + height /= max; + return Mth.clamp(height, 0, 1); + } + + private void makeBoundingBox() { + int minX = MHelper.floor(center.getX() - radius - 8); + int minY = MHelper.floor(center.getY() - depth - 8); + int minZ = MHelper.floor(center.getZ() - radius - 8); + int maxX = MHelper.floor(center.getX() + radius + 8); + int maxY = MHelper.floor(center.getY() + depth); + int maxZ = MHelper.floor(center.getZ() + radius + 8); + this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + } +} \ No newline at end of file diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/MountainPiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/MountainPiece.java new file mode 100644 index 00000000..1c48cc06 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/MountainPiece.java @@ -0,0 +1,147 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Holder; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; + +import com.google.common.collect.Maps; +import org.betterx.bclib.api.biomes.BiomeAPI; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.noise.OpenSimplexNoise; + +import java.util.Map; + +public abstract class MountainPiece extends BasePiece { + protected Map heightmap = Maps.newHashMap(); + protected OpenSimplexNoise noise1; + protected OpenSimplexNoise noise2; + protected BlockPos center; + protected float radius; + protected float height; + protected float r2; + protected ResourceLocation biomeID; + protected int seed1; + protected int seed2; + + public MountainPiece(StructurePieceType type, + BlockPos center, + float radius, + float height, + RandomSource random, + Holder biome) { + super(type, random.nextInt(), null); + this.center = center; + this.radius = radius; + this.height = height; + this.r2 = radius * radius; + this.seed1 = random.nextInt(); + this.seed2 = random.nextInt(); + this.noise1 = new OpenSimplexNoise(this.seed1); + this.noise2 = new OpenSimplexNoise(this.seed2); + this.biomeID = BiomeAPI.getBiomeID(biome); + makeBoundingBox(); + } + + public MountainPiece(StructurePieceType type, CompoundTag tag) { + super(type, tag); + makeBoundingBox(); + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + tag.put("center", NbtUtils.writeBlockPos(center)); + tag.putFloat("radius", radius); + tag.putFloat("height", height); + tag.putString("biome", biomeID.toString()); + tag.putInt("seed1", seed1); + tag.putInt("seed2", seed2); + } + + @Override + protected void fromNbt(CompoundTag tag) { + center = NbtUtils.readBlockPos(tag.getCompound("center")); + radius = tag.getFloat("radius"); + height = tag.getFloat("height"); + biomeID = new ResourceLocation(tag.getString("biome")); + r2 = radius * radius; + seed1 = tag.getInt("seed1"); + seed2 = tag.getInt("seed2"); + noise1 = new OpenSimplexNoise(seed1); + noise2 = new OpenSimplexNoise(seed2); + } + + private int getHeight(WorldGenLevel world, BlockPos pos) { + int p = ((pos.getX() & 2047) << 11) | (pos.getZ() & 2047); + int h = heightmap.getOrDefault(p, Integer.MIN_VALUE); + if (h > Integer.MIN_VALUE) { + return h; + } + + if (!BiomeAPI.getBiomeID(world.getBiome(pos)).equals(biomeID)) { + heightmap.put(p, -10); + return -10; + } + h = world.getHeight(Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); + h = Mth.abs(h - center.getY()); + if (h > 4) { + h = 4 - h; + heightmap.put(p, h); + return h; + } + + h = MHelper.floor(noise2.eval(pos.getX() * 0.01, pos.getZ() * 0.01) * noise2.eval( + pos.getX() * 0.002, + pos.getZ() * 0.002 + ) * 8 + 8); + + if (h < 0) { + heightmap.put(p, 0); + return 0; + } + + heightmap.put(p, h); + + return h; + } + + protected float getHeightClamp(WorldGenLevel world, int radius, int posX, int posZ) { + MutableBlockPos mut = new MutableBlockPos(); + float height = 0; + float max = 0; + for (int x = -radius; x <= radius; x++) { + mut.setX(posX + x); + int x2 = x * x; + for (int z = -radius; z <= radius; z++) { + mut.setZ(posZ + z); + int z2 = z * z; + float mult = 1 - (float) Math.sqrt(x2 + z2) / radius; + if (mult > 0) { + max += mult; + height += getHeight(world, mut) * mult; + } + } + } + height /= max; + return Mth.clamp(height / radius, 0, 1); + } + + private void makeBoundingBox() { + int minX = MHelper.floor(center.getX() - radius); + int minY = MHelper.floor(center.getY() - radius); + int minZ = MHelper.floor(center.getZ() - radius); + int maxX = MHelper.floor(center.getX() + radius + 1); + int maxY = MHelper.floor(center.getY() + radius + 1); + int maxZ = MHelper.floor(center.getZ() + radius + 1); + this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/NBTPiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/NBTPiece.java new file mode 100644 index 00000000..2cfcd47e --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/NBTPiece.java @@ -0,0 +1,112 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import org.betterx.bclib.util.MHelper; +import org.betterx.bclib.util.StructureHelper; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.util.StructureErode; +import org.betterx.betterend.world.biome.EndBiome; + +public class NBTPiece extends BasePiece { + private ResourceLocation structureID; + private Rotation rotation; + private Mirror mirror; + private StructureTemplate structure; + private BlockPos pos; + private int erosion; + private boolean cover; + + public NBTPiece(ResourceLocation structureID, + StructureTemplate structure, + BlockPos pos, + int erosion, + boolean cover, + RandomSource random) { + super(EndStructures.NBT_PIECE, random.nextInt(), null); + this.structureID = structureID; + this.structure = structure; + this.rotation = Rotation.getRandom(random); + this.mirror = Mirror.values()[random.nextInt(3)]; + this.pos = StructureHelper.offsetPos(pos, structure, rotation, mirror); + this.erosion = erosion; + this.cover = cover; + makeBoundingBox(); + } + + public NBTPiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.NBT_PIECE, tag); + makeBoundingBox(); + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putString("structureID", structureID.toString()); + tag.putInt("rotation", rotation.ordinal()); + tag.putInt("mirror", mirror.ordinal()); + tag.putInt("erosion", erosion); + tag.put("pos", NbtUtils.writeBlockPos(pos)); + tag.putBoolean("cover", cover); + } + + @Override + protected void fromNbt(CompoundTag tag) { + structureID = new ResourceLocation(tag.getString("structureID")); + rotation = Rotation.values()[tag.getInt("rotation")]; + mirror = Mirror.values()[tag.getInt("mirror")]; + erosion = tag.getInt("erosion"); + pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + cover = tag.getBoolean("cover"); + structure = StructureHelper.readStructure(structureID); + } + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + BoundingBox bounds = BoundingBox.fromCorners(new Vec3i( + blockBox.minX(), + this.boundingBox.minY(), + blockBox.minZ() + ), new Vec3i(blockBox.maxX(), this.boundingBox.maxX(), blockBox.maxZ())); + StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation) + .setMirror(mirror) + .setBoundingBox(bounds); + structure.placeInWorld(world, pos, pos, placementData, random, 2); + if (erosion > 0) { + int x1 = MHelper.min(bounds.maxX(), boundingBox.maxX()); + int x0 = MHelper.max(bounds.minX(), boundingBox.minX()); + int z1 = MHelper.min(bounds.maxZ(), boundingBox.maxZ()); + int z0 = MHelper.max(bounds.minZ(), boundingBox.minZ()); + bounds = BoundingBox.fromCorners(new Vec3i(x0, bounds.minY(), z0), new Vec3i(x1, bounds.maxY(), z1)); + StructureErode.erode(world, bounds, erosion, random); + } + if (cover) { + StructureErode.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); + } + } + + private void makeBoundingBox() { + this.boundingBox = StructureHelper.getStructureBounds(pos, structure, rotation, mirror); + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/PaintedMountainPiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/PaintedMountainPiece.java new file mode 100644 index 00000000..5b719e2a --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/PaintedMountainPiece.java @@ -0,0 +1,118 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Holder; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.registry.EndStructures; +import org.betterx.betterend.util.GlobalState; + +public class PaintedMountainPiece extends MountainPiece { + private BlockState[] slises; + + public PaintedMountainPiece(BlockPos center, + float radius, + float height, + RandomSource random, + Holder biome, + BlockState[] slises) { + super(EndStructures.PAINTED_MOUNTAIN_PIECE, center, radius, height, random, biome); + this.slises = slises; + } + + public PaintedMountainPiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.PAINTED_MOUNTAIN_PIECE, tag); + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + ListTag slise = new ListTag(); + for (BlockState state : slises) { + slise.add(NbtUtils.writeBlockState(state)); + } + tag.put("slises", slise); + } + + @Override + protected void fromNbt(CompoundTag tag) { + super.fromNbt(tag); + ListTag slise = tag.getList("slises", 10); + slises = new BlockState[slise.size()]; + for (int i = 0; i < slises.length; i++) { + slises[i] = NbtUtils.readBlockState(slise.getCompound(i)); + } + } + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + int sx = chunkPos.getMinBlockX(); + int sz = chunkPos.getMinBlockZ(); + final MutableBlockPos pos = GlobalState.stateForThread().POS; + ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); + Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); + Heightmap map2 = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE_WG); + for (int x = 0; x < 16; x++) { + int px = x + sx; + int px2 = px - center.getX(); + px2 *= px2; + pos.setX(x); + for (int z = 0; z < 16; z++) { + int pz = z + sz; + int pz2 = pz - center.getZ(); + pz2 *= pz2; + float dist = px2 + pz2; + if (dist < r2) { + pos.setZ(z); + dist = 1 - dist / r2; + int minY = map.getFirstAvailable(x, z); + pos.setY(minY - 1); + while (chunk.getBlockState(pos).isAir() && pos.getY() > 50) { + pos.setY(minY--); + } + minY = pos.getY(); + minY = Math.max(minY, map2.getFirstAvailable(x, z)); + if (minY > center.getY() - 8) { + float maxY = dist * height * getHeightClamp(world, 10, px, pz); + if (maxY > 0) { + maxY *= (float) noise1.eval(px * 0.05, pz * 0.05) * 0.3F + 0.7F; + maxY *= (float) noise1.eval(px * 0.1, pz * 0.1) * 0.1F + 0.9F; + maxY += center.getY(); + float offset = (float) (noise1.eval(px * 0.07, pz * 0.07) * 5 + noise1.eval( + px * 0.2, + pz * 0.2 + ) * 2 + 7); + for (int y = minY - 1; y < maxY; y++) { + pos.setY(y); + int index = MHelper.floor((y + offset) * 0.65F) % slises.length; + chunk.setBlockState(pos, slises[index], false); + } + } + } + } + } + } + } +} diff --git a/src/main/java/org/betterx/betterend/world/structures/piece/VoxelPiece.java b/src/main/java/org/betterx/betterend/world/structures/piece/VoxelPiece.java new file mode 100644 index 00000000..b4533585 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/structures/piece/VoxelPiece.java @@ -0,0 +1,53 @@ +package org.betterx.betterend.world.structures.piece; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + +import org.betterx.bclib.world.structures.StructureWorld; +import org.betterx.betterend.registry.EndStructures; + +import java.util.function.Consumer; + +public class VoxelPiece extends BasePiece { + private StructureWorld world; + + public VoxelPiece(Consumer function, int id) { + super(EndStructures.VOXEL_PIECE, id, null); + world = new StructureWorld(); + function.accept(world); + this.boundingBox = world.getBounds(); + } + + public VoxelPiece(StructurePieceSerializationContext type, CompoundTag tag) { + super(EndStructures.VOXEL_PIECE, tag); + this.boundingBox = world.getBounds(); + } + + @Override + protected void addAdditionalSaveData(CompoundTag tag) { + tag.put("world", world.toBNT()); + } + + @Override + protected void fromNbt(CompoundTag tag) { + world = new StructureWorld(tag.getCompound("world")); + } + + @Override + public void postProcess(WorldGenLevel world, + StructureManager arg, + ChunkGenerator chunkGenerator, + RandomSource random, + BoundingBox blockBox, + ChunkPos chunkPos, + BlockPos blockPos) { + this.world.placeChunk(world, chunkPos); + } +} diff --git a/src/main/java/org/betterx/betterend/world/surface/SplitNoiseCondition.java b/src/main/java/org/betterx/betterend/world/surface/SplitNoiseCondition.java new file mode 100644 index 00000000..d62cbc7d --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/surface/SplitNoiseCondition.java @@ -0,0 +1,39 @@ +package org.betterx.betterend.world.surface; + +import net.minecraft.core.Registry; + +import com.mojang.serialization.Codec; +import org.betterx.bclib.interfaces.NumericProvider; +import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.noise.OpenSimplexNoise; + +/** + * Noise source that returns a value in [0, 1] + */ +public class SplitNoiseCondition implements NumericProvider { + public static final SplitNoiseCondition DEFAULT = new SplitNoiseCondition(); + public static final Codec CODEC = Codec.BYTE.fieldOf("split_noise") + .xmap((obj) -> DEFAULT, obj -> (byte) 0) + .codec(); + + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(4141); + + @Override + public int getNumber(SurfaceRulesContextAccessor context) { + final int x = context.getBlockX(); + final int z = context.getBlockZ(); + float noise = (float) NOISE.eval(x * 0.1, z * 0.1) + MHelper.randRange(-0.4F, 0.4F, MHelper.RANDOM_SOURCE); + return noise > 0 ? 1 : 0; + } + + @Override + public Codec pcodec() { + return CODEC; + } + + static { + Registry.register(NumericProvider.NUMERIC_PROVIDER, BetterEnd.makeID("split_noise"), SplitNoiseCondition.CODEC); + } +} diff --git a/src/main/java/org/betterx/betterend/world/surface/SulphuricSurfaceNoiseCondition.java b/src/main/java/org/betterx/betterend/world/surface/SulphuricSurfaceNoiseCondition.java new file mode 100644 index 00000000..524034aa --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/surface/SulphuricSurfaceNoiseCondition.java @@ -0,0 +1,47 @@ +package org.betterx.betterend.world.surface; + +import net.minecraft.core.Registry; + +import com.mojang.serialization.Codec; +import org.betterx.bclib.interfaces.NumericProvider; +import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.noise.OpenSimplexNoise; + +/** + * Noise source that returns a value in [0, 3] + */ +public class SulphuricSurfaceNoiseCondition implements NumericProvider { + public static final SulphuricSurfaceNoiseCondition DEFAULT = new SulphuricSurfaceNoiseCondition(); + public static final Codec CODEC = Codec.BYTE.fieldOf("sulphuric_surf") + .xmap((obj) -> DEFAULT, obj -> (byte) 0) + .codec(); + + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(5123); + + @Override + public int getNumber(SurfaceRulesContextAccessor context) { + final int x = context.getBlockX(); + final int z = context.getBlockZ(); + final double value = NOISE.eval(x * 0.03, z * 0.03) + NOISE.eval(x * 0.1, + z * 0.1) * 0.3 + MHelper.randRange(-0.1, + 0.1, + MHelper.RANDOM_SOURCE); + if (value < -0.6) return 0; + if (value < -0.3) return 1; + if (value < 0.5) return 2; + return 3; + } + + @Override + public Codec pcodec() { + return CODEC; + } + + static { + Registry.register(NumericProvider.NUMERIC_PROVIDER, + BetterEnd.makeID("sulphuric_surf"), + SulphuricSurfaceNoiseCondition.CODEC); + } +} diff --git a/src/main/java/org/betterx/betterend/world/surface/UmbraSurfaceNoiseCondition.java b/src/main/java/org/betterx/betterend/world/surface/UmbraSurfaceNoiseCondition.java new file mode 100644 index 00000000..52eaf9d8 --- /dev/null +++ b/src/main/java/org/betterx/betterend/world/surface/UmbraSurfaceNoiseCondition.java @@ -0,0 +1,52 @@ +package org.betterx.betterend.world.surface; + +import net.minecraft.core.Registry; + +import com.mojang.serialization.Codec; +import org.betterx.bclib.interfaces.NumericProvider; +import org.betterx.bclib.mixin.common.SurfaceRulesContextAccessor; +import org.betterx.bclib.util.MHelper; +import org.betterx.betterend.BetterEnd; +import org.betterx.betterend.noise.OpenSimplexNoise; + +/** + * Noise source that returns a value in [0, 4] + */ +public class UmbraSurfaceNoiseCondition implements NumericProvider { + public static final UmbraSurfaceNoiseCondition DEFAULT = new UmbraSurfaceNoiseCondition(); + public static final Codec CODEC = Codec.BYTE.fieldOf("umbra_srf") + .xmap((obj) -> DEFAULT, obj -> (byte) 0) + .codec(); + + private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(1512); + + @Override + public int getNumber(SurfaceRulesContextAccessor context) { + final int x = context.getBlockX(); + final int z = context.getBlockZ(); + return getDepth(x, z); + } + + public static int getDepth(int x, int z) { + final double value = NOISE.eval(x * 0.03, z * 0.03) + NOISE.eval(x * 0.1, + z * 0.1) * 0.3 + MHelper.randRange(-0.1, + 0.1, + MHelper.RANDOM_SOURCE); + if (value > 0.4) return 0; + if (value > 0.15) return 1; + if (value > -0.15) return 2; + if (value > -0.4) return 3; + return 4; + } + + @Override + public Codec pcodec() { + return CODEC; + } + + static { + Registry.register(NumericProvider.NUMERIC_PROVIDER, + BetterEnd.makeID("umbra_srf"), + UmbraSurfaceNoiseCondition.CODEC); + } +} diff --git a/src/main/java/ru/betterend/BetterEnd.java b/src/main/java/ru/betterend/BetterEnd.java deleted file mode 100644 index 6a6a765f..00000000 --- a/src/main/java/ru/betterend/BetterEnd.java +++ /dev/null @@ -1,87 +0,0 @@ -package ru.betterend; - -import net.fabricmc.api.ModInitializer; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.biome.Biomes; -import ru.bclib.api.WorldDataAPI; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.util.Logger; -import ru.betterend.api.BetterEndPlugin; -import ru.betterend.config.Configs; -import ru.betterend.effects.EndPotions; -import ru.betterend.integration.Integrations; -import ru.betterend.recipe.AlloyingRecipes; -import ru.betterend.recipe.AnvilRecipes; -import ru.betterend.recipe.CraftingRecipes; -import ru.betterend.recipe.FurnaceRecipes; -import ru.betterend.recipe.InfusionRecipes; -import ru.betterend.recipe.SmithingRecipes; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndBlockEntities; -import ru.betterend.registry.EndEnchantments; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndPortals; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.registry.EndTags; -import ru.betterend.util.BonemealPlants; -import ru.betterend.util.LootTableUtil; -import ru.betterend.world.generator.GeneratorOptions; -import ru.betterend.world.generator.TerrainGenerator; - -public class BetterEnd implements ModInitializer { - public static final String MOD_ID = "betterend"; - public static final Logger LOGGER = new Logger(MOD_ID); - public static final boolean RUNS_FALL_FLYING_LIB = FabricLoader.getInstance().getModContainer("fallflyinglib").isPresent(); - - @Override - public void onInitialize() { - WorldDataAPI.registerModCache(MOD_ID); - EndPortals.loadPortals(); - EndSounds.register(); - EndBlockEntities.register(); - EndFeatures.register(); - EndEntities.register(); - EndBiomes.register(); - EndTags.register(); - EndEnchantments.register(); - EndPotions.register(); - CraftingRecipes.register(); - FurnaceRecipes.register(); - AlloyingRecipes.register(); - AnvilRecipes.register(); - SmithingRecipes.register(); - InfusionRecipes.register(); - EndStructures.register(); - BonemealPlants.init(); - GeneratorOptions.init(); - LootTableUtil.init(); - FabricLoader.getInstance().getEntrypoints("betterend", BetterEndPlugin.class).forEach(BetterEndPlugin::register); - Integrations.init(); - Configs.saveConfigs(); - - if (GeneratorOptions.useNewGenerator()) { - ru.bclib.world.generator.GeneratorOptions.setFarEndBiomes(GeneratorOptions.getIslandDistBlock()); - ru.bclib.world.generator.GeneratorOptions.setEndLandFunction((pos) -> TerrainGenerator.isLand(pos.x, pos.y)); - } - - BiomeAPI.registerEndBiomeModification((biomeID, biome) -> { - if (!biomeID.equals(Biomes.THE_VOID.location())) { - EndFeatures.addBiomeFeatures(biomeID, biome); - } - }); - - BiomeAPI.onFinishingEndBiomeTags((biomeID, biome) -> { - if (!biomeID.equals(Biomes.THE_VOID.location())) { - EndStructures.addBiomeStructures(biomeID, biome); - } - }); - - } - public static ResourceLocation makeID(String path) { - return new ResourceLocation(MOD_ID, path); - } - -} diff --git a/src/main/java/ru/betterend/api/BetterEndPlugin.java b/src/main/java/ru/betterend/api/BetterEndPlugin.java deleted file mode 100644 index e4b64c6c..00000000 --- a/src/main/java/ru/betterend/api/BetterEndPlugin.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.betterend.api; - -public interface BetterEndPlugin { - /** - * Alloying recipes registration. - * See AlloyingRecipe.Builder for details. - */ - default void registerAlloyingRecipes() { - } - - /** - * Smithing recipes registration. - * See AnvilSmithingRecipe.Builder for details. - */ - default void registerSmithingRecipes() { - } - - /** - * Additional biomes registration. - * See BiomeRegistry.registerBiome for details. - */ - default void registerEndBiomes() { - } - - /** - * Register other mod stuff, for example, EndITEM_HAMMERS. - */ - default void registerOthers() { - } - - - public static void register(BetterEndPlugin plugin) { - plugin.registerAlloyingRecipes(); - plugin.registerSmithingRecipes(); - plugin.registerEndBiomes(); - plugin.registerOthers(); - } -} diff --git a/src/main/java/ru/betterend/blocks/AeterniumAnvil.java b/src/main/java/ru/betterend/blocks/AeterniumAnvil.java deleted file mode 100644 index c0655fe4..00000000 --- a/src/main/java/ru/betterend/blocks/AeterniumAnvil.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.BlockItem; -import ru.bclib.items.BaseAnvilItem; -import ru.betterend.blocks.basis.EndAnvilBlock; -import ru.betterend.item.material.EndToolMaterial; -import ru.betterend.registry.EndBlocks; - -public class AeterniumAnvil extends EndAnvilBlock { - public AeterniumAnvil() { - super(EndBlocks.AETERNIUM_BLOCK.defaultMaterialColor(), EndToolMaterial.AETERNIUM.getLevel()); - } - - @Override - public int getMaxDurability() { - return 8; - } - - @Override - public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { - return new BaseAnvilItem(this, settings.fireproof()); - } -} diff --git a/src/main/java/ru/betterend/blocks/AeterniumBlock.java b/src/main/java/ru/betterend/blocks/AeterniumBlock.java deleted file mode 100644 index 21727368..00000000 --- a/src/main/java/ru/betterend/blocks/AeterniumBlock.java +++ /dev/null @@ -1,28 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.CustomItemProvider; - -public class AeterniumBlock extends BaseBlock implements CustomItemProvider { - public AeterniumBlock() { - super(FabricBlockSettings - .of(Material.METAL, MaterialColor.COLOR_GRAY) - .hardness(65F) - .resistance(1200F) - .requiresCorrectToolForDrops() - .sound(SoundType.NETHERITE_BLOCK) - ); - } - - @Override - public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { - return new BlockItem(this, settings.fireproof()); - } -} diff --git a/src/main/java/ru/betterend/blocks/AmaranitaHymenophoreBlock.java b/src/main/java/ru/betterend/blocks/AmaranitaHymenophoreBlock.java deleted file mode 100644 index f001201b..00000000 --- a/src/main/java/ru/betterend/blocks/AmaranitaHymenophoreBlock.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineableAxe; - -public class AmaranitaHymenophoreBlock extends BaseBlock implements RenderLayerProvider, AddMineableAxe { - public AmaranitaHymenophoreBlock() { - super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } -} diff --git a/src/main/java/ru/betterend/blocks/AncientEmeraldIceBlock.java b/src/main/java/ru/betterend/blocks/AncientEmeraldIceBlock.java deleted file mode 100644 index a7d209e8..00000000 --- a/src/main/java/ru/betterend/blocks/AncientEmeraldIceBlock.java +++ /dev/null @@ -1,93 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndParticles; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class AncientEmeraldIceBlock extends BaseBlock { - public AncientEmeraldIceBlock() { - super(FabricBlockSettings.copyOf(Blocks.BLUE_ICE).randomTicks()); - } - - @Override - @SuppressWarnings("deprecation") - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - Direction dir = BlocksHelper.randomDirection(random); - - if (random.nextBoolean()) { - int x = MHelper.randRange(-2, 2, random); - int y = MHelper.randRange(-2, 2, random); - int z = MHelper.randRange(-2, 2, random); - BlockPos p = pos.offset(x, y, z); - if (world.getBlockState(p).is(Blocks.WATER)) { - world.setBlockAndUpdate(p, EndBlocks.EMERALD_ICE.defaultBlockState()); - makeParticles(world, p, random); - } - } - - pos = pos.relative(dir); - state = world.getBlockState(pos); - if (state.is(Blocks.WATER)) { - world.setBlockAndUpdate(pos, EndBlocks.EMERALD_ICE.defaultBlockState()); - makeParticles(world, pos, random); - } - else if (state.is(EndBlocks.EMERALD_ICE)) { - world.setBlockAndUpdate(pos, EndBlocks.DENSE_EMERALD_ICE.defaultBlockState()); - makeParticles(world, pos, random); - } - } - - private void makeParticles(ServerLevel world, BlockPos pos, RandomSource random) { - world.sendParticles( - EndParticles.SNOWFLAKE, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - 20, - 0.5, - 0.5, - 0.5, - 0 - ); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); - if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { - return Collections.singletonList(new ItemStack(this)); - } - else { - return Collections.emptyList(); - } - } - - @Override - public void stepOn(Level level, BlockPos blockPos, BlockState blockState, Entity entity) { - super.stepOn(level, blockPos, blockState, entity); - entity.setIsInPowderSnow(true); - } -} diff --git a/src/main/java/ru/betterend/blocks/AuroraCrystalBlock.java b/src/main/java/ru/betterend/blocks/AuroraCrystalBlock.java deleted file mode 100644 index 5e30a6c7..00000000 --- a/src/main/java/ru/betterend/blocks/AuroraCrystalBlock.java +++ /dev/null @@ -1,130 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.AbstractGlassBlock; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineableHammer; -import ru.bclib.interfaces.tools.AddMineablePickaxe; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndItems; - -import java.util.List; - -; - -public class AuroraCrystalBlock extends AbstractGlassBlock implements RenderLayerProvider, CustomColorProvider, AddMineablePickaxe, AddMineableHammer { - public static final Vec3i[] COLORS; - private static final int MIN_DROP = 1; - private static final int MAX_DROP = 4; - - public AuroraCrystalBlock() { - super(FabricBlockSettings - .of(Material.GLASS) - .hardness(1F) - .resistance(1F) - .luminance(15) - .noOcclusion() - .isSuffocating((state, world, pos) -> false) - .sound(SoundType.GLASS)); - } - - @Override - @Deprecated - public VoxelShape getVisualShape(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext) { - return this.getCollisionShape(blockState, blockGetter, blockPos, collisionContext); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> { - if (pos == null) { - pos = BlockPos.ZERO; - } - ; - - long i = (long) pos.getX() + (long) pos.getY() + (long) pos.getZ(); - double delta = i * 0.1; - int index = MHelper.floor(delta); - int index2 = (index + 1) & 3; - delta -= index; - index &= 3; - - Vec3i color1 = COLORS[index]; - Vec3i color2 = COLORS[index2]; - - int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); - int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); - int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); - - return ColorUtil.color(r, g, b); - }; - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> { - return ColorUtil.color(COLORS[3].getX(), COLORS[3].getY(), COLORS[3].getZ()); - }; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && tool.isCorrectToolForDrops(state)) { - int count = 0; - int enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool); - if (enchant > 0) { - return Lists.newArrayList(new ItemStack(this)); - } - enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool); - if (enchant > 0) { - int min = Mth.clamp(MIN_DROP + enchant, MIN_DROP, MAX_DROP); - int max = MAX_DROP + (enchant / Enchantments.BLOCK_FORTUNE.getMaxLevel()); - if (min == max) { - return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, max)); - } - count = MHelper.randRange(min, max, MHelper.RANDOM_SOURCE); - } - else { - count = MHelper.randRange(MIN_DROP, MAX_DROP, MHelper.RANDOM_SOURCE); - } - return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, count)); - } - return Lists.newArrayList(); - } - - static { - COLORS = new Vec3i[] { - new Vec3i(247, 77, 161), - new Vec3i(120, 184, 255), - new Vec3i(120, 255, 168), - new Vec3i(243, 58, 255) - }; - } -} diff --git a/src/main/java/ru/betterend/blocks/BlueVineBlock.java b/src/main/java/ru/betterend/blocks/BlueVineBlock.java deleted file mode 100644 index 5e13a8f5..00000000 --- a/src/main/java/ru/betterend/blocks/BlueVineBlock.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.UpDownPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class BlueVineBlock extends UpDownPlantBlock { - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.getBlock() == EndBlocks.END_MOSS || state.getBlock() == EndBlocks.END_MYCELIUM; - } -} diff --git a/src/main/java/ru/betterend/blocks/BlueVineLanternBlock.java b/src/main/java/ru/betterend/blocks/BlueVineLanternBlock.java deleted file mode 100644 index 963c0bbd..00000000 --- a/src/main/java/ru/betterend/blocks/BlueVineLanternBlock.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.interfaces.tools.AddMineableAxe; -import ru.betterend.registry.EndBlocks; - -public class BlueVineLanternBlock extends BaseBlock implements AddMineableAxe { - public static final BooleanProperty NATURAL = BlockProperties.NATURAL; - - public BlueVineLanternBlock() { - super(FabricBlockSettings.of(Material.WOOD) - .luminance(15) - .sound(SoundType.WART_BLOCK)); - this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false)); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return !state.getValue(NATURAL) || world.getBlockState(pos.below()).getBlock() == EndBlocks.BLUE_VINE; - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return Blocks.AIR.defaultBlockState(); - } - else { - return state; - } - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(NATURAL); - } -} diff --git a/src/main/java/ru/betterend/blocks/BlueVineSeedBlock.java b/src/main/java/ru/betterend/blocks/BlueVineSeedBlock.java deleted file mode 100644 index 8daec7ea..00000000 --- a/src/main/java/ru/betterend/blocks/BlueVineSeedBlock.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BlueVineSeedBlock extends EndPlantWithAgeBlock { - public BlueVineSeedBlock(){ - super(p -> p.offsetType(BlockBehaviour.OffsetType.NONE)); - } - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - int height = MHelper.randRange(2, 5, random); - int h = BlocksHelper.upRay(world, pos, height + 2); - if (h < height + 1) { - return; - } - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.BLUE_VINE.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM) - ); - for (int i = 1; i < height; i++) { - BlocksHelper.setWithoutUpdate( - world, - pos.above(i), - EndBlocks.BLUE_VINE.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE) - ); - } - BlocksHelper.setWithoutUpdate( - world, - pos.above(height), - EndBlocks.BLUE_VINE.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP) - ); - placeLantern(world, pos.above(height + 1)); - } - - private void placeLantern(WorldGenLevel world, BlockPos pos) { - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.BLUE_VINE_LANTERN.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true) - ); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos p = pos.relative(dir); - if (world.isEmptyBlock(p)) { - BlocksHelper.setWithoutUpdate( - world, - p, - EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, dir) - ); - } - } - if (world.isEmptyBlock(pos.above())) { - BlocksHelper.setWithoutUpdate( - world, - pos.above(), - EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, Direction.UP) - ); - } - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM); - } -} diff --git a/src/main/java/ru/betterend/blocks/BoluxMushroomBlock.java b/src/main/java/ru/betterend/blocks/BoluxMushroomBlock.java deleted file mode 100644 index 2df20c99..00000000 --- a/src/main/java/ru/betterend/blocks/BoluxMushroomBlock.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BoluxMushroomBlock extends EndPlantBlock { - private static final VoxelShape SHAPE = Block.box(1, 0, 1, 15, 9, 15); - - public BoluxMushroomBlock() { - super(10, p->p.offsetType(BlockBehaviour.OffsetType.NONE)); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.RUTISCUS); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return Lists.newArrayList(new ItemStack(this)); - } -} diff --git a/src/main/java/ru/betterend/blocks/BrimstoneBlock.java b/src/main/java/ru/betterend/blocks/BrimstoneBlock.java deleted file mode 100644 index 5ab2a588..00000000 --- a/src/main/java/ru/betterend/blocks/BrimstoneBlock.java +++ /dev/null @@ -1,104 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.MaterialColor; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BrimstoneBlock extends BaseBlock { - public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; - - public BrimstoneBlock() { - super(FabricBlockSettings.copyOf(Blocks.END_STONE).mapColor(MaterialColor.COLOR_BROWN).randomTicks()); - registerDefaultState(stateDefinition.any().setValue(ACTIVATED, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(ACTIVATED); - } - - @Override - public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { - if (world.isClientSide()) { - updateChunks((ClientLevel) world, pos); - } - } - - public void destroy(LevelAccessor world, BlockPos pos, BlockState state) { - if (world.isClientSide()) { - updateChunks((ClientLevel) world, pos); - } - } - - private void updateChunks(ClientLevel world, BlockPos pos) { - int y = pos.getY() >> 4; - int x1 = (pos.getX() - 2) >> 4; - int z1 = (pos.getZ() - 2) >> 4; - int x2 = (pos.getX() + 2) >> 4; - int z2 = (pos.getZ() + 2) >> 4; - for (int x = x1; x <= x2; x++) { - for (int z = z1; z <= z2; z++) { - world.setSectionDirtyWithNeighbors(x, y, z); - } - } - } - - @Override - @SuppressWarnings("deprecation") - public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - boolean deactivate = true; - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (world.getFluidState(pos.relative(dir)).getType().equals(Fluids.WATER)) { - deactivate = false; - break; - } - } - if (state.getValue(ACTIVATED)) { - if (deactivate) { - world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, false)); - } - else if (state.getValue(ACTIVATED) && random.nextInt(16) == 0) { - Direction dir = BlocksHelper.randomDirection(random); - BlockPos side = pos.relative(dir); - BlockState sideState = world.getBlockState(side); - if (sideState.getBlock() instanceof SulphurCrystalBlock) { - if (sideState.getValue(SulphurCrystalBlock.AGE) < 2 && sideState.getValue(SulphurCrystalBlock.WATERLOGGED)) { - int age = sideState.getValue(SulphurCrystalBlock.AGE) + 1; - world.setBlockAndUpdate(side, sideState.setValue(SulphurCrystalBlock.AGE, age)); - } - } - else if (sideState.getFluidState().getType() == Fluids.WATER) { - BlockState crystal = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() - .setValue(SulphurCrystalBlock.FACING, dir) - .setValue(SulphurCrystalBlock.WATERLOGGED, true) - .setValue(SulphurCrystalBlock.AGE, 0); - world.setBlockAndUpdate(side, crystal); - } - } - } - else if (!deactivate && !state.getValue(ACTIVATED)) { - world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, true)); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/BubbleCoralBlock.java b/src/main/java/ru/betterend/blocks/BubbleCoralBlock.java deleted file mode 100644 index 56d62d40..00000000 --- a/src/main/java/ru/betterend/blocks/BubbleCoralBlock.java +++ /dev/null @@ -1,56 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.betterend.blocks.basis.EndUnderwaterPlantBlock; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BubbleCoralBlock extends EndUnderwaterPlantBlock implements AddMineableShears { - - private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 14, 16); - - public BubbleCoralBlock() { - super(FabricBlockSettings.of(Material.WATER_PLANT) - .sound(SoundType.CORAL_BLOCK) - .noCollission() - .offsetType(BlockBehaviour.OffsetType.NONE)); - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - double x = pos.getX() + random.nextDouble(); - double y = pos.getY() + random.nextDouble() * 0.5F + 0.5F; - double z = pos.getZ() + random.nextDouble(); - world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0.0D, 0.0D, 0.0D); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/BulbVineBlock.java b/src/main/java/ru/betterend/blocks/BulbVineBlock.java deleted file mode 100644 index eccdd7ea..00000000 --- a/src/main/java/ru/betterend/blocks/BulbVineBlock.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.List; - -public class BulbVineBlock extends BaseVineBlock { - public BulbVineBlock() { - super(15, true); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.getValue(SHAPE) == TripleShape.BOTTOM) { - return Lists.newArrayList(new ItemStack(EndItems.GLOWING_BULB)); - } - else if (MHelper.RANDOM.nextInt(8) == 0) { - return Lists.newArrayList(new ItemStack(EndBlocks.BULB_VINE_SEED)); - } - else { - return Lists.newArrayList(); - } - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - boolean canPlace = super.canSurvive(state, world, pos); - return (state.is(this) && state.getValue(SHAPE) == TripleShape.BOTTOM) ? canPlace : canPlace && world.getBlockState( - pos.below()).is(this); - } -} diff --git a/src/main/java/ru/betterend/blocks/BulbVineLanternBlock.java b/src/main/java/ru/betterend/blocks/BulbVineLanternBlock.java deleted file mode 100644 index e5e62fea..00000000 --- a/src/main/java/ru/betterend/blocks/BulbVineLanternBlock.java +++ /dev/null @@ -1,82 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.BlockModelProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineablePickaxe; -import ru.betterend.blocks.basis.EndLanternBlock; -import ru.betterend.client.models.Patterns; - -import java.util.Map; -import java.util.Optional; - -public class BulbVineLanternBlock extends EndLanternBlock implements RenderLayerProvider, BlockModelProvider, AddMineablePickaxe { - private static final VoxelShape SHAPE_CEIL = Block.box(4, 4, 4, 12, 16, 12); - private static final VoxelShape SHAPE_FLOOR = Block.box(4, 0, 4, 12, 12, 12); - - public BulbVineLanternBlock() { - this(FabricBlockSettings.of(Material.METAL) - .hardness(1) - .resistance(1) - .mapColor(MaterialColor.COLOR_LIGHT_GRAY) - .luminance(15) - .requiresCorrectToolForDrops() - .sound(SoundType.LANTERN)); - } - - public BulbVineLanternBlock(Properties settings) { - super(settings); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - Map textures = Maps.newHashMap(); - textures.put("%glow%", getGlowTexture()); - textures.put("%metal%", getMetalTexture(resourceLocation)); - Optional pattern = blockState.getValue(IS_FLOOR) ? Patterns.createJson( - Patterns.BLOCK_BULB_LANTERN_FLOOR, - textures - ) : Patterns.createJson(Patterns.BLOCK_BULB_LANTERN_CEIL, textures); - return ModelsHelper.fromPattern(pattern); - } - - protected String getMetalTexture(ResourceLocation blockId) { - String name = blockId.getPath(); - name = name.substring(0, name.indexOf('_')); - return name + "_bulb_vine_lantern_metal"; - } - - protected String getGlowTexture() { - return "bulb_vine_lantern_bulb"; - } - -} diff --git a/src/main/java/ru/betterend/blocks/BulbVineLanternColoredBlock.java b/src/main/java/ru/betterend/blocks/BulbVineLanternColoredBlock.java deleted file mode 100644 index 41821469..00000000 --- a/src/main/java/ru/betterend/blocks/BulbVineLanternColoredBlock.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.ColorUtil; - -public class BulbVineLanternColoredBlock extends BulbVineLanternBlock implements CustomColorProvider { - public BulbVineLanternColoredBlock(FabricBlockSettings settings) { - super(settings); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> getColor(); - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> getColor(); - } - - private int getColor() { - int color = BlocksHelper.getBlockColor(this); - int b = (color & 255); - int g = ((color >> 8) & 255); - int r = ((color >> 16) & 255); - float[] hsv = ColorUtil.RGBtoHSB(r, g, b, new float[3]); - return ColorUtil.HSBtoRGB(hsv[0], hsv[1], hsv[1] > 0.2 ? 1 : hsv[2]); - } - - @Override - protected String getGlowTexture() { - return "bulb_vine_lantern_overlay"; - } -} diff --git a/src/main/java/ru/betterend/blocks/BulbVineSeedBlock.java b/src/main/java/ru/betterend/blocks/BulbVineSeedBlock.java deleted file mode 100644 index d0e3d996..00000000 --- a/src/main/java/ru/betterend/blocks/BulbVineSeedBlock.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BulbVineSeedBlock extends EndPlantWithAgeBlock { - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState up = world.getBlockState(pos.above()); - return up.is(CommonBlockTags.GEN_END_STONES) || up.is(BlockTags.LOGS) || up.is(BlockTags.LEAVES); - } - - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - int h = BlocksHelper.downRay(world, pos, random.nextInt(24)) - 1; - if (h > 2) { - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) - ); - for (int i = 1; i < h; i++) { - BlocksHelper.setWithoutUpdate( - world, - pos.below(i), - EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) - ); - } - BlocksHelper.setWithoutUpdate( - world, - pos.below(h), - EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM) - ); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/CavePumpkinBlock.java b/src/main/java/ru/betterend/blocks/CavePumpkinBlock.java deleted file mode 100644 index 9a52391c..00000000 --- a/src/main/java/ru/betterend/blocks/CavePumpkinBlock.java +++ /dev/null @@ -1,68 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.betterend.registry.EndBlocks; - -import java.util.Collections; -import java.util.List; - -public class CavePumpkinBlock extends BaseBlockNotFull implements RenderLayerProvider { - public static final BooleanProperty SMALL = BlockProperties.SMALL; - private static final VoxelShape SHAPE_SMALL; - private static final VoxelShape SHAPE_BIG; - - public CavePumpkinBlock() { - super(FabricBlockSettings.copyOf(Blocks.PUMPKIN).luminance((state) -> state.getValue(SMALL) ? 10 : 15)); - registerDefaultState(defaultBlockState().setValue(SMALL, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SMALL); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { - return state.getValue(SMALL) ? SHAPE_SMALL : SHAPE_BIG; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return state.getValue(SMALL) ? Collections.singletonList(new ItemStack(EndBlocks.CAVE_PUMPKIN_SEED)) : Collections - .singletonList(new ItemStack(this)); - } - - static { - VoxelShape lantern = Block.box(1, 0, 1, 15, 13, 15); - VoxelShape cap = Block.box(0, 12, 0, 16, 15, 16); - VoxelShape top = Block.box(5, 15, 5, 11, 16, 11); - SHAPE_BIG = Shapes.or(lantern, cap, top); - - lantern = Block.box(5, 7, 5, 11, 13, 11); - cap = Block.box(4, 12, 4, 12, 15, 12); - top = Block.box(6, 15, 6, 10, 16, 10); - SHAPE_SMALL = Shapes.or(lantern, cap, top); - } -} diff --git a/src/main/java/ru/betterend/blocks/CavePumpkinVineBlock.java b/src/main/java/ru/betterend/blocks/CavePumpkinVineBlock.java deleted file mode 100644 index 4ac027b8..00000000 --- a/src/main/java/ru/betterend/blocks/CavePumpkinVineBlock.java +++ /dev/null @@ -1,75 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BlockProperties; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class CavePumpkinVineBlock extends EndPlantWithAgeBlock { - public CavePumpkinVineBlock(){ - super(p->p.offsetType(BlockBehaviour.OffsetType.NONE)); - } - private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12); - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState down = world.getBlockState(pos.above()); - return isTerrain(down); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - int age = state.getValue(AGE); - BlockState down = world.getBlockState(pos.below()); - if (down.getMaterial() - .isReplaceable() || (down.is(EndBlocks.CAVE_PUMPKIN) && down.getValue(BlockProperties.SMALL))) { - if (age < 3) { - world.setBlockAndUpdate(pos, state.setValue(AGE, age + 1)); - } - if (age == 2) { - world.setBlockAndUpdate( - pos.below(), - EndBlocks.CAVE_PUMPKIN.defaultBlockState().setValue(BlockProperties.SMALL, true) - ); - } - else if (age == 3) { - world.setBlockAndUpdate(pos.below(), EndBlocks.CAVE_PUMPKIN.defaultBlockState()); - } - } - } - - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - state = super.updateShape(state, facing, neighborState, world, pos, neighborPos); - if (state.is(this) && state.getValue(BlockProperties.AGE) > 1) { - BlockState down = world.getBlockState(pos.below()); - if (!down.is(EndBlocks.CAVE_PUMPKIN)) { - state = state.setValue(BlockProperties.AGE, 1); - } - } - return state; - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } -} diff --git a/src/main/java/ru/betterend/blocks/ChandelierBlock.java b/src/main/java/ru/betterend/blocks/ChandelierBlock.java deleted file mode 100644 index a4fe4a9c..00000000 --- a/src/main/java/ru/betterend/blocks/ChandelierBlock.java +++ /dev/null @@ -1,113 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.BlockModelRotation; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.BlockModelProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.betterend.client.models.Patterns; - -import java.util.EnumMap; -import java.util.Map; -import java.util.Optional; - -public class ChandelierBlock extends BaseAttachedBlock implements RenderLayerProvider, BlockModelProvider { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - - public ChandelierBlock(Block source) { - super(FabricBlockSettings.copyOf(source) - .luminance(15) - .noCollission() - .noOcclusion() - .requiresCorrectToolForDrops()); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation blockId) { - return ModelsHelper.createItemModel(blockId); - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - Optional pattern; - switch (blockState.getValue(FACING)) { - case UP: - pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_FLOOR, resourceLocation.getPath()); - break; - case DOWN: - pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_CEIL, resourceLocation.getPath()); - break; - default: - pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_WALL, resourceLocation.getPath()); - } - return ModelsHelper.fromPattern(pattern); - } - - @Override - @Environment(EnvType.CLIENT) - public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map modelCache) { - String state = "_wall"; - BlockModelRotation rotation = BlockModelRotation.X0_Y0; - switch (blockState.getValue(FACING)) { - case UP: - state = "_floor"; - break; - case DOWN: - state = "_ceil"; - break; - case EAST: - rotation = BlockModelRotation.X0_Y270; - break; - case NORTH: - rotation = BlockModelRotation.X0_Y180; - break; - case WEST: - rotation = BlockModelRotation.X0_Y90; - break; - default: - break; - } - ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath() + state); - registerBlockModel(stateId, modelId, blockState, modelCache); - return ModelsHelper.createMultiVariant(modelId, rotation.getRotation(), false); - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Block.box(5, 0, 5, 11, 13, 11)); - BOUNDING_SHAPES.put(Direction.DOWN, Block.box(5, 3, 5, 11, 16, 11)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); - } -} diff --git a/src/main/java/ru/betterend/blocks/CharniaBlock.java b/src/main/java/ru/betterend/blocks/CharniaBlock.java deleted file mode 100644 index dff8ef06..00000000 --- a/src/main/java/ru/betterend/blocks/CharniaBlock.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import ru.betterend.blocks.basis.EndUnderwaterPlantBlock; - -public class CharniaBlock extends EndUnderwaterPlantBlock { - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return canSupportCenter(world, pos.below(), Direction.UP) && world.getFluidState(pos).getType() == Fluids.WATER; - } -} diff --git a/src/main/java/ru/betterend/blocks/ChorusGrassBlock.java b/src/main/java/ru/betterend/blocks/ChorusGrassBlock.java deleted file mode 100644 index 71635d36..00000000 --- a/src/main/java/ru/betterend/blocks/ChorusGrassBlock.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class ChorusGrassBlock extends EndPlantBlock { - public ChorusGrassBlock() { - super(true); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.getBlock() == EndBlocks.CHORUS_NYLIUM; - } -} diff --git a/src/main/java/ru/betterend/blocks/DenseEmeraldIceBlock.java b/src/main/java/ru/betterend/blocks/DenseEmeraldIceBlock.java deleted file mode 100644 index d38b8902..00000000 --- a/src/main/java/ru/betterend/blocks/DenseEmeraldIceBlock.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; - -import java.util.Collections; -import java.util.List; - -public class DenseEmeraldIceBlock extends BaseBlock implements RenderLayerProvider { - public DenseEmeraldIceBlock() { - super(FabricBlockSettings.copyOf(Blocks.PACKED_ICE)); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); - if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { - return Collections.singletonList(new ItemStack(this)); - } - else { - return Collections.emptyList(); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/DragonTreeSaplingBlock.java b/src/main/java/ru/betterend/blocks/DragonTreeSaplingBlock.java deleted file mode 100644 index 4c34dbde..00000000 --- a/src/main/java/ru/betterend/blocks/DragonTreeSaplingBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class DragonTreeSaplingBlock extends PottableFeatureSapling { - public DragonTreeSaplingBlock() { - super((state)->EndFeatures.DRAGON_TREE.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.SHADOW_GRASS); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.SHADOW_GRASS; - } -} diff --git a/src/main/java/ru/betterend/blocks/EmeraldIceBlock.java b/src/main/java/ru/betterend/blocks/EmeraldIceBlock.java deleted file mode 100644 index 4975af91..00000000 --- a/src/main/java/ru/betterend/blocks/EmeraldIceBlock.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.HalfTransparentBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import org.jetbrains.annotations.Nullable; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.BlockModelProvider; -import ru.bclib.interfaces.RenderLayerProvider; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EmeraldIceBlock extends HalfTransparentBlock implements RenderLayerProvider, BlockModelProvider { - public EmeraldIceBlock() { - super(FabricBlockSettings.copyOf(Blocks.ICE)); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { - super.playerDestroy(world, player, pos, state, blockEntity, stack); - if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { - if (world.dimensionType().ultraWarm()) { - world.removeBlock(pos, false); - return; - } - - Material material = world.getBlockState(pos.below()).getMaterial(); - if (material.blocksMotion() || material.isLiquid()) { - world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState()); - } - } - - } - - @Override - @SuppressWarnings("deprecation") - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (world.getBrightness(LightLayer.BLOCK, pos) > 11 - state.getLightBlock(world, pos)) { - this.melt(state, world, pos); - } - - } - - protected void melt(BlockState state, Level world, BlockPos pos) { - if (world.dimensionType().ultraWarm()) { - world.removeBlock(pos, false); - } - else { - world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState()); - world.neighborChanged(pos, Blocks.WATER, pos); - } - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); - if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) { - return Collections.singletonList(new ItemStack(this)); - } - else { - return Collections.emptyList(); - } - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - return getBlockModel(resourceLocation, defaultBlockState()); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndBlockProperties.java b/src/main/java/ru/betterend/blocks/EndBlockProperties.java deleted file mode 100644 index d26385e5..00000000 --- a/src/main/java/ru/betterend/blocks/EndBlockProperties.java +++ /dev/null @@ -1,130 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import ru.bclib.blocks.BlockProperties; -import ru.betterend.registry.EndPortals; - -public class EndBlockProperties extends BlockProperties { - public static final EnumProperty HYDRALUX_SHAPE = EnumProperty.create("shape", HydraluxShape.class); - public static final EnumProperty PEDESTAL_STATE = EnumProperty.create("state", PedestalState.class); - public static final EnumProperty CACTUS_BOTTOM = EnumProperty.create("bottom", CactusBottom.class); - - public static final IntegerProperty PORTAL = IntegerProperty.create("portal", 0, EndPortals.getCount()); - public static final IntegerProperty PLANT_ID = IntegerProperty.create("plant_id", 0, 63); - public static final IntegerProperty SOIL_ID = IntegerProperty.create("soil_id", 0, 16); - public static final IntegerProperty POT_LIGHT = IntegerProperty.create("pot_light", 0, 3); - public static final BooleanProperty HAS_ITEM = BooleanProperty.create("has_item"); - - public enum PedestalState implements StringRepresentable { - PEDESTAL_TOP("pedestal_top"), - COLUMN_TOP("column_top"), - BOTTOM("bottom"), - PILLAR("pillar"), - COLUMN("column"), - DEFAULT("default"); - - private final String name; - - PedestalState(String name) { - this.name = name; - } - - @Override - public String getSerializedName() { - return this.name; - } - - @Override - public String toString() { - return this.name; - } - } - - public enum HydraluxShape implements StringRepresentable { - FLOWER_BIG_BOTTOM("flower_big_bottom", true), - FLOWER_BIG_TOP("flower_big_top", true), - FLOWER_SMALL_BOTTOM("flower_small_bottom", true), - FLOWER_SMALL_TOP("flower_small_top", true), - VINE("vine", false), - ROOTS("roots", false); - - private final String name; - private final boolean glow; - - HydraluxShape(String name, boolean glow) { - this.name = name; - this.glow = glow; - } - - @Override - public String getSerializedName() { - return name; - } - - @Override - public String toString() { - return name; - } - - public boolean hasGlow() { - return glow; - } - } - - public enum LumecornShape implements StringRepresentable { - LIGHT_TOP("light_top", 15), - LIGHT_TOP_MIDDLE("light_top_middle", 15), - LIGHT_MIDDLE("light_middle", 15), - LIGHT_BOTTOM("light_bottom", 15), - MIDDLE("middle", 0), - BOTTOM_BIG("bottom_big", 0), - BOTTOM_SMALL("bottom_small", 0); - - private final String name; - private final int light; - - LumecornShape(String name, int light) { - this.name = name; - this.light = light; - } - - @Override - public String getSerializedName() { - return name; - } - - @Override - public String toString() { - return name; - } - - public int getLight() { - return light; - } - } - - public enum CactusBottom implements StringRepresentable { - EMPTY("empty"), - SAND("sand"), - MOSS("moss"); - - private final String name; - - CactusBottom(String name) { - this.name = name; - } - - @Override - public String getSerializedName() { - return name; - } - - @Override - public String toString() { - return name; - } - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLilyBlock.java b/src/main/java/ru/betterend/blocks/EndLilyBlock.java deleted file mode 100644 index 6b4579d1..00000000 --- a/src/main/java/ru/betterend/blocks/EndLilyBlock.java +++ /dev/null @@ -1,121 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndUnderwaterPlantBlock; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLilyBlock extends EndUnderwaterPlantBlock implements AddMineableShears { - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 16, 12); - private static final VoxelShape SHAPE_TOP = Block.box(2, 0, 2, 14, 6, 14); - - public EndLilyBlock() { - super(FabricBlockSettings.of(Material.WATER_PLANT) - .sound(SoundType.WET_GRASS) - .lightLevel((state) -> state.getValue(SHAPE) == TripleShape.TOP ? 13 : 0) - .noCollission()); - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return state.getValue(SHAPE) == TripleShape.TOP ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState(); - } - else { - return state; - } - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - Vec3 vec3d = state.getOffset(view, pos); - VoxelShape shape = state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM; - return shape.move(vec3d.x, vec3d.y, vec3d.z); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(SHAPE) == TripleShape.TOP ? Fluids.EMPTY.defaultFluidState() : Fluids.WATER.getSource( - false); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - if (state.getValue(SHAPE) == TripleShape.TOP) { - return world.getBlockState(pos.below()).getBlock() == this; - } - else if (state.getValue(SHAPE) == TripleShape.BOTTOM) { - return isTerrain(world.getBlockState(pos.below())); - } - else { - BlockState up = world.getBlockState(pos.above()); - BlockState down = world.getBlockState(pos.below()); - return up.getBlock() == this && down.getBlock() == this; - } - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.getValue(SHAPE) == TripleShape.TOP) { - return Lists.newArrayList( - new ItemStack(EndItems.END_LILY_LEAF, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)), - new ItemStack(EndBlocks.END_LILY_SEED, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)) - ); - } - return Collections.emptyList(); - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - return new ItemStack(EndBlocks.END_LILY_SEED); - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLilySeedBlock.java b/src/main/java/ru/betterend/blocks/EndLilySeedBlock.java deleted file mode 100644 index 5e133022..00000000 --- a/src/main/java/ru/betterend/blocks/EndLilySeedBlock.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.blocks.UnderwaterPlantWithAgeBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLilySeedBlock extends UnderwaterPlantWithAgeBlock { - @Override - public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { - if (canGrow(world, pos)) { - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.BOTTOM) - ); - BlockPos up = pos.above(); - while (world.getFluidState(up).isSource()) { - BlocksHelper.setWithoutUpdate( - world, - up, - EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.MIDDLE) - ); - up = up.above(); - } - BlocksHelper.setWithoutUpdate( - world, - up, - EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.TOP) - ); - } - } - - private boolean canGrow(WorldGenLevel world, BlockPos pos) { - BlockPos up = pos.above(); - while (world.getBlockState(up).getFluidState().getType().equals(Fluids.WATER.getSource())) { - up = up.above(); - } - return world.isEmptyBlock(up); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLotusFlowerBlock.java b/src/main/java/ru/betterend/blocks/EndLotusFlowerBlock.java deleted file mode 100644 index c218558c..00000000 --- a/src/main/java/ru/betterend/blocks/EndLotusFlowerBlock.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class EndLotusFlowerBlock extends EndPlantBlock { - private static final VoxelShape SHAPE_OUTLINE = Block.box(2, 0, 2, 14, 14, 14); - private static final VoxelShape SHAPE_COLLISION = Block.box(0, 0, 0, 16, 2, 16); - - public EndLotusFlowerBlock() { - //TODO: 1.19 Test if we can remove dynamic shape and offsetType - super(FabricBlockSettings.of(Material.PLANT).luminance(15).noOcclusion().dynamicShape().offsetType(BlockBehaviour.OffsetType.NONE)); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_LOTUS_STEM); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE_OUTLINE; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE_COLLISION; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - int count = MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE); - return Lists.newArrayList(new ItemStack(EndBlocks.END_LOTUS_SEED, count)); - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - return new ItemStack(EndBlocks.END_LOTUS_SEED); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLotusLeafBlock.java b/src/main/java/ru/betterend/blocks/EndLotusLeafBlock.java deleted file mode 100644 index e15c1ab4..00000000 --- a/src/main/java/ru/betterend/blocks/EndLotusLeafBlock.java +++ /dev/null @@ -1,80 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -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.EnumProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.WaterFluid; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -public class EndLotusLeafBlock extends BaseBlockNotFull implements RenderLayerProvider { - public static final EnumProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - private static final VoxelShape VSHAPE = Block.box(0, 0, 0, 16, 1, 16); - - public EndLotusLeafBlock() { - super(FabricBlockSettings.of(Material.PLANT).noOcclusion().sound(SoundType.WET_GRASS)); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState down = world.getBlockState(pos.below()); - return !down.getFluidState().isEmpty() && down.getFluidState().getType() instanceof WaterFluid; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(SHAPE, HORIZONTAL_FACING); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return VSHAPE; - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) { - return BlocksHelper.rotateHorizontal(state, rotation, HORIZONTAL_FACING); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirror) { - return BlocksHelper.mirrorHorizontal(state, mirror, HORIZONTAL_FACING); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - return new ItemStack(EndBlocks.END_LOTUS_SEED); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLotusSeedBlock.java b/src/main/java/ru/betterend/blocks/EndLotusSeedBlock.java deleted file mode 100644 index 558dc676..00000000 --- a/src/main/java/ru/betterend/blocks/EndLotusSeedBlock.java +++ /dev/null @@ -1,140 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.blocks.UnderwaterPlantWithAgeBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLotusSeedBlock extends UnderwaterPlantWithAgeBlock { - @Override - public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { - if (canGrow(world, pos)) { - BlockState startLeaf = EndBlocks.END_LOTUS_STEM.defaultBlockState().setValue(EndLotusStemBlock.LEAF, true); - BlockState roots = EndBlocks.END_LOTUS_STEM.defaultBlockState() - .setValue(EndLotusStemBlock.SHAPE, TripleShape.BOTTOM) - .setValue(EndLotusStemBlock.WATERLOGGED, true); - BlockState stem = EndBlocks.END_LOTUS_STEM.defaultBlockState(); - BlockState flower = EndBlocks.END_LOTUS_FLOWER.defaultBlockState(); - - BlocksHelper.setWithoutUpdate(world, pos, roots); - MutableBlockPos bpos = new MutableBlockPos().set(pos); - bpos.setY(bpos.getY() + 1); - while (world.getFluidState(bpos).isSource()) { - BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.WATERLOGGED, true)); - bpos.setY(bpos.getY() + 1); - } - - int height = random.nextBoolean() ? 0 : random.nextBoolean() ? 1 : random.nextBoolean() ? 1 : -1; - TripleShape shape = (height == 0) ? TripleShape.TOP : TripleShape.MIDDLE; - Direction dir = BlocksHelper.randomHorizontal(random); - BlockPos leafCenter = bpos.immutable().relative(dir); - if (hasLeaf(world, leafCenter)) { - generateLeaf(world, leafCenter); - BlocksHelper.setWithoutUpdate( - world, - bpos, - startLeaf.setValue(EndLotusStemBlock.SHAPE, shape).setValue(EndLotusStemBlock.FACING, dir) - ); - } - else { - BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, shape)); - } - - bpos.setY(bpos.getY() + 1); - for (int i = 1; i <= height; i++) { - if (!world.isEmptyBlock(bpos)) { - bpos.setY(bpos.getY() - 1); - BlocksHelper.setWithoutUpdate(world, bpos, flower); - bpos.setY(bpos.getY() - 1); - stem = world.getBlockState(bpos); - BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP)); - return; - } - BlocksHelper.setWithoutUpdate(world, bpos, stem); - bpos.setY(bpos.getY() + 1); - } - - if (!world.isEmptyBlock(bpos) || height < 0) { - bpos.setY(bpos.getY() - 1); - } - - BlocksHelper.setWithoutUpdate(world, bpos, flower); - bpos.setY(bpos.getY() - 1); - stem = world.getBlockState(bpos); - if (!stem.is(EndBlocks.END_LOTUS_STEM)) { - stem = EndBlocks.END_LOTUS_STEM.defaultBlockState(); - if (!world.getBlockState(bpos.north()).getFluidState().isEmpty()) { - stem = stem.setValue(EndLotusStemBlock.WATERLOGGED, true); - } - } - - if (world.getBlockState(bpos.relative(dir)).is(EndBlocks.END_LOTUS_LEAF)) { - stem = stem.setValue(EndLotusStemBlock.LEAF, true).setValue(EndLotusStemBlock.FACING, dir); - } - - BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP)); - } - } - - private boolean canGrow(WorldGenLevel world, BlockPos pos) { - MutableBlockPos bpos = new MutableBlockPos(); - bpos.set(pos); - while (world.getBlockState(bpos).getFluidState().getType().equals(Fluids.WATER.getSource())) { - bpos.setY(bpos.getY() + 1); - } - return world.isEmptyBlock(bpos) && world.isEmptyBlock(bpos.above()); - } - - private void generateLeaf(WorldGenLevel world, BlockPos pos) { - MutableBlockPos p = new MutableBlockPos(); - BlockState leaf = EndBlocks.END_LOTUS_LEAF.defaultBlockState(); - BlocksHelper.setWithoutUpdate(world, pos, leaf.setValue(EndLotusLeafBlock.SHAPE, TripleShape.BOTTOM)); - for (Direction move : BlocksHelper.HORIZONTAL) { - BlocksHelper.setWithoutUpdate( - world, - p.set(pos).move(move), - leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, move) - .setValue(EndLotusLeafBlock.SHAPE, TripleShape.MIDDLE) - ); - } - for (int i = 0; i < 4; i++) { - Direction d1 = BlocksHelper.HORIZONTAL[i]; - Direction d2 = BlocksHelper.HORIZONTAL[(i + 1) & 3]; - BlocksHelper.setWithoutUpdate( - world, - p.set(pos).move(d1).move(d2), - leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, d1) - .setValue(EndLotusLeafBlock.SHAPE, TripleShape.TOP) - ); - } - } - - private boolean hasLeaf(WorldGenLevel world, BlockPos pos) { - MutableBlockPos p = new MutableBlockPos(); - p.setY(pos.getY()); - int count = 0; - for (int x = -1; x < 2; x++) { - p.setX(pos.getX() + x); - for (int z = -1; z < 2; z++) { - p.setZ(pos.getZ() + z); - if (world.isEmptyBlock(p) && !world.getFluidState(p.below()).isEmpty()) count++; - } - } - return count == 9; - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndLotusStemBlock.java b/src/main/java/ru/betterend/blocks/EndLotusStemBlock.java deleted file mode 100644 index 46244688..00000000 --- a/src/main/java/ru/betterend/blocks/EndLotusStemBlock.java +++ /dev/null @@ -1,106 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; - -import java.util.Map; - -public class EndLotusStemBlock extends BaseBlock implements SimpleWaterloggedBlock, RenderLayerProvider { - public static final EnumProperty FACING = BlockStateProperties.FACING; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public static final BooleanProperty LEAF = BooleanProperty.create("leaf"); - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - private static final Map SHAPES = Maps.newEnumMap(Axis.class); - - public EndLotusStemBlock() { - super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS)); - this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) - .setValue(SHAPE, TripleShape.MIDDLE) - .setValue(LEAF, false) - .setValue(FACING, Direction.UP)); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(LEAF) ? SHAPES.get(Axis.Y) : SHAPES.get(state.getValue(FACING).getAxis()); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(FACING, WATERLOGGED, SHAPE, LEAF); - } - - @Override - @SuppressWarnings("deprecation") - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - LevelAccessor worldAccess = ctx.getLevel(); - BlockPos blockPos = ctx.getClickedPos(); - return this.defaultBlockState() - .setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER) - .setValue(FACING, ctx.getClickedFace()); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) { - return BlocksHelper.rotateHorizontal(state, rotation, FACING); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirror) { - return BlocksHelper.mirrorHorizontal(state, mirror, FACING); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - if (state.getValue(WATERLOGGED)) { - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - } - return state; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - static { - SHAPES.put(Axis.X, Block.box(0, 6, 6, 16, 10, 10)); - SHAPES.put(Axis.Y, Block.box(6, 0, 6, 10, 16, 10)); - SHAPES.put(Axis.Z, Block.box(6, 6, 0, 10, 10, 16)); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndPedestal.java b/src/main/java/ru/betterend/blocks/EndPedestal.java deleted file mode 100644 index b0106f95..00000000 --- a/src/main/java/ru/betterend/blocks/EndPedestal.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.basis.PedestalBlock; - -import java.util.Map; - -public class EndPedestal extends PedestalBlock { - - public EndPedestal(Block parent) { - super(parent); - } - - @Override - protected Map createTexturesMap() { - ResourceLocation blockId = Registry.BLOCK.getKey(parent); - String name = blockId.getPath(); - Map textures = Maps.newHashMap(); - textures.put("%mod%", BetterEnd.MOD_ID); - textures.put("%top%", name + "_polished"); - textures.put("%base%", name + "_polished"); - textures.put("%pillar%", name + "_pillar_side"); - textures.put("%bottom%", name + "_polished"); - return textures; - } -} diff --git a/src/main/java/ru/betterend/blocks/EndPortalBlock.java b/src/main/java/ru/betterend/blocks/EndPortalBlock.java deleted file mode 100644 index 62240a44..00000000 --- a/src/main/java/ru/betterend/blocks/EndPortalBlock.java +++ /dev/null @@ -1,214 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.NetherPortalBlock; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.dimension.DimensionType; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.betterend.interfaces.TeleportingEntity; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndPortals; -import ru.betterend.rituals.EternalRitual; - -import java.util.Objects; -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProvider, CustomColorProvider { - public static final IntegerProperty PORTAL = EndBlockProperties.PORTAL; - - public EndPortalBlock() { - super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL) - .resistance(Blocks.BEDROCK.getExplosionResistance()) - .luminance(15)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder); - builder.add(PORTAL); - } - - @Override - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - if (random.nextInt(100) == 0) { - world.playLocalSound( - pos.getX() + 0.5D, - pos.getY() + 0.5D, - pos.getZ() + 0.5D, - SoundEvents.PORTAL_AMBIENT, - SoundSource.BLOCKS, - 0.5F, - random.nextFloat() * 0.4F + 0.8F, - false - ); - } - - double x = pos.getX() + random.nextDouble(); - double y = pos.getY() + random.nextDouble(); - double z = pos.getZ() + random.nextDouble(); - int k = random.nextInt(2) * 2 - 1; - if (!world.getBlockState(pos.west()).is(this) && !world.getBlockState(pos.east()).is(this)) { - x = pos.getX() + 0.5D + 0.25D * k; - } - else { - z = pos.getZ() + 0.5D + 0.25D * k; - } - - world.addParticle(EndParticles.PORTAL_SPHERE, x, y, z, 0, 0, 0); - } - - @Override - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - } - - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - return state; - } - - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - if (world.isClientSide || !validate(entity)) return; - entity.setPortalCooldown(); - ServerLevel currentWorld = (ServerLevel) world; - MinecraftServer server = currentWorld.getServer(); - ServerLevel targetWorld = EndPortals.getWorld(server, state.getValue(PORTAL)); - boolean isInEnd = currentWorld.dimension().equals(Level.END); - ServerLevel destination = isInEnd ? targetWorld : server.getLevel(Level.END); - BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity); - if (exitPos == null) return; - if (entity instanceof ServerPlayer && ((ServerPlayer) entity).isCreative()) { - ((ServerPlayer) entity).teleportTo( - destination, - exitPos.getX() + 0.5, - exitPos.getY(), - exitPos.getZ() + 0.5, - entity.getYRot(), - entity.getXRot() - ); - } - else { - ((TeleportingEntity) entity).be_setExitPos(exitPos); - Optional teleported = Optional.ofNullable(entity.changeDimension(destination)); - teleported.ifPresent(Entity::setPortalCooldown); - } - } - - private boolean validate(Entity entity) { - return !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && !entity.isOnPortalCooldown(); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - private BlockPos findExitPos(ServerLevel currentWorld, ServerLevel targetWorld, BlockPos currentPos, Entity entity) { - if (targetWorld == null) return null; - Registry registry = targetWorld.registryAccess() - .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - ResourceLocation targetWorldId = targetWorld.dimension().location(); - ResourceLocation currentWorldId = currentWorld.dimension().location(); - double targetMultiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale(); - double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).coordinateScale(); - double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier; - MutableBlockPos basePos = currentPos.mutable() - .set(currentPos.getX() * multiplier, - currentPos.getY(), - currentPos.getZ() * multiplier - ); - MutableBlockPos checkPos = basePos.mutable(); - BlockState currentState = currentWorld.getBlockState(currentPos); - int radius = (EternalRitual.SEARCH_RADIUS >> 4) + 1; - checkPos = EternalRitual.findBlockPos( - targetWorld, - checkPos, - radius, - this, - state -> state.is(this) && state.getValue(PORTAL).equals(currentState.getValue(PORTAL)) - ); - if (checkPos != null) { - BlockState checkState = targetWorld.getBlockState(checkPos); - Axis axis = checkState.getValue(AXIS); - checkPos = findCenter(targetWorld, checkPos, axis); - Direction frontDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE).getClockWise(); - Direction entityDir = entity.getMotionDirection(); - if (entityDir.getAxis().isVertical()) { - entityDir = frontDir; - } - if (frontDir != entityDir && frontDir.getOpposite() != entityDir) { - entity.rotate(Rotation.CLOCKWISE_90); - entityDir = entityDir.getClockWise(); - } - return checkPos.relative(entityDir); - } - return null; - } - - private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis) { - return findCenter(world, pos, axis, 1); - } - - private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis, int step) { - if (step > 8) return pos; - BlockState right, left; - Direction rightDir, leftDir; - rightDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - leftDir = rightDir.getOpposite(); - right = world.getBlockState(pos.relative(rightDir)); - left = world.getBlockState(pos.relative(leftDir)); - BlockState down = world.getBlockState(pos.below()); - if (down.is(this)) { - return findCenter(world, pos.move(Direction.DOWN), axis, step); - } - else if (right.is(this) && left.is(this)) { - return pos; - } - else if (right.is(this)) { - return findCenter(world, pos.move(rightDir), axis, ++step); - } - else if (left.is(this)) { - return findCenter(world, pos.move(leftDir), axis, ++step); - } - return pos; - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> EndPortals.getColor(state.getValue(PORTAL)); - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> EndPortals.getColor(0); - } -} diff --git a/src/main/java/ru/betterend/blocks/EndStoneSmelter.java b/src/main/java/ru/betterend/blocks/EndStoneSmelter.java deleted file mode 100644 index cf8b5b48..00000000 --- a/src/main/java/ru/betterend/blocks/EndStoneSmelter.java +++ /dev/null @@ -1,180 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -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.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.BlockHitResult; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlockWithEntity; -import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity; -import ru.betterend.registry.EndBlockEntities; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndStoneSmelter extends BaseBlockWithEntity { - public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; - public static final BooleanProperty LIT = BlockStateProperties.LIT; - public static final String ID = "end_stone_smelter"; - - public EndStoneSmelter() { - super(FabricBlockSettings.of(Material.STONE, MaterialColor.COLOR_GRAY) - .luminance(state -> state.getValue(LIT) ? 15 : 0) - .hardness(4F) - .resistance(100F) - .requiresCorrectToolForDrops() - .sound(SoundType.STONE)); - registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(LIT, false)); - } - - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (world.isClientSide) { - return InteractionResult.SUCCESS; - } - else { - this.openScreen(world, pos, player); - return InteractionResult.CONSUME; - } - } - - private void openScreen(Level world, BlockPos pos, Player player) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof EndStoneSmelterBlockEntity) { - player.openMenu((EndStoneSmelterBlockEntity) blockEntity); - } - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - return defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite()); - } - - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new EndStoneSmelterBlockEntity(blockPos, blockState); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - List drop = Lists.newArrayList(new ItemStack(this)); - BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); - if (blockEntity instanceof EndStoneSmelterBlockEntity) { - EndStoneSmelterBlockEntity smelterBlockEntity = (EndStoneSmelterBlockEntity) blockEntity; - for (int i = 0; i < smelterBlockEntity.getContainerSize(); i++) { - ItemStack item = smelterBlockEntity.getItem(i); - if (!item.isEmpty()) { - drop.add(item); - } - } - } - return drop; - } - - @Override - @SuppressWarnings("deprecation") - public boolean hasAnalogOutputSignal(BlockState state) { - return true; - } - - @Override - @SuppressWarnings("deprecation") - public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { - //TODO - return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(world.getBlockEntity(pos)); - } - - @Override - public RenderShape getRenderShape(BlockState state) { - return RenderShape.MODEL; - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) { - return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirror) { - return state.rotate(mirror.getRotation(state.getValue(FACING))); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(FACING, LIT); - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - if (state.getValue(LIT)) { - double x = pos.getX() + 0.5D; - double y = pos.getY(); - double z = pos.getZ() + 0.5D; - if (random.nextDouble() < 0.1D) { - world.playLocalSound( - x, - y, - z, - SoundEvents.BLASTFURNACE_FIRE_CRACKLE, - SoundSource.BLOCKS, - 1.0F, - 1.0F, - false - ); - } - - Direction direction = state.getValue(FACING); - Direction.Axis axis = direction.getAxis(); - double defOffset = random.nextDouble() * 0.6D - 0.3D; - double offX = axis == Direction.Axis.X ? direction.getStepX() * 0.52D : defOffset; - double offY = random.nextDouble() * 9.0D / 16.0D; - double offZ = axis == Direction.Axis.Z ? direction.getStepZ() * 0.52D : defOffset; - world.addParticle(ParticleTypes.SMOKE, x + offX, y + offY, z + offZ, 0.0D, 0.0D, 0.0D); - } - } - - - @Override - @Nullable - public BlockEntityTicker getTicker(Level level, BlockState blockState, BlockEntityType blockEntityType) { - return level.isClientSide() ? null : createTickerHelper( - blockEntityType, - EndBlockEntities.END_STONE_SMELTER, - EndStoneSmelterBlockEntity::tick - ); - } -} diff --git a/src/main/java/ru/betterend/blocks/EnderBlock.java b/src/main/java/ru/betterend/blocks/EnderBlock.java deleted file mode 100644 index 5e4566d8..00000000 --- a/src/main/java/ru/betterend/blocks/EnderBlock.java +++ /dev/null @@ -1,28 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; - -public class EnderBlock extends BaseBlock { - - public EnderBlock() { - super(FabricBlockSettings.of(Material.STONE, MaterialColor.WARPED_WART_BLOCK) - .hardness(5F) - .resistance(6F) - .requiresCorrectToolForDrops() - .sound(SoundType.STONE)); - } - - @Environment(EnvType.CLIENT) - public int getColor(BlockState state, BlockGetter world, BlockPos pos) { - return 0xFF005548; - } -} diff --git a/src/main/java/ru/betterend/blocks/EndstoneDustBlock.java b/src/main/java/ru/betterend/blocks/EndstoneDustBlock.java deleted file mode 100644 index c27cdaf6..00000000 --- a/src/main/java/ru/betterend/blocks/EndstoneDustBlock.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.FallingBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; - -import ru.bclib.api.tag.CommonBlockTags; - -import ru.bclib.interfaces.TagProvider; -import ru.bclib.interfaces.tools.AddMineableShovel; -import ru.bclib.util.ColorUtil; - -import java.util.Collections; -import java.util.List; - -public class EndstoneDustBlock extends FallingBlock implements TagProvider, AddMineableShovel { - @Environment(EnvType.CLIENT) - private static final int COLOR = ColorUtil.color(226, 239, 168); - - public EndstoneDustBlock() { - super(FabricBlockSettings - .copyOf(Blocks.SAND) - .mapColor(Blocks.END_STONE.defaultMaterialColor()) - ); - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) { - return Collections.singletonList(new ItemStack(this)); - } - - @Environment(EnvType.CLIENT) - public int getDustColor(BlockState state, BlockGetter world, BlockPos pos) { - return COLOR; - } - - @Override - public void addTags(List> blockTags, List> itemTags) { - blockTags.add(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/EternalPedestal.java b/src/main/java/ru/betterend/blocks/EternalPedestal.java deleted file mode 100644 index a2b843fa..00000000 --- a/src/main/java/ru/betterend/blocks/EternalPedestal.java +++ /dev/null @@ -1,139 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.blocks.entities.EternalPedestalEntity; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndPortals; -import ru.betterend.rituals.EternalRitual; - -import java.util.List; - -public class EternalPedestal extends PedestalBlock { - public static final BooleanProperty ACTIVATED = EndBlockProperties.ACTIVE; - - public EternalPedestal() { - super(EndBlocks.FLAVOLITE_RUNED_ETERNAL); - this.registerDefaultState(defaultBlockState().setValue(ACTIVATED, false)); - } - - @Override - public void checkRitual(Level world, BlockPos pos) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof EternalPedestalEntity) { - EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity; - BlockState updatedState = world.getBlockState(pos); - if (pedestal.isEmpty()) { - if (pedestal.hasRitual()) { - EternalRitual ritual = pedestal.getRitual(); - if (ritual.isActive()) { - ResourceLocation targetWorld = ritual.getTargetWorldId(); - int portalId; - if (targetWorld != null) { - portalId = EndPortals.getPortalIdByWorld(targetWorld); - } - else { - portalId = EndPortals.getPortalIdByWorld(EndPortals.OVERWORLD_ID); - } - ritual.disablePortal(portalId); - } - } - world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, false).setValue(HAS_LIGHT, false)); - } - else { - ItemStack itemStack = pedestal.getItem(0); - ResourceLocation id = Registry.ITEM.getKey(itemStack.getItem()); - if (EndPortals.isAvailableItem(id)) { - world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, true).setValue(HAS_LIGHT, true)); - if (pedestal.hasRitual()) { - pedestal.getRitual().checkStructure(); - } - else { - EternalRitual ritual = new EternalRitual(world, pos); - ritual.checkStructure(); - } - } - } - } - } - - @Override - @Deprecated - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - BlockState updated = super.updateShape(state, direction, newState, world, pos, posFrom); - if (!updated.is(this)) return updated; - if (!this.isPlaceable(updated)) { - return updated.setValue(ACTIVATED, false); - } - return updated; - } - - @Override - @Deprecated - public float getDestroyProgress(BlockState state, Player player, BlockGetter world, BlockPos pos) { - return 0.0F; - } - - @Override - public float getExplosionResistance() { - return Blocks.BEDROCK.getExplosionResistance(); - } - - @Override - public boolean dropFromExplosion(Explosion explosion) { - return false; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.is(this)) { - EndBlockProperties.PedestalState currentState = state.getValue(EndBlockProperties.PEDESTAL_STATE); - if (currentState.equals(EndBlockProperties.PedestalState.BOTTOM) || currentState.equals(EndBlockProperties.PedestalState.PILLAR)) { - return Lists.newArrayList(); - } - } - List drop = Lists.newArrayList(); - BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); - if (blockEntity instanceof EternalPedestalEntity) { - EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity; - if (!pedestal.isEmpty()) { - drop.add(pedestal.getItem(0)); - } - } - return drop; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - super.createBlockStateDefinition(stateManager); - stateManager.add(ACTIVATED); - } - - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new EternalPedestalEntity(blockPos, blockState); - } - - @Override - public boolean hasUniqueEntity() { - return true; - } -} diff --git a/src/main/java/ru/betterend/blocks/FilaluxBlock.java b/src/main/java/ru/betterend/blocks/FilaluxBlock.java deleted file mode 100644 index e977f40e..00000000 --- a/src/main/java/ru/betterend/blocks/FilaluxBlock.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.world.level.block.state.BlockBehaviour; -import ru.bclib.blocks.BaseVineBlock; - -public class FilaluxBlock extends BaseVineBlock { - public FilaluxBlock() { - super(15, true, p->p.offsetType(BlockBehaviour.OffsetType.NONE)); - } -} diff --git a/src/main/java/ru/betterend/blocks/FilaluxLanternBlock.java b/src/main/java/ru/betterend/blocks/FilaluxLanternBlock.java deleted file mode 100644 index 60bfca4a..00000000 --- a/src/main/java/ru/betterend/blocks/FilaluxLanternBlock.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.tools.AddMineableAxe; - -public class FilaluxLanternBlock extends BaseBlock implements AddMineableAxe { - public FilaluxLanternBlock() { - super(FabricBlockSettings.of(Material.WOOD) - .luminance(15) - .sound(SoundType.WOOD)); - } -} diff --git a/src/main/java/ru/betterend/blocks/FilaluxWingsBlock.java b/src/main/java/ru/betterend/blocks/FilaluxWingsBlock.java deleted file mode 100644 index 8544dff8..00000000 --- a/src/main/java/ru/betterend/blocks/FilaluxWingsBlock.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineableShears; - -import java.util.EnumMap; - -public class FilaluxWingsBlock extends BaseAttachedBlock implements RenderLayerProvider, AddMineableShears { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - - public FilaluxWingsBlock() { - super(FabricBlockSettings.of(Material.PLANT) - .sound(SoundType.WET_GRASS) - .noCollission()); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.0, 0.0, 0.0, 1.0, 0.5, 1.0)); - BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.0, 0.5, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); - } -} diff --git a/src/main/java/ru/betterend/blocks/FlamaeaBlock.java b/src/main/java/ru/betterend/blocks/FlamaeaBlock.java deleted file mode 100644 index 188f3904..00000000 --- a/src/main/java/ru/betterend/blocks/FlamaeaBlock.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.PlaceOnWaterBlockItem; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.interfaces.CustomItemProvider; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.betterend.blocks.basis.EndPlantBlock; - -import java.util.List; - -public class FlamaeaBlock extends EndPlantBlock implements CustomItemProvider, AddMineableShears { - private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 1, 16); - - public FlamaeaBlock() { - //TODO: 1.19 Test if we can remove dynamic shape and offsetType - super(FabricBlockSettings.of(Material.PLANT) - .sound(SoundType.WET_GRASS) - .dynamicShape() - .offsetType( BlockBehaviour.OffsetType.NONE)); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(Blocks.WATER); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return Lists.newArrayList(new ItemStack(this)); - } - - @Override - public boolean canBePotted() { - return false; - } - - @Override - public BlockItem getCustomItem(ResourceLocation resourceLocation, FabricItemSettings fabricItemSettings) { - return new PlaceOnWaterBlockItem(this, fabricItemSettings); - } -} diff --git a/src/main/java/ru/betterend/blocks/FlammalixBlock.java b/src/main/java/ru/betterend/blocks/FlammalixBlock.java deleted file mode 100644 index 400a3048..00000000 --- a/src/main/java/ru/betterend/blocks/FlammalixBlock.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.client.models.ModelsHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class FlammalixBlock extends EndPlantBlock { - private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14); - - public FlammalixBlock() { - super(false, 12, p->p.offsetType(OffsetType.NONE)); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.PALLIDIUM_FULL) || - state.is(EndBlocks.PALLIDIUM_HEAVY) || - state.is(EndBlocks.PALLIDIUM_THIN) || - state.is(EndBlocks.PALLIDIUM_TINY); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - return ModelsHelper.createItemModel(resourceLocation); - } -} diff --git a/src/main/java/ru/betterend/blocks/FlowerPotBlock.java b/src/main/java/ru/betterend/blocks/FlowerPotBlock.java deleted file mode 100644 index 56aa5e36..00000000 --- a/src/main/java/ru/betterend/blocks/FlowerPotBlock.java +++ /dev/null @@ -1,447 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.math.Transformation; -import com.mojang.math.Vector3f; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SaplingBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.storage.loot.LootContext.Builder; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.client.models.BasePatterns; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.client.models.ModelsHelper.MultiPartBuilder; -import ru.bclib.client.models.PatternsHelper; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.PostInitable; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.JsonFactory; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.basis.PottableLeavesBlock; -import ru.betterend.client.models.Patterns; -import ru.betterend.config.Configs; -import ru.betterend.interfaces.PottablePlant; -import ru.betterend.interfaces.PottableTerrain; -import ru.betterend.registry.EndBlocks; - -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public class FlowerPotBlock extends BaseBlockNotFull implements RenderLayerProvider, PostInitable { - private static final IntegerProperty PLANT_ID = EndBlockProperties.PLANT_ID; - private static final IntegerProperty SOIL_ID = EndBlockProperties.SOIL_ID; - private static final IntegerProperty POT_LIGHT = EndBlockProperties.POT_LIGHT; - private static final VoxelShape SHAPE_EMPTY; - private static final VoxelShape SHAPE_FULL; - private static Block[] plants; - private static Block[] soils; - - public FlowerPotBlock(Block source) { - super(FabricBlockSettings.copyOf(source).luminance(state -> state.getValue(POT_LIGHT) * 5)); - this.registerDefaultState( - this.defaultBlockState() - .setValue(PLANT_ID, 0) - .setValue(SOIL_ID, 0) - .setValue(POT_LIGHT, 0) - ); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder); - builder.add(PLANT_ID, SOIL_ID, POT_LIGHT); - } - - @Override - public List getDrops(BlockState state, Builder builder) { - List drop = Lists.newArrayList(new ItemStack(this)); - int id = state.getValue(SOIL_ID) - 1; - if (id >= 0 && id < soils.length && soils[id] != null) { - drop.add(new ItemStack(soils[id])); - } - id = state.getValue(PLANT_ID) - 1; - if (id >= 0 && id < plants.length && plants[id] != null) { - drop.add(new ItemStack(plants[id])); - } - return drop; - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - int plantID = state.getValue(PLANT_ID); - if (plantID < 1 || plantID > plants.length || plants[plantID - 1] == null) { - return state.getValue(POT_LIGHT) > 0 ? state.setValue(POT_LIGHT, 0) : state; - } - int light = plants[plantID - 1].defaultBlockState().getLightEmission() / 5; - if (state.getValue(POT_LIGHT) != light) { - state = state.setValue(POT_LIGHT, light); - } - return state; - } - - @Override - public void postInit() { - if (FlowerPotBlock.plants != null) { - return; - } - - Block[] plants = new Block[128]; - Block[] soils = new Block[16]; - - Map reservedPlantsIDs = Maps.newHashMap(); - Map reservedSoilIDs = Maps.newHashMap(); - - JsonObject obj = JsonFactory.getJsonObject(new File( - FabricLoader.getInstance().getConfigDir().toFile(), - BetterEnd.MOD_ID + "/blocks.json" - )); - if (obj.get("flower_pots") != null) { - JsonElement plantsObj = obj.get("flower_pots").getAsJsonObject().get("plants"); - JsonElement soilsObj = obj.get("flower_pots").getAsJsonObject().get("soils"); - if (plantsObj != null) { - plantsObj.getAsJsonObject().entrySet().forEach(entry -> { - String name = entry.getKey().substring(0, entry.getKey().indexOf(' ')); - reservedPlantsIDs.put(name, entry.getValue().getAsInt()); - }); - } - if (soilsObj != null) { - soilsObj.getAsJsonObject().entrySet().forEach(entry -> { - String name = entry.getKey().substring(0, entry.getKey().indexOf(' ')); - reservedSoilIDs.put(name, entry.getValue().getAsInt()); - }); - } - } - - EndBlocks.getModBlocks().forEach(block -> { - if (block instanceof PottablePlant && ((PottablePlant) block).canBePotted()) { - processBlock(plants, block, "flower_pots.plants", reservedPlantsIDs); - } - else if (block instanceof PottableTerrain && ((PottableTerrain) block).canBePotted()) { - processBlock(soils, block, "flower_pots.soils", reservedSoilIDs); - } - }); - Configs.BLOCK_CONFIG.saveChanges(); - - FlowerPotBlock.plants = new Block[maxNotNull(plants) + 1]; - System.arraycopy(plants, 0, FlowerPotBlock.plants, 0, FlowerPotBlock.plants.length); - - FlowerPotBlock.soils = new Block[maxNotNull(soils) + 1]; - System.arraycopy(soils, 0, FlowerPotBlock.soils, 0, FlowerPotBlock.soils.length); - - if (PLANT_ID.getValue(Integer.toString(FlowerPotBlock.plants.length)).isEmpty()) { - throw new RuntimeException("There are too much plant ID values!"); - } - if (SOIL_ID.getValue(Integer.toString(FlowerPotBlock.soils.length)).isEmpty()) { - throw new RuntimeException("There are too much soil ID values!"); - } - } - - private int maxNotNull(Block[] array) { - int max = 0; - for (int i = 0; i < array.length; i++) { - if (array[i] != null) { - max = i; - } - } - return max; - } - - private void processBlock(Block[] target, Block block, String path, Map idMap) { - ResourceLocation location = Registry.BLOCK.getKey(block); - if (idMap.containsKey(location.getPath())) { - target[idMap.get(location.getPath())] = block; - } - else { - for (int i = 0; i < target.length; i++) { - if (!idMap.values().contains(i)) { - target[i] = block; - idMap.put(location.getPath(), i); - Configs.BLOCK_CONFIG.getInt(path, location.getPath(), i); - break; - } - } - } - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.isClientSide) { - return InteractionResult.CONSUME; - } - ItemStack itemStack = player.getItemInHand(hand); - int soilID = state.getValue(SOIL_ID); - if (soilID == 0 || soilID > soils.length || soils[soilID - 1] == null) { - if (!(itemStack.getItem() instanceof BlockItem)) { - return InteractionResult.PASS; - } - Block block = ((BlockItem) itemStack.getItem()).getBlock(); - for (int i = 0; i < soils.length; i++) { - if (block == soils[i]) { - BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, i + 1)); - if (!player.isCreative()) { - itemStack.shrink(1); - } - level.playSound( - player, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - SoundEvents.SOUL_SOIL_PLACE, - SoundSource.BLOCKS, - 1, - 1 - ); - return InteractionResult.SUCCESS; - } - } - return InteractionResult.PASS; - } - - int plantID = state.getValue(PLANT_ID); - if (itemStack.isEmpty()) { - if (plantID > 0 && plantID <= plants.length && plants[plantID - 1] != null) { - BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, 0).setValue(POT_LIGHT, 0)); - player.addItem(new ItemStack(plants[plantID - 1])); - return InteractionResult.SUCCESS; - } - if (soilID > 0 && soilID <= soils.length && soils[soilID - 1] != null) { - BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, 0)); - player.addItem(new ItemStack(soils[soilID - 1])); - } - return InteractionResult.PASS; - } - if (!(itemStack.getItem() instanceof BlockItem)) { - return InteractionResult.PASS; - } - BlockItem item = (BlockItem) itemStack.getItem(); - for (int i = 0; i < plants.length; i++) { - if (item.getBlock() == plants[i]) { - if (!((PottablePlant) plants[i]).canPlantOn(soils[soilID - 1])) { - return InteractionResult.PASS; - } - int light = plants[i].defaultBlockState().getLightEmission() / 5; - BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, i + 1).setValue(POT_LIGHT, light)); - level.playSound( - player, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - SoundEvents.HOE_TILL, - SoundSource.BLOCKS, - 1, - 1 - ); - if (!player.isCreative()) { - itemStack.shrink(1); - } - return InteractionResult.SUCCESS; - } - } - return InteractionResult.PASS; - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation blockId) { - Optional pattern = PatternsHelper.createJson(Patterns.BLOCK_FLOWER_POT, blockId); - return ModelsHelper.fromPattern(pattern); - } - - @Override - @Environment(EnvType.CLIENT) - public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map modelCache) { - MultiPartBuilder model = MultiPartBuilder.create(stateDefinition); - model.part(new ModelResourceLocation(stateId.getNamespace(), stateId.getPath(), "inventory")).add(); - Transformation offset = new Transformation(new Vector3f(0, 7.5F / 16F, 0), null, null, null); - - for (int i = 0; i < plants.length; i++) { - if (plants[i] == null) { - continue; - } - - final int compareID = i + 1; - ResourceLocation modelPath = Registry.BLOCK.getKey(plants[i]); - ResourceLocation objSource = new ResourceLocation( - modelPath.getNamespace(), - "models/block/" + modelPath.getPath() + "_potted.json" - ); - - if (Minecraft.getInstance().getResourceManager().getResource(objSource).isPresent()) { - objSource = new ResourceLocation(modelPath.getNamespace(), "block/" + modelPath.getPath() + "_potted"); - model.part(objSource) - .setTransformation(offset) - .setCondition(state -> state.getValue(PLANT_ID) == compareID) - .add(); - continue; - } - - else if (plants[i] instanceof SaplingBlock) { - ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); - modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); - Map textures = Maps.newHashMap(); - textures.put("%modid%", loc.getNamespace()); - textures.put("%texture%", loc.getPath()); - Optional pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures); - UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); - modelCache.put(modelPath, unbakedModel); - model.part(modelPath) - .setTransformation(offset) - .setCondition(state -> state.getValue(PLANT_ID) == compareID) - .add(); - continue; - } - else if (plants[i] instanceof PottableLeavesBlock) { - ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); - modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); - Map textures = Maps.newHashMap(); - textures.put("%leaves%", loc.getPath().contains("lucernia") ? loc.getPath() + "_1" : loc.getPath()); - textures.put("%stem%", loc.getPath().replace("_leaves", "_log_side")); - Optional pattern = Patterns.createJson(Patterns.BLOCK_POTTED_LEAVES, textures); - UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); - modelCache.put(modelPath, unbakedModel); - model.part(modelPath) - .setTransformation(offset) - .setCondition(state -> state.getValue(PLANT_ID) == compareID) - .add(); - continue; - } - - objSource = new ResourceLocation(modelPath.getNamespace(), "blockstates/" + modelPath.getPath() + ".json"); - JsonObject obj = JsonFactory.getJsonObject(objSource); - if (obj != null) { - JsonElement variants = obj.get("variants"); - JsonElement list = null; - String path = null; - - if (variants == null) { - continue; - } - - if (variants.isJsonArray()) { - list = variants.getAsJsonArray().get(0); - } - else if (variants.isJsonObject()) { - list = variants.getAsJsonObject().get(((PottablePlant) plants[i]).getPottedState()); - } - - if (list == null) { - BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants"); - continue; - } - - if (list.isJsonArray()) { - path = list.getAsJsonArray().get(0).getAsJsonObject().get("model").getAsString(); - } - else { - path = list.getAsJsonObject().get("model").getAsString(); - } - - if (path == null) { - BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants"); - continue; - } - - model.part(new ResourceLocation(path)) - .setTransformation(offset) - .setCondition(state -> state.getValue(PLANT_ID) == compareID) - .add(); - } - else { - ResourceLocation loc = Registry.BLOCK.getKey(plants[i]); - modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted"); - Map textures = Maps.newHashMap(); - textures.put("%modid%", loc.getNamespace()); - textures.put("%texture%", loc.getPath()); - Optional pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures); - UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern); - modelCache.put(modelPath, unbakedModel); - model.part(modelPath) - .setTransformation(offset) - .setCondition(state -> state.getValue(PLANT_ID) == compareID) - .add(); - } - } - - for (int i = 0; i < soils.length; i++) { - if (soils[i] == null) { - continue; - } - - ResourceLocation soilLoc = BetterEnd.makeID("flower_pot_soil_" + i); - if (!modelCache.containsKey(soilLoc)) { - String texture = Registry.BLOCK.getKey(soils[i]).getPath() + "_top"; - if (texture.contains("rutiscus")) { - texture += "_1"; - } - Optional pattern = Patterns.createJson(Patterns.BLOCK_FLOWER_POT_SOIL, texture); - UnbakedModel soil = ModelsHelper.fromPattern(pattern); - modelCache.put(soilLoc, soil); - } - final int compareID = i + 1; - model.part(soilLoc).setCondition(state -> state.getValue(SOIL_ID) == compareID).add(); - } - - UnbakedModel result = model.build(); - modelCache.put(stateId, result); - return result; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - int id = state.getValue(PLANT_ID); - return id > 0 && id <= plants.length ? SHAPE_FULL : SHAPE_EMPTY; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE_EMPTY; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - static { - SHAPE_EMPTY = Shapes.or(Block.box(4, 1, 4, 12, 8, 12), Block.box(5, 0, 5, 11, 1, 11)); - SHAPE_FULL = Shapes.or(SHAPE_EMPTY, Block.box(3, 8, 3, 13, 16, 13)); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/blocks/GlowingHymenophoreBlock.java b/src/main/java/ru/betterend/blocks/GlowingHymenophoreBlock.java deleted file mode 100644 index 0ca65ca7..00000000 --- a/src/main/java/ru/betterend/blocks/GlowingHymenophoreBlock.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.tools.AddMineableAxe; - -public class GlowingHymenophoreBlock extends BaseBlock implements AddMineableAxe { - public GlowingHymenophoreBlock() { - super(FabricBlockSettings.of(Material.WOOD) - .luminance(15) - .sound(SoundType.WART_BLOCK)); - } -} diff --git a/src/main/java/ru/betterend/blocks/GlowingMossBlock.java b/src/main/java/ru/betterend/blocks/GlowingMossBlock.java deleted file mode 100644 index 5b065c01..00000000 --- a/src/main/java/ru/betterend/blocks/GlowingMossBlock.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class GlowingMossBlock extends EndPlantBlock { - public GlowingMossBlock(int light) { - super(light); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.getBlock() == EndBlocks.END_MOSS || state.getBlock() == EndBlocks.END_MYCELIUM; - } - - @Environment(EnvType.CLIENT) - public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { - return true; - } - - @Environment(EnvType.CLIENT) - public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { - return 1F; - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/blocks/GlowingPillarLuminophorBlock.java b/src/main/java/ru/betterend/blocks/GlowingPillarLuminophorBlock.java deleted file mode 100644 index 70d1e000..00000000 --- a/src/main/java/ru/betterend/blocks/GlowingPillarLuminophorBlock.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.betterend.registry.EndBlocks; - -public class GlowingPillarLuminophorBlock extends BaseBlock implements AddMineableShears { - public static final BooleanProperty NATURAL = EndBlockProperties.NATURAL; - - public GlowingPillarLuminophorBlock() { - super(FabricBlockSettings.of(Material.LEAVES) - .mapColor(MaterialColor.COLOR_ORANGE) - .strength(0.2F) - .luminance(15) - .sound(SoundType.GRASS)); - this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false)); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return !state.getValue(NATURAL) || world.getBlockState(pos.below()).is(EndBlocks.GLOWING_PILLAR_ROOTS); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return Blocks.AIR.defaultBlockState(); - } - else { - return state; - } - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(NATURAL); - } -} diff --git a/src/main/java/ru/betterend/blocks/GlowingPillarRootsBlock.java b/src/main/java/ru/betterend/blocks/GlowingPillarRootsBlock.java deleted file mode 100644 index fe1f49ef..00000000 --- a/src/main/java/ru/betterend/blocks/GlowingPillarRootsBlock.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.blocks.UpDownPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class GlowingPillarRootsBlock extends UpDownPlantBlock { - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.AMBER_MOSS); - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - return new ItemStack(EndBlocks.GLOWING_PILLAR_SEED); - } -} diff --git a/src/main/java/ru/betterend/blocks/GlowingPillarSeedBlock.java b/src/main/java/ru/betterend/blocks/GlowingPillarSeedBlock.java deleted file mode 100644 index 1eebf853..00000000 --- a/src/main/java/ru/betterend/blocks/GlowingPillarSeedBlock.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class GlowingPillarSeedBlock extends EndPlantWithAgeBlock implements AddMineableShears { - - public GlowingPillarSeedBlock() { - super(FabricBlockSettings.of(Material.PLANT) - .sound(SoundType.GRASS) - .lightLevel(state -> state.getValue(AGE) * 3 + 3) - .randomTicks() - .noCollission() - .offsetType(OffsetType.NONE)); - } - - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - int height = MHelper.randRange(1, 2, random); - int h = BlocksHelper.upRay(world, pos, height + 2); - if (h < height) { - return; - } - - MutableBlockPos mut = new MutableBlockPos().set(pos); - BlockState roots = EndBlocks.GLOWING_PILLAR_ROOTS.defaultBlockState(); - if (height < 2) { - BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE)); - } - else { - BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM)); - mut.move(Direction.UP); - BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP)); - } - mut.move(Direction.UP); - BlocksHelper.setWithUpdate( - world, - mut, - EndBlocks.GLOWING_PILLAR_LUMINOPHOR.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true) - ); - for (Direction dir : BlocksHelper.DIRECTIONS) { - pos = mut.relative(dir); - if (world.isEmptyBlock(pos)) { - BlocksHelper.setWithUpdate( - world, - pos, - EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState().setValue(BlockStateProperties.FACING, dir) - ); - } - } - mut.move(Direction.UP); - if (world.isEmptyBlock(mut)) { - BlocksHelper.setWithUpdate( - world, - mut, - EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState().setValue(BlockStateProperties.FACING, Direction.UP) - ); - } - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.AMBER_MOSS); - } -} diff --git a/src/main/java/ru/betterend/blocks/HelixTreeLeavesBlock.java b/src/main/java/ru/betterend/blocks/HelixTreeLeavesBlock.java deleted file mode 100644 index bb6f3946..00000000 --- a/src/main/java/ru/betterend/blocks/HelixTreeLeavesBlock.java +++ /dev/null @@ -1,82 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.api.tag.NamedBlockTags; -import ru.bclib.api.tag.TagAPI; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BaseLeavesBlock; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class HelixTreeLeavesBlock extends BaseBlock implements CustomColorProvider, AddMineableShears { - public static final IntegerProperty COLOR = EndBlockProperties.COLOR; - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); - - public HelixTreeLeavesBlock() { - super(FabricBlockSettings - .of(Material.LEAVES) - .mapColor(MaterialColor.COLOR_ORANGE) - .sound(SoundType.WART_BLOCK) - .sound(SoundType.GRASS) - .strength(0.2F) - ); - - TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(COLOR); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> { - return ColorUtil.color(237, getGreen(state.getValue(COLOR)), 20); - }; - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> { - return ColorUtil.color(237, getGreen(4), 20); - }; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - double px = ctx.getClickedPos().getX() * 0.1; - double py = ctx.getClickedPos().getY() * 0.1; - double pz = ctx.getClickedPos().getZ() * 0.1; - return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); - } - - private int getGreen(int color) { - float delta = color / 7F; - return (int) Mth.lerp(delta, 80, 158); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return BaseLeavesBlock.getLeaveDrops(this, EndBlocks.HELIX_TREE_SAPLING, builder, 16, 32); - } -} diff --git a/src/main/java/ru/betterend/blocks/HelixTreeSaplingBlock.java b/src/main/java/ru/betterend/blocks/HelixTreeSaplingBlock.java deleted file mode 100644 index 4fea40b2..00000000 --- a/src/main/java/ru/betterend/blocks/HelixTreeSaplingBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class HelixTreeSaplingBlock extends PottableFeatureSapling { - public HelixTreeSaplingBlock() { - super((state)->EndFeatures.HELIX_TREE.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.AMBER_MOSS; - } -} diff --git a/src/main/java/ru/betterend/blocks/HydraluxBlock.java b/src/main/java/ru/betterend/blocks/HydraluxBlock.java deleted file mode 100644 index e8c14681..00000000 --- a/src/main/java/ru/betterend/blocks/HydraluxBlock.java +++ /dev/null @@ -1,98 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.UnderwaterPlantBlock; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.EndBlockProperties.HydraluxShape; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class HydraluxBlock extends UnderwaterPlantBlock implements AddMineableShears { - - public static final EnumProperty SHAPE = EndBlockProperties.HYDRALUX_SHAPE; - - public HydraluxBlock() { - super(FabricBlockSettings.of(Material.WATER_PLANT) - .sound(SoundType.WET_GRASS) - .lightLevel((state) -> state.getValue(SHAPE).hasGlow() ? 15 : 0) - .noCollission()); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState down = world.getBlockState(pos.below()); - HydraluxShape shape = state.getValue(SHAPE); - if (shape == HydraluxShape.FLOWER_BIG_TOP || shape == HydraluxShape.FLOWER_SMALL_TOP) { - return down.is(this); - } - else if (shape == HydraluxShape.ROOTS) { - return down.is(EndBlocks.SULPHURIC_ROCK.stone) && world.getBlockState(pos.above()).is(this); - } - else { - return down.is(this) && world.getBlockState(pos.above()).is(this); - } - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - return new ItemStack(EndBlocks.HYDRALUX_SAPLING); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - HydraluxShape shape = state.getValue(SHAPE); - if (shape == HydraluxShape.FLOWER_BIG_BOTTOM || shape == HydraluxShape.FLOWER_SMALL_BOTTOM) { - return Lists.newArrayList(new ItemStack(EndItems.HYDRALUX_PETAL, MHelper.randRange(1, 4, MHelper.RANDOM_SOURCE))); - } - else if (shape == HydraluxShape.ROOTS) { - return Lists.newArrayList(new ItemStack( - EndBlocks.HYDRALUX_SAPLING, - MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE) - )); - } - return Collections.emptyList(); - } -} diff --git a/src/main/java/ru/betterend/blocks/HydraluxPetalBlock.java b/src/main/java/ru/betterend/blocks/HydraluxPetalBlock.java deleted file mode 100644 index e2a21dfd..00000000 --- a/src/main/java/ru/betterend/blocks/HydraluxPetalBlock.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.tools.AddMineableAxe; - -public class HydraluxPetalBlock extends BaseBlock implements AddMineableAxe { - public HydraluxPetalBlock() { - this( - FabricBlockSettings - .of(Material.PLANT) - .hardness(1) - .resistance(1) - .mapColor(MaterialColor.PODZOL) - .sound(SoundType.WART_BLOCK) - ); - } - - public HydraluxPetalBlock(Properties settings) { - super(settings); - } - - @Override - public void fallOn(Level level, BlockState blockState, BlockPos blockPos, Entity entity, float f) { - } -} diff --git a/src/main/java/ru/betterend/blocks/HydraluxPetalColoredBlock.java b/src/main/java/ru/betterend/blocks/HydraluxPetalColoredBlock.java deleted file mode 100644 index 7e7236a4..00000000 --- a/src/main/java/ru/betterend/blocks/HydraluxPetalColoredBlock.java +++ /dev/null @@ -1,41 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Nullable; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.util.BlocksHelper; -import ru.betterend.client.models.Patterns; - -import java.util.Optional; - -public class HydraluxPetalColoredBlock extends HydraluxPetalBlock implements CustomColorProvider { - public HydraluxPetalColoredBlock(FabricBlockSettings settings) { - super(settings); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> BlocksHelper.getBlockColor(this); - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> BlocksHelper.getBlockColor(this); - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - String path = "betterend:block/block_petal_colored"; - Optional pattern = Patterns.createJson(Patterns.BLOCK_PETAL_COLORED, path, path); - return ModelsHelper.fromPattern(pattern); - } -} diff --git a/src/main/java/ru/betterend/blocks/HydraluxSaplingBlock.java b/src/main/java/ru/betterend/blocks/HydraluxSaplingBlock.java deleted file mode 100644 index ee32bd52..00000000 --- a/src/main/java/ru/betterend/blocks/HydraluxSaplingBlock.java +++ /dev/null @@ -1,73 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.UnderwaterPlantWithAgeBlock; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.EndBlockProperties.HydraluxShape; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class HydraluxSaplingBlock extends UnderwaterPlantWithAgeBlock { - - @Override - public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) { - int h = MHelper.randRange(4, 8, random); - MutableBlockPos mut = new MutableBlockPos().set(pos); - - for (int i = 1; i < h; i++) { - mut.setY(pos.getY() + i); - if (!world.getBlockState(mut).is(Blocks.WATER)) { - return; - } - } - - mut.setY(pos.getY()); - BlockState state = EndBlocks.HYDRALUX.defaultBlockState(); - BlocksHelper.setWithoutUpdate( - world, - pos, - state.setValue(EndBlockProperties.HYDRALUX_SHAPE, HydraluxShape.ROOTS) - ); - for (int i = 1; i < h - 2; i++) { - mut.setY(pos.getY() + i); - BlocksHelper.setWithoutUpdate( - world, - mut, - state.setValue(EndBlockProperties.HYDRALUX_SHAPE, HydraluxShape.VINE) - ); - } - - mut.setY(mut.getY() + 1); - boolean big = random.nextBoolean(); - BlocksHelper.setWithoutUpdate( - world, - mut, - state.setValue( - EndBlockProperties.HYDRALUX_SHAPE, - big ? HydraluxShape.FLOWER_BIG_BOTTOM : HydraluxShape.FLOWER_SMALL_BOTTOM - ) - ); - - mut.setY(mut.getY() + 1); - BlocksHelper.setWithoutUpdate( - world, - mut, - state.setValue( - EndBlockProperties.HYDRALUX_SHAPE, - big ? HydraluxShape.FLOWER_BIG_TOP : HydraluxShape.FLOWER_SMALL_TOP - ) - ); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.SULPHURIC_ROCK.stone); - } -} diff --git a/src/main/java/ru/betterend/blocks/HydrothermalVentBlock.java b/src/main/java/ru/betterend/blocks/HydrothermalVentBlock.java deleted file mode 100644 index 762c23a4..00000000 --- a/src/main/java/ru/betterend/blocks/HydrothermalVentBlock.java +++ /dev/null @@ -1,149 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.SoundType; -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.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -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.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.interfaces.tools.AddMineablePickaxe; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.entities.BlockEntityHydrothermalVent; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@SuppressWarnings("deprecation") -public class HydrothermalVentBlock extends BaseBlockNotFull implements EntityBlock, LiquidBlockContainer, SimpleWaterloggedBlock, AddMineablePickaxe { - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; - private static final VoxelShape SHAPE = Block.box(1, 1, 1, 15, 16, 15); - - public HydrothermalVentBlock() { - super(FabricBlockSettings.of(Material.STONE) - .sound(SoundType.STONE) - .noCollission() - .requiresCorrectToolForDrops()); - this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, true).setValue(ACTIVATED, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(WATERLOGGED, ACTIVATED); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { - return false; - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { - return false; - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - state = world.getBlockState(pos.below()); - return state.is(EndBlocks.SULPHURIC_ROCK.stone); - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return Blocks.WATER.defaultBlockState(); - } - else if (state.getValue(WATERLOGGED) && facing == Direction.UP && neighborState.is(Blocks.WATER)) { - world.scheduleTick(pos, this, 20); - } - return state; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - LevelAccessor worldAccess = ctx.getLevel(); - BlockPos blockPos = ctx.getClickedPos(); - return this.defaultBlockState() - .setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER); - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } - - @Override - public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new BlockEntityHydrothermalVent(pos, state); - } - - @Override - public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - BlockPos up = pos.above(); - if (world.getBlockState(up).is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate(world, up, EndBlocks.VENT_BUBBLE_COLUMN); - world.scheduleTick(up, EndBlocks.VENT_BUBBLE_COLUMN, 5); - } - } - - @Override - public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { - if (world instanceof ServerLevel && state.getValue(WATERLOGGED) && world.getBlockState(pos.above()) - .is(Blocks.WATER)) { - tick(state, (ServerLevel) world, pos, world.random); - } - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - super.animateTick(state, world, pos, random); - if (!state.getValue(ACTIVATED) && random.nextBoolean()) { - double x = pos.getX() + random.nextDouble(); - double y = pos.getY() + 0.9 + random.nextDouble() * 0.3; - double z = pos.getZ() + random.nextDouble(); - world.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, 0, 0, 0); - } - } - - @Nullable - @Override - public BlockEntityTicker getTicker(Level level, BlockState blockState, BlockEntityType blockEntityType) { - return BlockEntityHydrothermalVent::tick; - } -} diff --git a/src/main/java/ru/betterend/blocks/InfusionPedestal.java b/src/main/java/ru/betterend/blocks/InfusionPedestal.java deleted file mode 100644 index bc802776..00000000 --- a/src/main/java/ru/betterend/blocks/InfusionPedestal.java +++ /dev/null @@ -1,98 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -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.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.blocks.entities.InfusionPedestalEntity; -import ru.betterend.rituals.InfusionRitual; - -@SuppressWarnings("deprecation") -public class InfusionPedestal extends PedestalBlock { - private static final VoxelShape SHAPE_DEFAULT; - private static final VoxelShape SHAPE_PEDESTAL_TOP; - - public InfusionPedestal() { - super(Blocks.OBSIDIAN); - this.height = 1.08F; - } - - @Override - public void checkRitual(Level world, BlockPos pos) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof InfusionPedestalEntity) { - InfusionPedestalEntity pedestal = (InfusionPedestalEntity) blockEntity; - if (pedestal.hasRitual()) { - InfusionRitual ritual = pedestal.getRitual(); - if (!ritual.isValid()) { - ritual.configure(); - } - pedestal.getRitual().checkRecipe(); - } - else { - InfusionRitual ritual = new InfusionRitual(pedestal, world, pos); - pedestal.linkRitual(ritual); - ritual.checkRecipe(); - } - } - } - - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new InfusionPedestalEntity(blockPos, blockState); - } - - @Override - public boolean hasUniqueEntity() { - return true; - } - - @Override - @Deprecated - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { - if (state.is(this)) { - switch (state.getValue(STATE)) { - case PEDESTAL_TOP: { - return SHAPE_PEDESTAL_TOP; - } - case DEFAULT: { - return SHAPE_DEFAULT; - } - default: { - return super.getShape(state, world, pos, context); - } - } - } - return super.getShape(state, world, pos, context); - } - - @Override - @Nullable - public BlockEntityTicker getTicker(Level level, BlockState blockState, BlockEntityType blockEntityType) { - return InfusionPedestalEntity::tickEnity; - } - - static { - VoxelShape basinUp = Block.box(2, 3, 2, 14, 4, 14); - VoxelShape basinDown = Block.box(0, 0, 0, 16, 3, 16); - VoxelShape pedestalTop = Block.box(1, 9, 1, 15, 11, 15); - VoxelShape pedestalDefault = Block.box(1, 13, 1, 15, 15, 15); - VoxelShape pillar = Block.box(3, 0, 3, 13, 9, 13); - VoxelShape pillarDefault = Block.box(3, 4, 3, 13, 13, 13); - VoxelShape eyeDefault = Block.box(4, 15, 4, 12, 16, 12); - VoxelShape eyeTop = Block.box(4, 11, 4, 12, 12, 12); - VoxelShape basin = Shapes.or(basinDown, basinUp); - SHAPE_DEFAULT = Shapes.or(basin, pillarDefault, pedestalDefault, eyeDefault); - SHAPE_PEDESTAL_TOP = Shapes.or(pillar, pedestalTop, eyeTop); - } -} diff --git a/src/main/java/ru/betterend/blocks/JellyshroomCapBlock.java b/src/main/java/ru/betterend/blocks/JellyshroomCapBlock.java deleted file mode 100644 index 44f5e696..00000000 --- a/src/main/java/ru/betterend/blocks/JellyshroomCapBlock.java +++ /dev/null @@ -1,104 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.Vec3i; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SlimeBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import org.jetbrains.annotations.Nullable; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.BlockModelProvider; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.client.models.Patterns; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.List; -import java.util.Optional; - -public class JellyshroomCapBlock extends SlimeBlock implements RenderLayerProvider, BlockModelProvider, CustomColorProvider { - public static final IntegerProperty COLOR = EndBlockProperties.COLOR; - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); - private final Vec3i colorStart; - private final Vec3i colorEnd; - private final int coloritem; - - public JellyshroomCapBlock(int r1, int g1, int b1, int r2, int g2, int b2) { - super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK)); - colorStart = new Vec3i(r1, g1, b1); - colorEnd = new Vec3i(r2, g2, b2); - coloritem = ColorUtil.color((r1 + r2) >> 1, (g1 + g2) >> 1, (b1 + b2) >> 1); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - double px = ctx.getClickedPos().getX() * 0.1; - double py = ctx.getClickedPos().getY() * 0.1; - double pz = ctx.getClickedPos().getZ() * 0.1; - return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(COLOR); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) { - return Lists.newArrayList(new ItemStack(this)); - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - return getBlockModel(resourceLocation, defaultBlockState()); - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - Optional pattern = Patterns.createJson(Patterns.BLOCK_COLORED, "jellyshroom_cap"); - return ModelsHelper.fromPattern(pattern); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> { - float delta = (float) state.getValue(COLOR) / 7F; - int r = Mth.floor(Mth.lerp(delta, colorStart.getX() / 255F, colorEnd.getX() / 255F) * 255F); - int g = Mth.floor(Mth.lerp(delta, colorStart.getY() / 255F, colorEnd.getY() / 255F) * 255F); - int b = Mth.floor(Mth.lerp(delta, colorStart.getZ() / 255F, colorEnd.getZ() / 255F) * 255F); - return ColorUtil.color(r, g, b); - }; - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> { - return coloritem; - }; - } -} diff --git a/src/main/java/ru/betterend/blocks/LacugroveSaplingBlock.java b/src/main/java/ru/betterend/blocks/LacugroveSaplingBlock.java deleted file mode 100644 index ebb1e3b5..00000000 --- a/src/main/java/ru/betterend/blocks/LacugroveSaplingBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class LacugroveSaplingBlock extends PottableFeatureSapling { - public LacugroveSaplingBlock() { - super((state)->EndFeatures.LACUGROVE.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below()) - .is(EndBlocks.ENDSTONE_DUST); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.END_MOSS; - } -} diff --git a/src/main/java/ru/betterend/blocks/LanceleafBlock.java b/src/main/java/ru/betterend/blocks/LanceleafBlock.java deleted file mode 100644 index eeab0ae4..00000000 --- a/src/main/java/ru/betterend/blocks/LanceleafBlock.java +++ /dev/null @@ -1,71 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.PentaShape; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Collections; -import java.util.List; - -public class LanceleafBlock extends EndPlantBlock { - - public static final EnumProperty SHAPE = BlockProperties.PENTA_SHAPE; - public static final IntegerProperty ROTATION = BlockProperties.ROTATION; - - public LanceleafBlock() { - super(); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE, ROTATION); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - PentaShape shape = state.getValue(SHAPE); - if (shape == PentaShape.TOP) { - return world.getBlockState(pos.below()).is(this); - } - else if (shape == PentaShape.BOTTOM) { - return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS) && world.getBlockState(pos.above()) - .is(this); - } - else { - return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); - } - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return Blocks.AIR.defaultBlockState(); - } - else { - return state; - } - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.getValue(SHAPE) == PentaShape.BOTTOM) { - return Collections.singletonList(new ItemStack(EndBlocks.LANCELEAF_SEED)); - } - return MHelper.RANDOM.nextBoolean() ? Collections.emptyList() : Collections.singletonList(new ItemStack( - EndBlocks.LANCELEAF_SEED)); - } -} diff --git a/src/main/java/ru/betterend/blocks/LanceleafSeedBlock.java b/src/main/java/ru/betterend/blocks/LanceleafSeedBlock.java deleted file mode 100644 index 4714bff3..00000000 --- a/src/main/java/ru/betterend/blocks/LanceleafSeedBlock.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.PentaShape; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LanceleafSeedBlock extends EndPlantWithAgeBlock { - public LanceleafSeedBlock() { - super(p->p.offsetType(OffsetType.NONE)); - } - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - int height = MHelper.randRange(4, 6, random); - int h = BlocksHelper.upRay(world, pos, height + 2); - if (h < height + 1) { - return; - } - int rotation = random.nextInt(4); - MutableBlockPos mut = new MutableBlockPos().set(pos); - BlockState plant = EndBlocks.LANCELEAF.defaultBlockState().setValue(BlockProperties.ROTATION, rotation); - BlocksHelper.setWithoutUpdate(world, mut, plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.BOTTOM)); - BlocksHelper.setWithoutUpdate( - world, - mut.move(Direction.UP), - plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_BOTTOM) - ); - for (int i = 2; i < height - 2; i++) { - BlocksHelper.setWithoutUpdate( - world, - mut.move(Direction.UP), - plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.MIDDLE) - ); - } - BlocksHelper.setWithoutUpdate( - world, - mut.move(Direction.UP), - plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_TOP) - ); - BlocksHelper.setWithoutUpdate( - world, - mut.move(Direction.UP), - plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.TOP) - ); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.AMBER_MOSS); - } -} diff --git a/src/main/java/ru/betterend/blocks/LargeAmaranitaBlock.java b/src/main/java/ru/betterend/blocks/LargeAmaranitaBlock.java deleted file mode 100644 index 739cc7bd..00000000 --- a/src/main/java/ru/betterend/blocks/LargeAmaranitaBlock.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LargeAmaranitaBlock extends EndPlantBlock implements AddMineableShears { - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 14, 12); - private static final VoxelShape SHAPE_TOP = Shapes.or(Block.box(1, 3, 1, 15, 16, 15), SHAPE_BOTTOM); - - public LargeAmaranitaBlock() { - //TODO: 1.19 Test if we can remove dynamic shape and offsetType - super(FabricBlockSettings.of(Material.PLANT) - - .sound(SoundType.GRASS) - .lightLevel((state) -> (state.getValue(SHAPE) == TripleShape.TOP) ? 15 : 0) - .dynamicShape() - .offsetType(OffsetType.NONE)); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM; - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.SANGNUM) || state.is(EndBlocks.MOSSY_OBSIDIAN) || state.is(EndBlocks.MOSSY_DRAGON_BONE); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - TripleShape shape = state.getValue(SHAPE); - if (shape == TripleShape.BOTTOM) { - return isTerrain(world.getBlockState(pos.below())) && world.getBlockState(pos.above()).is(this); - } - else if (shape == TripleShape.TOP) { - return world.getBlockState(pos.below()).is(this); - } - else { - return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); - } - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/LucerniaSaplingBlock.java b/src/main/java/ru/betterend/blocks/LucerniaSaplingBlock.java deleted file mode 100644 index e1881306..00000000 --- a/src/main/java/ru/betterend/blocks/LucerniaSaplingBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class LucerniaSaplingBlock extends PottableFeatureSapling { - public LucerniaSaplingBlock() { - super((state)->EndFeatures.LUCERNIA.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.RUTISCUS); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.RUTISCUS; - } -} diff --git a/src/main/java/ru/betterend/blocks/LumecornBlock.java b/src/main/java/ru/betterend/blocks/LumecornBlock.java deleted file mode 100644 index 7419c25e..00000000 --- a/src/main/java/ru/betterend/blocks/LumecornBlock.java +++ /dev/null @@ -1,107 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineableAxe; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.EndBlockProperties.LumecornShape; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.Collections; -import java.util.List; - -@SuppressWarnings("deprecation") -public class LumecornBlock extends BaseBlockNotFull implements RenderLayerProvider, AddMineableAxe { - public static final EnumProperty SHAPE = EnumProperty.create("shape", LumecornShape.class); - private static final VoxelShape SHAPE_BOTTOM = Block.box(6, 0, 6, 10, 16, 10); - private static final VoxelShape SHAPE_TOP = Block.box(6, 0, 6, 10, 8, 10); - - public LumecornBlock() { - super(FabricBlockSettings.of(Material.WOOD) - .hardness(0.5F) - .luminance(state -> state.getValue(SHAPE).getLight())); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(SHAPE) == LumecornShape.LIGHT_TOP ? SHAPE_TOP : SHAPE_BOTTOM; - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - LumecornShape shape = state.getValue(SHAPE); - if (shape == LumecornShape.BOTTOM_BIG || shape == LumecornShape.BOTTOM_SMALL) { - return world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES); - } - else if (shape == LumecornShape.LIGHT_TOP) { - return world.getBlockState(pos.below()).is(this); - } - else { - return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this); - } - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!canSurvive(state, world, pos)) { - return Blocks.AIR.defaultBlockState(); - } - else { - return state; - } - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - LumecornShape shape = state.getValue(SHAPE); - if (shape == LumecornShape.BOTTOM_BIG || shape == LumecornShape.BOTTOM_SMALL || shape == LumecornShape.MIDDLE) { - return Collections.singletonList(new ItemStack( - EndBlocks.LUMECORN_SEED, - MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE) - )); - } - return MHelper.RANDOM.nextBoolean() ? Collections.singletonList(new ItemStack(EndItems.LUMECORN_ROD)) : Collections - .emptyList(); - } - - @Override - @Environment(EnvType.CLIENT) - public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { - LumecornShape shape = state.getValue(SHAPE); - if (shape == LumecornShape.BOTTOM_BIG || shape == LumecornShape.BOTTOM_SMALL || shape == LumecornShape.MIDDLE) { - return new ItemStack(EndBlocks.LUMECORN_SEED); - } - return new ItemStack(EndItems.LUMECORN_ROD); - } -} diff --git a/src/main/java/ru/betterend/blocks/LumecornSeedBlock.java b/src/main/java/ru/betterend/blocks/LumecornSeedBlock.java deleted file mode 100644 index 6c9440b8..00000000 --- a/src/main/java/ru/betterend/blocks/LumecornSeedBlock.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LumecornSeedBlock extends EndPlantWithAgeBlock { - - public LumecornSeedBlock(){ - super(p->p.offsetType(OffsetType.NONE)); - } - - @Override - public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) { - ((Feature) (EndFeatures.LUMECORN.getFeature())).place(new FeaturePlaceContext<>( - Optional.empty(), - world, - null, - random, - pos, - (NoneFeatureConfiguration) null)); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS); - } -} diff --git a/src/main/java/ru/betterend/blocks/MengerSpongeBlock.java b/src/main/java/ru/betterend/blocks/MengerSpongeBlock.java deleted file mode 100644 index 02fdf11e..00000000 --- a/src/main/java/ru/betterend/blocks/MengerSpongeBlock.java +++ /dev/null @@ -1,127 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.FluidTags; -import net.minecraft.util.Tuple; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.BucketPickup; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.betterend.registry.EndBlocks; - -import java.util.Queue; - -@SuppressWarnings("deprecation") -public class MengerSpongeBlock extends BaseBlockNotFull implements RenderLayerProvider { - private static final VoxelShape SHAPE; - - public MengerSpongeBlock() { - super(FabricBlockSettings.copyOf(Blocks.SPONGE).noOcclusion()); - } - - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - if (absorbWater(world, pos)) { - world.setBlockAndUpdate(pos, EndBlocks.MENGER_SPONGE_WET.defaultBlockState()); - } - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (absorbWater(world, pos)) { - return EndBlocks.MENGER_SPONGE_WET.defaultBlockState(); - } - return state; - } - - private boolean absorbWater(LevelAccessor world, BlockPos pos) { - Queue> queue = Lists.newLinkedList(); - queue.add(new Tuple<>(pos, 0)); - int i = 0; - - while (!queue.isEmpty()) { - Tuple pair = queue.poll(); - BlockPos blockPos = pair.getA(); - int j = pair.getB(); - - for (Direction direction : Direction.values()) { - BlockPos blockPos2 = blockPos.relative(direction); - BlockState blockState = world.getBlockState(blockPos2); - FluidState fluidState = world.getFluidState(blockPos2); - Material material = blockState.getMaterial(); - if (fluidState.is(FluidTags.WATER)) { - if (blockState.getBlock() instanceof BucketPickup && !((BucketPickup) blockState.getBlock()).pickupBlock( - world, - blockPos2, - blockState - ).isEmpty()) { - ++i; - if (j < 6) { - queue.add(new Tuple<>(blockPos2, j + 1)); - } - } - else if (blockState.getBlock() instanceof LiquidBlock) { - world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3); - ++i; - if (j < 6) { - queue.add(new Tuple<>(blockPos2, j + 1)); - } - } - else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - BlockEntity blockEntity = blockState.hasBlockEntity() ? world.getBlockEntity(blockPos2) : null; - dropResources(blockState, world, blockPos2, blockEntity); - world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3); - ++i; - if (j < 6) { - queue.add(new Tuple<>(blockPos2, j + 1)); - } - } - } - } - - if (i > 64) { - break; - } - } - - return i > 0; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public VoxelShape getShape(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext) { - return SHAPE; - } - - static { - SHAPE = Shapes.or( - Shapes.or(box(0, 0, 0, 16, 6, 6), box(0, 0, 10, 16, 6, 16), - Shapes.or(box(0, 10, 0, 16, 16, 6), box(0, 10, 10, 16, 16, 16)), - - Shapes.or(box(0, 0, 0, 6, 6, 16), box(10, 0, 0, 16, 6, 16)), - Shapes.or(box(0, 10, 0, 6, 16, 16), box(10, 10, 0, 16, 16, 16)), - - Shapes.or(box(0, 0, 0, 6, 16, 6), box(10, 0, 0, 16, 16, 6)), - Shapes.or(box(0, 0, 10, 6, 16, 16), box(10, 0, 10, 16, 16, 16)) - )); - } -} diff --git a/src/main/java/ru/betterend/blocks/MengerSpongeWetBlock.java b/src/main/java/ru/betterend/blocks/MengerSpongeWetBlock.java deleted file mode 100644 index 464d8797..00000000 --- a/src/main/java/ru/betterend/blocks/MengerSpongeWetBlock.java +++ /dev/null @@ -1,129 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@SuppressWarnings("deprecation") -public class MengerSpongeWetBlock extends BaseBlockNotFull implements RenderLayerProvider { - public MengerSpongeWetBlock() { - super(FabricBlockSettings.copyOf(Blocks.WET_SPONGE).noOcclusion()); - } - - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { - if (world.dimensionType().ultraWarm()) { - world.setBlock(pos, EndBlocks.MENGER_SPONGE.defaultBlockState(), 3); - world.levelEvent(2009, pos, 0); - world.playSound( - null, - pos, - SoundEvents.FIRE_EXTINGUISH, - SoundSource.BLOCKS, - 1.0F, - (1.0F + world.getRandom().nextFloat() * 0.2F) * 0.7F - ); - } - } - - @Override - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - Direction direction = Direction.getRandom(random); - if (direction != Direction.UP) { - BlockPos blockPos = pos.relative(direction); - BlockState blockState = world.getBlockState(blockPos); - if (!state.canOcclude() || !blockState.isFaceSturdy(world, blockPos, direction.getOpposite())) { - double x = pos.getX(); - double y = pos.getY(); - double z = pos.getZ(); - if (direction == Direction.DOWN) { - y -= 0.05; - x += random.nextDouble(); - z += random.nextDouble(); - } - else { - y += random.nextDouble() * 0.8; - if (direction.getAxis() == Direction.Axis.X) { - z += random.nextDouble(); - if (direction == Direction.EAST) { - ++x; - } - else { - x += 0.05; - } - } - else { - x += random.nextDouble(); - if (direction == Direction.SOUTH) { - ++z; - } - else { - z += 0.05; - } - } - } - - world.addParticle(ParticleTypes.DRIPPING_WATER, x, y, z, 0, 0, 0); - } - } - } - - @Override - public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { - BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); - if (!world.isClientSide()) { - world.levelEvent(2001, pos, getId(state)); - } - if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && (player == null || !player.isCreative())) { - ItemEntity drop = new ItemEntity( - world, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - new ItemStack(this) - ); - world.addFreshEntity(drop); - } - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public FluidState getFluidState(BlockState state) { - return Fluids.WATER.getSource(false); - } - - @Override - public VoxelShape getShape(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext) { - return EndBlocks.MENGER_SPONGE.getShape(blockState, blockGetter, blockPos, collisionContext); - } -} diff --git a/src/main/java/ru/betterend/blocks/MissingTileBlock.java b/src/main/java/ru/betterend/blocks/MissingTileBlock.java deleted file mode 100644 index 7a516557..00000000 --- a/src/main/java/ru/betterend/blocks/MissingTileBlock.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.blocks.BaseBlock; - -public class MissingTileBlock extends BaseBlock { - public MissingTileBlock() { - super(FabricBlockSettings.copyOf(Blocks.END_STONE)); - } -} diff --git a/src/main/java/ru/betterend/blocks/MossyDragonBoneBlock.java b/src/main/java/ru/betterend/blocks/MossyDragonBoneBlock.java deleted file mode 100644 index c3863cda..00000000 --- a/src/main/java/ru/betterend/blocks/MossyDragonBoneBlock.java +++ /dev/null @@ -1,70 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SnowLayerBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.lighting.LayerLightEngine; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.bclib.blocks.BaseRotatedPillarBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@SuppressWarnings("deprecation") -public class MossyDragonBoneBlock extends BaseRotatedPillarBlock { - public MossyDragonBoneBlock() { - super(FabricBlockSettings.copyOf(Blocks.BONE_BLOCK).hardness(0.5F).randomTicks()); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { - return Collections.singletonList(new ItemStack(this)); - } - return Collections.singletonList(new ItemStack(EndBlocks.DRAGON_BONE_BLOCK)); - } - - @Override - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) { - world.setBlockAndUpdate(pos, Blocks.BONE_BLOCK.defaultBlockState().setValue(AXIS, state.getValue(AXIS))); - } - } - - @Override - public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) { - BlockPos blockPos = pos.above(); - BlockState blockState = worldView.getBlockState(blockPos); - if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) { - return true; - } - else if (blockState.getFluidState().getAmount() == 8) { - return false; - } - else { - int i = LayerLightEngine.getLightBlockInto( - worldView, - state, - pos, - blockState, - blockPos, - Direction.UP, - blockState.getLightBlock(worldView, blockPos) - ); - return i < 5; - } - } -} diff --git a/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java b/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java deleted file mode 100644 index b4da16ac..00000000 --- a/src/main/java/ru/betterend/blocks/MossyGlowshroomCapBlock.java +++ /dev/null @@ -1,46 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.NamedMineableTags; - -import ru.bclib.blocks.BaseBlock; -import ru.bclib.interfaces.TagProvider; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class MossyGlowshroomCapBlock extends BaseBlock implements TagProvider { - public static final BooleanProperty TRANSITION = EndBlockProperties.TRANSITION; - - public MossyGlowshroomCapBlock() { - super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD)); - this.registerDefaultState(this.stateDefinition.any().setValue(TRANSITION, false)); - } - - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - return this.defaultBlockState() - .setValue( - TRANSITION, - EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(ctx.getLevel().getBlockState(ctx.getClickedPos().below())) - ); - } - - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(TRANSITION); - } - - @Override - public void addTags(List> blockTags, List> itemTags) { - blockTags.add(NamedMineableTags.AXE); - } -} diff --git a/src/main/java/ru/betterend/blocks/MossyGlowshroomSaplingBlock.java b/src/main/java/ru/betterend/blocks/MossyGlowshroomSaplingBlock.java deleted file mode 100644 index 5e63fdce..00000000 --- a/src/main/java/ru/betterend/blocks/MossyGlowshroomSaplingBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class MossyGlowshroomSaplingBlock extends PottableFeatureSapling { - public MossyGlowshroomSaplingBlock() { - super(7, (state)->EndFeatures.MOSSY_GLOWSHROOM.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below()) - .is(EndBlocks.END_MYCELIUM); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.END_MOSS || block == EndBlocks.END_MYCELIUM; - } -} diff --git a/src/main/java/ru/betterend/blocks/MossyObsidian.java b/src/main/java/ru/betterend/blocks/MossyObsidian.java deleted file mode 100644 index 8e4f3092..00000000 --- a/src/main/java/ru/betterend/blocks/MossyObsidian.java +++ /dev/null @@ -1,69 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SnowLayerBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.lighting.LayerLightEngine; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.bclib.blocks.BaseBlock; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class MossyObsidian extends BaseBlock { - public MossyObsidian() { - super(FabricBlockSettings.copyOf(Blocks.OBSIDIAN).hardness(3).randomTicks()); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { - return Collections.singletonList(new ItemStack(this)); - } - return Collections.singletonList(new ItemStack(Blocks.OBSIDIAN)); - } - - @Override - @SuppressWarnings("deprecation") - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) { - world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState()); - } - } - - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) { - BlockPos blockPos = pos.above(); - BlockState blockState = worldView.getBlockState(blockPos); - if (blockState.is(Blocks.SNOW) && (Integer) blockState.getValue(SnowLayerBlock.LAYERS) == 1) { - return true; - } - else if (blockState.getFluidState().getAmount() == 8) { - return false; - } - else { - int i = LayerLightEngine.getLightBlockInto( - worldView, - state, - pos, - blockState, - blockPos, - Direction.UP, - blockState.getLightBlock(worldView, blockPos) - ); - return i < 5; - } - } -} diff --git a/src/main/java/ru/betterend/blocks/MurkweedBlock.java b/src/main/java/ru/betterend/blocks/MurkweedBlock.java deleted file mode 100644 index 15f663c8..00000000 --- a/src/main/java/ru/betterend/blocks/MurkweedBlock.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class MurkweedBlock extends EndPlantBlock { - @Override - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - double x = pos.getX() + random.nextDouble(); - double y = pos.getY() + random.nextDouble() * 0.5 + 0.5; - double z = pos.getZ() + random.nextDouble(); - double v = random.nextDouble() * 0.1; - world.addParticle(ParticleTypes.ENTITY_EFFECT, x, y, z, v, v, v); - } - - @Override - @SuppressWarnings("deprecation") - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - if (entity instanceof LivingEntity && !((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS)) { - ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 50)); - } - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.SHADOW_GRASS); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/NeedlegrassBlock.java b/src/main/java/ru/betterend/blocks/NeedlegrassBlock.java deleted file mode 100644 index 7cc40161..00000000 --- a/src/main/java/ru/betterend/blocks/NeedlegrassBlock.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import ru.bclib.items.tool.BaseShearsItem; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class NeedlegrassBlock extends EndPlantBlock { - @Override - @SuppressWarnings("deprecation") - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - if (entity instanceof LivingEntity) { - entity.hurt(DamageSource.CACTUS, 0.1F); - } - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( - Enchantments.SILK_TOUCH, - tool - ) > 0) { - return Lists.newArrayList(new ItemStack(this)); - } - else { - return Lists.newArrayList(new ItemStack(Items.STICK, MHelper.randRange(0, 2, MHelper.RANDOM_SOURCE))); - } - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.SHADOW_GRASS); - } - - @Override - @SuppressWarnings("deprecation") - public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/NeonCactusBlock.java b/src/main/java/ru/betterend/blocks/NeonCactusBlock.java deleted file mode 100644 index db9468c8..00000000 --- a/src/main/java/ru/betterend/blocks/NeonCactusBlock.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Blocks; -import ru.betterend.blocks.basis.LitPillarBlock; - -public class NeonCactusBlock extends LitPillarBlock { - public NeonCactusBlock() { - super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15)); - } -} diff --git a/src/main/java/ru/betterend/blocks/NeonCactusPlantBlock.java b/src/main/java/ru/betterend/blocks/NeonCactusPlantBlock.java deleted file mode 100644 index ff12f671..00000000 --- a/src/main/java/ru/betterend/blocks/NeonCactusPlantBlock.java +++ /dev/null @@ -1,429 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.EndBlockProperties.CactusBottom; -import ru.betterend.interfaces.PottablePlant; -import ru.betterend.registry.EndBlocks; - -import java.util.EnumMap; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@SuppressWarnings("deprecation") -public class NeonCactusPlantBlock extends BaseBlockNotFull implements SimpleWaterloggedBlock, RenderLayerProvider, PottablePlant { - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - public static final EnumProperty CACTUS_BOTTOM = EndBlockProperties.CACTUS_BOTTOM; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public static final DirectionProperty FACING = BlockStateProperties.FACING; - - private static final EnumMap BIG_SHAPES_OPEN = Maps.newEnumMap(Direction.class); - private static final EnumMap MEDIUM_SHAPES_OPEN = Maps.newEnumMap(Direction.class); - private static final EnumMap SMALL_SHAPES_OPEN = Maps.newEnumMap(Direction.class); - private static final EnumMap BIG_SHAPES = Maps.newEnumMap(Axis.class); - private static final EnumMap MEDIUM_SHAPES = Maps.newEnumMap(Axis.class); - private static final EnumMap SMALL_SHAPES = Maps.newEnumMap(Axis.class); - private static final int MAX_LENGTH = 12; - - public NeonCactusPlantBlock() { - super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15).randomTicks()); - registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) - .setValue(FACING, Direction.UP) - .setValue(SHAPE, TripleShape.TOP)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE, CACTUS_BOTTOM, WATERLOGGED, FACING); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - LevelAccessor world = ctx.getLevel(); - BlockPos pos = ctx.getClickedPos(); - Direction dir = ctx.getClickedFace(); - BlockState down = world.getBlockState(pos.relative(dir.getOpposite())); - BlockState state = this.defaultBlockState() - .setValue(WATERLOGGED, world.getFluidState(pos).getType() == Fluids.WATER) - .setValue(FACING, ctx.getClickedFace()); - if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); - } - else if (down.is(EndBlocks.END_MOSS)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); - } - else { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); - } - return state; - } - - @Override - public BlockState rotate(BlockState state, Rotation rotation) { - return BlocksHelper.rotateHorizontal(state, rotation, FACING); - } - - @Override - public BlockState mirror(BlockState state, Mirror mirror) { - return BlocksHelper.mirrorHorizontal(state, mirror, FACING); - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } - - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - world.scheduleTick(pos, this, 2); - if (state.getValue(WATERLOGGED)) { - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - } - Direction dir = state.getValue(FACING); - BlockState downState = world.getBlockState(pos.relative(dir.getOpposite())); - if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); - } - else if (downState.is(EndBlocks.END_MOSS)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); - } - else { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); - } - return state; - } - - @Override - public void tick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource random) { - if (!blockState.canSurvive(serverLevel, blockPos)) { - serverLevel.destroyBlock(blockPos, true, null, 1); - } - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - TripleShape shape = state.getValue(SHAPE); - Direction dir = state.getValue(FACING); - BlockState next = view.getBlockState(pos.relative(dir)); - if (next.is(this)) { - Axis axis = dir.getAxis(); - if (shape == TripleShape.BOTTOM) { - return BIG_SHAPES.get(axis); - } - return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES.get(axis) : SMALL_SHAPES.get(axis); - } - else { - if (shape == TripleShape.BOTTOM) { - return BIG_SHAPES_OPEN.get(dir); - } - return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES_OPEN.get(dir) : SMALL_SHAPES_OPEN.get(dir); - } - } - - @Override - public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { - Direction dir = state.getValue(FACING); - BlockPos supportPos = pos.relative(dir.getOpposite()); - BlockState support = level.getBlockState(supportPos); - return support.is(this) || support.isFaceSturdy(level, supportPos, dir); - } - - @Override - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (!this.canSurvive(state, world, pos) || random.nextInt(8) > 0) { - return; - } - Direction dir = state.getValue(FACING); - if (!world.isEmptyBlock(pos.relative(dir))) { - return; - } - int length = getLength(state, world, pos, MAX_LENGTH); - if (length < 0 || length > MAX_LENGTH - 1) { - return; - } - if (dir.getAxis().isHorizontal()) { - int horizontal = getHorizontal(state, world, pos, 2); - if (horizontal > random.nextInt(2)) { - dir = Direction.UP; - if (!world.getBlockState(pos.above()).isAir()) { - return; - } - } - } - else if (length > 1 && world.getBlockState(pos.relative(dir.getOpposite())).is(this)) { - Direction side = getSideDirection(world, pos, state, dir, random); - BlockPos sidePos = pos.relative(side); - if (world.isEmptyBlock(sidePos)) { - BlockState placement = state.setValue(SHAPE, TripleShape.TOP) - .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) - .setValue(WATERLOGGED, false) - .setValue(FACING, side); - BlocksHelper.setWithoutUpdate(world, sidePos, placement); - } - } - BlockState placement = state.setValue(SHAPE, TripleShape.TOP) - .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) - .setValue(WATERLOGGED, false) - .setValue(FACING, dir); - BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement); - mutateStem(placement, world, pos, MAX_LENGTH); - } - - public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random) { - growPlant(world, pos, random, MHelper.randRange(MAX_LENGTH >> 1, MAX_LENGTH, random)); - } - - public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random, int iterations) { - BlockState state = defaultBlockState(); - BlockState downState = world.getBlockState(pos.below()); - if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND); - } - else if (downState.is(EndBlocks.END_MOSS)) { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS); - } - else { - state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY); - } - BlocksHelper.setWithoutUpdate(world, pos, state); - List ends = Lists.newArrayList(pos.mutable()); - for (int i = 0; i < iterations; i++) { - int count = ends.size(); - for (int n = 0; n < count; n++) { - if (!growIteration(world, ends.get(n), random, ends, i)) { - ends.remove(n); - count--; - n--; - } - } - } - } - - private boolean growIteration(WorldGenLevel world, MutableBlockPos pos, RandomSource random, List ends, int length) { - BlockState state = world.getBlockState(pos); - if (!state.is(this)) { - return false; - } - Direction dir = state.getValue(FACING); - if (!world.isEmptyBlock(pos.relative(dir))) { - return false; - } - if (dir.getAxis().isHorizontal()) { - int horizontal = getHorizontal(state, world, pos, 2); - if (horizontal > random.nextInt(2)) { - dir = Direction.UP; - if (!world.getBlockState(pos.above()).isAir()) { - return false; - } - } - } - else if (length > 1 && world.getBlockState(pos.below()).is(this)) { - Direction side = getSideDirection(world, pos, state, dir, random); - BlockPos sidePos = pos.relative(side); - if (world.isEmptyBlock(sidePos)) { - BlockState placement = state.setValue(SHAPE, TripleShape.TOP) - .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) - .setValue(WATERLOGGED, false) - .setValue(FACING, side); - BlocksHelper.setWithoutUpdate(world, sidePos, placement); - ends.add(sidePos.mutable()); - } - } - BlockState placement = state.setValue(SHAPE, TripleShape.TOP) - .setValue(CACTUS_BOTTOM, CactusBottom.EMPTY) - .setValue(WATERLOGGED, false) - .setValue(FACING, dir); - BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement); - mutateStem(placement, world, pos, MAX_LENGTH); - pos.move(dir); - return true; - } - - private Direction getSideDirection(WorldGenLevel world, BlockPos pos, BlockState iterState, Direction dir, RandomSource random) { - MutableBlockPos iterPos = pos.mutable(); - Direction startDir = dir; - Direction lastDir = null; - while (iterState.is(this) && startDir.getAxis().isVertical()) { - startDir = iterState.getValue(FACING); - if (lastDir == null) { - for (Direction side : BlocksHelper.HORIZONTAL) { - BlockState sideState = world.getBlockState(iterPos.relative(side)); - if (sideState.is(this)) { - Direction sideDir = sideState.getValue(FACING); - if (sideDir != side) { - continue; - } - lastDir = sideDir; - } - } - } - iterPos.move(dir); - iterState = world.getBlockState(iterPos); - } - - Direction side = lastDir == null ? BlocksHelper.randomHorizontal(random) : lastDir.getClockWise(); - if (side.getOpposite() == startDir) { - side = side.getOpposite(); - } - return side; - } - - @Override - public boolean isPathfindable(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, PathComputationType pathComputationType) { - return false; - } - - @Override - public void entityInside(BlockState blockState, Level level, BlockPos blockPos, Entity entity) { - entity.hurt(DamageSource.CACTUS, 1.0F); - } - - private int getLength(BlockState state, ServerLevel world, BlockPos pos, int max) { - int length = 0; - Direction dir = state.getValue(FACING).getOpposite(); - MutableBlockPos mut = new MutableBlockPos().set(pos); - for (int i = 0; i < max; i++) { - mut.move(dir); - state = world.getBlockState(mut); - if (!state.is(this)) { - if (!state.is(CommonBlockTags.END_STONES)) { - length = -1; - } - break; - } - dir = state.getValue(FACING).getOpposite(); - length++; - } - return length; - } - - private int getHorizontal(BlockState state, WorldGenLevel world, BlockPos pos, int max) { - int count = 0; - Direction dir = state.getValue(FACING).getOpposite(); - MutableBlockPos mut = new MutableBlockPos().set(pos); - for (int i = 0; i < max; i++) { - mut.move(dir); - state = world.getBlockState(mut); - if (!state.is(this)) { - break; - } - dir = state.getValue(FACING).getOpposite(); - if (dir.getStepY() != 0) { - break; - } - count++; - } - return count; - } - - private void mutateStem(BlockState state, WorldGenLevel world, BlockPos pos, int max) { - Direction dir = state.getValue(FACING).getOpposite(); - MutableBlockPos mut = new MutableBlockPos().set(pos); - for (int i = 0; i < max; i++) { - mut.move(dir); - state = world.getBlockState(mut); - if (!state.is(this)) { - return; - } - int size = (i + 2) * 3 / max; - int src = state.getValue(SHAPE).getIndex(); - dir = state.getValue(FACING).getOpposite(); - if (src < size) { - TripleShape shape = TripleShape.fromIndex(size); - BlocksHelper.setWithoutUpdate(world, mut, state.setValue(SHAPE, shape)); - } - } - } - - static { - BIG_SHAPES.put(Axis.X, Block.box(0, 2, 2, 16, 14, 14)); - BIG_SHAPES.put(Axis.Y, Block.box(2, 0, 2, 14, 16, 14)); - BIG_SHAPES.put(Axis.Z, Block.box(2, 2, 0, 14, 14, 16)); - - MEDIUM_SHAPES.put(Axis.X, Block.box(0, 3, 3, 16, 13, 13)); - MEDIUM_SHAPES.put(Axis.Y, Block.box(3, 0, 3, 13, 16, 13)); - MEDIUM_SHAPES.put(Axis.Z, Block.box(3, 3, 0, 13, 13, 16)); - - SMALL_SHAPES.put(Axis.X, Block.box(0, 4, 4, 16, 12, 12)); - SMALL_SHAPES.put(Axis.Y, Block.box(4, 0, 4, 12, 16, 12)); - SMALL_SHAPES.put(Axis.Z, Block.box(4, 4, 0, 12, 12, 16)); - - BIG_SHAPES_OPEN.put(Direction.UP, Block.box(2, 0, 2, 14, 14, 14)); - BIG_SHAPES_OPEN.put(Direction.DOWN, Block.box(2, 2, 2, 14, 16, 14)); - BIG_SHAPES_OPEN.put(Direction.NORTH, Block.box(2, 2, 2, 14, 14, 16)); - BIG_SHAPES_OPEN.put(Direction.SOUTH, Block.box(2, 2, 0, 14, 14, 14)); - BIG_SHAPES_OPEN.put(Direction.WEST, Block.box(2, 2, 2, 16, 14, 14)); - BIG_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 2, 2, 14, 14, 14)); - - MEDIUM_SHAPES_OPEN.put(Direction.UP, Block.box(3, 0, 3, 13, 13, 13)); - MEDIUM_SHAPES_OPEN.put(Direction.DOWN, Block.box(3, 3, 3, 13, 16, 13)); - MEDIUM_SHAPES_OPEN.put(Direction.NORTH, Block.box(3, 3, 3, 13, 13, 16)); - MEDIUM_SHAPES_OPEN.put(Direction.SOUTH, Block.box(3, 3, 0, 13, 13, 13)); - MEDIUM_SHAPES_OPEN.put(Direction.WEST, Block.box(3, 3, 3, 16, 13, 13)); - MEDIUM_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 3, 3, 13, 13, 13)); - - SMALL_SHAPES_OPEN.put(Direction.UP, Block.box(4, 0, 4, 12, 12, 12)); - SMALL_SHAPES_OPEN.put(Direction.DOWN, Block.box(4, 4, 4, 12, 16, 12)); - SMALL_SHAPES_OPEN.put(Direction.NORTH, Block.box(4, 4, 4, 12, 12, 16)); - SMALL_SHAPES_OPEN.put(Direction.SOUTH, Block.box(4, 4, 0, 12, 12, 12)); - SMALL_SHAPES_OPEN.put(Direction.WEST, Block.box(4, 4, 4, 16, 12, 12)); - SMALL_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 4, 4, 12, 12, 12)); - } - - @Override - public boolean canPlantOn(Block block) { - return true; - } - - @Override - @Environment(EnvType.CLIENT) - public String getPottedState() { - return "bottom=moss,shape=top,facing=up"; - } -} diff --git a/src/main/java/ru/betterend/blocks/PallidiumBlock.java b/src/main/java/ru/betterend/blocks/PallidiumBlock.java deleted file mode 100644 index 593f5f45..00000000 --- a/src/main/java/ru/betterend/blocks/PallidiumBlock.java +++ /dev/null @@ -1,66 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.phys.BlockHitResult; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndTerrainBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Map; - -public class PallidiumBlock extends EndTerrainBlock { - private final Block nextLevel; - - public PallidiumBlock(String thickness, Block nextLevel) { - super(MaterialColor.COLOR_LIGHT_GRAY); - this.nextLevel = nextLevel; - } - - public boolean canBePotted() { - return this == EndBlocks.PALLIDIUM_FULL; - } - - @Override - public Block getBaseBlock() { - return EndBlocks.UMBRALITH.stone; - } - - @Override - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (nextLevel == null) { - return InteractionResult.PASS; - } - else if (level.isClientSide) { - return InteractionResult.PASS; - } - - ItemStack itemStack = player.getItemInHand(hand); - if (itemStack.is(Items.BONE_MEAL)) { - BlocksHelper.setWithUpdate(level, pos, nextLevel); - if (!player.isCreative()) { - itemStack.shrink(1); - } - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } - - @Override - @Environment(EnvType.CLIENT) - public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map modelCache) { - return this.getBlockModel(stateId, blockState); - } -} diff --git a/src/main/java/ru/betterend/blocks/PedestalVanilla.java b/src/main/java/ru/betterend/blocks/PedestalVanilla.java deleted file mode 100644 index 44004e98..00000000 --- a/src/main/java/ru/betterend/blocks/PedestalVanilla.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import ru.betterend.blocks.basis.PedestalBlock; - -import java.util.HashMap; -import java.util.Map; - -public class PedestalVanilla extends PedestalBlock { - - public PedestalVanilla(Block parent) { - super(parent); - } - - @Override - protected Map createTexturesMap() { - ResourceLocation blockId = Registry.BLOCK.getKey(parent); - String name = blockId.getPath().replace("_block", ""); - return new HashMap() { - private static final long serialVersionUID = 1L; - - { - put("%mod%", blockId.getNamespace()); - put("%top%", "polished_" + name); - put("%base%", "polished_" + name); - put("%pillar%", name + "_pillar"); - put("%bottom%", "polished_" + name); - } - }; - } -} diff --git a/src/main/java/ru/betterend/blocks/PondAnemoneBlock.java b/src/main/java/ru/betterend/blocks/PondAnemoneBlock.java deleted file mode 100644 index 6ac8785e..00000000 --- a/src/main/java/ru/betterend/blocks/PondAnemoneBlock.java +++ /dev/null @@ -1,57 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.betterend.blocks.basis.EndUnderwaterPlantBlock; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class PondAnemoneBlock extends EndUnderwaterPlantBlock implements AddMineableShears { - private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14); - - public PondAnemoneBlock() { - super(FabricBlockSettings.of(Material.WATER_PLANT) - - .luminance(13) - .sound(SoundType.CORAL_BLOCK) - .noCollission() - .offsetType(OffsetType.NONE)); - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - double x = pos.getX() + random.nextDouble(); - double y = pos.getY() + random.nextDouble() * 0.5F + 0.5F; - double z = pos.getZ() + random.nextDouble(); - world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0.0D, 0.0D, 0.0D); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/PythadendronSaplingBlock.java b/src/main/java/ru/betterend/blocks/PythadendronSaplingBlock.java deleted file mode 100644 index 9d6afd70..00000000 --- a/src/main/java/ru/betterend/blocks/PythadendronSaplingBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class PythadendronSaplingBlock extends PottableFeatureSapling { - public PythadendronSaplingBlock() { - super((state)->EndFeatures.PYTHADENDRON_TREE.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.CHORUS_NYLIUM); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.CHORUS_NYLIUM; - } -} diff --git a/src/main/java/ru/betterend/blocks/RespawnObeliskBlock.java b/src/main/java/ru/betterend/blocks/RespawnObeliskBlock.java deleted file mode 100644 index d96c3bf5..00000000 --- a/src/main/java/ru/betterend/blocks/RespawnObeliskBlock.java +++ /dev/null @@ -1,209 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; - -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.ColorUtil; -import ru.betterend.particle.InfusionParticleType; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.List; - -public class RespawnObeliskBlock extends BaseBlock implements CustomColorProvider, RenderLayerProvider { - private static final VoxelShape VOXEL_SHAPE_BOTTOM = Block.box(1, 0, 1, 15, 16, 15); - private static final VoxelShape VOXEL_SHAPE_MIDDLE_TOP = Block.box(2, 0, 2, 14, 16, 14); - - public static final EnumProperty SHAPE = BlockProperties.TRIPLE_SHAPE; - - public RespawnObeliskBlock() { - super(FabricBlockSettings.copyOf(Blocks.END_STONE).luminance((state) -> { - return (state.getValue(SHAPE) == TripleShape.BOTTOM) ? 0 : 15; - })); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return (state.getValue(SHAPE) == TripleShape.BOTTOM) ? VOXEL_SHAPE_BOTTOM : VOXEL_SHAPE_MIDDLE_TOP; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(SHAPE); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - for (int i = 0; i < 3; i++) { - if (!world.getBlockState(pos.above(i)).getMaterial().isReplaceable()) { - return false; - } - } - return true; - } - - @Override - public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { - state = this.defaultBlockState(); - BlocksHelper.setWithUpdate(world, pos, state.setValue(SHAPE, TripleShape.BOTTOM)); - BlocksHelper.setWithUpdate(world, pos.above(), state.setValue(SHAPE, TripleShape.MIDDLE)); - BlocksHelper.setWithUpdate(world, pos.above(2), state.setValue(SHAPE, TripleShape.TOP)); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - TripleShape shape = state.getValue(SHAPE); - if (shape == TripleShape.BOTTOM) { - if (world.getBlockState(pos.above()).is(this)) { - return state; - } - else { - return Blocks.AIR.defaultBlockState(); - } - } - else if (shape == TripleShape.MIDDLE) { - if (world.getBlockState(pos.above()).is(this) && world.getBlockState(pos.below()).is(this)) { - return state; - } - else { - return Blocks.AIR.defaultBlockState(); - } - } - else { - if (world.getBlockState(pos.below()).is(this)) { - return state; - } - else { - return Blocks.AIR.defaultBlockState(); - } - } - } - - @Override - public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { - if (player.isCreative()) { - TripleShape shape = state.getValue(SHAPE); - if (shape == TripleShape.MIDDLE) { - BlocksHelper.setWithUpdate(world, pos.below(), Blocks.AIR); - } - else if (shape == TripleShape.TOP) { - BlocksHelper.setWithUpdate(world, pos.below(2), Blocks.AIR); - } - } - super.playerWillDestroy(world, pos, state, player); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.getValue(SHAPE) == TripleShape.BOTTOM) { - return Lists.newArrayList(new ItemStack(this)); - } - else { - return Lists.newArrayList(); - } - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - public BlockColor getProvider() { - return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getProvider(); - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> { - return ColorUtil.color(255, 255, 255); - }; - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - ItemStack itemStack = player.getItemInHand(hand); - boolean canActivate = itemStack.getItem() == EndItems.AMBER_GEM && itemStack.getCount() > 5; - if (hand != InteractionHand.MAIN_HAND || !canActivate) { - if (!world.isClientSide && !(itemStack.getItem() instanceof BlockItem) && !player.isCreative()) { - ServerPlayer serverPlayerEntity = (ServerPlayer) player; - serverPlayerEntity.displayClientMessage( - Component.translatable("message.betterend.fail_spawn"), - true - ); - } - return InteractionResult.FAIL; - } - else if (!world.isClientSide) { - ServerPlayer serverPlayerEntity = (ServerPlayer) player; - serverPlayerEntity.setRespawnPosition(world.dimension(), pos, 0.0F, false, false); - serverPlayerEntity.displayClientMessage(Component.translatable("message.betterend.set_spawn"), true); - double px = pos.getX() + 0.5; - double py = pos.getY() + 0.5; - double pz = pos.getZ() + 0.5; - InfusionParticleType particle = new InfusionParticleType(new ItemStack(EndItems.AMBER_GEM)); - if (world instanceof ServerLevel) { - double py1 = py; - double py2 = py - 0.2; - if (state.getValue(SHAPE) == TripleShape.BOTTOM) { - py1 += 1; - py2 += 2; - } - else if (state.getValue(SHAPE) == TripleShape.MIDDLE) { - py1 += 0; - py2 += 1; - } - else { - py1 -= 2; - } - ((ServerLevel) world).sendParticles(particle, px, py1, pz, 20, 0.14, 0.5, 0.14, 0.1); - ((ServerLevel) world).sendParticles(particle, px, py2, pz, 20, 0.14, 0.3, 0.14, 0.1); - } - world.playSound(null, px, py, py, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1F, 1F); - if (!player.isCreative()) { - itemStack.shrink(6); - } - } - return player.isCreative() ? InteractionResult.PASS : InteractionResult.sidedSuccess(world.isClientSide); - } -} diff --git a/src/main/java/ru/betterend/blocks/RunedFlavolite.java b/src/main/java/ru/betterend/blocks/RunedFlavolite.java deleted file mode 100644 index 3ebe6c4d..00000000 --- a/src/main/java/ru/betterend/blocks/RunedFlavolite.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class RunedFlavolite extends BaseBlock { - public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE; - - public RunedFlavolite(boolean unbreakable) { - super(FabricBlockSettings.copyOf(EndBlocks.FLAVOLITE.polished) - .strength( - unbreakable ? -1 : 1, - unbreakable ? Blocks.BEDROCK.getExplosionResistance() : Blocks.OBSIDIAN.getExplosionResistance() - ) - .luminance(state -> { - return state.getValue(ACTIVATED) ? 8 : 0; - })); - this.registerDefaultState(stateDefinition.any().setValue(ACTIVATED, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(ACTIVATED); - } - - @Override - public boolean dropFromExplosion(Explosion explosion) { - return !BlocksHelper.isInvulnerableUnsafe(this.defaultBlockState()); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - if (BlocksHelper.isInvulnerableUnsafe(this.defaultBlockState())) { - return Lists.newArrayList(); - } - return super.getDrops(state, builder); - } -} diff --git a/src/main/java/ru/betterend/blocks/ShadowBerryBlock.java b/src/main/java/ru/betterend/blocks/ShadowBerryBlock.java deleted file mode 100644 index e31de007..00000000 --- a/src/main/java/ru/betterend/blocks/ShadowBerryBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.betterend.blocks.basis.PottableCropBlock; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class ShadowBerryBlock extends PottableCropBlock { - private static final VoxelShape SHAPE = Block.box(1, 0, 1, 15, 8, 15); - - public ShadowBerryBlock() { - super(EndItems.SHADOW_BERRY_RAW, EndBlocks.SHADOW_GRASS); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return SHAPE; - } -} diff --git a/src/main/java/ru/betterend/blocks/ShadowGrassBlock.java b/src/main/java/ru/betterend/blocks/ShadowGrassBlock.java deleted file mode 100644 index 65214756..00000000 --- a/src/main/java/ru/betterend/blocks/ShadowGrassBlock.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.MaterialColor; - -import ru.bclib.api.tag.CommonBlockTags; - -import ru.bclib.interfaces.TagProvider; -import ru.betterend.blocks.basis.EndTerrainBlock; -import ru.betterend.registry.EndParticles; - -import java.util.List; - -import net.minecraft.util.RandomSource; - -public class ShadowGrassBlock extends EndTerrainBlock implements TagProvider { - public ShadowGrassBlock() { - super(MaterialColor.COLOR_BLACK); - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - super.animateTick(state, world, pos, random); - if (random.nextInt(32) == 0) { - world.addParticle( - EndParticles.BLACK_SPORE, - (double) pos.getX() + random.nextDouble(), - (double) pos.getY() + 1.1D, - (double) pos.getZ() + random.nextDouble(), - 0.0D, - 0.0D, - 0.0D - ); - } - } - - @Override - public void addTags(List> blockTags, List> itemTags) { - blockTags.add(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/SilkMothHiveBlock.java b/src/main/java/ru/betterend/blocks/SilkMothHiveBlock.java deleted file mode 100644 index da3db0f5..00000000 --- a/src/main/java/ru/betterend/blocks/SilkMothHiveBlock.java +++ /dev/null @@ -1,126 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -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.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -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.IntegerProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.items.tool.BaseShearsItem; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.entity.SilkMothEntity; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndItems; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SilkMothHiveBlock extends BaseBlock { - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; - public static final IntegerProperty FULLNESS = EndBlockProperties.FULLNESS; - - public SilkMothHiveBlock() { - super(FabricBlockSettings.of(Material.WOOD) - .hardness(0.5F) - .resistance(0.1F) - .sound(SoundType.WOOL) - .noOcclusion() - .randomTicks()); - this.registerDefaultState(defaultBlockState().setValue(FULLNESS, 0)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(FACING, FULLNESS); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - Direction dir = ctx.getHorizontalDirection().getOpposite(); - return this.defaultBlockState().setValue(FACING, dir); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) { - return BlocksHelper.rotateHorizontal(state, rotation, FACING); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirror) { - return BlocksHelper.mirrorHorizontal(state, mirror, FACING); - } - - @Override - @SuppressWarnings("deprecation") - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - Direction dir = state.getValue(FACING); - BlockPos spawn = pos.relative(dir); - if (!world.getBlockState(spawn).isAir()) { - return; - } - int count = world.getEntities(EndEntities.SILK_MOTH, new AABB(pos).inflate(16), (entity) -> { - return true; - }).size(); - if (count > 6) { - return; - } - SilkMothEntity moth = new SilkMothEntity(EndEntities.SILK_MOTH, world); - moth.moveTo(spawn.getX() + 0.5, spawn.getY() + 0.5, spawn.getZ() + 0.5, dir.toYRot(), 0); - moth.setDeltaMovement(new Vec3(dir.getStepX() * 0.4, 0, dir.getStepZ() * 0.4)); - moth.setHive(world, pos); - world.addFreshEntity(moth); - world.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1, 1); - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (hand == InteractionHand.MAIN_HAND) { - ItemStack stack = player.getMainHandItem(); - if (BaseShearsItem.isShear(stack) && state.getValue(FULLNESS) == 3) { - BlocksHelper.setWithUpdate(world, pos, state.setValue(FULLNESS, 0)); - Direction dir = state.getValue(FACING); - double px = pos.getX() + dir.getStepX() + 0.5; - double py = pos.getY() + dir.getStepY() + 0.5; - double pz = pos.getZ() + dir.getStepZ() + 0.5; - ItemStack drop = new ItemStack(EndItems.SILK_FIBER, MHelper.randRange(8, 16, world.getRandom())); - ItemEntity entity = new ItemEntity(world, px, py, pz, drop); - world.addFreshEntity(entity); - if (world.getRandom().nextInt(4) == 0) { - drop = new ItemStack(EndItems.SILK_MOTH_MATRIX); - entity = new ItemEntity(world, px, py, pz, drop); - world.addFreshEntity(entity); - } - if (!player.isCreative()) { - stack.setDamageValue(stack.getDamageValue() + 1); - } - return InteractionResult.SUCCESS; - } - } - return InteractionResult.FAIL; - } -} diff --git a/src/main/java/ru/betterend/blocks/SilkMothNestBlock.java b/src/main/java/ru/betterend/blocks/SilkMothNestBlock.java deleted file mode 100644 index 6620c94f..00000000 --- a/src/main/java/ru/betterend/blocks/SilkMothNestBlock.java +++ /dev/null @@ -1,188 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -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.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.items.tool.BaseShearsItem; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.entity.SilkMothEntity; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndItems; - -import java.util.Collections; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SilkMothNestBlock extends BaseBlock implements RenderLayerProvider { - public static final BooleanProperty ACTIVE = EndBlockProperties.ACTIVE; - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; - public static final IntegerProperty FULLNESS = EndBlockProperties.FULLNESS; - private static final VoxelShape TOP = box(6, 0, 6, 10, 16, 10); - private static final VoxelShape BOTTOM = box(0, 0, 0, 16, 16, 16); - - public SilkMothNestBlock() { - super(FabricBlockSettings.of(Material.WOOL) - .hardness(0.5F) - .resistance(0.1F) - .sound(SoundType.WOOL) - .noOcclusion() - .randomTicks()); - this.registerDefaultState(defaultBlockState().setValue(ACTIVE, true).setValue(FULLNESS, 0)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(ACTIVE, FACING, FULLNESS); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(ACTIVE) ? BOTTOM : TOP; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - Direction dir = ctx.getHorizontalDirection().getOpposite(); - return this.defaultBlockState().setValue(FACING, dir); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - if (!state.getValue(ACTIVE)) { - if (canSupportCenter(world, pos.above(), Direction.DOWN) || world.getBlockState(pos.above()) - .is(BlockTags.LEAVES)) { - return state; - } - else { - return Blocks.AIR.defaultBlockState(); - } - } - return state; - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) { - return BlocksHelper.rotateHorizontal(state, rotation, FACING); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirror) { - return BlocksHelper.mirrorHorizontal(state, mirror, FACING); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return state.getValue(ACTIVE) ? Collections.singletonList(new ItemStack(this)) : Collections.emptyList(); - } - - @Override - public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) { - if (!state.getValue(ACTIVE) && player.isCreative()) { - BlocksHelper.setWithUpdate(world, pos.below(), Blocks.AIR); - } - BlockState up = world.getBlockState(pos.above()); - if (up.is(this) && !up.getValue(ACTIVE)) { - BlocksHelper.setWithUpdate(world, pos.above(), Blocks.AIR); - } - super.playerWillDestroy(world, pos, state, player); - } - - @Override - @SuppressWarnings("deprecation") - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (!state.getValue(ACTIVE)) { - return; - } - if (random.nextBoolean()) { - return; - } - Direction dir = state.getValue(FACING); - BlockPos spawn = pos.relative(dir); - if (!world.getBlockState(spawn).isAir()) { - return; - } - int count = world.getEntities(EndEntities.SILK_MOTH, new AABB(pos).inflate(16), (entity) -> { - return true; - }).size(); - if (count > 6) { - return; - } - SilkMothEntity moth = new SilkMothEntity(EndEntities.SILK_MOTH, world); - moth.moveTo(spawn.getX() + 0.5, spawn.getY() + 0.5, spawn.getZ() + 0.5, dir.toYRot(), 0); - moth.setDeltaMovement(new Vec3(dir.getStepX() * 0.4, 0, dir.getStepZ() * 0.4)); - moth.setHive(world, pos); - world.addFreshEntity(moth); - world.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1, 1); - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (hand == InteractionHand.MAIN_HAND) { - ItemStack stack = player.getMainHandItem(); - if (BaseShearsItem.isShear(stack) && state.getValue(ACTIVE) && state.getValue(FULLNESS) == 3) { - BlocksHelper.setWithUpdate(world, pos, state.setValue(FULLNESS, 0)); - Direction dir = state.getValue(FACING); - double px = pos.getX() + dir.getStepX() + 0.5; - double py = pos.getY() + dir.getStepY() + 0.5; - double pz = pos.getZ() + dir.getStepZ() + 0.5; - ItemStack drop = new ItemStack(EndItems.SILK_FIBER, MHelper.randRange(1, 4, world.getRandom())); - ItemEntity entity = new ItemEntity(world, px, py, pz, drop); - world.addFreshEntity(entity); - drop = new ItemStack(EndItems.SILK_MOTH_MATRIX, MHelper.randRange(1, 3, world.getRandom())); - entity = new ItemEntity(world, px, py, pz, drop); - world.addFreshEntity(entity); - if (!player.isCreative()) { - stack.setDamageValue(stack.getDamageValue() + 1); - } - return InteractionResult.SUCCESS; - } - } - return InteractionResult.FAIL; - } -} diff --git a/src/main/java/ru/betterend/blocks/SmallAmaranitaBlock.java b/src/main/java/ru/betterend/blocks/SmallAmaranitaBlock.java deleted file mode 100644 index 8748051f..00000000 --- a/src/main/java/ru/betterend/blocks/SmallAmaranitaBlock.java +++ /dev/null @@ -1,82 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SmallAmaranitaBlock extends EndPlantBlock { - private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 10, 12); - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.SANGNUM) || state.is(EndBlocks.MOSSY_OBSIDIAN) || state.is(EndBlocks.MOSSY_DRAGON_BONE); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - BlockPos bigPos = growBig(world, pos); - if (bigPos != null) { - if (((Feature)EndFeatures.GIGANTIC_AMARANITA.getFeature()) - .place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, bigPos, null))) { - replaceMushroom(world, bigPos); - replaceMushroom(world, bigPos.south()); - replaceMushroom(world, bigPos.east()); - replaceMushroom(world, bigPos.south().east()); - } - return; - } - ((Feature)EndFeatures.LARGE_AMARANITA.getFeature()).place( new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos, null)); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - Vec3 vec3d = state.getOffset(view, pos); - return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); - } - - private BlockPos growBig(ServerLevel world, BlockPos pos) { - for (int x = -1; x < 2; x++) { - for (int z = -1; z < 2; z++) { - BlockPos p = pos.offset(x, 0, z); - if (checkFrame(world, p)) { - return p; - } - } - } - return null; - } - - private boolean checkFrame(ServerLevel world, BlockPos pos) { - return world.getBlockState(pos).is(this) && world.getBlockState(pos.south()).is(this) && world.getBlockState(pos - .east()).is(this) && world.getBlockState(pos.south().east()).is(this); - } - - private void replaceMushroom(ServerLevel world, BlockPos pos) { - if (world.getBlockState(pos).is(this)) { - BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); - } - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return random.nextInt(8) == 0; - } -} diff --git a/src/main/java/ru/betterend/blocks/SmallJellyshroomBlock.java b/src/main/java/ru/betterend/blocks/SmallJellyshroomBlock.java deleted file mode 100644 index 6fd8e66c..00000000 --- a/src/main/java/ru/betterend/blocks/SmallJellyshroomBlock.java +++ /dev/null @@ -1,121 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.BonemealableBlock; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.items.tool.BaseShearsItem; -import ru.bclib.util.BlocksHelper; -import ru.betterend.interfaces.PottablePlant; -import ru.betterend.registry.EndFeatures; - -import java.util.EnumMap; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SmallJellyshroomBlock extends BaseAttachedBlock implements RenderLayerProvider, BonemealableBlock, PottablePlant { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - - public SmallJellyshroomBlock() { - super(FabricBlockSettings.of(Material.PLANT).sound(SoundType.NETHER_WART).noCollission()); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( - Enchantments.SILK_TOUCH, - tool - ) > 0) { - return Lists.newArrayList(new ItemStack(this)); - } - else { - return Lists.newArrayList(); - } - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - Direction direction = state.getValue(FACING); - BlockPos blockPos = pos.relative(direction.getOpposite()); - BlockState support = world.getBlockState(blockPos); - return canSupportCenter(world, blockPos, direction) && support.canOcclude() && support.getLightEmission() == 0; - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Block.box(3, 0, 3, 13, 16, 13)); - BOUNDING_SHAPES.put(Direction.DOWN, Block.box(3, 0, 3, 13, 16, 13)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return state.getValue(FACING) == Direction.UP && world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES); - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return random.nextInt(16) == 0; - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - BlocksHelper.setWithUpdate(world, pos, Blocks.AIR); - ((Feature)EndFeatures.JELLYSHROOM.getFeature()).place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos, null)); - } - - @Override - public boolean canPlantOn(Block block) { - return true; - } - - @Override - @Environment(EnvType.CLIENT) - public String getPottedState() { - return "facing=up"; - } -} diff --git a/src/main/java/ru/betterend/blocks/SmaragdantCrystalBlock.java b/src/main/java/ru/betterend/blocks/SmaragdantCrystalBlock.java deleted file mode 100644 index 19152ecc..00000000 --- a/src/main/java/ru/betterend/blocks/SmaragdantCrystalBlock.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; -import ru.bclib.interfaces.tools.AddMineablePickaxe; -import ru.betterend.blocks.basis.LitPillarBlock; - -public class SmaragdantCrystalBlock extends LitPillarBlock implements AddMineablePickaxe { - public SmaragdantCrystalBlock() { - super(FabricBlockSettings.of(Material.GLASS) - .luminance(15) - .hardness(1F) - .resistance(1F) - .noOcclusion() - .sound(SoundType.AMETHYST)); - } -} diff --git a/src/main/java/ru/betterend/blocks/SmaragdantCrystalShardBlock.java b/src/main/java/ru/betterend/blocks/SmaragdantCrystalShardBlock.java deleted file mode 100644 index 72f83eb7..00000000 --- a/src/main/java/ru/betterend/blocks/SmaragdantCrystalShardBlock.java +++ /dev/null @@ -1,106 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -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.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineablePickaxe; - -import java.util.EnumMap; - -@SuppressWarnings("deprecation") -public class SmaragdantCrystalShardBlock extends BaseAttachedBlock implements AddMineablePickaxe, RenderLayerProvider, SimpleWaterloggedBlock, LiquidBlockContainer { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - - public SmaragdantCrystalShardBlock() { - super(FabricBlockSettings.of(Material.STONE) - .materialColor(MaterialColor.COLOR_GREEN) - .luminance(15) - .sound(SoundType.AMETHYST_CLUSTER) - .requiresCorrectToolForDrops() - .noCollission()); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - super.createBlockStateDefinition(stateManager); - stateManager.add(WATERLOGGED); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { - return !state.getValue(WATERLOGGED); - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { - return !state.getValue(WATERLOGGED); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - BlockState state = super.getStateForPlacement(ctx); - if (state != null) { - LevelReader worldView = ctx.getLevel(); - BlockPos blockPos = ctx.getClickedPos(); - boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; - return state.setValue(WATERLOGGED, water); - } - return null; - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - Direction direction = state.getValue(FACING); - BlockPos blockPos = pos.relative(direction.getOpposite()); - return world.getBlockState(blockPos).isFaceSturdy(world, blockPos, direction); - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.125, 0.0, 0.125, 0.875F, 0.875F, 0.875F)); - BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.125, 0.125, 0.125, 0.875F, 1.0, 0.875F)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.125, 0.125, 0.125, 0.875F, 0.875F, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.125, 0.125, 0.0, 0.875F, 0.875F, 0.875F)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.125, 0.125, 0.125, 1.0, 0.875F, 0.875F)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.125, 0.125, 0.875F, 0.875F, 0.875F)); - } -} diff --git a/src/main/java/ru/betterend/blocks/SulphurCrystalBlock.java b/src/main/java/ru/betterend/blocks/SulphurCrystalBlock.java deleted file mode 100644 index f49e5ed3..00000000 --- a/src/main/java/ru/betterend/blocks/SulphurCrystalBlock.java +++ /dev/null @@ -1,123 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -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.level.material.Material; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineablePickaxe; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; - -@SuppressWarnings("deprecation") -public class SulphurCrystalBlock extends BaseAttachedBlock implements AddMineablePickaxe, RenderLayerProvider, SimpleWaterloggedBlock, LiquidBlockContainer { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - public static final IntegerProperty AGE = IntegerProperty.create("age", 0, 2); - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - - public SulphurCrystalBlock() { - super(FabricBlockSettings.of(Material.STONE) - .materialColor(MaterialColor.COLOR_YELLOW) - .sound(SoundType.GLASS) - .requiresCorrectToolForDrops() - .noCollission()); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - super.createBlockStateDefinition(stateManager); - stateManager.add(AGE, WATERLOGGED); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - return state.getValue(AGE) < 2 ? Collections.emptyList() : Lists.newArrayList(new ItemStack( - EndItems.CRYSTALLINE_SULPHUR, - MHelper.randRange(1, 3, MHelper.RANDOM_SOURCE) - )); - } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { - return !state.getValue(WATERLOGGED); - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { - return !state.getValue(WATERLOGGED); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - BlockState state = super.getStateForPlacement(ctx); - if (state != null) { - LevelReader worldView = ctx.getLevel(); - BlockPos blockPos = ctx.getClickedPos(); - boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; - return state.setValue(WATERLOGGED, water); - } - return null; - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - Direction direction = state.getValue(FACING); - BlockPos blockPos = pos.relative(direction.getOpposite()); - return world.getBlockState(blockPos).is(EndBlocks.BRIMSTONE); - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.125, 0.0, 0.125, 0.875F, 0.5, 0.875F)); - BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.125, 0.5, 0.125, 0.875F, 1.0, 0.875F)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.125, 0.125, 0.5, 0.875F, 0.875F, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.125, 0.125, 0.0, 0.875F, 0.875F, 0.5)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.125, 0.125, 1.0, 0.875F, 0.875F)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.125, 0.125, 0.5, 0.875F, 0.875F)); - } -} diff --git a/src/main/java/ru/betterend/blocks/TenaneaFlowersBlock.java b/src/main/java/ru/betterend/blocks/TenaneaFlowersBlock.java deleted file mode 100644 index 060a1742..00000000 --- a/src/main/java/ru/betterend/blocks/TenaneaFlowersBlock.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndParticles; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class TenaneaFlowersBlock extends BaseVineBlock implements CustomColorProvider { - public static final Vec3i[] COLORS; - - public TenaneaFlowersBlock() { - super(15); - } - - @Override - public BlockColor getProvider() { - return (state, world, pos, tintIndex) -> { - if (pos == null) { - pos = BlockPos.ZERO; - } - ; - long i = (MHelper.getRandom(pos.getX(), pos.getZ()) & 63) + pos.getY(); - double delta = i * 0.1; - int index = MHelper.floor(delta); - int index2 = (index + 1) & 3; - delta -= index; - index &= 3; - - Vec3i color1 = COLORS[index]; - Vec3i color2 = COLORS[index2]; - - int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); - int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); - int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); - float[] hsb = ColorUtil.RGBtoHSB(r, g, b, new float[3]); - - return ColorUtil.HSBtoRGB(hsb[0], MHelper.max(0.5F, hsb[1]), hsb[2]); - }; - } - - @Override - public ItemColor getItemProvider() { - return (stack, tintIndex) -> ColorUtil.color(255, 255, 255); - } - - @Override - public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { - return false; - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - super.animateTick(state, world, pos, random); - if (random.nextInt(32) == 0) { - double x = (double) pos.getX() + random.nextGaussian() + 0.5; - double z = (double) pos.getZ() + random.nextGaussian() + 0.5; - double y = (double) pos.getY() + random.nextDouble(); - world.addParticle(EndParticles.TENANEA_PETAL, x, y, z, 0, 0, 0); - } - } - - static { - COLORS = new Vec3i[] { - new Vec3i(250, 111, 222), - new Vec3i(167, 89, 255), - new Vec3i(120, 207, 239), - new Vec3i(255, 87, 182) - }; - } -} diff --git a/src/main/java/ru/betterend/blocks/TenaneaSaplingBlock.java b/src/main/java/ru/betterend/blocks/TenaneaSaplingBlock.java deleted file mode 100644 index b56c1cfc..00000000 --- a/src/main/java/ru/betterend/blocks/TenaneaSaplingBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class TenaneaSaplingBlock extends PottableFeatureSapling { - public TenaneaSaplingBlock() { - super((state)->EndFeatures.TENANEA.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.PINK_MOSS); - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.PINK_MOSS; - } -} diff --git a/src/main/java/ru/betterend/blocks/TerrainPlantBlock.java b/src/main/java/ru/betterend/blocks/TerrainPlantBlock.java deleted file mode 100644 index 3d7d62ab..00000000 --- a/src/main/java/ru/betterend/blocks/TerrainPlantBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.basis.EndPlantBlock; - -public class TerrainPlantBlock extends EndPlantBlock { - private final Block[] ground; - - public TerrainPlantBlock(Block... ground) { - super(true); - this.ground = ground; - } - - @Override - protected boolean isTerrain(BlockState state) { - for (Block block : ground) { - if (state.is(block)) { - return true; - } - } - return false; - } -} diff --git a/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossBlock.java b/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossBlock.java deleted file mode 100644 index 864c563a..00000000 --- a/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossBlock.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class TwistedUmbrellaMossBlock extends EndPlantBlock { - public TwistedUmbrellaMossBlock() { - super(11); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); - } - - @Environment(EnvType.CLIENT) - public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { - return true; - } - - @Environment(EnvType.CLIENT) - public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { - return 1F; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return world.isEmptyBlock(pos.above()); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - int rot = world.random.nextInt(4); - BlockState bs = EndBlocks.TWISTED_UMBRELLA_MOSS_TALL.defaultBlockState() - .setValue(BaseDoublePlantBlock.ROTATION, rot); - BlocksHelper.setWithoutUpdate(world, pos, bs); - BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(BaseDoublePlantBlock.TOP, true)); - } -} diff --git a/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossTallBlock.java b/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossTallBlock.java deleted file mode 100644 index 47ce316e..00000000 --- a/src/main/java/ru/betterend/blocks/TwistedUmbrellaMossTallBlock.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class TwistedUmbrellaMossTallBlock extends BaseDoublePlantBlock { - public TwistedUmbrellaMossTallBlock() { - super(12); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - ItemEntity item = new ItemEntity( - world, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - new ItemStack(EndBlocks.TWISTED_UMBRELLA_MOSS) - ); - world.addFreshEntity(item); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaMossBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaMossBlock.java deleted file mode 100644 index 7e28e05f..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaMossBlock.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class UmbrellaMossBlock extends EndPlantBlock { - public UmbrellaMossBlock() { - super(11); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); - } - - @Environment(EnvType.CLIENT) - public boolean hasEmissiveLighting(BlockGetter world, BlockPos pos) { - return true; - } - - @Environment(EnvType.CLIENT) - public float getAmbientOcclusionLightLevel(BlockGetter world, BlockPos pos) { - return 1F; - } - - @Override - public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) { - return world.isEmptyBlock(pos.above()); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - int rot = world.random.nextInt(4); - BlockState bs = EndBlocks.UMBRELLA_MOSS_TALL.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); - BlocksHelper.setWithoutUpdate(world, pos, bs); - BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(BaseDoublePlantBlock.TOP, true)); - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaMossTallBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaMossTallBlock.java deleted file mode 100644 index f749e10a..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaMossTallBlock.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class UmbrellaMossTallBlock extends BaseDoublePlantBlock { - public UmbrellaMossTallBlock() { - super(12); - } - - @Override - public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { - ItemEntity item = new ItemEntity( - world, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - new ItemStack(EndBlocks.UMBRELLA_MOSS) - ); - world.addFreshEntity(item); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM) || state.is(EndBlocks.JUNGLE_MOSS); - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterBlock.java deleted file mode 100644 index 3993962f..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterBlock.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.MaterialColor; -import net.minecraft.world.phys.BlockHitResult; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class UmbrellaTreeClusterBlock extends BaseBlock { - public static final BooleanProperty NATURAL = BlockProperties.NATURAL; - - public UmbrellaTreeClusterBlock() { - super(FabricBlockSettings - .copyOf(Blocks.NETHER_WART_BLOCK) - .mapColor(MaterialColor.COLOR_PURPLE) - .luminance(15) - ); - registerDefaultState(stateDefinition.any().setValue(NATURAL, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(NATURAL); - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - ItemStack stack = player.getMainHandItem(); - if (stack.getItem() == Items.GLASS_BOTTLE) { - if (!player.isCreative()) { - stack.shrink(1); - } - stack = new ItemStack(EndItems.UMBRELLA_CLUSTER_JUICE); - player.addItem(stack); - world.playLocalSound( - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - SoundEvents.BOTTLE_FILL, - SoundSource.BLOCKS, - 1, - 1, - false - ); - BlocksHelper.setWithUpdate( - world, - pos, - EndBlocks.UMBRELLA_TREE_CLUSTER_EMPTY.defaultBlockState().setValue(NATURAL, state.getValue(NATURAL)) - ); - return InteractionResult.SUCCESS; - } - return InteractionResult.FAIL; - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java deleted file mode 100644 index 10b4b8aa..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaTreeClusterEmptyBlock.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class UmbrellaTreeClusterEmptyBlock extends BaseBlock { - public static final BooleanProperty NATURAL = EndBlockProperties.NATURAL; - - public UmbrellaTreeClusterEmptyBlock() { - super(FabricBlockSettings - .copyOf(Blocks.NETHER_WART_BLOCK) - .mapColor(MaterialColor.COLOR_PURPLE) - .randomTicks() - ); - registerDefaultState(stateDefinition.any().setValue(NATURAL, false)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(NATURAL); - } - - @Override - @SuppressWarnings("deprecation") - public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - if (state.getValue(NATURAL) && random.nextInt(16) == 0) { - BlocksHelper.setWithUpdate( - world, - pos, - EndBlocks.UMBRELLA_TREE_CLUSTER.defaultBlockState().setValue(UmbrellaTreeClusterBlock.NATURAL, true) - ); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaTreeMembraneBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaTreeMembraneBlock.java deleted file mode 100644 index 7eaca069..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaTreeMembraneBlock.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.betterend.blocks; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SlimeBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.BlockModelProvider; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.Collections; -import java.util.List; - -public class UmbrellaTreeMembraneBlock extends SlimeBlock implements RenderLayerProvider, BlockModelProvider { - public static final IntegerProperty COLOR = EndBlockProperties.COLOR; - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0); - - public UmbrellaTreeMembraneBlock() { - super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK)); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - double px = ctx.getClickedPos().getX() * 0.1; - double py = ctx.getClickedPos().getY() * 0.1; - double pz = ctx.getClickedPos().getZ() * 0.1; - return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4)); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(COLOR); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) { - if (state.getValue(COLOR) > 0) { - return Lists.newArrayList(new ItemStack(this)); - } - else { - return MHelper.RANDOM.nextInt(4) == 0 ? Lists.newArrayList(new ItemStack(EndBlocks.UMBRELLA_TREE_SAPLING)) : Collections - .emptyList(); - } - } - - @Override - public boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) { - return state.getValue(COLOR) > 0; - } - - @Environment(EnvType.CLIENT) - public boolean skipRendering(BlockState state, BlockState stateFrom, Direction direction) { - if (state.getValue(COLOR) > 0) { - return super.skipRendering(state, stateFrom, direction); - } - else { - return false; - } - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - return getBlockModel(resourceLocation, defaultBlockState()); - } -} diff --git a/src/main/java/ru/betterend/blocks/UmbrellaTreeSaplingBlock.java b/src/main/java/ru/betterend/blocks/UmbrellaTreeSaplingBlock.java deleted file mode 100644 index 0ff48c93..00000000 --- a/src/main/java/ru/betterend/blocks/UmbrellaTreeSaplingBlock.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.blocks; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.client.render.BCLRenderLayer; -import ru.betterend.blocks.basis.PottableFeatureSapling; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; - -public class UmbrellaTreeSaplingBlock extends PottableFeatureSapling { - public UmbrellaTreeSaplingBlock() { - super((state)-> EndFeatures.UMBRELLA_TREE.getFeature()); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - return world.getBlockState(pos.below()).is(EndBlocks.JUNGLE_MOSS); - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.TRANSLUCENT; - } - - @Override - public boolean canPlantOn(Block block) { - return block == EndBlocks.JUNGLE_MOSS; - } -} diff --git a/src/main/java/ru/betterend/blocks/VentBubbleColumnBlock.java b/src/main/java/ru/betterend/blocks/VentBubbleColumnBlock.java deleted file mode 100644 index c0e69b95..00000000 --- a/src/main/java/ru/betterend/blocks/VentBubbleColumnBlock.java +++ /dev/null @@ -1,169 +0,0 @@ -package ru.betterend.blocks; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.BucketPickup; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.block.state.BlockState; -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.level.material.Material; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class VentBubbleColumnBlock extends Block implements BucketPickup, LiquidBlockContainer { - public VentBubbleColumnBlock() { - super(FabricBlockSettings.of(Material.BUBBLE_COLUMN).nonOpaque().noCollision().noLootTable()); - } - - @Override - public ItemStack pickupBlock(LevelAccessor world, BlockPos pos, BlockState state) { - world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); - return new ItemStack(Items.WATER_BUCKET); - } - - @Override - @SuppressWarnings("deprecation") - public RenderShape getRenderShape(BlockState state) { - return RenderShape.INVISIBLE; - } - - @Override - @SuppressWarnings("deprecation") - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState blockState = world.getBlockState(pos.below()); - return blockState.is(this) || blockState.is(EndBlocks.HYDROTHERMAL_VENT); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { - return Shapes.empty(); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - if (!state.canSurvive(world, pos)) { - return Blocks.WATER.defaultBlockState(); - } - else { - BlockPos up = pos.above(); - if (world.getBlockState(up).is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate(world, up, this); - world.scheduleTick(up, this, 5); - } - } - return state; - } - - @Environment(EnvType.CLIENT) - public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { - if (random.nextInt(4) == 0) { - double px = pos.getX() + random.nextDouble(); - double py = pos.getY() + random.nextDouble(); - double pz = pos.getZ() + random.nextDouble(); - world.addAlwaysVisibleParticle(ParticleTypes.BUBBLE_COLUMN_UP, px, py, pz, 0, 0.04, 0); - } - if (random.nextInt(200) == 0) { - world.playLocalSound( - pos.getX(), - pos.getY(), - pos.getZ(), - SoundEvents.BUBBLE_COLUMN_UPWARDS_AMBIENT, - SoundSource.BLOCKS, - 0.2F + random.nextFloat() * 0.2F, - 0.9F + random.nextFloat() * 0.15F, - false - ); - } - } - - @Environment(EnvType.CLIENT) - @SuppressWarnings("deprecation") - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - BlockState blockState = world.getBlockState(pos.above()); - if (blockState.isAir()) { - entity.onAboveBubbleCol(false); - if (!world.isClientSide) { - ServerLevel serverWorld = (ServerLevel) world; - - for (int i = 0; i < 2; ++i) { - serverWorld.sendParticles( - ParticleTypes.SPLASH, - (double) pos.getX() + world.random.nextDouble(), - (double) (pos.getY() + 1), - (double) pos.getZ() + world.random.nextDouble(), - 1, - 0.0D, - 0.0D, - 0.0D, - 1.0D - ); - serverWorld.sendParticles( - ParticleTypes.BUBBLE, - (double) pos.getX() + world.random.nextDouble(), - (double) (pos.getY() + 1), - (double) pos.getZ() + world.random.nextDouble(), - 1, - 0.0D, - 0.01D, - 0.0D, - 0.2D - ); - } - } - } - else { - entity.onInsideBubbleColumn(false); - } - } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { - return false; - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { - return false; - } - - @Override - @SuppressWarnings("deprecation") - public FluidState getFluidState(BlockState state) { - return Fluids.WATER.getSource(false); - } - - - @Override - public Optional getPickupSound() { - return Fluids.WATER.getPickupSound(); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndAnvilBlock.java b/src/main/java/ru/betterend/blocks/basis/EndAnvilBlock.java deleted file mode 100644 index 4bcf5664..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndAnvilBlock.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.LeveledAnvilBlock; -import ru.betterend.complexmaterials.MetalMaterial; - -public class EndAnvilBlock extends LeveledAnvilBlock { - protected MetalMaterial metalMaterial; - - public EndAnvilBlock(MaterialColor color, int level) { - super(color, level); - } - - public EndAnvilBlock(MetalMaterial metalMaterial, MaterialColor color, int level) { - super(color, level); - this.metalMaterial = metalMaterial; - } - - public int getCraftingLevel() { - return level; - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndLanternBlock.java b/src/main/java/ru/betterend/blocks/basis/EndLanternBlock.java deleted file mode 100644 index 065444ed..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndLanternBlock.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.state.BlockState; -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.BooleanProperty; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.client.models.ModelsHelper; - -import java.util.Map; - -@SuppressWarnings("deprecation") -public class EndLanternBlock extends BaseBlockNotFull implements SimpleWaterloggedBlock, LiquidBlockContainer { - public static final BooleanProperty IS_FLOOR = BlockProperties.IS_FLOOR; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - - public EndLanternBlock(Block source) { - this(FabricBlockSettings.copyOf(source).luminance(15).noOcclusion()); - } - - public EndLanternBlock(Properties settings) { - super(settings.noOcclusion()); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(IS_FLOOR, WATERLOGGED); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - LevelReader worldView = ctx.getLevel(); - BlockPos blockPos = ctx.getClickedPos(); - Direction dir = ctx.getClickedFace(); - boolean water = worldView.getFluidState(blockPos).getType() == Fluids.WATER; - if (dir != Direction.DOWN && dir != Direction.UP) { - if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { - return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); - } - else if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { - return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); - } - else { - return null; - } - } - else if (dir == Direction.DOWN) { - if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { - return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); - } - else if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { - return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); - } - else { - return null; - } - } - else { - if (canSupportCenter(worldView, blockPos.below(), Direction.UP)) { - return defaultBlockState().setValue(IS_FLOOR, true).setValue(WATERLOGGED, water); - } - else if (canSupportCenter(worldView, blockPos.above(), Direction.DOWN)) { - return defaultBlockState().setValue(IS_FLOOR, false).setValue(WATERLOGGED, water); - } - else { - return null; - } - } - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - if (state.getValue(IS_FLOOR)) { - return canSupportCenter(world, pos.below(), Direction.UP); - } - else { - return canSupportCenter(world, pos.above(), Direction.DOWN); - } - } - - @Override - public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { - Boolean water = state.getValue(WATERLOGGED); - if (water) { - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - } - if (!canSurvive(state, world, pos)) { - return water ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); - } - else { - return state; - } - } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { - return false; - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { - return false; - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); - } - - @Override - @Environment(EnvType.CLIENT) - public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map modelCache) { - String floor = blockState.getValue(IS_FLOOR) ? "_floor" : ""; - ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath() + floor); - registerBlockModel(stateId, modelId, blockState, modelCache); - return ModelsHelper.createBlockSimple(modelId); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndPlantBlock.java b/src/main/java/ru/betterend/blocks/basis/EndPlantBlock.java deleted file mode 100644 index c935cc34..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndPlantBlock.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BasePlantBlock; -import ru.betterend.interfaces.PottablePlant; - -import java.util.function.Function; - -public class EndPlantBlock extends BasePlantBlock implements PottablePlant { - public EndPlantBlock() { - this(false, p->p); - } - - public EndPlantBlock(int light) { - this(light, p->p); - } - public EndPlantBlock(int light, Function propMod) { - this(false, light, propMod); - } - - public EndPlantBlock(boolean replaceable) { - super(replaceable); - } - public EndPlantBlock(boolean replaceable, Function propMod) { - super(replaceable, propMod); - } - - public EndPlantBlock(boolean replaceable, int light){ - this(replaceable, light, p->p); - } - public EndPlantBlock(boolean replaceable, int light, Function propMod) { - super(replaceable, light, propMod); - } - - public EndPlantBlock(Properties settings) { - super(settings); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } - - @Override - public boolean canPlantOn(Block block) { - return isTerrain(block.defaultBlockState()); - } - - @Override - public boolean canBePotted() { - return getStateDefinition().getProperties().isEmpty(); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndPlantWithAgeBlock.java b/src/main/java/ru/betterend/blocks/basis/EndPlantWithAgeBlock.java deleted file mode 100644 index 3019f1b5..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndPlantWithAgeBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BasePlantWithAgeBlock; - -import java.util.function.Function; - -public abstract class EndPlantWithAgeBlock extends BasePlantWithAgeBlock { - - public EndPlantWithAgeBlock() { - } - - public EndPlantWithAgeBlock(Function propMod) { - super(propMod); - } - - public EndPlantWithAgeBlock(Properties settings) { - super(settings); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndTerrainBlock.java b/src/main/java/ru/betterend/blocks/basis/EndTerrainBlock.java deleted file mode 100644 index 9fa7d4fd..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndTerrainBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; - -import ru.bclib.api.tag.CommonBlockTags; - -import ru.bclib.blocks.BaseTerrainBlock; -import ru.bclib.interfaces.TagProvider; -import ru.betterend.interfaces.PottableTerrain; - -import java.util.List; - -public class EndTerrainBlock extends BaseTerrainBlock implements PottableTerrain, TagProvider { - public EndTerrainBlock(MaterialColor color) { - super(Blocks.END_STONE, color); - } - - @Override - public void addTags(List> blockTags, List> itemTags) { - blockTags.add(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndTripleTerrain.java b/src/main/java/ru/betterend/blocks/basis/EndTripleTerrain.java deleted file mode 100644 index 10d4d7b1..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndTripleTerrain.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.TripleTerrainBlock; -import ru.betterend.interfaces.PottableTerrain; - -public class EndTripleTerrain extends TripleTerrainBlock implements PottableTerrain { - public EndTripleTerrain(MaterialColor color) { - super(Blocks.END_STONE, color); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndUnderwaterPlantBlock.java b/src/main/java/ru/betterend/blocks/basis/EndUnderwaterPlantBlock.java deleted file mode 100644 index 0e5675eb..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndUnderwaterPlantBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.UnderwaterPlantBlock; - -import java.util.function.Function; - -public class EndUnderwaterPlantBlock extends UnderwaterPlantBlock { - - public EndUnderwaterPlantBlock() { - } - - public EndUnderwaterPlantBlock(int light, Function propMod) { - super(light, propMod); - } - - public EndUnderwaterPlantBlock(Properties settings) { - super(settings); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java b/src/main/java/ru/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java deleted file mode 100644 index b5fa2d18..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndUnderwaterWallPlantBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BaseUnderwaterWallPlantBlock; - -public class EndUnderwaterWallPlantBlock extends BaseUnderwaterWallPlantBlock { - - public EndUnderwaterWallPlantBlock() { - } - - public EndUnderwaterWallPlantBlock(int light) { - super(light); - } - - public EndUnderwaterWallPlantBlock(Properties settings) { - super(settings); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndWallMushroom.java b/src/main/java/ru/betterend/blocks/basis/EndWallMushroom.java deleted file mode 100644 index a08cc07b..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndWallMushroom.java +++ /dev/null @@ -1,17 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.WallMushroomBlock; - -public class EndWallMushroom extends WallMushroomBlock { - - public EndWallMushroom(int light) { - super(light); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/EndWallPlantBlock.java b/src/main/java/ru/betterend/blocks/basis/EndWallPlantBlock.java deleted file mode 100644 index f08d6da1..00000000 --- a/src/main/java/ru/betterend/blocks/basis/EndWallPlantBlock.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BaseWallPlantBlock; - -public class EndWallPlantBlock extends BaseWallPlantBlock { - public EndWallPlantBlock() { - } - - public EndWallPlantBlock(int light) { - super(light); - } - - public EndWallPlantBlock(Properties settings) { - super(settings); - } - - @Override - protected boolean isTerrain(BlockState state) { - return state.is(CommonBlockTags.END_STONES); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/FurBlock.java b/src/main/java/ru/betterend/blocks/basis/FurBlock.java deleted file mode 100644 index e2c32149..00000000 --- a/src/main/java/ru/betterend/blocks/basis/FurBlock.java +++ /dev/null @@ -1,94 +0,0 @@ -package ru.betterend.blocks.basis; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.bclib.api.tag.NamedBlockTags; -import ru.bclib.api.tag.TagAPI; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.client.render.BCLRenderLayer; -import ru.bclib.interfaces.RenderLayerProvider; -import ru.bclib.interfaces.tools.AddMineableShears; -import ru.bclib.items.tool.BaseShearsItem; -import ru.bclib.util.MHelper; - -import java.util.EnumMap; -import java.util.List; - -public class FurBlock extends BaseAttachedBlock implements RenderLayerProvider, AddMineableShears { - private static final EnumMap BOUNDING_SHAPES = Maps.newEnumMap(Direction.class); - private final ItemLike drop; - private final int dropChance; - - public FurBlock(ItemLike drop, int light, int dropChance, boolean wet) { - super(FabricBlockSettings.of(Material.REPLACEABLE_PLANT) - .luminance(light) - .sound(wet ? SoundType.WET_GRASS : SoundType.GRASS) - .noCollission()); - this.drop = drop; - this.dropChance = dropChance; - TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); - } - - public FurBlock(ItemLike drop, int dropChance) { - super(FabricBlockSettings.of(Material.REPLACEABLE_PLANT) - - .sound(SoundType.GRASS) - .noCollission()); - this.drop = drop; - this.dropChance = dropChance; - TagAPI.addBlockTag(NamedBlockTags.LEAVES, this); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return BOUNDING_SHAPES.get(state.getValue(FACING)); - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel( - Enchantments.SILK_TOUCH, - tool - ) > 0) { - return Lists.newArrayList(new ItemStack(this)); - } - else if (dropChance < 1 || MHelper.RANDOM.nextInt(dropChance) == 0) { - return Lists.newArrayList(new ItemStack(drop)); - } - else { - return Lists.newArrayList(); - } - } - - @Override - public BCLRenderLayer getRenderLayer() { - return BCLRenderLayer.CUTOUT; - } - - static { - BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.0, 0.0, 0.0, 1.0, 0.5, 1.0)); - BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.0, 0.5, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5)); - BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0)); - BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0)); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/LitBaseBlock.java b/src/main/java/ru/betterend/blocks/basis/LitBaseBlock.java deleted file mode 100644 index af09b680..00000000 --- a/src/main/java/ru/betterend/blocks/basis/LitBaseBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlock; - -public class LitBaseBlock extends BaseBlock { - private static final String PATTERN = "{\"parent\":\"betterend:block/cube_noshade\",\"textures\":{\"texture\":\"betterend:block/name\"}}"; - - public LitBaseBlock(Properties settings) { - super(settings); - } - - @Nullable - @Override - @Environment(EnvType.CLIENT) - public BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - return BlockModel.fromString(PATTERN.replace("name", resourceLocation.getPath())); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/LitPillarBlock.java b/src/main/java/ru/betterend/blocks/basis/LitPillarBlock.java deleted file mode 100644 index d09a9c40..00000000 --- a/src/main/java/ru/betterend/blocks/basis/LitPillarBlock.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.resources.ResourceLocation; -import ru.bclib.blocks.BaseRotatedPillarBlock; - -import java.util.Optional; - -public class LitPillarBlock extends BaseRotatedPillarBlock { - private static final String PATTERN = "{\"parent\":\"betterend:block/pillar_noshade\",\"textures\":{\"end\":\"betterend:block/name_top\",\"side\":\"betterend:block/name_side\"}}"; - - public LitPillarBlock(Properties settings) { - super(settings); - } - - @Override - @Environment(EnvType.CLIENT) - protected Optional createBlockPattern(ResourceLocation blockId) { - String name = blockId.getPath(); - return Optional.of(PATTERN.replace("name", name)); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/PedestalBlock.java b/src/main/java/ru/betterend/blocks/basis/PedestalBlock.java deleted file mode 100644 index 3bd8db5b..00000000 --- a/src/main/java/ru/betterend/blocks/basis/PedestalBlock.java +++ /dev/null @@ -1,460 +0,0 @@ -package ru.betterend.blocks.basis; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -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.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BaseBlockNotFull; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.client.models.ModelsHelper; -import ru.betterend.blocks.EndBlockProperties; -import ru.betterend.blocks.EndBlockProperties.PedestalState; -import ru.betterend.blocks.InfusionPedestal; -import ru.betterend.blocks.entities.InfusionPedestalEntity; -import ru.betterend.blocks.entities.PedestalBlockEntity; -import ru.betterend.client.models.Patterns; -import ru.betterend.rituals.InfusionRitual; - -import java.awt.Point; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.ToIntFunction; - -public class PedestalBlock extends BaseBlockNotFull implements EntityBlock { - public final static EnumProperty STATE = EndBlockProperties.PEDESTAL_STATE; - public static final BooleanProperty HAS_ITEM = EndBlockProperties.HAS_ITEM; - public static final BooleanProperty HAS_LIGHT = BlockProperties.HAS_LIGHT; - - private static final VoxelShape SHAPE_DEFAULT; - private static final VoxelShape SHAPE_COLUMN; - private static final VoxelShape SHAPE_PILLAR; - private static final VoxelShape SHAPE_PEDESTAL_TOP; - private static final VoxelShape SHAPE_COLUMN_TOP; - private static final VoxelShape SHAPE_BOTTOM; - - protected final Block parent; - protected float height = 1.0F; - - public PedestalBlock(Block parent) { - super(FabricBlockSettings.copyOf(parent).luminance(getLuminance(parent.defaultBlockState()))); - this.registerDefaultState( - stateDefinition - .any() - .setValue(STATE, PedestalState.DEFAULT) - .setValue(HAS_ITEM, false) - .setValue(HAS_LIGHT, false) - ); - this.parent = parent; - } - - private static ToIntFunction getLuminance(BlockState parent) { - final int light = parent.getLightEmission(); - if (light > 0) { - return state -> light; - } - return state -> state.getValue(HAS_LIGHT) ? 12 : 0; - } - - public float getHeight(BlockState state) { - if (state.getBlock() instanceof PedestalBlock && state.getValue(STATE) == PedestalState.PEDESTAL_TOP) { - return this.height - 0.2F; - } - return this.height; - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (!state.is(this) || !isPlaceable(state)) { - return InteractionResult.PASS; - } - BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof PedestalBlockEntity) { - PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; - if (pedestal.isEmpty()) { - ItemStack itemStack = player.getItemInHand(hand); - if (itemStack.isEmpty()) return InteractionResult.CONSUME; - pedestal.setItem(0, itemStack); - level.blockEntityChanged(pos); - checkRitual(level, pos); - return InteractionResult.sidedSuccess(level.isClientSide()); - } - else { - ItemStack itemStack = pedestal.getItem(0); - if (player.addItem(itemStack)) { - pedestal.removeItemNoUpdate(0); - level.blockEntityChanged(pos); - checkRitual(level, pos); - return InteractionResult.sidedSuccess(level.isClientSide()); - } - return InteractionResult.FAIL; - } - } - return InteractionResult.PASS; - } - - @Override - public void destroy(LevelAccessor levelAccessor, BlockPos blockPos, BlockState blockState) { - MutableBlockPos posMutable = new MutableBlockPos(); - for (Point point : InfusionRitual.getMap()) { - posMutable.set(blockPos).move(point.x, 0, point.y); - BlockState state = levelAccessor.getBlockState(posMutable); - if (state.getBlock() instanceof InfusionPedestal) { - BlockEntity blockEntity = levelAccessor.getBlockEntity(posMutable); - if (blockEntity instanceof InfusionPedestalEntity) { - InfusionPedestalEntity pedestal = (InfusionPedestalEntity) blockEntity; - if (pedestal.hasRitual()) { - pedestal.getRitual().setDirty(); - } - } - break; - } - } - } - - public void checkRitual(Level world, BlockPos pos) { - MutableBlockPos posMutable = new MutableBlockPos(); - for (Point point : InfusionRitual.getMap()) { - posMutable.set(pos).move(point.x, 0, point.y); - BlockState state = world.getBlockState(posMutable); - if (state.getBlock() instanceof InfusionPedestal) { - ((InfusionPedestal) state.getBlock()).checkRitual(world, posMutable); - break; - } - } - } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) { - Level world = context.getLevel(); - BlockPos pos = context.getClickedPos(); - BlockState upState = world.getBlockState(pos.above()); - BlockState downState = world.getBlockState(pos.below()); - boolean upSideSolid = upState.isFaceSturdy(world, pos.above(), Direction.DOWN) || upState.is(BlockTags.WALLS); - boolean hasPedestalOver = upState.getBlock() instanceof PedestalBlock; - boolean hasPedestalUnder = downState.getBlock() instanceof PedestalBlock; - if (!hasPedestalOver && hasPedestalUnder && upSideSolid) { - return defaultBlockState().setValue(STATE, PedestalState.COLUMN_TOP); - } - else if (!hasPedestalOver && !hasPedestalUnder && upSideSolid) { - return defaultBlockState().setValue(STATE, PedestalState.COLUMN); - } - else if (hasPedestalUnder && hasPedestalOver) { - return defaultBlockState().setValue(STATE, PedestalState.PILLAR); - } - else if (hasPedestalUnder) { - return defaultBlockState().setValue(STATE, PedestalState.PEDESTAL_TOP); - } - else if (hasPedestalOver) { - return defaultBlockState().setValue(STATE, PedestalState.BOTTOM); - } - return defaultBlockState(); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - BlockState updated = getUpdatedState(state, direction, newState, world, pos, posFrom); - if (!updated.is(this)) return updated; - if (!isPlaceable(updated)) { - moveStoredStack(world, updated, pos); - } - return updated; - } - - private BlockState getUpdatedState(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom) { - if (!state.is(this)) return state.updateShape(direction, newState, world, pos, posFrom); - if (direction != Direction.UP && direction != Direction.DOWN) return state; - BlockState upState = world.getBlockState(pos.above()); - BlockState downState = world.getBlockState(pos.below()); - boolean upSideSolid = upState.isFaceSturdy(world, pos.above(), Direction.DOWN) || upState.is(BlockTags.WALLS); - boolean hasPedestalOver = upState.getBlock() instanceof PedestalBlock; - boolean hasPedestalUnder = downState.getBlock() instanceof PedestalBlock; - if (direction == Direction.UP) { - upSideSolid = newState.isFaceSturdy(world, posFrom, Direction.DOWN) || newState.is(BlockTags.WALLS); - hasPedestalOver = newState.getBlock() instanceof PedestalBlock; - } - else { - hasPedestalUnder = newState.getBlock() instanceof PedestalBlock; - } - BlockState updatedState; - if (!hasPedestalOver && hasPedestalUnder && upSideSolid) { - updatedState = state.setValue(STATE, PedestalState.COLUMN_TOP); - } - else if (!hasPedestalOver && !hasPedestalUnder && upSideSolid) { - updatedState = state.setValue(STATE, PedestalState.COLUMN); - } - else if (hasPedestalUnder && hasPedestalOver) { - updatedState = state.setValue(STATE, PedestalState.PILLAR); - } - else if (hasPedestalUnder) { - updatedState = state.setValue(STATE, PedestalState.PEDESTAL_TOP); - } - else if (hasPedestalOver) { - updatedState = state.setValue(STATE, PedestalState.BOTTOM); - } - else { - updatedState = state.setValue(STATE, PedestalState.DEFAULT); - } - if (!isPlaceable(updatedState)) { - updatedState = updatedState.setValue(HAS_ITEM, false).setValue(HAS_LIGHT, false); - } - return updatedState; - } - - @Override - public List getDrops(BlockState state, LootContext.Builder builder) { - List drop = Lists.newArrayList(super.getDrops(state, builder)); - if (state.is(this)) { - if (isPlaceable(state)) { - BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); - if (blockEntity instanceof PedestalBlockEntity) { - PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; - if (!pedestal.isEmpty()) { - drop.add(pedestal.getItem(0)); - } - } - } - else { - return drop; - } - } - return drop; - } - - private void moveStoredStack(LevelAccessor world, BlockState state, BlockPos pos) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof PedestalBlockEntity && state.is(this)) { - PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; - ItemStack stack = pedestal.removeItemNoUpdate(0); - if (!stack.isEmpty()) { - moveStoredStack(blockEntity, world, stack, pos.above()); - } - } - } - - private void moveStoredStack(BlockEntity blockEntity, LevelAccessor world, ItemStack stack, BlockPos pos) { - BlockState state = world.getBlockState(pos); - if (!state.is(this)) { - dropStoredStack(blockEntity, stack, pos); - } - else if (state.getValue(STATE).equals(PedestalState.PILLAR)) { - moveStoredStack(blockEntity, world, stack, pos.above()); - } - else if (!isPlaceable(state)) { - dropStoredStack(blockEntity, stack, pos); - } - else if (blockEntity instanceof PedestalBlockEntity) { - PedestalBlockEntity pedestal = (PedestalBlockEntity) blockEntity; - if (pedestal.isEmpty()) { - pedestal.setItem(0, stack); - } - else { - dropStoredStack(blockEntity, stack, pos); - } - } - else { - dropStoredStack(blockEntity, stack, pos); - } - } - - private void dropStoredStack(BlockEntity blockEntity, ItemStack stack, BlockPos pos) { - if (blockEntity != null && blockEntity.getLevel() != null) { - Level world = blockEntity.getLevel(); - Block.popResource(world, getDropPos(world, pos), stack); - } - } - - private BlockPos getDropPos(LevelAccessor world, BlockPos pos) { - BlockPos dropPos; - if (world.getBlockState(pos).isAir()) { - return pos; - } - if (world.getBlockState(pos.above()).isAir()) { - return pos.above(); - } - for (int i = 2; i < Direction.values().length; i++) { - dropPos = pos.relative(Direction.from3DDataValue(i)); - if (world.getBlockState(dropPos).isAir()) { - return dropPos.immutable(); - } - } - return getDropPos(world, pos.above()); - } - - public boolean isPlaceable(BlockState state) { - if (!state.is(this)) return false; - PedestalState currentState = state.getValue(STATE); - return currentState == PedestalState.DEFAULT || currentState == PedestalState.PEDESTAL_TOP; - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { - if (state.is(this)) { - switch (state.getValue(STATE)) { - case BOTTOM: { - return SHAPE_BOTTOM; - } - case PEDESTAL_TOP: { - return SHAPE_PEDESTAL_TOP; - } - case COLUMN_TOP: { - return SHAPE_COLUMN_TOP; - } - case PILLAR: { - return SHAPE_PILLAR; - } - case COLUMN: { - return SHAPE_COLUMN; - } - default: { - return SHAPE_DEFAULT; - } - } - } - return super.getShape(state, world, pos, context); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder stateManager) { - stateManager.add(STATE, HAS_ITEM, HAS_LIGHT); - } - - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new PedestalBlockEntity(blockPos, blockState); - } - - public boolean hasUniqueEntity() { - return false; - } - - @Override - @SuppressWarnings("deprecation") - public boolean hasAnalogOutputSignal(BlockState state) { - return state.getBlock() instanceof PedestalBlock; - } - - @Override - @SuppressWarnings("deprecation") - public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { - return state.getValue(HAS_ITEM) ? 15 : 0; - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation blockId) { - return getBlockModel(blockId, defaultBlockState()); - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - Map textures = createTexturesMap(); - PedestalState state = blockState.getValue(STATE); - Optional pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_DEFAULT, textures); - switch (state) { - case COLUMN_TOP: - pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_COLUMN_TOP, textures); - break; - case COLUMN: - pattern = Patterns.createJson(Patterns.BLOKC_PEDESTAL_COLUMN, textures); - break; - case PEDESTAL_TOP: - pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_TOP, textures); - break; - case BOTTOM: - pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_BOTTOM, textures); - break; - case PILLAR: - pattern = Patterns.createJson(Patterns.BLOCK_PEDESTAL_PILLAR, textures); - break; - default: - break; - } - return ModelsHelper.fromPattern(pattern); - } - - @Override - @Environment(EnvType.CLIENT) - public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map modelCache) { - PedestalState state = blockState.getValue(STATE); - ResourceLocation modelId = new ResourceLocation( - stateId.getNamespace(), - "block/" + stateId.getPath() + "_" + state - ); - registerBlockModel(stateId, modelId, blockState, modelCache); - return ModelsHelper.createBlockSimple(modelId); - } - - protected Map createTexturesMap() { - ResourceLocation blockId = Registry.BLOCK.getKey(parent); - String name = blockId.getPath(); - Map textures = Maps.newHashMap(); - textures.put("%mod%", blockId.getNamespace()); - textures.put("%top%", name + "_top"); - textures.put("%base%", name + "_base"); - textures.put("%pillar%", name + "_pillar"); - textures.put("%bottom%", name + "_bottom"); - return textures; - } - - static { - VoxelShape basinUp = Block.box(2, 3, 2, 14, 4, 14); - VoxelShape basinDown = Block.box(0, 0, 0, 16, 3, 16); - VoxelShape columnTopUp = Block.box(1, 14, 1, 15, 16, 15); - VoxelShape columnTopDown = Block.box(2, 13, 2, 14, 14, 14); - VoxelShape pedestalTop = Block.box(1, 8, 1, 15, 10, 15); - VoxelShape pedestalDefault = Block.box(1, 12, 1, 15, 14, 15); - VoxelShape pillar = Block.box(3, 0, 3, 13, 8, 13); - VoxelShape pillarDefault = Block.box(3, 0, 3, 13, 12, 13); - VoxelShape columnTop = Shapes.or(columnTopDown, columnTopUp); - VoxelShape basin = Shapes.or(basinDown, basinUp); - SHAPE_PILLAR = Block.box(3, 0, 3, 13, 16, 13); - SHAPE_DEFAULT = Shapes.or(basin, pillarDefault, pedestalDefault); - SHAPE_PEDESTAL_TOP = Shapes.or(pillar, pedestalTop); - SHAPE_COLUMN_TOP = Shapes.or(SHAPE_PILLAR, columnTop); - SHAPE_COLUMN = Shapes.or(basin, SHAPE_PILLAR, columnTop); - SHAPE_BOTTOM = Shapes.or(basin, SHAPE_PILLAR); - } - - /*@Override - @Nullable - public BlockEntityTicker getTicker(Level level, BlockState blockState, BlockEntityType blockEntityType) { - return level.isClientSide() ? PedestalBlockEntity::tick : null; - }*/ -} diff --git a/src/main/java/ru/betterend/blocks/basis/PottableCropBlock.java b/src/main/java/ru/betterend/blocks/basis/PottableCropBlock.java deleted file mode 100644 index 13978e19..00000000 --- a/src/main/java/ru/betterend/blocks/basis/PottableCropBlock.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import ru.bclib.blocks.BaseCropBlock; -import ru.betterend.interfaces.PottablePlant; - -public class PottableCropBlock extends BaseCropBlock implements PottablePlant { - private final Block[] terrain; - - public PottableCropBlock(Item drop, Block... terrain) { - super(drop, terrain); - this.terrain = terrain; - } - - @Override - public boolean canPlantOn(Block block) { - for (Block ter : terrain) { - if (block == ter) { - return true; - } - } - return false; - } - - @Override - public String getPottedState() { - return "age=3"; - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/PottableFeatureSapling.java b/src/main/java/ru/betterend/blocks/basis/PottableFeatureSapling.java deleted file mode 100644 index b8dc1fb4..00000000 --- a/src/main/java/ru/betterend/blocks/basis/PottableFeatureSapling.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.Feature; -import ru.bclib.blocks.FeatureSaplingBlock; -import ru.betterend.interfaces.PottablePlant; - -import java.util.function.Function; - -public abstract class PottableFeatureSapling extends FeatureSaplingBlock implements PottablePlant { - public PottableFeatureSapling(Function> featureSupplier) { - super(featureSupplier); - } - - public PottableFeatureSapling(int light, Function> featureSupplier) { - super(light, featureSupplier); - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/PottableLeavesBlock.java b/src/main/java/ru/betterend/blocks/basis/PottableLeavesBlock.java deleted file mode 100644 index 24382dd7..00000000 --- a/src/main/java/ru/betterend/blocks/basis/PottableLeavesBlock.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.blocks.BaseLeavesBlock; -import ru.betterend.interfaces.PottablePlant; - -public class PottableLeavesBlock extends BaseLeavesBlock implements PottablePlant { - - public PottableLeavesBlock(Block sapling, MaterialColor color) { - super(sapling, color); - } - - public PottableLeavesBlock(Block sapling, MaterialColor color, int light) { - super(sapling, color, light); - } - - @Override - public boolean canPlantOn(Block block) { - if (sapling instanceof PottablePlant) { - return ((PottablePlant) sapling).canPlantOn(block); - } - return true; - } -} diff --git a/src/main/java/ru/betterend/blocks/basis/StoneLanternBlock.java b/src/main/java/ru/betterend/blocks/basis/StoneLanternBlock.java deleted file mode 100644 index 69ccbdd7..00000000 --- a/src/main/java/ru/betterend/blocks/basis/StoneLanternBlock.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.betterend.blocks.basis; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.Nullable; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.interfaces.CustomColorProvider; -import ru.betterend.client.models.Patterns; -import ru.betterend.registry.EndBlocks; - -import java.util.Optional; - -public class StoneLanternBlock extends EndLanternBlock implements CustomColorProvider { - private static final VoxelShape SHAPE_CEIL = Block.box(3, 1, 3, 13, 16, 13); - private static final VoxelShape SHAPE_FLOOR = Block.box(3, 0, 3, 13, 15, 13); - - public StoneLanternBlock(Block source) { - super(FabricBlockSettings.copyOf(source).luminance(15)); - } - - @Override - public BlockColor getProvider() { - return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getProvider(); - } - - @Override - public ItemColor getItemProvider() { - return ((CustomColorProvider) EndBlocks.AURORA_CRYSTAL).getItemProvider(); - } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { - return state.getValue(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL; - } - - @Override - @Environment(EnvType.CLIENT) - public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) { - String blockName = resourceLocation.getPath(); - Optional pattern = blockState.getValue(IS_FLOOR) ? Patterns.createJson( - Patterns.BLOCK_STONE_LANTERN_FLOOR, - blockName, - blockName - ) : Patterns.createJson(Patterns.BLOCK_STONE_LANTERN_CEIL, blockName, blockName); - return ModelsHelper.fromPattern(pattern); - } -} diff --git a/src/main/java/ru/betterend/blocks/entities/BlockEntityHydrothermalVent.java b/src/main/java/ru/betterend/blocks/entities/BlockEntityHydrothermalVent.java deleted file mode 100644 index e2bd0ad5..00000000 --- a/src/main/java/ru/betterend/blocks/entities/BlockEntityHydrothermalVent.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.blocks.entities; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import ru.betterend.blocks.HydrothermalVentBlock; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.registry.EndBlockEntities; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndParticles; -import ru.betterend.util.GlobalState; - -import java.util.List; - -public class BlockEntityHydrothermalVent extends BlockEntity { - private final static Vec3 POSITIVE_Y = new Vec3(0.0f, 1.0f, 0.0f); - - public BlockEntityHydrothermalVent(BlockPos blockPos, BlockState blockState) { - super(EndBlockEntities.HYDROTHERMAL_VENT, blockPos, blockState); - } - - public static void tick(Level level, BlockPos worldPosition, BlockState state, T uncastedEntity) { - if (level != null && uncastedEntity instanceof BlockEntityHydrothermalVent && state.is(EndBlocks.HYDROTHERMAL_VENT)) { - BlockEntityHydrothermalVent blockEntity = (BlockEntityHydrothermalVent) uncastedEntity; - if (level.isClientSide()) { - clientTick(level, worldPosition, state, blockEntity); - } - //else { - serverTick(level, worldPosition, state, blockEntity); - //} - } - } - - private static void clientTick(Level level, BlockPos worldPosition, BlockState state, BlockEntityHydrothermalVent blockEntity) { - boolean active = state.getValue(HydrothermalVentBlock.ACTIVATED); - if (active && level.random.nextInt(20) == 0 && state.getValue(HydrothermalVentBlock.WATERLOGGED)) { - double x = worldPosition.getX() + level.random.nextDouble(); - double y = worldPosition.getY() + 0.9 + level.random.nextDouble() * 0.3; - double z = worldPosition.getZ() + level.random.nextDouble(); - level.addParticle(EndParticles.GEYSER_PARTICLE, x, y, z, 0, 0, 0); - } - } - - private static void serverTick(Level level, BlockPos worldPosition, BlockState state, BlockEntityHydrothermalVent blockEntity) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - boolean active = state.getValue(HydrothermalVentBlock.ACTIVATED); - POS.set(worldPosition).move(Direction.UP); - int height = active ? 85 : 25; - AABB box = new AABB(POS.offset(-1, 0, -1), POS.offset(1, height, 1)); - List entities = level.getEntitiesOfClass(LivingEntity.class, box); - if (entities.size() > 0) { - while (POS.getY() < box.maxY) { - BlockState blockState = level.getBlockState(POS); - if (blockState.isSolidRender(level, POS)) break; - if (blockState.isAir()) { - double mult = active ? 3.0 : 5.0; - float force = (float) ((1.0 - (POS.getY() / box.maxY)) / mult); - entities.stream() - .filter(entity -> (int) entity.getY() == POS.getY() && blockEntity.hasElytra(entity) && entity - .isFallFlying()) - .forEach(entity -> entity.moveRelative(force, POSITIVE_Y)); - } - POS.move(Direction.UP); - } - } - } - - private boolean hasElytra(LivingEntity entity) { - Item item = entity.getItemBySlot(EquipmentSlot.CHEST).getItem(); - return item instanceof ElytraItem || item instanceof FallFlyingItem; - } -} diff --git a/src/main/java/ru/betterend/blocks/entities/EndStoneSmelterBlockEntity.java b/src/main/java/ru/betterend/blocks/entities/EndStoneSmelterBlockEntity.java deleted file mode 100644 index 2392d869..00000000 --- a/src/main/java/ru/betterend/blocks/entities/EndStoneSmelterBlockEntity.java +++ /dev/null @@ -1,480 +0,0 @@ -package ru.betterend.blocks.entities; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.fabricmc.fabric.api.registry.FuelRegistry; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.WorldlyContainer; -import net.minecraft.world.entity.ExperienceOrb; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.player.StackedContents; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.RecipeHolder; -import net.minecraft.world.inventory.StackedContentsCompatible; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.BlastingRecipe; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndStoneSmelter; -import ru.betterend.client.gui.EndStoneSmelterScreenHandler; -import ru.betterend.recipe.builders.AlloyingRecipe; -import ru.betterend.registry.EndBlockEntities; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class EndStoneSmelterBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeHolder, StackedContentsCompatible { - - private static final int[] TOP_SLOTS = new int[] {0, 1}; - private static final int[] BOTTOM_SLOTS = new int[] {2, 3}; - private static final int[] SIDE_SLOTS = new int[] {1, 2}; - private static final Map AVAILABLE_FUELS = Maps.newHashMap(); - - private final Object2IntOpenHashMap recipesUsed; - protected NonNullList inventory; - protected final ContainerData propertyDelegate; - private Recipe lastRecipe; - private int smeltTimeTotal; - private int smeltTime; - private int burnTime; - private int fuelTime; - - public EndStoneSmelterBlockEntity(BlockPos blockPos, BlockState blockState) { - super(EndBlockEntities.END_STONE_SMELTER, blockPos, blockState); - this.inventory = NonNullList.withSize(4, ItemStack.EMPTY); - this.recipesUsed = new Object2IntOpenHashMap<>(); - this.propertyDelegate = new ContainerData() { - public int get(int index) { - switch (index) { - case 0: - return EndStoneSmelterBlockEntity.this.burnTime; - case 1: - return EndStoneSmelterBlockEntity.this.fuelTime; - case 2: - return EndStoneSmelterBlockEntity.this.smeltTime; - case 3: - return EndStoneSmelterBlockEntity.this.smeltTimeTotal; - default: - return 0; - } - } - - public void set(int index, int value) { - switch (index) { - case 0: - EndStoneSmelterBlockEntity.this.burnTime = value; - break; - case 1: - EndStoneSmelterBlockEntity.this.fuelTime = value; - break; - case 2: - EndStoneSmelterBlockEntity.this.smeltTime = value; - break; - case 3: - EndStoneSmelterBlockEntity.this.smeltTimeTotal = value; - } - } - - public int getCount() { - return 4; - } - }; - } - - private boolean isBurning() { - return burnTime > 0; - } - - @Override - public int getContainerSize() { - return inventory.size(); - } - - @Override - public boolean isEmpty() { - Iterator iterator = inventory.iterator(); - ItemStack itemStack; - do { - if (!iterator.hasNext()) { - return true; - } - itemStack = iterator.next(); - } while (itemStack.isEmpty()); - - return false; - } - - @Override - public ItemStack getItem(int slot) { - return inventory.get(slot); - } - - @Override - public ItemStack removeItem(int slot, int amount) { - return ContainerHelper.removeItem(inventory, slot, amount); - } - - @Override - public ItemStack removeItemNoUpdate(int slot) { - return ContainerHelper.takeItem(inventory, slot); - } - - @Override - public void setItem(int slot, ItemStack stack) { - ItemStack itemStack = inventory.get(slot); - boolean stackValid = !stack.isEmpty() && stack.sameItem(itemStack) && ItemStack.tagMatches(stack, itemStack); - inventory.set(slot, stack); - if (stack.getCount() > getMaxStackSize()) { - stack.setCount(getMaxStackSize()); - } - if ((slot == 0 || slot == 1) && !stackValid) { - smeltTimeTotal = getSmeltTime(); - smeltTime = 0; - setChanged(); - } - } - - protected int getSmeltTime() { - if (level == null) return 200; - int smeltTime = level.getRecipeManager() - .getRecipeFor(AlloyingRecipe.TYPE, this, level) - .map(AlloyingRecipe::getSmeltTime) - .orElse(0); - if (smeltTime == 0) { - smeltTime = level.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, this, level) - .map(BlastingRecipe::getCookingTime) - .orElse(200); - smeltTime /= 1.5; - } - return smeltTime; - } - - public void dropExperience(Player player) { - if (level == null) return; - List> list = Lists.newArrayList(); - for (Entry entry : recipesUsed.object2IntEntrySet()) { - level.getRecipeManager().byKey(entry.getKey()).ifPresent((recipe) -> { - list.add(recipe); - if (recipe instanceof AlloyingRecipe) { - AlloyingRecipe alloying = (AlloyingRecipe) recipe; - dropExperience(player.level, player.position(), entry.getIntValue(), alloying.getExperience()); - } - else { - BlastingRecipe blasting = (BlastingRecipe) recipe; - dropExperience(player.level, player.position(), entry.getIntValue(), blasting.getExperience()); - } - }); - } - player.awardRecipes(list); - recipesUsed.clear(); - } - - private void dropExperience(Level world, Vec3 vec3d, int count, float amount) { - int expTotal = Mth.floor(count * amount); - float g = Mth.frac(count * amount); - if (g != 0.0F && Math.random() < g) { - expTotal++; - } - - while (expTotal > 0) { - int expVal = ExperienceOrb.getExperienceValue(expTotal); - expTotal -= expVal; - world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, expVal)); - } - } - - @Override - public boolean stillValid(Player player) { - if (level != null && level.getBlockEntity(worldPosition) != this) { - return false; - } - return player.distanceToSqr( - worldPosition.getX() + 0.5D, - worldPosition.getY() + 0.5D, - worldPosition.getZ() + 0.5D - ) <= 64.0D; - } - - @Override - public void clearContent() { - inventory.clear(); - } - - @Override - protected Component getDefaultName() { - return Component.translatable(String.format("block.%s.%s", BetterEnd.MOD_ID, EndStoneSmelter.ID)); - } - - @Override - protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) { - return new EndStoneSmelterScreenHandler(syncId, playerInventory, this, propertyDelegate); - } - - public static void tick(Level tickLevel, BlockPos tickPos, BlockState tickState, EndStoneSmelterBlockEntity blockEntity) { - if (tickLevel == null) return; - - boolean initialBurning = blockEntity.isBurning(); - if (initialBurning) { - blockEntity.burnTime--; - } - - boolean burning = initialBurning; - if (!tickLevel.isClientSide) { - ItemStack fuel = blockEntity.inventory.get(2); - if (!burning && (fuel.isEmpty() || blockEntity.inventory.get(0).isEmpty() && blockEntity.inventory.get(1) - .isEmpty())) { - if (blockEntity.smeltTime > 0) { - blockEntity.smeltTime = Mth.clamp(blockEntity.smeltTime - 2, 0, blockEntity.smeltTimeTotal); - } - } - else { - Recipe recipe = tickLevel.getRecipeManager() - .getRecipeFor(AlloyingRecipe.TYPE, blockEntity, tickLevel) - .orElse(null); - if (recipe == null) { - recipe = tickLevel.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, blockEntity, tickLevel) - .orElse(null); - } - boolean accepted = blockEntity.canAcceptRecipeOutput(recipe); - if (!burning && accepted) { - blockEntity.burnTime = blockEntity.getFuelTime(fuel); - blockEntity.fuelTime = blockEntity.burnTime; - burning = blockEntity.isBurning(); - if (burning) { - if (!fuel.isEmpty()) { - Item item = fuel.getItem(); - fuel.shrink(1); - if (fuel.isEmpty()) { - Item remainFuel = item.getCraftingRemainingItem(); - blockEntity.inventory.set( - 2, - remainFuel == null ? ItemStack.EMPTY : new ItemStack(remainFuel) - ); - } - } - blockEntity.setChanged(); - } - } - - if (burning && accepted) { - blockEntity.smeltTime++; - if (blockEntity.smeltTime == blockEntity.smeltTimeTotal) { - blockEntity.smeltTime = 0; - blockEntity.smeltTimeTotal = blockEntity.getSmeltTime(); - blockEntity.craftRecipe(recipe); - blockEntity.setChanged(); - } - } - else { - blockEntity.smeltTime = 0; - } - } - burning = blockEntity.isBurning(); - if (initialBurning != burning) { - tickLevel.setBlock(tickPos, tickState.setValue(EndStoneSmelter.LIT, burning), 3); - blockEntity.setChanged(); - } - } - } - - protected boolean canAcceptRecipeOutput(Recipe recipe) { - if (recipe == null) return false; - boolean validInput; - if (recipe instanceof AlloyingRecipe) { - validInput = !inventory.get(0).isEmpty() && !inventory.get(1).isEmpty(); - } - else { - validInput = !inventory.get(0).isEmpty() || !inventory.get(1).isEmpty(); - } - if (validInput) { - ItemStack result = recipe.getResultItem(); - if (result.isEmpty()) { - return false; - } - ItemStack output = this.inventory.get(3); - int outCount = output.getCount(); - int total = outCount + result.getCount(); - if (output.isEmpty()) { - return true; - } - if (!output.sameItem(result)) { - return false; - } - if (outCount < getMaxStackSize() && outCount < output.getMaxStackSize()) { - return getMaxStackSize() >= total; - } - return output.getCount() < result.getMaxStackSize(); - } - return false; - } - - private void craftRecipe(Recipe recipe) { - if (recipe == null || !canAcceptRecipeOutput(recipe)) return; - - ItemStack result = recipe.getResultItem(); - ItemStack output = inventory.get(3); - if (output.isEmpty()) { - inventory.set(3, result.copy()); - } - else if (output.getItem() == result.getItem()) { - output.grow(result.getCount()); - } - - assert this.level != null; - if (!this.level.isClientSide) { - setRecipeUsed(recipe); - } - - if (recipe instanceof AlloyingRecipe) { - inventory.get(0).shrink(1); - inventory.get(1).shrink(1); - } - else { - if (!inventory.get(0).isEmpty()) { - inventory.get(0).shrink(1); - } - else { - inventory.get(1).shrink(1); - } - } - } - - @Override - public void fillStackedContents(StackedContents finder) { - for (ItemStack itemStack : this.inventory) { - finder.accountStack(itemStack); - } - } - - @Override - public void setRecipeUsed(Recipe recipe) { - if (recipe != null) { - ResourceLocation recipeId = recipe.getId(); - recipesUsed.addTo(recipeId, 1); - lastRecipe = recipe; - } - } - - @Override - public Recipe getRecipeUsed() { - return this.lastRecipe; - } - - @Override - public int[] getSlotsForFace(Direction side) { - if (side == Direction.DOWN) { - return BOTTOM_SLOTS; - } - return side == Direction.UP ? TOP_SLOTS : SIDE_SLOTS; - } - - @Override - public boolean canPlaceItemThroughFace(int slot, ItemStack stack, Direction dir) { - return this.canPlaceItem(slot, stack); - } - - @Override - public boolean canTakeItemThroughFace(int slot, ItemStack stack, Direction dir) { - if (dir == Direction.DOWN && slot == 2) { - return stack.getItem() == Items.BUCKET; - } - return true; - } - - protected int getFuelTime(ItemStack fuel) { - if (fuel.isEmpty()) { - return 0; - } - Item item = fuel.getItem(); - return AVAILABLE_FUELS.getOrDefault(item, getFabricFuel(fuel)); - } - - @Override - public void load(CompoundTag tag) { - super.load(tag); - inventory = NonNullList.withSize(getContainerSize(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(tag, inventory); - burnTime = tag.getShort("BurnTime"); - fuelTime = tag.getShort("FuelTime"); - smeltTime = tag.getShort("SmeltTime"); - smeltTimeTotal = tag.getShort("SmeltTimeTotal"); - CompoundTag compoundTag = tag.getCompound("RecipesUsed"); - for (String id : compoundTag.getAllKeys()) { - recipesUsed.put(new ResourceLocation(id), compoundTag.getInt(id)); - } - } - - @Override - public void saveAdditional(CompoundTag tag) { - super.saveAdditional(tag); - - tag.putShort("BurnTime", (short) burnTime); - tag.putShort("FuelTime", (short) fuelTime); - tag.putShort("SmeltTime", (short) smeltTime); - tag.putShort("SmeltTimeTotal", (short) smeltTimeTotal); - ContainerHelper.saveAllItems(tag, inventory); - CompoundTag usedRecipes = new CompoundTag(); - recipesUsed.forEach((identifier, integer) -> usedRecipes.putInt(identifier.toString(), integer)); - tag.put("RecipesUsed", usedRecipes); - } - - public boolean canPlaceItem(int slot, ItemStack stack) { - if (slot == 3) { - return false; - } - else if (slot != 2) { - return true; - } - ItemStack itemStack = this.inventory.get(2); - return canUseAsFuel(stack) || stack.getItem() == Items.BUCKET && itemStack.getItem() != Items.BUCKET; - } - - public static boolean canUseAsFuel(ItemStack stack) { - return AVAILABLE_FUELS.containsKey(stack.getItem()) || getFabricFuel(stack) > 2000; - } - - public static void registerFuel(ItemLike fuel, int time) { - AVAILABLE_FUELS.put(fuel.asItem(), time); - } - - public static Map availableFuels() { - return AVAILABLE_FUELS; - } - - private static int getFabricFuel(ItemStack stack) { - Integer ticks = FuelRegistry.INSTANCE.get(stack.getItem()); - return ticks == null ? 0 : ticks; - } - - static { - AbstractFurnaceBlockEntity.getFuel().forEach((item, time) -> { - if (time >= 2000) { - registerFuel(item, time); - } - }); - } -} diff --git a/src/main/java/ru/betterend/blocks/entities/EternalPedestalEntity.java b/src/main/java/ru/betterend/blocks/entities/EternalPedestalEntity.java deleted file mode 100644 index 4546cf14..00000000 --- a/src/main/java/ru/betterend/blocks/entities/EternalPedestalEntity.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.betterend.blocks.entities; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.registry.EndBlockEntities; -import ru.betterend.rituals.EternalRitual; - -public class EternalPedestalEntity extends PedestalBlockEntity { - private EternalRitual linkedRitual; - - public EternalPedestalEntity(BlockPos blockPos, BlockState blockState) { - super(EndBlockEntities.ETERNAL_PEDESTAL, blockPos, blockState); - } - - public boolean hasRitual() { - return linkedRitual != null; - } - - public void linkRitual(EternalRitual ritual) { - this.linkedRitual = ritual; - } - - public EternalRitual getRitual() { - return linkedRitual; - } - - @Override - public void setLevel(Level level) { - super.setLevel(level); - if (hasRitual()) { - linkedRitual.setWorld(level); - } - } - - @Override - public void saveAdditional(CompoundTag tag) { - if (hasRitual()) { - tag.put("ritual", linkedRitual.toTag(new CompoundTag())); - } - super.saveAdditional(tag); - } - - @Override - protected void fromTag(CompoundTag tag) { - super.fromTag(tag); - if (tag.contains("ritual")) { - linkedRitual = new EternalRitual(level); - linkedRitual.fromTag(tag.getCompound("ritual")); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/entities/InfusionPedestalEntity.java b/src/main/java/ru/betterend/blocks/entities/InfusionPedestalEntity.java deleted file mode 100644 index 47420b67..00000000 --- a/src/main/java/ru/betterend/blocks/entities/InfusionPedestalEntity.java +++ /dev/null @@ -1,68 +0,0 @@ -package ru.betterend.blocks.entities; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.registry.EndBlockEntities; -import ru.betterend.rituals.InfusionRitual; - -public class InfusionPedestalEntity extends PedestalBlockEntity { - - private InfusionRitual linkedRitual; - - public InfusionPedestalEntity(BlockPos blockPos, BlockState blockState) { - super(EndBlockEntities.INFUSION_PEDESTAL, blockPos, blockState); - } - - @Override - public void setLevel(Level world) { - super.setLevel(world); - if (hasRitual()) { - linkedRitual.setLocation(world, this.getBlockPos()); - } - else { - linkRitual(new InfusionRitual(this, world, this.getBlockPos())); - } - } - - public void linkRitual(InfusionRitual ritual) { - linkedRitual = ritual; - } - - public InfusionRitual getRitual() { - return linkedRitual; - } - - public boolean hasRitual() { - return linkedRitual != null; - } - - @Override - public void saveAdditional(CompoundTag tag) { - if (hasRitual()) { - tag.put("ritual", linkedRitual.toTag(new CompoundTag())); - } - super.saveAdditional(tag); - } - - @Override - protected void fromTag(CompoundTag tag) { - super.fromTag(tag); - if (tag.contains("ritual")) { - linkedRitual = new InfusionRitual(this, level, worldPosition); - linkedRitual.fromTag(tag.getCompound("ritual")); - } - } - - public static void tickEnity(Level level, BlockPos blockPos, BlockState blockState, T uncastedEntity) { - if (uncastedEntity instanceof InfusionPedestalEntity) { - InfusionPedestalEntity blockEntity = (InfusionPedestalEntity) uncastedEntity; - if (blockEntity.hasRitual()) { - blockEntity.linkedRitual.tick(); - } - //PedestalBlockEntity.tick(level, blockPos, blockState, blockEntity); - } - } -} diff --git a/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java b/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java deleted file mode 100644 index 650a3d25..00000000 --- a/src/main/java/ru/betterend/blocks/entities/PedestalBlockEntity.java +++ /dev/null @@ -1,124 +0,0 @@ -package ru.betterend.blocks.entities; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -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 ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.registry.EndBlockEntities; -import ru.betterend.registry.EndItems; - -public class PedestalBlockEntity extends BlockEntity implements Container { - private ItemStack activeItem = ItemStack.EMPTY; - - public PedestalBlockEntity(BlockPos blockPos, BlockState blockState) { - this(EndBlockEntities.PEDESTAL, blockPos, blockState); - } - - public PedestalBlockEntity(BlockEntityType blockEntityType, BlockPos blockPos, BlockState blockState) { - super(blockEntityType, blockPos, blockState); - } - - protected void toTag(CompoundTag tag) { - if (activeItem != ItemStack.EMPTY) { - tag.put("active_item", activeItem.save(new CompoundTag())); - } - } - - protected void fromTag(CompoundTag tag) { - if (tag.contains("active_item")) { - CompoundTag itemTag = tag.getCompound("active_item"); - activeItem = ItemStack.of(itemTag); - } - } - - @Override - public int getContainerSize() { - return 1; - } - - @Override - public boolean isEmpty() { - return activeItem.isEmpty(); - } - - @Override - public ItemStack getItem(int slot) { - return activeItem; - } - - @Override - public ItemStack removeItem(int slot, int amount) { - return removeItemNoUpdate(slot); - } - - @Override - public boolean canPlaceItem(int slot, ItemStack stack) { - return isEmpty(); - } - - @Override - public void clearContent() { - activeItem = ItemStack.EMPTY; - setChanged(); - } - - @Override - public ItemStack removeItemNoUpdate(int slot) { - ItemStack stored = activeItem; - clearContent(); - return stored; - } - - @Override - public void setItem(int slot, ItemStack stack) { - activeItem = stack.split(1); - setChanged(); - } - - @Override - public void setChanged() { - if (level != null && !level.isClientSide()) { - BlockState state = level.getBlockState(worldPosition); - if (state.getBlock() instanceof PedestalBlock) { - state = state.setValue(PedestalBlock.HAS_ITEM, !isEmpty()); - state = state.setValue(PedestalBlock.HAS_LIGHT, activeItem.getItem() == EndItems.ETERNAL_CRYSTAL); - } - level.setBlockAndUpdate(worldPosition, state); - level.blockEntityChanged(worldPosition); - } - super.setChanged(); - } - - @Override - public boolean stillValid(Player player) { - return true; - } - - @Override - public void load(CompoundTag tag) { - super.load(tag); - fromTag(tag); - } - - @Override - protected void saveAdditional(CompoundTag tag) { - super.saveAdditional(tag); - toTag(tag); - } - - @Override - public ClientboundBlockEntityDataPacket getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this); - } - - @Override - public CompoundTag getUpdateTag() { - return this.saveWithoutMetadata(); - } -} diff --git a/src/main/java/ru/betterend/client/BetterEndClient.java b/src/main/java/ru/betterend/client/BetterEndClient.java deleted file mode 100644 index b912a380..00000000 --- a/src/main/java/ru/betterend/client/BetterEndClient.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.betterend.client; - -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; -import net.fabricmc.fabric.api.client.rendering.v1.DimensionRenderingRegistry; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; -import ru.bclib.BCLib; -import ru.bclib.util.TranslationHelper; -import ru.betterend.BetterEnd; -import ru.betterend.client.render.BetterEndSkyRenderer; -import ru.betterend.events.ItemTooltipCallback; -import ru.betterend.interfaces.MultiModelItem; -import ru.betterend.item.CrystaliteArmor; -import ru.betterend.registry.EndBlockEntityRenders; -import ru.betterend.registry.EndEntitiesRenders; -import ru.betterend.registry.EndModelProviders; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndScreens; -import ru.betterend.world.generator.GeneratorOptions; - -public class BetterEndClient implements ClientModInitializer { - @Override - public void onInitializeClient() { - EndBlockEntityRenders.register(); - EndScreens.register(); - EndParticles.register(); - EndEntitiesRenders.register(); - EndModelProviders.register(); - MultiModelItem.register(); - ClientOptions.init(); - registerTooltips(); - - if (BCLib.isDevEnvironment()) { - TranslationHelper.printMissingEnNames(BetterEnd.MOD_ID); - TranslationHelper.printMissingNames(BetterEnd.MOD_ID, "ru_ru"); - } - - ResourceLocation checkFlowerId = new ResourceLocation("item/chorus_flower"); - ResourceLocation checkPlantId = new ResourceLocation("item/chorus_plant"); - ResourceLocation toLoadFlowerId = new ResourceLocation("betterend", "item/custom_chorus_flower"); - ResourceLocation toLoadPlantId = new ResourceLocation("betterend", "item/custom_chorus_plant"); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> (resourceId, context) -> { - if (GeneratorOptions.changeChorusPlant()) { - if (resourceId.equals(checkFlowerId)) { - return context.loadModel(toLoadFlowerId); - } - else if (resourceId.equals(checkPlantId)) { - return context.loadModel(toLoadPlantId); - } - } - return null; - }); - - if(ClientOptions.isCustomSky()) { - DimensionRenderingRegistry.registerSkyRenderer(Level.END, new BetterEndSkyRenderer()); - } - } - - public static void registerTooltips() { - ItemTooltipCallback.EVENT.register((player, stack, context, lines) -> { - if (stack.getItem() instanceof CrystaliteArmor) { - boolean hasSet = false; - if (player != null) { - hasSet = CrystaliteArmor.hasFullSet(player); - } - MutableComponent setDesc = Component.translatable("tooltip.armor.crystalite_set"); - - setDesc.setStyle(Style.EMPTY.applyFormats( - hasSet ? ChatFormatting.BLUE : ChatFormatting.DARK_GRAY, - ChatFormatting.ITALIC - )); - lines.add(Component.empty()); - lines.add(setDesc); - } - }); - } -} diff --git a/src/main/java/ru/betterend/client/ClientOptions.java b/src/main/java/ru/betterend/client/ClientOptions.java deleted file mode 100644 index b40be6f8..00000000 --- a/src/main/java/ru/betterend/client/ClientOptions.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.client; - -import ru.betterend.config.Configs; - -public class ClientOptions { - private static boolean customSky; - private static boolean useFogDensity; - private static boolean blendBiomeMusic; - private static boolean sulfurWaterColor; - - public static void init() { - customSky = Configs.CLENT_CONFIG.getBooleanRoot("customSky", true); - useFogDensity = Configs.CLENT_CONFIG.getBooleanRoot("useFogDensity", true); - blendBiomeMusic = Configs.CLENT_CONFIG.getBooleanRoot("blendBiomeMusic", true); - sulfurWaterColor = Configs.CLENT_CONFIG.getBooleanRoot("sulfurWaterColor", true); - Configs.CLENT_CONFIG.saveChanges(); - } - - public static boolean isCustomSky() { - return customSky; - } - - public static void setCustomSky(boolean customSky) { - ClientOptions.customSky = customSky; - } - - public static boolean useFogDensity() { - return useFogDensity; - } - - public static void setUseFogDensity(boolean useFogDensity) { - ClientOptions.useFogDensity = useFogDensity; - } - - public static boolean blendBiomeMusic() { - return blendBiomeMusic; - } - - public static void setBlendBiomeMusic(boolean blendBiomeMusic) { - ClientOptions.blendBiomeMusic = blendBiomeMusic; - } - - public static boolean useSulfurWaterColor() { - return sulfurWaterColor; - } - - public static void setSulfurWaterColor(boolean sulfurWaterColor) { - ClientOptions.sulfurWaterColor = sulfurWaterColor; - } -} diff --git a/src/main/java/ru/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java b/src/main/java/ru/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java deleted file mode 100644 index 8eafb3d8..00000000 --- a/src/main/java/ru/betterend/client/gui/EndStoneSmelterRecipeBookScreen.java +++ /dev/null @@ -1,108 +0,0 @@ -package ru.betterend.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.recipebook.BlastingRecipeBookComponent; -import net.minecraft.core.NonNullList; -import net.minecraft.world.inventory.Slot; -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.Recipe; -import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity; - -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -@Environment(EnvType.CLIENT) -public class EndStoneSmelterRecipeBookScreen extends BlastingRecipeBookComponent { - private Iterator fuelIterator; - private Set fuels; - private Slot fuelSlot; - private Item currentItem; - private float frameTime; - - @Override - protected Set getFuelItems() { - return EndStoneSmelterBlockEntity.availableFuels().keySet(); - } - - @Override - public void slotClicked(Slot slot) { - super.slotClicked(slot); - if (slot != null && slot.index < this.menu.getSize()) { - this.fuelSlot = null; - } - } - - @Override - public void setupGhostRecipe(Recipe recipe, List slots) { - this.ghostRecipe.clear(); - ItemStack result = recipe.getResultItem(); - this.ghostRecipe.setRecipe(recipe); - this.ghostRecipe.addIngredient(Ingredient.of(result), (slots.get(3)).x, (slots.get(3)).y); - NonNullList inputs = recipe.getIngredients(); - Iterator iterator = inputs.iterator(); - for (int i = 0; i < 2; i++) { - if (!iterator.hasNext()) { - return; - } - Ingredient ingredient = iterator.next(); - if (!ingredient.isEmpty()) { - Slot slot = slots.get(i); - this.ghostRecipe.addIngredient(ingredient, slot.x, slot.y); - } - } - this.fuelSlot = slots.get(2); - if (this.fuels == null) { - this.fuels = this.getFuelItems(); - } - - this.fuelIterator = this.fuels.iterator(); - this.currentItem = null; - } - - @Override - public void renderGhostRecipe(PoseStack matrices, int x, int y, boolean bl, float f) { - this.ghostRecipe.render(matrices, minecraft, x, y, bl, f); - if (fuelSlot != null) { - if (!Screen.hasControlDown()) { - this.frameTime += f; - } - - int slotX = this.fuelSlot.x + x; - int slotY = this.fuelSlot.y + y; - GuiComponent.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822018048); - //TODO: test k=0 - this.minecraft.getItemRenderer() - .renderAndDecorateItem(minecraft.player, - this.getFuel().getDefaultInstance(), - slotX, - slotY, - 0 - ); - RenderSystem.depthFunc(516); - GuiComponent.fill(matrices, slotX, slotY, slotX + 16, slotY + 16, 822083583); - RenderSystem.depthFunc(515); - } - } - - private Item getFuel() { - if (this.currentItem == null || this.frameTime > 30.0F) { - this.frameTime = 0.0F; - if (this.fuelIterator == null || !this.fuelIterator.hasNext()) { - if (this.fuels == null) { - this.fuels = this.getFuelItems(); - } - this.fuelIterator = this.fuels.iterator(); - } - this.currentItem = this.fuelIterator.next(); - } - return this.currentItem; - } -} diff --git a/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreen.java b/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreen.java deleted file mode 100644 index c4a60fa2..00000000 --- a/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreen.java +++ /dev/null @@ -1,151 +0,0 @@ -package ru.betterend.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.gui.components.ImageButton; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; -import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.Slot; -import ru.betterend.BetterEnd; - -@Environment(EnvType.CLIENT) -public class EndStoneSmelterScreen extends AbstractContainerScreen implements RecipeUpdateListener { - - private final static ResourceLocation RECIPE_BUTTON_TEXTURE = new ResourceLocation("textures/gui/recipe_button.png"); - private final static ResourceLocation BACKGROUND_TEXTURE = BetterEnd.makeID("textures/gui/smelter_gui.png"); - - public final EndStoneSmelterRecipeBookScreen recipeBook; - private boolean narrow; - - public EndStoneSmelterScreen(EndStoneSmelterScreenHandler handler, Inventory inventory, Component title) { - super(handler, inventory, title); - recipeBook = new EndStoneSmelterRecipeBookScreen(); - } - - public void init() { - super.init(); - //TODO: test in 1.17 - narrow = width < 379; - recipeBook.init(width, height, minecraft, narrow, menu); - leftPos = recipeBook.updateScreenPosition(width, imageWidth); - addRenderableWidget(new ImageButton( - leftPos + 20, - height / 2 - 49, - 20, - 18, - 0, - 0, - 19, - RECIPE_BUTTON_TEXTURE, - (buttonWidget) -> { - recipeBook.initVisuals(); - recipeBook.toggleVisibility(); - leftPos = recipeBook.updateScreenPosition(width, imageWidth); - ((ImageButton) buttonWidget).setPosition(leftPos + 20, height / 2 - 49); - } - )); - titleLabelX = (imageWidth - font.width(title)) / 2; - } - - @Override - public void containerTick() { - super.containerTick(); - recipeBook.tick(); - } - - @Override - public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { - renderBackground(matrices); - if (recipeBook.isVisible() && narrow) { - renderBg(matrices, delta, mouseX, mouseY); - recipeBook.render(matrices, mouseX, mouseY, delta); - } - else { - recipeBook.render(matrices, mouseX, mouseY, delta); - super.render(matrices, mouseX, mouseY, delta); - recipeBook.renderGhostRecipe(matrices, leftPos, topPos, true, delta); - } - renderTooltip(matrices, mouseX, mouseY); - recipeBook.renderTooltip(matrices, leftPos, topPos, mouseX, mouseY); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (this.recipeBook.mouseClicked(mouseX, mouseY, button)) { - return true; - } - else { - return narrow && recipeBook.isVisible() || super.mouseClicked(mouseX, mouseY, button); - } - } - - @Override - protected void slotClicked(Slot slot, int invSlot, int clickData, ClickType actionType) { - super.slotClicked(slot, invSlot, clickData, actionType); - this.recipeBook.slotClicked(slot); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - return !recipeBook.keyPressed(keyCode, scanCode, modifiers) && super.keyPressed(keyCode, scanCode, modifiers); - } - - @Override - protected boolean hasClickedOutside(double mouseX, double mouseY, int left, int top, int button) { - boolean isMouseOut = mouseX < left || mouseY < top || mouseX >= (left + imageWidth) || mouseY >= (top + imageHeight); - return this.recipeBook.hasClickedOutside( - mouseX, - mouseY, - leftPos, - topPos, - imageWidth, - imageHeight, - button - ) && isMouseOut; - } - - @Override - public boolean charTyped(char chr, int keyCode) { - return recipeBook.charTyped(chr, keyCode) || super.charTyped(chr, keyCode); - } - - @Override - public void recipesUpdated() { - recipeBook.recipesUpdated(); - } - - @Override - public RecipeBookComponent getRecipeBookComponent() { - return recipeBook; - } - - @Override - protected void renderBg(PoseStack matrices, float delta, int mouseX, int mouseY) { - if (minecraft == null) return; - //TODO: verify - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShaderTexture(0, BACKGROUND_TEXTURE); - //minecraft.getTextureManager().bind(BACKGROUND_TEXTURE); - blit(matrices, leftPos, topPos, 0, 0, imageWidth, imageHeight); - int progress; - if (menu.isBurning()) { - progress = menu.getFuelProgress(); - blit(matrices, leftPos + 56, topPos + 36 + 12 - progress, 176, 12 - progress, 14, progress + 1); - } - progress = menu.getSmeltProgress(); - blit(matrices, leftPos + 92, topPos + 34, 176, 14, progress + 1, 16); - } - - @Override - public void removed() { - recipeBook.removed(); - super.removed(); - } -} diff --git a/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreenHandler.java b/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreenHandler.java deleted file mode 100644 index 0ca2b76a..00000000 --- a/src/main/java/ru/betterend/client/gui/EndStoneSmelterScreenHandler.java +++ /dev/null @@ -1,207 +0,0 @@ -package ru.betterend.client.gui; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; -import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.player.StackedContents; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.RecipeBookMenu; -import net.minecraft.world.inventory.RecipeBookType; -import net.minecraft.world.inventory.SimpleContainerData; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.inventory.StackedContentsCompatible; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.Level; -import org.anti_ad.mc.ipn.api.IPNIgnore; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndStoneSmelter; -import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity; -import ru.betterend.client.gui.slot.SmelterFuelSlot; -import ru.betterend.client.gui.slot.SmelterOutputSlot; -import ru.betterend.recipe.builders.AlloyingRecipe; - -@IPNIgnore -public class EndStoneSmelterScreenHandler extends RecipeBookMenu { - - public final static MenuType HANDLER_TYPE = ScreenHandlerRegistry.registerSimple( - BetterEnd.makeID(EndStoneSmelter.ID), - EndStoneSmelterScreenHandler::new - ); - - private final Container inventory; - private final ContainerData propertyDelegate; - protected final Level world; - - public EndStoneSmelterScreenHandler(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, new SimpleContainer(4), new SimpleContainerData(4)); - } - - public EndStoneSmelterScreenHandler(int syncId, Inventory playerInventory, Container inventory, ContainerData propertyDelegate) { - super(HANDLER_TYPE, syncId); - this.inventory = inventory; - this.propertyDelegate = propertyDelegate; - this.world = playerInventory.player.level; - - addDataSlots(propertyDelegate); - addSlot(new Slot(inventory, 0, 45, 17)); - addSlot(new Slot(inventory, 1, 67, 17)); - addSlot(new SmelterFuelSlot(this, inventory, 2, 56, 53)); - addSlot(new SmelterOutputSlot(playerInventory.player, inventory, 3, 129, 35)); - - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 9; ++j) { - addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); - } - } - for (int i = 0; i < 9; ++i) { - addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); - } - } - - @Override - public MenuType getType() { - return HANDLER_TYPE; - } - - @Override - public void fillCraftSlotsStackedContents(StackedContents finder) { - if (inventory instanceof StackedContentsCompatible) { - ((StackedContentsCompatible) inventory).fillStackedContents(finder); - } - } - - @Override - public void clearCraftingContent() { - inventory.clearContent(); - } - - @Override - public boolean recipeMatches(Recipe recipe) { - return recipe.matches(inventory, world); - } - - @Override - public int getResultSlotIndex() { - return 3; - } - - @Override - public int getGridWidth() { - return 2; - } - - @Override - public int getGridHeight() { - return 1; - } - - @Override - public int getSize() { - return 4; - } - - @Override - public RecipeBookType getRecipeBookType() { - return RecipeBookType.BLAST_FURNACE; - } - - @Override - public boolean shouldMoveToInventory(int i) { - return i != this.getResultSlotIndex(); - } - - @Override - public boolean stillValid(Player player) { - return inventory.stillValid(player); - } - - protected boolean isSmeltable(ItemStack itemStack) { - return world.getRecipeManager() - .getRecipeFor(AlloyingRecipe.TYPE, new SimpleContainer(itemStack), world) - .isPresent(); - } - - public boolean isFuel(ItemStack itemStack) { - return EndStoneSmelterBlockEntity.canUseAsFuel(itemStack); - } - - @Override - public ItemStack quickMoveStack(Player player, int index) { - Slot slot = slots.get(index); - if (slot == null || !slot.hasItem()) return ItemStack.EMPTY; - - ItemStack slotStack = slot.getItem(); - ItemStack itemStack = slotStack.copy(); - if (index == 3) { - if (!moveItemStackTo(slotStack, 4, 40, true)) { - return ItemStack.EMPTY; - } - slot.onQuickCraft(slotStack, itemStack); - } - else if (index != 2 && index != 1 && index != 0) { - if (isSmeltable(slotStack)) { - if (!moveItemStackTo(slotStack, 0, 2, false)) { - return ItemStack.EMPTY; - } - } - else if (isFuel(slotStack)) { - if (!moveItemStackTo(slotStack, 2, 3, false)) { - return ItemStack.EMPTY; - } - } - else if (index < 31) { - if (!moveItemStackTo(slotStack, 31, 40, false)) { - return ItemStack.EMPTY; - } - } - else if (index < 40 && !moveItemStackTo(slotStack, 4, 31, false)) { - return ItemStack.EMPTY; - } - } - else if (!moveItemStackTo(slotStack, 4, 40, false)) { - return ItemStack.EMPTY; - } - - if (slotStack.isEmpty()) { - slot.set(ItemStack.EMPTY); - } - else { - slot.setChanged(); - } - - if (slotStack.getCount() == itemStack.getCount()) { - return ItemStack.EMPTY; - } - - slot.onTake(player, slotStack); - - return itemStack; - } - - @Environment(EnvType.CLIENT) - public int getSmeltProgress() { - int time = propertyDelegate.get(2); - int timeTotal = propertyDelegate.get(3); - return timeTotal != 0 && time != 0 ? time * 24 / timeTotal : 0; - } - - @Environment(EnvType.CLIENT) - public int getFuelProgress() { - int fuelTime = propertyDelegate.get(1); - if (fuelTime == 0) { - fuelTime = 200; - } - return propertyDelegate.get(0) * 13 / fuelTime; - } - - @Environment(EnvType.CLIENT) - public boolean isBurning() { - return propertyDelegate.get(0) > 0; - } -} diff --git a/src/main/java/ru/betterend/client/gui/slot/SmelterFuelSlot.java b/src/main/java/ru/betterend/client/gui/slot/SmelterFuelSlot.java deleted file mode 100644 index 60b69a99..00000000 --- a/src/main/java/ru/betterend/client/gui/slot/SmelterFuelSlot.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.client.gui.slot; - -import net.minecraft.world.Container; -import net.minecraft.world.inventory.FurnaceFuelSlot; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import ru.betterend.client.gui.EndStoneSmelterScreenHandler; - -public class SmelterFuelSlot extends Slot { - - private final EndStoneSmelterScreenHandler handler; - - public SmelterFuelSlot(EndStoneSmelterScreenHandler handler, Container inventory, int index, int x, int y) { - super(inventory, index, x, y); - this.handler = handler; - } - - public boolean mayPlace(ItemStack stack) { - return this.handler.isFuel(stack) || FurnaceFuelSlot.isBucket(stack); - } - - public int getMaxStackSize(ItemStack stack) { - return FurnaceFuelSlot.isBucket(stack) ? 1 : super.getMaxStackSize(stack); - } -} diff --git a/src/main/java/ru/betterend/client/gui/slot/SmelterOutputSlot.java b/src/main/java/ru/betterend/client/gui/slot/SmelterOutputSlot.java deleted file mode 100644 index 3fa93cd8..00000000 --- a/src/main/java/ru/betterend/client/gui/slot/SmelterOutputSlot.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.client.gui.slot; - -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity; - -public class SmelterOutputSlot extends Slot { - - private Player player; - private int amount; - - public SmelterOutputSlot(Player player, Container inventory, int index, int x, int y) { - super(inventory, index, x, y); - this.player = player; - } - - public boolean mayPlace(ItemStack stack) { - return false; - } - - public ItemStack remove(int amount) { - if (this.hasItem()) { - this.amount += Math.min(amount, this.getItem().getCount()); - } - - return super.remove(amount); - } - - public void onTake(Player player, ItemStack stack) { - this.checkTakeAchievements(stack); - super.onTake(player, stack); - } - - protected void onQuickCraft(ItemStack stack, int amount) { - this.amount += amount; - this.checkTakeAchievements(stack); - } - - protected void checkTakeAchievements(ItemStack stack) { - stack.onCraftedBy(this.player.level, this.player, this.amount); - if (!this.player.level.isClientSide && this.container instanceof EndStoneSmelterBlockEntity) { - ((EndStoneSmelterBlockEntity) this.container).dropExperience(player); - } - this.amount = 0; - } -} diff --git a/src/main/java/ru/betterend/client/models/Patterns.java b/src/main/java/ru/betterend/client/models/Patterns.java deleted file mode 100644 index e8643783..00000000 --- a/src/main/java/ru/betterend/client/models/Patterns.java +++ /dev/null @@ -1,152 +0,0 @@ -package ru.betterend.client.models; - -import com.google.common.collect.Maps; -import net.minecraft.client.Minecraft; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import ru.betterend.BetterEnd; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.stream.Collectors; - -public class Patterns { - //Block Models - public final static ResourceLocation BLOCK_EMPTY = BetterEnd.makeID("patterns/block/empty.json"); - public final static ResourceLocation BLOCK_BASE = BetterEnd.makeID("patterns/block/block.json"); - public final static ResourceLocation BLOCK_SIDED = BetterEnd.makeID("patterns/block/block_sided.json"); - public final static ResourceLocation BLOCK_BOTTOM_TOP = BetterEnd.makeID("patterns/block/block_bottom_top.json"); - public final static ResourceLocation BLOCK_SLAB = BetterEnd.makeID("patterns/block/slab.json"); - public final static ResourceLocation BLOCK_STAIR = BetterEnd.makeID("patterns/block/stairs.json"); - public final static ResourceLocation BLOCK_STAIR_INNER = BetterEnd.makeID("patterns/block/inner_stairs.json"); - public final static ResourceLocation BLOCK_STAIR_OUTER = BetterEnd.makeID("patterns/block/outer_stairs.json"); - public final static ResourceLocation BLOCK_WALL_POST = BetterEnd.makeID("patterns/block/wall_post.json"); - public final static ResourceLocation BLOCK_WALL_SIDE = BetterEnd.makeID("patterns/block/wall_side.json"); - public final static ResourceLocation BLOCK_WALL_SIDE_TALL = BetterEnd.makeID("patterns/block/wall_side_tall.json"); - public final static ResourceLocation BLOCK_FENCE_POST = BetterEnd.makeID("patterns/block/fence_post.json"); - public final static ResourceLocation BLOCK_FENCE_SIDE = BetterEnd.makeID("patterns/block/fence_side.json"); - public final static ResourceLocation BLOCK_BUTTON = BetterEnd.makeID("patterns/block/button.json"); - public final static ResourceLocation BLOCK_BUTTON_PRESSED = BetterEnd.makeID("patterns/block/button_pressed.json"); - public final static ResourceLocation BLOCK_PILLAR = BetterEnd.makeID("patterns/block/pillar.json"); - public final static ResourceLocation BLOCK_PLATE_UP = BetterEnd.makeID("patterns/block/pressure_plate_up.json"); - public final static ResourceLocation BLOCK_PLATE_DOWN = BetterEnd.makeID("patterns/block/pressure_plate_down.json"); - public final static ResourceLocation BLOCK_DOOR_TOP = BetterEnd.makeID("patterns/block/door_top.json"); - public final static ResourceLocation BLOCK_DOOR_TOP_HINGE = BetterEnd.makeID("patterns/block/door_top_hinge.json"); - public final static ResourceLocation BLOCK_DOOR_BOTTOM = BetterEnd.makeID("patterns/block/door_bottom.json"); - public final static ResourceLocation BLOCK_DOOR_BOTTOM_HINGE = BetterEnd.makeID( - "patterns/block/door_bottom_hinge.json"); - public final static ResourceLocation BLOCK_CROSS = BetterEnd.makeID("patterns/block/cross.json"); - public final static ResourceLocation BLOCK_CROSS_SHADED = BetterEnd.makeID("patterns/block/cross_shaded.json"); - public final static ResourceLocation BLOCK_GATE_CLOSED = BetterEnd.makeID("patterns/block/fence_gate_closed.json"); - public final static ResourceLocation BLOCK_GATE_CLOSED_WALL = BetterEnd.makeID( - "patterns/block/wall_gate_closed.json"); - public final static ResourceLocation BLOCK_GATE_OPEN = BetterEnd.makeID("patterns/block/fence_gate_open.json"); - public final static ResourceLocation BLOCK_GATE_OPEN_WALL = BetterEnd.makeID("patterns/block/wall_gate_open.json"); - public final static ResourceLocation BLOCK_TRAPDOOR = BetterEnd.makeID("patterns/block/trapdoor.json"); - public final static ResourceLocation BLOCK_LADDER = BetterEnd.makeID("patterns/block/ladder.json"); - public final static ResourceLocation BLOCK_BARREL_OPEN = BetterEnd.makeID("patterns/block/barrel_open.json"); - public final static ResourceLocation BLOCK_PEDESTAL_DEFAULT = BetterEnd.makeID( - "patterns/block/pedestal_default.json"); - public final static ResourceLocation BLOKC_PEDESTAL_COLUMN = BetterEnd.makeID("patterns/block/pedestal_column.json"); - public final static ResourceLocation BLOCK_PEDESTAL_COLUMN_TOP = BetterEnd.makeID( - "patterns/block/pedestal_column_top.json"); - public final static ResourceLocation BLOCK_PEDESTAL_TOP = BetterEnd.makeID("patterns/block/pedestal_top.json"); - public final static ResourceLocation BLOCK_PEDESTAL_BOTTOM = BetterEnd.makeID("patterns/block/pedestal_bottom.json"); - public final static ResourceLocation BLOCK_PEDESTAL_PILLAR = BetterEnd.makeID("patterns/block/pedestal_pillar.json"); - public final static ResourceLocation BLOCK_BOOKSHELF = BetterEnd.makeID("patterns/block/bookshelf.json"); - public final static ResourceLocation BLOCK_STONE_LANTERN_CEIL = BetterEnd.makeID( - "patterns/block/stone_lantern_ceil.json"); - public final static ResourceLocation BLOCK_STONE_LANTERN_FLOOR = BetterEnd.makeID( - "patterns/block/stone_lantern_floor.json"); - public final static ResourceLocation BLOCK_BULB_LANTERN_FLOOR = BetterEnd.makeID( - "patterns/block/bulb_lantern_floor.json"); - public final static ResourceLocation BLOCK_BULB_LANTERN_CEIL = BetterEnd.makeID( - "patterns/block/bulb_lantern_ceil.json"); - public final static ResourceLocation BLOCK_PETAL_COLORED = BetterEnd.makeID("models/block/block_petal_colored.json"); - public final static ResourceLocation BLOCK_COMPOSTER = BetterEnd.makeID("patterns/block/composter.json"); - public final static ResourceLocation BLOCK_COLORED = BetterEnd.makeID("patterns/block/block_colored.json"); - public final static ResourceLocation BLOCK_BARS_POST = BetterEnd.makeID("patterns/block/bars_post.json"); - public final static ResourceLocation BLOCK_BARS_SIDE = BetterEnd.makeID("patterns/block/bars_side.json"); - public final static ResourceLocation BLOCK_ANVIL = BetterEnd.makeID("patterns/block/anvil.json"); - public final static ResourceLocation BLOCK_CHAIN = BetterEnd.makeID("patterns/block/chain.json"); - public final static ResourceLocation BLOCK_CHANDELIER_FLOOR = BetterEnd.makeID( - "patterns/block/chandelier_floor.json"); - public final static ResourceLocation BLOCK_CHANDELIER_WALL = BetterEnd.makeID("patterns/block/chandelier_wall.json"); - public final static ResourceLocation BLOCK_CHANDELIER_CEIL = BetterEnd.makeID("patterns/block/chandelier_ceil.json"); - public final static ResourceLocation BLOCK_FURNACE = BetterEnd.makeID("patterns/block/furnace.json"); - public final static ResourceLocation BLOCK_FURNACE_LIT = BetterEnd.makeID("patterns/block/furnace_glow.json"); - public final static ResourceLocation BLOCK_TOP_SIDE_BOTTOM = BetterEnd.makeID("patterns/block/top_side_bottom.json"); - public final static ResourceLocation BLOCK_PATH = BetterEnd.makeID("patterns/block/path.json"); - public final static ResourceLocation BLOCK_FLOWER_POT = BetterEnd.makeID("patterns/block/flower_pot.json"); - public final static ResourceLocation BLOCK_FLOWER_POT_SOIL = BetterEnd.makeID("patterns/block/flower_pot_soil.json"); - public final static ResourceLocation BLOCK_POTTED_LEAVES = BetterEnd.makeID("patterns/block/potted_leaves.json"); - - //Item Models - public final static ResourceLocation ITEM_WALL = BetterEnd.makeID("patterns/item/pattern_wall.json"); - public final static ResourceLocation ITEM_FENCE = BetterEnd.makeID("patterns/item/pattern_fence.json"); - public final static ResourceLocation ITEM_BUTTON = BetterEnd.makeID("patterns/item/pattern_button.json"); - public final static ResourceLocation ITEM_CHEST = BetterEnd.makeID("patterns/item/pattern_chest.json"); - public final static ResourceLocation ITEM_BLOCK = BetterEnd.makeID("patterns/item/pattern_block_item.json"); - public final static ResourceLocation ITEM_GENERATED = BetterEnd.makeID("patterns/item/pattern_item_generated.json"); - public final static ResourceLocation ITEM_HANDHELD = BetterEnd.makeID("patterns/item/pattern_item_handheld.json"); - public final static ResourceLocation ITEM_SPAWN_EGG = BetterEnd.makeID("patterns/item/pattern_item_spawn_egg.json"); - - public static Optional createItemGenerated(String name) { - return createJson(ITEM_GENERATED, name); - } - - public static Optional createBlockSimple(String name) { - return Patterns.createJson(Patterns.BLOCK_BASE, name, name); - } - - public static Optional createBlockPillar(String name) { - return Patterns.createJson(Patterns.BLOCK_PILLAR, name, name); - } - - public static String createJson(Reader data, String parent, String block) { - try (BufferedReader buffer = new BufferedReader(data)) { - return buffer.lines().collect(Collectors.joining()).replace("%parent%", parent).replace("%block%", block); - } - catch (Exception ex) { - return null; - } - } - - public static Optional createJson(ResourceLocation patternId, String parent, String block) { - ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); - try (InputStream input = resourceManager.getResource(patternId).get().open()) { - return Optional.ofNullable(createJson(new InputStreamReader(input, StandardCharsets.UTF_8), parent, block)); - } - catch (Exception ex) { - return Optional.empty(); - } - } - - public static Optional createJson(ResourceLocation patternId, String texture) { - Map textures = Maps.newHashMap(); - textures.put("%texture%", texture); - return createJson(patternId, textures); - } - - public static Optional createJson(ResourceLocation patternId, Map textures) { - ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); - try (InputStream input = resourceManager.getResource(patternId).get().open()) { - String json = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() - .collect(Collectors.joining()); - for (Entry texture : textures.entrySet()) { - json = json.replace(texture.getKey(), texture.getValue()); - } - return Optional.of(json); - } - catch (Exception ex) { - return Optional.empty(); - } - } - -} diff --git a/src/main/java/ru/betterend/client/render/ArmoredElytraLayer.java b/src/main/java/ru/betterend/client/render/ArmoredElytraLayer.java deleted file mode 100644 index c85799c2..00000000 --- a/src/main/java/ru/betterend/client/render/ArmoredElytraLayer.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.model.EntityModel; -import net.minecraft.client.model.geom.EntityModelSet; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import net.minecraft.client.renderer.entity.layers.ElytraLayer; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.PlayerModelPart; -import net.minecraft.world.item.ItemStack; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.item.model.ArmoredElytraModel; -import ru.betterend.registry.EndEntitiesRenders; - -public class ArmoredElytraLayer> extends ElytraLayer { - private final ArmoredElytraModel elytraModel; - - public ArmoredElytraLayer(RenderLayerParent renderLayerParent, EntityModelSet entityModelSet) { - super(renderLayerParent, entityModelSet); - elytraModel = new ArmoredElytraModel<>(entityModelSet.bakeLayer(EndEntitiesRenders.ARMORED_ELYTRA)); - } - - public void render(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, T livingEntity, float f, float g, float h, float j, float k, float l) { - ItemStack itemStack = livingEntity.getItemBySlot(EquipmentSlot.CHEST); - if (itemStack.getItem() instanceof FallFlyingItem) { - ResourceLocation wingsTexture = ((FallFlyingItem) itemStack.getItem()).getModelTexture(); - if (livingEntity instanceof AbstractClientPlayer) { - AbstractClientPlayer abstractClientPlayer = (AbstractClientPlayer) livingEntity; - if (abstractClientPlayer.isElytraLoaded() && abstractClientPlayer.getElytraTextureLocation() != null) { - wingsTexture = abstractClientPlayer.getElytraTextureLocation(); - } - else if (abstractClientPlayer.isCapeLoaded() && abstractClientPlayer.getCloakTextureLocation() != null && abstractClientPlayer - .isModelPartShown(PlayerModelPart.CAPE)) { - wingsTexture = abstractClientPlayer.getCloakTextureLocation(); - } - } - - poseStack.pushPose(); - poseStack.translate(0.0D, 0.0D, 0.125D); - getParentModel().copyPropertiesTo(elytraModel); - elytraModel.setupAnim(livingEntity, f, g, j, k, l); - VertexConsumer vertexConsumer = ItemRenderer.getArmorFoilBuffer( - multiBufferSource, - RenderType.armorCutoutNoCull(wingsTexture), - false, - itemStack.hasFoil() - ); - elytraModel.renderToBuffer(poseStack, vertexConsumer, i, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); - poseStack.popPose(); - } - } -} diff --git a/src/main/java/ru/betterend/client/render/BeamRenderer.java b/src/main/java/ru/betterend/client/render/BeamRenderer.java deleted file mode 100644 index 18a77275..00000000 --- a/src/main/java/ru/betterend/client/render/BeamRenderer.java +++ /dev/null @@ -1,182 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Matrix3f; -import com.mojang.math.Matrix4f; -import com.mojang.math.Vector3f; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; - -public class BeamRenderer { - private static final ResourceLocation BEAM_TEXTURE = new ResourceLocation("textures/entity/end_gateway_beam.png"); - - public static void renderLightBeam(PoseStack matrices, MultiBufferSource vertexConsumers, int age, float tick, int minY, int maxY, float[] colors, float alpha, float beamIn, float beamOut) { - float red = colors[0]; - float green = colors[1]; - float blue = colors[2]; - - int maxBY = minY + maxY; - float delta = maxY < 0 ? tick : -tick; - float fractDelta = Mth.frac(delta * 0.2F - (float) Mth.floor(delta * 0.1F)); - float xIn = -beamIn; - float minV = Mth.clamp(fractDelta - 1.0F, 0.0F, 1.0F); - float maxV = (float) maxY * (0.5F / beamIn) + minV; - float rotation = (age + tick) / 25.0F + 6.0F; - - VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderType.beaconBeam(BEAM_TEXTURE, true)); - - matrices.pushPose(); - matrices.mulPose(Vector3f.YP.rotation(-rotation)); - renderBeam( - matrices, - vertexConsumer, - red, - green, - blue, - alpha, - minY, - maxBY, - beamIn, - 0.0F, - 0.0F, - beamIn, - 0.0F, - xIn, - xIn, - 0.0F, - 0.0F, - 1.0F, - minV, - maxV - ); - - float xOut = -beamOut; - maxV = (float) maxY + minV; - renderBeam( - matrices, - vertexConsumer, - red, - green, - blue, - alpha, - minY, - maxBY, - xOut, - xOut, - beamOut, - xOut, - xOut, - beamOut, - beamOut, - beamOut, - 0.0F, - 1.0F, - minV, - maxV - ); - matrices.popPose(); - } - - private static void renderBeam(PoseStack matrices, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int minY, int maxY, float x1, float d1, float x2, float d2, float x3, float d3, float x4, float d4, float minU, float maxU, float minV, float maxV) { - PoseStack.Pose entry = matrices.last(); - Matrix4f matrix4f = entry.pose(); - Matrix3f matrix3f = entry.normal(); - renderBeam( - matrix4f, - matrix3f, - vertexConsumer, - red, - green, - blue, - alpha, - maxY, - minY, - x1, - d1, - x2, - d2, - minU, - maxU, - minV, - maxV - ); - renderBeam( - matrix4f, - matrix3f, - vertexConsumer, - red, - green, - blue, - alpha, - maxY, - minY, - x4, - d4, - x3, - d3, - minU, - maxU, - minV, - maxV - ); - renderBeam( - matrix4f, - matrix3f, - vertexConsumer, - red, - green, - blue, - alpha, - maxY, - minY, - x2, - d2, - x4, - d4, - minU, - maxU, - minV, - maxV - ); - renderBeam( - matrix4f, - matrix3f, - vertexConsumer, - red, - green, - blue, - alpha, - maxY, - minY, - x3, - d3, - x1, - d1, - minU, - maxU, - minV, - maxV - ); - } - - private static void renderBeam(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, int minY, int maxY, float minX, float minD, float maxX, float maxD, float minU, float maxU, float minV, float maxV) { - addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, maxX, minY, maxD, maxU, minV); - addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, maxX, maxY, maxD, maxU, maxV); - addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, minX, maxY, minD, minU, maxV); - addVertex(matrix4f, matrix3f, vertexConsumer, red, green, blue, alpha, minX, minY, minD, minU, minV); - } - - private static void addVertex(Matrix4f matrix4f, Matrix3f matrix3f, VertexConsumer vertexConsumer, float red, float green, float blue, float alpha, float x, float y, float d, float u, float v) { - vertexConsumer.vertex(matrix4f, x, y, d) - .color(red, green, blue, alpha) - .uv(u, v) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(15728880) - .normal(matrix3f, 0.0F, 1.0F, 0.0F) - .endVertex(); - } -} diff --git a/src/main/java/ru/betterend/client/render/BetterEndSkyRenderer.java b/src/main/java/ru/betterend/client/render/BetterEndSkyRenderer.java deleted file mode 100644 index 0d579a48..00000000 --- a/src/main/java/ru/betterend/client/render/BetterEndSkyRenderer.java +++ /dev/null @@ -1,385 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.platform.GlDebug; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexBuffer; -import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.math.Matrix4f; -import com.mojang.math.Quaternion; -import com.mojang.math.Vector3f; -import net.fabricmc.fabric.api.client.rendering.v1.DimensionRenderingRegistry; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.minecraft.client.renderer.FogRenderer; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.resources.ResourceLocation; - -import org.lwjgl.opengl.GLDebugMessageAMDCallback; -import ru.bclib.util.BackgroundInfo; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.LegacyRandomSource; - -public class BetterEndSkyRenderer implements DimensionRenderingRegistry.SkyRenderer { - @FunctionalInterface - static interface BufferFunction { - void make(BufferBuilder bufferBuilder, double minSize, double maxSize, int count, long seed); - } - private static final ResourceLocation NEBULA_1 = BetterEnd.makeID("textures/sky/nebula_2.png"); - private static final ResourceLocation NEBULA_2 = BetterEnd.makeID("textures/sky/nebula_3.png"); - private static final ResourceLocation HORIZON = BetterEnd.makeID("textures/sky/nebula_1.png"); - private static final ResourceLocation STARS = BetterEnd.makeID("textures/sky/stars.png"); - private static final ResourceLocation FOG = BetterEnd.makeID("textures/sky/fog.png"); - - private VertexBuffer nebula1; - private VertexBuffer nebula2; - private VertexBuffer horizon; - private VertexBuffer stars1; - private VertexBuffer stars2; - private VertexBuffer stars3; - private VertexBuffer stars4; - private VertexBuffer fog; - private Vector3f axis1; - private Vector3f axis2; - private Vector3f axis3; - private Vector3f axis4; - - private boolean initialised; - - private void initialise() { - if (!initialised) { - initStars(); - RandomSource random = new LegacyRandomSource(131); - axis1 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); - axis2 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); - axis3 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); - axis4 = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat()); - axis1.normalize(); - axis2.normalize(); - axis3.normalize(); - axis4.normalize(); - initialised = true; - } - } - - @Override - public void render(WorldRenderContext context) { - if (context.world() == null || context.matrixStack() == null) { - return; - } - - initialise(); - - Matrix4f projectionMatrix = context.projectionMatrix(); - PoseStack matrices = context.matrixStack(); - - float time = ((context.world().getDayTime() + context.tickDelta()) % 360000) * 0.000017453292F; - float time2 = time * 2; - float time3 = time * 3; - - FogRenderer.levelFogColor(); - RenderSystem.depthMask(false); - RenderSystem.enableTexture(); - RenderSystem.enableBlend(); - RenderSystem.setShaderColor(1.0F ,1.0F ,1.0F ,1.0F); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - - float blindA = 1F - BackgroundInfo.blindness; - float blind02 = blindA * 0.2F; - float blind06 = blindA * 0.6F; - - if (blindA > 0) { - matrices.pushPose(); - matrices.mulPose(new Quaternion(0, time, 0, false)); - RenderSystem.setShaderTexture(0, HORIZON); - renderBuffer(matrices, projectionMatrix, horizon, DefaultVertexFormat.POSITION_TEX, 0.77F, 0.31F, 0.73F, 0.7F * blindA); - matrices.popPose(); - - matrices.pushPose(); - matrices.mulPose(new Quaternion(0, -time, 0, false)); - RenderSystem.setShaderTexture(0, NEBULA_1); - renderBuffer(matrices, projectionMatrix, nebula1, DefaultVertexFormat.POSITION_TEX, 0.77F, 0.31F, 0.73F, blind02); - matrices.popPose(); - - matrices.pushPose(); - matrices.mulPose(new Quaternion(0, time2, 0, false)); - RenderSystem.setShaderTexture(0, NEBULA_2); - renderBuffer(matrices, projectionMatrix, nebula2, DefaultVertexFormat.POSITION_TEX, 0.77F, 0.31F, 0.73F, blind02); - matrices.popPose(); - - RenderSystem.setShaderTexture(0, STARS); - - matrices.pushPose(); - matrices.mulPose(axis3.rotation(time)); - renderBuffer(matrices, projectionMatrix, stars3, DefaultVertexFormat.POSITION_TEX, 0.77F, 0.31F, 0.73F, blind06); - matrices.popPose(); - - matrices.pushPose(); - matrices.mulPose(axis4.rotation(time2)); - renderBuffer(matrices, projectionMatrix, stars4, DefaultVertexFormat.POSITION_TEX, 1F, 1F, 1F, blind06); - matrices.popPose(); - } - - float a = (BackgroundInfo.fogDensity - 1F); - if (a > 0) { - if (a > 1) a = 1; - RenderSystem.setShaderTexture(0, FOG); - renderBuffer( - matrices, - projectionMatrix, - fog, - DefaultVertexFormat.POSITION_TEX, - BackgroundInfo.fogColorRed, - BackgroundInfo.fogColorGreen, - BackgroundInfo.fogColorBlue, - a); - } - - RenderSystem.disableTexture(); - - if (blindA > 0) { - matrices.pushPose(); - matrices.mulPose(axis1.rotation(time3)); - renderBuffer(matrices, projectionMatrix, stars1, DefaultVertexFormat.POSITION, 1, 1, 1, blind06); - matrices.popPose(); - - matrices.pushPose(); - matrices.mulPose(axis2.rotation(time2)); - renderBuffer(matrices, projectionMatrix, stars2, DefaultVertexFormat.POSITION, 0.95F, 0.64F, 0.93F, blind06); - matrices.popPose(); - } - - RenderSystem.enableTexture(); - RenderSystem.depthMask(true); - RenderSystem.defaultBlendFunc(); - RenderSystem.disableBlend(); - } - - private void renderBuffer(PoseStack matrices, Matrix4f matrix4f, VertexBuffer buffer, VertexFormat format, float r, float g, float b, float a) { - RenderSystem.setShaderColor(r, g, b, a); - buffer.bind(); - if (format == DefaultVertexFormat.POSITION) { - buffer.drawWithShader(matrices.last().pose(), matrix4f, GameRenderer.getPositionShader()); - } - else { - buffer.drawWithShader(matrices.last().pose(), matrix4f, GameRenderer.getPositionTexShader()); - } - VertexBuffer.unbind(); - } - - private void initStars() { - BufferBuilder buffer = Tesselator.getInstance().getBuilder(); - stars1 = buildBuffer(buffer, stars1, 0.1, 0.30, 3500, 41315, this::makeStars); - stars2 = buildBuffer(buffer, stars2, 0.1, 0.35, 2000, 35151, this::makeStars); - stars3 = buildBuffer(buffer, stars3, 0.4, 1.2, 1000, 61354, this::makeUVStars); - stars4 = buildBuffer(buffer, stars4, 0.4, 1.2, 1000, 61355, this::makeUVStars); - nebula1 = buildBuffer(buffer, nebula1, 40, 60, 30, 11515, this::makeFarFog); - nebula2 = buildBuffer(buffer, nebula2, 40, 60, 10, 14151, this::makeFarFog); - horizon = buildBufferHorizon(buffer, horizon); - fog = buildBufferFog(buffer, fog); - } - - private VertexBuffer buildBuffer(BufferBuilder bufferBuilder, VertexBuffer buffer, double minSize, double maxSize, int count, long seed, BufferFunction fkt) { - if (buffer != null) { - buffer.close(); - } - - buffer = new VertexBuffer(); - fkt.make(bufferBuilder, minSize, maxSize, count, seed); - BufferBuilder.RenderedBuffer renderedBuffer = bufferBuilder.end(); - buffer.bind(); - buffer.upload(renderedBuffer); - - return buffer; - } - - - private VertexBuffer buildBufferHorizon(BufferBuilder bufferBuilder, VertexBuffer buffer) { - return buildBuffer( - bufferBuilder, buffer, 0, 0, 0, 0, - (_builder, _minSize, _maxSize, _count, _seed)->makeCylinder(_builder, 16, 50, 100)); - - } - - private VertexBuffer buildBufferFog(BufferBuilder bufferBuilder, VertexBuffer buffer) { - return buildBuffer( - bufferBuilder, buffer, 0, 0, 0, 0, - (_builder, _minSize, _maxSize, _count, _seed)->makeCylinder(_builder, 16, 50, 70)); - } - - private void makeStars(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { - RandomSource random = new LegacyRandomSource(seed); - RenderSystem.setShader(GameRenderer::getPositionShader); - buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); - - for (int i = 0; i < count; ++i) { - double posX = random.nextDouble() * 2.0 - 1.0; - double posY = random.nextDouble() * 2.0 - 1.0; - double posZ = random.nextDouble() * 2.0 - 1.0; - double size = MHelper.randRange(minSize, maxSize, random); - double length = posX * posX + posY * posY + posZ * posZ; - - if (length < 1.0 && length > 0.001) { - length = 1.0 / Math.sqrt(length); - posX *= length; - posY *= length; - posZ *= length; - - double px = posX * 100.0; - double py = posY * 100.0; - double pz = posZ * 100.0; - - double angle = Math.atan2(posX, posZ); - double sin1 = Math.sin(angle); - double cos1 = Math.cos(angle); - angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); - double sin2 = Math.sin(angle); - double cos2 = Math.cos(angle); - angle = random.nextDouble() * Math.PI * 2.0; - double sin3 = Math.sin(angle); - double cos3 = Math.cos(angle); - - for (int index = 0; index < 4; ++index) { - double x = (double) ((index & 2) - 1) * size; - double y = (double) ((index + 1 & 2) - 1) * size; - double aa = x * cos3 - y * sin3; - double ab = y * cos3 + x * sin3; - double dy = aa * sin2 + 0.0 * cos2; - double ae = 0.0 * sin2 - aa * cos2; - double dx = ae * sin1 - ab * cos1; - double dz = ab * sin1 + ae * cos1; - buffer.vertex(px + dx, py + dy, pz + dz).endVertex(); - } - } - } - } - - private void makeUVStars(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { - RandomSource random = new LegacyRandomSource(seed); - RenderSystem.setShader(GameRenderer::getPositionTexShader); - buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - - for (int i = 0; i < count; ++i) { - double posX = random.nextDouble() * 2.0 - 1.0; - double posY = random.nextDouble() * 2.0 - 1.0; - double posZ = random.nextDouble() * 2.0 - 1.0; - double size = MHelper.randRange(minSize, maxSize, random); - double length = posX * posX + posY * posY + posZ * posZ; - - if (length < 1.0 && length > 0.001) { - length = 1.0 / Math.sqrt(length); - posX *= length; - posY *= length; - posZ *= length; - - double px = posX * 100.0; - double py = posY * 100.0; - double pz = posZ * 100.0; - - double angle = Math.atan2(posX, posZ); - double sin1 = Math.sin(angle); - double cos1 = Math.cos(angle); - angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); - double sin2 = Math.sin(angle); - double cos2 = Math.cos(angle); - angle = random.nextDouble() * Math.PI * 2.0; - double sin3 = Math.sin(angle); - double cos3 = Math.cos(angle); - - float minV = random.nextInt(4) / 4F; - for (int index = 0; index < 4; ++index) { - double x = (double) ((index & 2) - 1) * size; - double y = (double) ((index + 1 & 2) - 1) * size; - double aa = x * cos3 - y * sin3; - double ab = y * cos3 + x * sin3; - double dy = aa * sin2 + 0.0 * cos2; - double ae = 0.0 * sin2 - aa * cos2; - double dx = ae * sin1 - ab * cos1; - double dz = ab * sin1 + ae * cos1; - float texU = (index >> 1) & 1; - float texV = (((index + 1) >> 1) & 1) / 4F + minV; - buffer.vertex(px + dx, py + dy, pz + dz).uv(texU, texV).endVertex(); - } - } - } - } - - private void makeFarFog(BufferBuilder buffer, double minSize, double maxSize, int count, long seed) { - RandomSource random = new LegacyRandomSource(seed); - RenderSystem.setShader(GameRenderer::getPositionTexShader); - buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - - for (int i = 0; i < count; ++i) { - double posX = random.nextDouble() * 2.0 - 1.0; - double posY = random.nextDouble() - 0.5; - double posZ = random.nextDouble() * 2.0 - 1.0; - double size = MHelper.randRange(minSize, maxSize, random); - double length = posX * posX + posY * posY + posZ * posZ; - double distance = 2.0; - - if (length < 1.0 && length > 0.001) { - length = distance / Math.sqrt(length); - size *= distance; - posX *= length; - posY *= length; - posZ *= length; - - double px = posX * 100.0; - double py = posY * 100.0; - double pz = posZ * 100.0; - - double angle = Math.atan2(posX, posZ); - double sin1 = Math.sin(angle); - double cos1 = Math.cos(angle); - angle = Math.atan2(Math.sqrt(posX * posX + posZ * posZ), posY); - double sin2 = Math.sin(angle); - double cos2 = Math.cos(angle); - angle = random.nextDouble() * Math.PI * 2.0; - double sin3 = Math.sin(angle); - double cos3 = Math.cos(angle); - - for (int index = 0; index < 4; ++index) { - double x = (double) ((index & 2) - 1) * size; - double y = (double) ((index + 1 & 2) - 1) * size; - double aa = x * cos3 - y * sin3; - double ab = y * cos3 + x * sin3; - double dy = aa * sin2 + 0.0 * cos2; - double ae = 0.0 * sin2 - aa * cos2; - double dx = ae * sin1 - ab * cos1; - double dz = ab * sin1 + ae * cos1; - float texU = (index >> 1) & 1; - float texV = ((index + 1) >> 1) & 1; - buffer.vertex(px + dx, py + dy, pz + dz).uv(texU, texV).endVertex(); - } - } - } - } - - private void makeCylinder(BufferBuilder buffer, int segments, double height, double radius) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - for (int i = 0; i < segments; i++) { - double a1 = (double) i * Math.PI * 2.0 / (double) segments; - double a2 = (double) (i + 1) * Math.PI * 2.0 / (double) segments; - double px1 = Math.sin(a1) * radius; - double pz1 = Math.cos(a1) * radius; - double px2 = Math.sin(a2) * radius; - double pz2 = Math.cos(a2) * radius; - - float u0 = (float) i / (float) segments; - float u1 = (float) (i + 1) / (float) segments; - - buffer.vertex(px1, -height, pz1).uv(u0, 0).endVertex(); - buffer.vertex(px1, height, pz1).uv(u0, 1).endVertex(); - buffer.vertex(px2, height, pz2).uv(u1, 1).endVertex(); - buffer.vertex(px2, -height, pz2).uv(u1, 0).endVertex(); - } - } -} diff --git a/src/main/java/ru/betterend/client/render/EndCrystalRenderer.java b/src/main/java/ru/betterend/client/render/EndCrystalRenderer.java deleted file mode 100644 index cb48989c..00000000 --- a/src/main/java/ru/betterend/client/render/EndCrystalRenderer.java +++ /dev/null @@ -1,78 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Quaternion; -import com.mojang.math.Vector3f; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartPose; -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.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; - -public class EndCrystalRenderer { - private static final ResourceLocation CRYSTAL_TEXTURE = new ResourceLocation( - "textures/entity/end_crystal/end_crystal.png"); - private static final ResourceLocation CRYSTAL_BEAM_TEXTURE = new ResourceLocation( - "textures/entity/end_crystal/end_crystal_beam.png"); - private static final RenderType END_CRYSTAL; - private static final ModelPart CORE; - private static final ModelPart FRAME; - private static final int AGE_CYCLE = 240; - private static final float SINE_45_DEGREES; - - public static void render(int age, int maxAge, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumerProvider, int light) { - float k = (float) AGE_CYCLE / maxAge; - float rotation = (age * k + tickDelta) * 3.0F; - VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(END_CRYSTAL); - matrices.pushPose(); - matrices.scale(0.8F, 0.8F, 0.8F); - matrices.translate(0.0D, -0.5D, 0.0D); - matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); - matrices.translate(0.0D, 0.8F, 0.0D); - matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); - FRAME.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); - matrices.scale(0.875F, 0.875F, 0.875F); - matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); - matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); - FRAME.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); - matrices.scale(0.875F, 0.875F, 0.875F); - matrices.mulPose(new Quaternion(new Vector3f(SINE_45_DEGREES, 0.0F, SINE_45_DEGREES), 60.0F, true)); - matrices.mulPose(Vector3f.YP.rotationDegrees(rotation)); - CORE.render(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY); - matrices.popPose(); - } - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - modelPartData.addOrReplaceChild( - "FRAME", - CubeListBuilder.create().texOffs(0, 0).addBox(-4.0f, -4.0f, -4.0f, 8.0f, 8.0f, 8.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - "CORE", - CubeListBuilder.create().texOffs(32, 0).addBox(-4.0f, -4.0f, -4.0f, 8.0f, 8.0f, 8.0f), - PartPose.ZERO - ); - - return LayerDefinition.create(modelData, 64, 32); - } - - static { - END_CRYSTAL = RenderType.entityCutoutNoCull(CRYSTAL_TEXTURE); - RenderType.entitySmoothCutout(CRYSTAL_BEAM_TEXTURE); - SINE_45_DEGREES = (float) Math.sin(0.7853981633974483D); - - ModelPart root = getTexturedModelData().bakeRoot(); - FRAME = root.getChild("FRAME"); - CORE = root.getChild("CORE"); - } -} diff --git a/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java b/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java deleted file mode 100644 index 1d250918..00000000 --- a/src/main/java/ru/betterend/client/render/EternalCrystalRenderer.java +++ /dev/null @@ -1,130 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Vector3f; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartPose; -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.renderer.texture.OverlayTexture; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.AuroraCrystalBlock; - -// TODO make crystals bright -public class EternalCrystalRenderer { - private static final RenderType RENDER_LAYER; - private static final ModelPart[] SHARDS; - private static final ModelPart CORE; - - public static void render(int age, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumerProvider, int light) { - VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RENDER_LAYER); - float[] colors = colors(age); - float rotation = (age + tickDelta) / 25.0F + 6.0F; - matrices.pushPose(); - matrices.scale(0.6F, 0.6F, 0.6F); - matrices.mulPose(Vector3f.YP.rotation(rotation)); - CORE.render( - matrices, - vertexConsumer, - light, - OverlayTexture.NO_OVERLAY, - colors[0], - colors[1], - colors[2], - colors[3] - ); - - for (int i = 0; i < 4; i++) { - matrices.pushPose(); - float offset = Mth.sin(rotation * 2 + i) * 0.15F; - matrices.translate(0, offset, 0); - SHARDS[i].render( - matrices, - vertexConsumer, - light, - OverlayTexture.NO_OVERLAY, - colors[0], - colors[1], - colors[2], - colors[3] - ); - matrices.popPose(); - } - - matrices.popPose(); - } - - public static float[] colors(int age) { - double delta = age * 0.01; - int index = MHelper.floor(delta); - int index2 = (index + 1) & 3; - delta -= index; - index &= 3; - - Vec3i color1 = AuroraCrystalBlock.COLORS[index]; - Vec3i color2 = AuroraCrystalBlock.COLORS[index2]; - - int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX())); - int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY())); - int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ())); - - return ColorUtil.toFloatArray(ColorUtil.color(r, g, b)); - } - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - modelPartData.addOrReplaceChild( - "SHARDS_0", - CubeListBuilder.create().texOffs(2, 4).addBox(-5.0f, 1.0f, -3.0f, 2.0f, 8.0f, 2.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - "SHARDS_1", - CubeListBuilder.create().texOffs(2, 4).addBox(3.0f, -1.0f, -1.0f, 2.0f, 8.0f, 2.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - "SHARDS_2", - CubeListBuilder.create().texOffs(2, 4).addBox(-1.0f, 0.0f, -5.0f, 2.0f, 4.0f, 2.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - "SHARDS_3", - CubeListBuilder.create().texOffs(2, 4).addBox(0.0f, 3.0f, 4.0f, 2.0f, 6.0f, 2.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - "CORE", - CubeListBuilder.create().texOffs(0, 0).addBox(-2.0f, -2.0f, -2.0f, 4.0f, 12.0f, 4.0f), - PartPose.ZERO - ); - - return LayerDefinition.create(modelData, 16, 16); - } - - static { - RENDER_LAYER = RenderType.itemEntityTranslucentCull(BetterEnd.makeID("textures/entity/eternal_crystal.png")); - SHARDS = new ModelPart[4]; - - ModelPart root = getTexturedModelData().bakeRoot(); - SHARDS[0] = root.getChild("SHARDS_0"); - SHARDS[1] = root.getChild("SHARDS_1"); - SHARDS[2] = root.getChild("SHARDS_2"); - SHARDS[3] = root.getChild("SHARDS_3"); - CORE = root.getChild("CORE"); - } -} diff --git a/src/main/java/ru/betterend/client/render/PedestalItemRenderer.java b/src/main/java/ru/betterend/client/render/PedestalItemRenderer.java deleted file mode 100644 index 9b19e613..00000000 --- a/src/main/java/ru/betterend/client/render/PedestalItemRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -package ru.betterend.client.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Vector3f; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.util.Mth; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.betterend.blocks.EternalPedestal; -import ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.blocks.entities.PedestalBlockEntity; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -@Environment(EnvType.CLIENT) -public class PedestalItemRenderer implements BlockEntityRenderer { - public PedestalItemRenderer(BlockEntityRendererProvider.Context ctx) { - super(); - } - - @Override - public void render(T blockEntity, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay) { - Level world = blockEntity.getLevel(); - if (world == null || blockEntity.isEmpty()) return; - - BlockState state = world.getBlockState(blockEntity.getBlockPos()); - if (!(state.getBlock() instanceof PedestalBlock)) return; - - ItemStack activeItem = blockEntity.getItem(0); - - matrices.pushPose(); - Minecraft minecraft = Minecraft.getInstance(); - BakedModel model = minecraft.getItemRenderer().getModel(activeItem, world, null, 0); - Vector3f translate = model.getTransforms().ground.translation; - PedestalBlock pedestal = (PedestalBlock) state.getBlock(); - matrices.translate(translate.x() + 0.5, translate.y() + pedestal.getHeight(state), translate.z() + 0.5); - if (activeItem.getItem() instanceof BlockItem) { - matrices.scale(1.5F, 1.5F, 1.5F); - } - else { - matrices.scale(1.25F, 1.25F, 1.25F); - } - int age = (int) (minecraft.level.getGameTime() % 314); - if (state.is(EndBlocks.ETERNAL_PEDESTAL) && state.getValue(EternalPedestal.ACTIVATED)) { - float[] colors = EternalCrystalRenderer.colors(age); - int y = blockEntity.getBlockPos().getY(); - - BeamRenderer.renderLightBeam(matrices, vertexConsumers, age, tickDelta, -y, 1024 - y, colors, 0.25F, 0.13F, 0.16F); - float altitude = Mth.sin((age + tickDelta) / 10.0F) * 0.1F + 0.1F; - matrices.translate(0.0D, altitude, 0.0D); - } - if (activeItem.getItem() == Items.END_CRYSTAL) { - EndCrystalRenderer.render(age, 314, tickDelta, matrices, vertexConsumers, light); - } - else if (activeItem.getItem() == EndItems.ETERNAL_CRYSTAL) { - EternalCrystalRenderer.render(age, tickDelta, matrices, vertexConsumers, light); - } - else { - float rotation = (age + tickDelta) / 25.0F + 6.0F; - matrices.mulPose(Vector3f.YP.rotation(rotation)); - minecraft.getItemRenderer().render(activeItem, ItemTransforms.TransformType.GROUND, false, matrices, vertexConsumers, light, overlay, model); - } - matrices.popPose(); - } -} diff --git a/src/main/java/ru/betterend/complexmaterials/ColoredMaterial.java b/src/main/java/ru/betterend/complexmaterials/ColoredMaterial.java deleted file mode 100644 index f27aa10a..00000000 --- a/src/main/java/ru/betterend/complexmaterials/ColoredMaterial.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.betterend.complexmaterials; - -import com.google.common.collect.Maps; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.core.Registry; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.item.DyeItem; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.recipes.GridRecipe; -import ru.bclib.util.BlocksHelper; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; - -import java.util.Map; -import java.util.function.Function; - -public class ColoredMaterial { - private static final Map DYES = Maps.newHashMap(); - private static final Map COLORS = Maps.newHashMap(); - private final Map colors = Maps.newHashMap(); - - public ColoredMaterial(Function constructor, Block source, boolean craftEight) { - this(constructor, source, COLORS, DYES, craftEight); - } - - public ColoredMaterial(Function constructor, Block source, Map colors, Map dyes, boolean craftEight) { - String id = Registry.BLOCK.getKey(source).getPath(); - colors.forEach((color, name) -> { - String blockName = id + "_" + name; - Block block = constructor.apply(FabricBlockSettings.copyOf(source).mapColor(MaterialColor.COLOR_BLACK)); - EndBlocks.registerBlock(blockName, block); - if (craftEight) { - GridRecipe.make(BetterEnd.MOD_ID, blockName, block) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(8) - .setShape("###", "#D#", "###") - .addMaterial('#', source) - .addMaterial('D', dyes.get(color)) - .build(); - } - else { - GridRecipe.make(BetterEnd.MOD_ID, blockName, block) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#D") - .addMaterial('#', source) - .addMaterial('D', dyes.get(color)) - .build(); - } - this.colors.put(color, block); - BlocksHelper.addBlockColor(block, color); - }); - } - - public Block getByColor(DyeColor color) { - return colors.get(color.getMaterialColor().col); - } - - public Block getByColor(int color) { - return colors.get(color); - } - - static { - for (DyeColor color : DyeColor.values()) { - int colorRGB = color.getMaterialColor().col; - COLORS.put(colorRGB, color.getName()); - DYES.put(colorRGB, DyeItem.byColor(color)); - } - } -} diff --git a/src/main/java/ru/betterend/complexmaterials/CrystalSubblocksMaterial.java b/src/main/java/ru/betterend/complexmaterials/CrystalSubblocksMaterial.java deleted file mode 100644 index 4e626a3b..00000000 --- a/src/main/java/ru/betterend/complexmaterials/CrystalSubblocksMaterial.java +++ /dev/null @@ -1,133 +0,0 @@ -package ru.betterend.complexmaterials; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Block; -import ru.bclib.api.tag.NamedBlockTags; -import ru.bclib.api.tag.NamedItemTags; -import ru.bclib.api.tag.TagAPI; -import ru.bclib.blocks.BaseSlabBlock; -import ru.bclib.blocks.BaseStairsBlock; -import ru.bclib.blocks.BaseWallBlock; -import ru.bclib.recipes.GridRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndPedestal; -import ru.betterend.blocks.basis.LitBaseBlock; -import ru.betterend.blocks.basis.LitPillarBlock; -import ru.betterend.config.Configs; -import ru.betterend.recipe.CraftingRecipes; -import ru.betterend.registry.EndBlocks; - -public class CrystalSubblocksMaterial { - public final Block polished; - public final Block tiles; - public final Block pillar; - public final Block stairs; - public final Block slab; - public final Block wall; - public final Block pedestal; - public final Block bricks; - public final Block brick_stairs; - public final Block brick_slab; - public final Block brick_wall; - - public CrystalSubblocksMaterial(String name, Block source) { - FabricBlockSettings material = FabricBlockSettings.copyOf(source); - polished = EndBlocks.registerBlock(name + "_polished", new LitBaseBlock(material)); - tiles = EndBlocks.registerBlock(name + "_tiles", new LitBaseBlock(material)); - pillar = EndBlocks.registerBlock(name + "_pillar", new LitPillarBlock(material)); - stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(source)); - slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(source)); - wall = EndBlocks.registerBlock(name + "_wall", new BaseWallBlock(source)); - pedestal = EndBlocks.registerBlock(name + "_pedestal", new EndPedestal(source)); - bricks = EndBlocks.registerBlock(name + "_bricks", new LitBaseBlock(material)); - brick_stairs = EndBlocks.registerBlock(name + "_bricks_stairs", new BaseStairsBlock(bricks)); - brick_slab = EndBlocks.registerBlock(name + "_bricks_slab", new BaseSlabBlock(bricks)); - brick_wall = EndBlocks.registerBlock(name + "_bricks_wall", new BaseWallBlock(bricks)); - - // Recipes // - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks", bricks) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', source) - .setGroup("end_bricks") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_polished", polished) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', bricks) - .setGroup("end_tile") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_tiles", tiles) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', polished) - .setGroup("end_small_tile") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_pillar", pillar) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("#", "#") - .addMaterial('#', slab) - .setGroup("end_pillar") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("# ", "## ", "###") - .addMaterial('#', source) - .setGroup("end_stone_stairs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###") - .addMaterial('#', source) - .setGroup("end_stone_slabs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_stairs", brick_stairs) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("# ", "## ", "###") - .addMaterial('#', bricks) - .setGroup("end_stone_stairs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_slab", brick_slab) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###") - .addMaterial('#', bricks) - .setGroup("end_stone_slabs") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_wall", wall) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###", "###") - .addMaterial('#', source) - .setGroup("end_wall") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_wall", brick_wall) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###", "###") - .addMaterial('#', bricks) - .setGroup("end_wall") - .build(); - - CraftingRecipes.registerPedestal(name + "_pedestal", pedestal, slab, pillar); - - // Item Tags // - TagAPI.addItemTag(NamedItemTags.SLABS, slab, brick_slab); - TagAPI.addItemTag(NamedItemTags.STONE_BRICKS, bricks); - TagAPI.addItemTag(NamedItemTags.STONE_CRAFTING_MATERIALS, source); - TagAPI.addItemTag(NamedItemTags.STONE_TOOL_MATERIALS, source); - - // Block Tags // - TagAPI.addBlockTag(NamedBlockTags.STONE_BRICKS, bricks); - TagAPI.addBlockTag(NamedBlockTags.WALLS, wall, brick_wall); - TagAPI.addBlockTag(NamedBlockTags.SLABS, slab, brick_slab); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/complexmaterials/EndWoodenComplexMaterial.java b/src/main/java/ru/betterend/complexmaterials/EndWoodenComplexMaterial.java deleted file mode 100644 index 4e01fbf0..00000000 --- a/src/main/java/ru/betterend/complexmaterials/EndWoodenComplexMaterial.java +++ /dev/null @@ -1,45 +0,0 @@ -package ru.betterend.complexmaterials; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.MaterialColor; -import ru.bclib.complexmaterials.WoodenComplexMaterial; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class EndWoodenComplexMaterial extends WoodenComplexMaterial { - private Block bark; - private Block log; - - public EndWoodenComplexMaterial(String name, MaterialColor woodColor, MaterialColor planksColor) { - super(BetterEnd.MOD_ID, name, name, woodColor, planksColor); - } - - public EndWoodenComplexMaterial init() { - return (EndWoodenComplexMaterial) super.init(EndBlocks.getBlockRegistry(), EndItems.getItemRegistry(), Configs.RECIPE_CONFIG); - } - - public boolean isTreeLog(Block block) { - return block == getLog() || block == getBark(); - } - - public boolean isTreeLog(BlockState state) { - return isTreeLog(state.getBlock()); - } - - public Block getLog() { - if (log == null) { - log = getBlock("log"); - } - return log; - } - - public Block getBark() { - if (bark == null) { - bark = getBlock("bark"); - } - return bark; - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/complexmaterials/MetalMaterial.java b/src/main/java/ru/betterend/complexmaterials/MetalMaterial.java deleted file mode 100644 index 58bbaa16..00000000 --- a/src/main/java/ru/betterend/complexmaterials/MetalMaterial.java +++ /dev/null @@ -1,497 +0,0 @@ -package ru.betterend.complexmaterials; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ArmorMaterial; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Item.Properties; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.Tier; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.material.MaterialColor; - -import ru.bclib.api.tag.*; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BaseChainBlock; -import ru.bclib.blocks.BaseDoorBlock; -import ru.bclib.blocks.BaseMetalBarsBlock; -import ru.bclib.blocks.BaseOreBlock; -import ru.bclib.blocks.BaseSlabBlock; -import ru.bclib.blocks.BaseStairsBlock; -import ru.bclib.blocks.BaseTrapdoorBlock; -import ru.bclib.blocks.WoodenPressurePlateBlock; -import ru.bclib.items.ModelProviderItem; -import ru.bclib.items.tool.BaseAxeItem; -import ru.bclib.items.tool.BaseHoeItem; -import ru.bclib.items.tool.BaseShovelItem; -import ru.bclib.items.tool.BaseSwordItem; -import ru.bclib.recipes.AnvilRecipe; -import ru.bclib.recipes.FurnaceRecipe; -import ru.bclib.recipes.GridRecipe; -import ru.bclib.recipes.SmithingTableRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.BulbVineLanternBlock; -import ru.betterend.blocks.BulbVineLanternColoredBlock; -import ru.betterend.blocks.ChandelierBlock; -import ru.betterend.blocks.basis.EndAnvilBlock; -import ru.betterend.config.Configs; -import ru.betterend.item.EndArmorItem; -import ru.betterend.item.tool.EndHammerItem; -import ru.betterend.item.tool.EndPickaxe; -import ru.betterend.recipe.builders.AlloyingRecipe; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class MetalMaterial { - public final Block ore; - public final Block block; - public final Block tile; - public final Block bars; - public final Block pressurePlate; - public final Block door; - public final Block trapdoor; - public final Block chain; - public final Block stairs; - public final Block slab; - - public final Block chandelier; - public final Block bulb_lantern; - public final ColoredMaterial bulb_lantern_colored; - - public final Block anvilBlock; - - public final Item rawOre; - public final Item nugget; - public final Item ingot; - - public final Item shovelHead; - public final Item pickaxeHead; - public final Item axeHead; - public final Item hoeHead; - public final Item swordBlade; - public final Item swordHandle; - - public final Item shovel; - public final Item sword; - public final Item pickaxe; - public final Item axe; - public final Item hoe; - public final Item hammer; - - public final Item forgedPlate; - public final Item helmet; - public final Item chestplate; - public final Item leggings; - public final Item boots; - - public final TagKey alloyingOre; - - public static MetalMaterial makeNormal(String name, MaterialColor color, Tier material, ArmorMaterial armor) { - return new MetalMaterial( - name, - true, - FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).mapColor(color), - EndItems.makeEndItemSettings(), - material, - armor - ); - } - - public static MetalMaterial makeNormal(String name, MaterialColor color, float hardness, float resistance, Tier material, ArmorMaterial armor) { - return new MetalMaterial( - name, - true, - FabricBlockSettings.copyOf(Blocks.IRON_BLOCK) - .mapColor(color) - .hardness(hardness) - .resistance(resistance), - EndItems.makeEndItemSettings(), - material, - armor - ); - } - - public static MetalMaterial makeOreless(String name, MaterialColor color, Tier material, ArmorMaterial armor) { - return new MetalMaterial( - name, - false, - FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).mapColor(color), - EndItems.makeEndItemSettings(), - material, - armor - ); - } - - public static MetalMaterial makeOreless(String name, MaterialColor color, float hardness, float resistance, Tier material, ArmorMaterial armor) { - return new MetalMaterial( - name, - false, - FabricBlockSettings.copyOf(Blocks.IRON_BLOCK) - .mapColor(color) - .hardness(hardness) - .resistance(resistance), - EndItems.makeEndItemSettings(), - material, - armor - ); - } - - private MetalMaterial(String name, boolean hasOre, FabricBlockSettings settings, Properties itemSettings, Tier material, ArmorMaterial armor) { - BlockBehaviour.Properties lanternProperties = FabricBlockSettings.copyOf(settings) - .hardness(1) - .resistance(1) - .luminance(15) - .sound(SoundType.LANTERN); - final int level = material.getLevel(); - - rawOre = hasOre ? EndItems.registerEndItem(name + "_raw", new ModelProviderItem(itemSettings)) : null; - ore = hasOre ? EndBlocks.registerBlock(name + "_ore", new BaseOreBlock(()->rawOre, 1, 3, 1)) : null; - alloyingOre = hasOre ? TagAPI.makeItemTag(BetterEnd.MOD_ID, name + "_alloying") : null; - if (hasOre) { - TagAPI.addItemTag(alloyingOre, ore, rawOre); - } - - block = EndBlocks.registerBlock(name + "_block", new BaseBlock(settings)); - tile = EndBlocks.registerBlock(name + "_tile", new BaseBlock(settings)); - stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(tile)); - slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(tile)); - door = EndBlocks.registerBlock(name + "_door", new BaseDoorBlock(block)); - trapdoor = EndBlocks.registerBlock(name + "_trapdoor", new BaseTrapdoorBlock(block)); - bars = EndBlocks.registerBlock(name + "_bars", new BaseMetalBarsBlock(block)); - chain = EndBlocks.registerBlock(name + "_chain", new BaseChainBlock(block.defaultMaterialColor())); - pressurePlate = EndBlocks.registerBlock(name + "_plate", new WoodenPressurePlateBlock(block)); - - chandelier = EndBlocks.registerBlock(name + "_chandelier", new ChandelierBlock(block)); - bulb_lantern = EndBlocks.registerBlock(name + "_bulb_lantern", new BulbVineLanternBlock(lanternProperties)); - bulb_lantern_colored = new ColoredMaterial(BulbVineLanternColoredBlock::new, bulb_lantern, false); - - nugget = EndItems.registerEndItem(name + "_nugget", new ModelProviderItem(itemSettings)); - ingot = EndItems.registerEndItem(name + "_ingot", new ModelProviderItem(itemSettings)); - - shovelHead = EndItems.registerEndItem(name + "_shovel_head"); - pickaxeHead = EndItems.registerEndItem(name + "_pickaxe_head"); - axeHead = EndItems.registerEndItem(name + "_axe_head"); - hoeHead = EndItems.registerEndItem(name + "_hoe_head"); - swordBlade = EndItems.registerEndItem(name + "_sword_blade"); - swordHandle = EndItems.registerEndItem(name + "_sword_handle"); - - shovel = EndItems.registerEndTool(name + "_shovel", new BaseShovelItem(material, 1.5F, -3.0F, itemSettings)); - sword = EndItems.registerEndTool(name + "_sword", new BaseSwordItem(material, 3, -2.4F, itemSettings)); - pickaxe = EndItems.registerEndTool(name + "_pickaxe", new EndPickaxe(material, 1, -2.8F, itemSettings)); - axe = EndItems.registerEndTool(name + "_axe", new BaseAxeItem(material, 6.0F, -3.0F, itemSettings)); - hoe = EndItems.registerEndTool(name + "_hoe", new BaseHoeItem(material, -3, 0.0F, itemSettings)); - hammer = EndItems.registerEndTool( - name + "_hammer", - new EndHammerItem(material, 5.0F, -3.2F, 0.3D, itemSettings) - ); - - forgedPlate = EndItems.registerEndItem(name + "_forged_plate"); - helmet = EndItems.registerEndItem(name + "_helmet", new EndArmorItem(armor, EquipmentSlot.HEAD, itemSettings)); - chestplate = EndItems.registerEndItem( - name + "_chestplate", - new EndArmorItem(armor, EquipmentSlot.CHEST, itemSettings) - ); - leggings = EndItems.registerEndItem( - name + "_leggings", - new EndArmorItem(armor, EquipmentSlot.LEGS, itemSettings) - ); - boots = EndItems.registerEndItem(name + "_boots", new EndArmorItem(armor, EquipmentSlot.FEET, itemSettings)); - - anvilBlock = EndBlocks.registerBlock( - name + "_anvil", - new EndAnvilBlock(this, block.defaultMaterialColor(), level) - ); - - if (hasOre) { - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_ingot_furnace_ore", ore, ingot) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_ingot") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_ingot_furnace_raw", rawOre, ingot) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_ingot") - .buildWithBlasting(); - AlloyingRecipe.Builder.create(name + "_ingot_alloy") - .setInput(alloyingOre, alloyingOre) - .setOutput(ingot, 3) - .setExpiriense(2.1F) - .build(); - } - - // Basic recipes - GridRecipe.make(BetterEnd.MOD_ID, name + "_ingot_from_nuggets", ingot) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "###", "###") - .addMaterial('#', nugget) - .setGroup("end_metal_ingots_nug") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_nuggets_from_ingot", nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(9) - .setList("#") - .addMaterial('#', ingot) - .setGroup("end_metal_nuggets_ing") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_block", block) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "###", "###") - .addMaterial('#', ingot) - .setGroup("end_metal_blocks") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_ingot_from_block", ingot) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(9) - .setList("#") - .addMaterial('#', block) - .setGroup("end_metal_ingots") - .build(); - - // Block recipes - GridRecipe.make(BetterEnd.MOD_ID, name + "_tile", tile) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', block) - .setGroup("end_metal_tiles") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bars", bars) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(16) - .setShape("###", "###") - .addMaterial('#', ingot) - .setGroup("end_metal_bars") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_pressure_plate", pressurePlate) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##") - .addMaterial('#', ingot) - .setGroup("end_metal_plates") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_door", door) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(3) - .setShape("##", "##", "##") - .addMaterial('#', ingot) - .setGroup("end_metal_doors") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_trapdoor", trapdoor) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', ingot) - .setGroup("end_metal_trapdoors") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("# ", "## ", "###") - .addMaterial('#', block, tile) - .setGroup("end_metal_stairs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###") - .addMaterial('#', block, tile) - .setGroup("end_metal_slabs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_chain", chain) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("N", "#", "N") - .addMaterial('#', ingot) - .addMaterial('N', nugget) - .setGroup("end_metal_chain") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_anvil", anvilBlock) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", " I ", "III") - .addMaterial('#', block, tile) - .addMaterial('I', ingot) - .setGroup("end_metal_anvil") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bulb_lantern", bulb_lantern) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("C", "I", "#") - .addMaterial('C', chain) - .addMaterial('I', ingot) - .addMaterial('#', EndItems.GLOWING_BULB) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_chandelier", chandelier) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("I#I", " # ") - .addMaterial('#', ingot) - .addMaterial('I', EndItems.LUMECORN_ROD) - .setGroup("end_metal_chandelier") - .build(); - - // Tools & armor into nuggets - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_axe_nugget", axe, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_hoe_nugget", hoe, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_pickaxe_nugget", pickaxe, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_sword_nugget", sword, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_hammer_nugget", hammer, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_helmet_nugget", helmet, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_chestplate_nugget", chestplate, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_leggings_nugget", leggings, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - FurnaceRecipe.make(BetterEnd.MOD_ID, name + "_boots_nugget", boots, nugget) - .checkConfig(Configs.RECIPE_CONFIG) - .setGroup("end_nugget") - .buildWithBlasting(); - - // Tool parts from ingots - AnvilRecipe.create(name + "_shovel_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setOutput(shovelHead) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - AnvilRecipe.create(name + "_pickaxe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setInputCount(3) - .setOutput(pickaxeHead) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - AnvilRecipe.create(name + "_axe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setInputCount(3) - .setOutput(axeHead) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - AnvilRecipe.create(name + "_hoe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setInputCount(2) - .setOutput(hoeHead) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - AnvilRecipe.create(name + "_sword_blade") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setOutput(swordBlade) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - AnvilRecipe.create(name + "_forged_plate") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(ingot) - .setOutput(forgedPlate) - .setAnvilLevel(level) - .setToolLevel(level) - .setDamage(level) - .build(); - - // Tools from parts - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_hammer") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(hammer) - .setBase(block) - .setAddition(Items.STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_axe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(axe) - .setBase(axeHead) - .setAddition(Items.STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_pickaxe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(pickaxe) - .setBase(pickaxeHead) - .setAddition(Items.STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_hoe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(hoe) - .setBase(hoeHead) - .setAddition(Items.STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_sword_handle") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(swordHandle) - .setBase(ingot) - .setAddition(Items.STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_sword") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(sword) - .setBase(swordBlade) - .setAddition(swordHandle) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, name + "_shovel") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(shovel) - .setBase(shovelHead) - .setAddition(Items.STICK) - .build(); - - // Armor crafting - GridRecipe.make(BetterEnd.MOD_ID, name + "_helmet", helmet) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "# #") - .addMaterial('#', forgedPlate) - .setGroup("end_metal_helmets") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_chestplate", chestplate) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("# #", "###", "###") - .addMaterial('#', forgedPlate) - .setGroup("end_metal_chestplates") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_leggings", leggings) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "# #", "# #") - .addMaterial('#', forgedPlate) - .setGroup("end_metal_leggings") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_boots", boots) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("# #", "# #") - .addMaterial('#', forgedPlate) - .setGroup("end_metal_boots") - .build(); - - TagAPI.addBlockTag(NamedBlockTags.ANVIL, anvilBlock); - TagAPI.addBlockTag(NamedBlockTags.BEACON_BASE_BLOCKS, block); - TagAPI.addItemTag(NamedItemTags.BEACON_PAYMENT_ITEMS, ingot); - TagAPI.addBlockTag(CommonBlockTags.DRAGON_IMMUNE, ore, bars); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/complexmaterials/StoneMaterial.java b/src/main/java/ru/betterend/complexmaterials/StoneMaterial.java deleted file mode 100644 index d723d8cd..00000000 --- a/src/main/java/ru/betterend/complexmaterials/StoneMaterial.java +++ /dev/null @@ -1,197 +0,0 @@ -package ru.betterend.complexmaterials; - -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; - -import ru.bclib.api.tag.*; -import ru.bclib.blocks.BaseBlock; -import ru.bclib.blocks.BaseFurnaceBlock; -import ru.bclib.blocks.BaseRotatedPillarBlock; -import ru.bclib.blocks.BaseSlabBlock; -import ru.bclib.blocks.BaseStairsBlock; -import ru.bclib.blocks.BaseStoneButtonBlock; -import ru.bclib.blocks.BaseWallBlock; -import ru.bclib.blocks.StonePressurePlateBlock; -import ru.bclib.recipes.GridRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndPedestal; -import ru.betterend.blocks.FlowerPotBlock; -import ru.betterend.blocks.basis.StoneLanternBlock; -import ru.betterend.config.Configs; -import ru.betterend.recipe.CraftingRecipes; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class StoneMaterial { - public final Block stone; - - public final Block polished; - public final Block tiles; - public final Block pillar; - public final Block stairs; - public final Block slab; - public final Block wall; - public final Block button; - public final Block pressurePlate; - public final Block pedestal; - public final Block lantern; - - public final Block bricks; - public final Block brickStairs; - public final Block brickSlab; - public final Block brickWall; - public final Block furnace; - public final Block flowerPot; - - public StoneMaterial(String name, MaterialColor color) { - FabricBlockSettings material = FabricBlockSettings.copyOf(Blocks.END_STONE).mapColor(color); - - stone = EndBlocks.registerBlock(name, new BaseBlock(material)); - polished = EndBlocks.registerBlock(name + "_polished", new BaseBlock(material)); - tiles = EndBlocks.registerBlock(name + "_tiles", new BaseBlock(material)); - pillar = EndBlocks.registerBlock(name + "_pillar", new BaseRotatedPillarBlock(material)); - stairs = EndBlocks.registerBlock(name + "_stairs", new BaseStairsBlock(stone)); - slab = EndBlocks.registerBlock(name + "_slab", new BaseSlabBlock(stone)); - wall = EndBlocks.registerBlock(name + "_wall", new BaseWallBlock(stone)); - button = EndBlocks.registerBlock(name + "_button", new BaseStoneButtonBlock(stone)); - pressurePlate = EndBlocks.registerBlock(name + "_plate", new StonePressurePlateBlock(stone)); - pedestal = EndBlocks.registerBlock(name + "_pedestal", new EndPedestal(stone)); - lantern = EndBlocks.registerBlock(name + "_lantern", new StoneLanternBlock(stone)); - - bricks = EndBlocks.registerBlock(name + "_bricks", new BaseBlock(material)); - brickStairs = EndBlocks.registerBlock(name + "_bricks_stairs", new BaseStairsBlock(bricks)); - brickSlab = EndBlocks.registerBlock(name + "_bricks_slab", new BaseSlabBlock(bricks)); - brickWall = EndBlocks.registerBlock(name + "_bricks_wall", new BaseWallBlock(bricks)); - furnace = EndBlocks.registerBlock(name + "_furnace", new BaseFurnaceBlock(bricks)); - flowerPot = EndBlocks.registerBlock(name + "_flower_pot", new FlowerPotBlock(bricks)); - - // Recipes // - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks", bricks) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', stone) - .setGroup("end_bricks") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_polished", polished) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', bricks) - .setGroup("end_tile") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_tiles", tiles) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("##", "##") - .addMaterial('#', polished) - .setGroup("end_small_tile") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_pillar", pillar) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("#", "#") - .addMaterial('#', slab) - .setGroup("end_pillar") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_stairs", stairs) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("# ", "## ", "###") - .addMaterial('#', stone) - .setGroup("end_stone_stairs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_slab", slab) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###") - .addMaterial('#', stone) - .setGroup("end_stone_slabs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_stairs", brickStairs) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("# ", "## ", "###") - .addMaterial('#', bricks) - .setGroup("end_stone_stairs") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_slab", brickSlab) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###") - .addMaterial('#', bricks) - .setGroup("end_stone_slabs") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_wall", wall) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###", "###") - .addMaterial('#', stone) - .setGroup("end_wall") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_bricks_wall", brickWall) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("###", "###") - .addMaterial('#', bricks) - .setGroup("end_wall") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, name + "_button", button) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', stone) - .setGroup("end_stone_buttons") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_pressure_plate", pressurePlate) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##") - .addMaterial('#', stone) - .setGroup("end_stone_plates") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_lantern", lantern) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("S", "#", "S") - .addMaterial('#', EndItems.CRYSTAL_SHARDS) - .addMaterial('S', slab, brickSlab) - .setGroup("end_stone_lanterns") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_furnace", furnace) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "# #", "###") - .addMaterial('#', stone) - .setGroup("end_stone_ITEM_FURNACES") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, name + "_flower_pot", flowerPot) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(3) - .setShape("# #", " # ") - .addMaterial('#', bricks) - .setGroup("end_pots") - .build(); - - CraftingRecipes.registerPedestal(name + "_pedestal", pedestal, slab, pillar); - - // Item Tags // - TagAPI.addItemTag(NamedItemTags.SLABS, slab, brickSlab); - TagAPI.addItemTag(NamedItemTags.STONE_BRICKS, bricks); - TagAPI.addItemTag(NamedItemTags.STONE_CRAFTING_MATERIALS, stone); - TagAPI.addItemTag(NamedItemTags.STONE_TOOL_MATERIALS, stone); - TagAPI.addItemTag(CommonItemTags.FURNACES, furnace); - - // Block Tags // - TagAPI.addBlockTag(NamedBlockTags.STONE_BRICKS, bricks); - TagAPI.addBlockTag(NamedBlockTags.WALLS, wall, brickWall); - TagAPI.addBlockTag(NamedBlockTags.SLABS, slab, brickSlab); - TagAPI.addBlockTags(pressurePlate, NamedBlockTags.PRESSURE_PLATES, NamedBlockTags.STONE_PRESSURE_PLATES); - TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); - - TagAPI.addBlockTag(CommonBlockTags.DRAGON_IMMUNE, stone, stairs, slab, wall); - - TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); - TagAPI.addBlockTag(CommonBlockTags.END_STONES, stone); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/config/Configs.java b/src/main/java/ru/betterend/config/Configs.java deleted file mode 100644 index effb9d62..00000000 --- a/src/main/java/ru/betterend/config/Configs.java +++ /dev/null @@ -1,36 +0,0 @@ -package ru.betterend.config; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import ru.bclib.BCLib; -import ru.bclib.config.EntryConfig; -import ru.bclib.config.IdConfig; -import ru.bclib.config.PathConfig; -import ru.betterend.BetterEnd; - -public class Configs { - public static final PathConfig ENTITY_CONFIG = new PathConfig(BetterEnd.MOD_ID, "entities"); - public static final PathConfig BLOCK_CONFIG = new PathConfig(BetterEnd.MOD_ID, "blocks"); - public static final PathConfig ITEM_CONFIG = new PathConfig(BetterEnd.MOD_ID, "items"); - public static final IdConfig BIOME_CONFIG = new EntryConfig(BetterEnd.MOD_ID, "biomes"); - public static final PathConfig GENERATOR_CONFIG = new PathConfig(BetterEnd.MOD_ID, "generator", false); - public static final PathConfig RECIPE_CONFIG = new PathConfig(BetterEnd.MOD_ID, "recipes"); - public static final PathConfig ENCHANTMENT_CONFIG = new PathConfig(BetterEnd.MOD_ID, "enchantments"); - - @Environment(value = EnvType.CLIENT) - public static final PathConfig CLENT_CONFIG = new PathConfig(BetterEnd.MOD_ID, "client", false); - - public static void saveConfigs() { - ENTITY_CONFIG.saveChanges(); - BLOCK_CONFIG.saveChanges(); - BIOME_CONFIG.saveChanges(); - ITEM_CONFIG.saveChanges(); - GENERATOR_CONFIG.saveChanges(); - RECIPE_CONFIG.saveChanges(); - ENCHANTMENT_CONFIG.saveChanges(); - - if (BCLib.isClient()) { - CLENT_CONFIG.saveChanges(); - } - } -} diff --git a/src/main/java/ru/betterend/effects/EndPotions.java b/src/main/java/ru/betterend/effects/EndPotions.java deleted file mode 100644 index 103f36bb..00000000 --- a/src/main/java/ru/betterend/effects/EndPotions.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.effects; - -import net.minecraft.core.Registry; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.Potions; -import ru.bclib.mixin.common.PotionBrewingAccessor; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class EndPotions { - public final static Potion END_VEIL = registerPotion("end_veil", EndStatusEffects.END_VEIL, 3600); - public final static Potion LONG_END_VEIL = registerPotion("long_end_veil", EndStatusEffects.END_VEIL, 9600); - - public static Potion registerPotion(String name, MobEffect effect, int duration) { - return registerPotion(name, new Potion(name, new MobEffectInstance(effect, duration))); - } - - public static Potion registerPotion(String name, Potion potion) { - return Registry.register(Registry.POTION, BetterEnd.makeID(name), potion); - } - - public static void register() { - PotionBrewingAccessor.callAddMix(Potions.AWKWARD, EndItems.ENDER_DUST, END_VEIL); - PotionBrewingAccessor.callAddMix(END_VEIL, Items.REDSTONE, LONG_END_VEIL); - PotionBrewingAccessor.callAddMix(Potions.AWKWARD, EndBlocks.MURKWEED.asItem(), Potions.NIGHT_VISION); - } -} diff --git a/src/main/java/ru/betterend/effects/EndStatusEffects.java b/src/main/java/ru/betterend/effects/EndStatusEffects.java deleted file mode 100644 index f0948097..00000000 --- a/src/main/java/ru/betterend/effects/EndStatusEffects.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.betterend.effects; - -import net.minecraft.core.Registry; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import ru.betterend.BetterEnd; -import ru.betterend.effects.status.EndVeilEffect; - -public class EndStatusEffects { - public final static MobEffectInstance CRYSTALITE_HEALTH_REGEN = new MobEffectInstance(MobEffects.REGENERATION, 80, 0, true, false, true); - public final static MobEffectInstance CRYSTALITE_DIG_SPEED = new MobEffectInstance(MobEffects.DIG_SPEED, 80, 0, true, false, true); - public final static MobEffectInstance CRYSTALITE_MOVE_SPEED = new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 80, 0, true, false, true); - - public final static MobEffect END_VEIL = registerEffect("end_veil", new EndVeilEffect()); - - public static MobEffect registerEffect(String name, E effect) { - return Registry.register(Registry.MOB_EFFECT, BetterEnd.makeID(name), effect); - } -} diff --git a/src/main/java/ru/betterend/effects/enchantment/EndVeilEnchantment.java b/src/main/java/ru/betterend/effects/enchantment/EndVeilEnchantment.java deleted file mode 100644 index 852c5854..00000000 --- a/src/main/java/ru/betterend/effects/enchantment/EndVeilEnchantment.java +++ /dev/null @@ -1,17 +0,0 @@ -package ru.betterend.effects.enchantment; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentCategory; - -public class EndVeilEnchantment extends Enchantment { - - public EndVeilEnchantment() { - super(Enchantment.Rarity.VERY_RARE, EnchantmentCategory.ARMOR_HEAD, new EquipmentSlot[] {EquipmentSlot.HEAD}); - } - - @Override - public boolean isDiscoverable() { - return false; - } -} diff --git a/src/main/java/ru/betterend/effects/status/EndVeilEffect.java b/src/main/java/ru/betterend/effects/status/EndVeilEffect.java deleted file mode 100644 index cbe52844..00000000 --- a/src/main/java/ru/betterend/effects/status/EndVeilEffect.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.betterend.effects.status; - -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectCategory; - -public class EndVeilEffect extends MobEffect { - - public EndVeilEffect() { - super(MobEffectCategory.BENEFICIAL, 0x0D554A); - } - - @Override - public boolean isDurationEffectTick(int duration, int amplifier) { - return false; - } -} diff --git a/src/main/java/ru/betterend/entity/CubozoaEntity.java b/src/main/java/ru/betterend/entity/CubozoaEntity.java deleted file mode 100644 index 60a6a0f8..00000000 --- a/src/main/java/ru/betterend/entity/CubozoaEntity.java +++ /dev/null @@ -1,155 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.game.ClientboundGameEventPacket; -import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.network.syncher.EntityDataSerializers; -import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EntityDimensions; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.SpawnGroupData; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.animal.AbstractSchoolingFish; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.ServerLevelAccessor; -import ru.bclib.api.biomes.BiomeAPI; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndItems; - -public class CubozoaEntity extends AbstractSchoolingFish { - public static final int VARIANTS = 2; - private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( - CubozoaEntity.class, - EntityDataSerializers.BYTE - ); - private static final EntityDataAccessor SCALE = SynchedEntityData.defineId( - CubozoaEntity.class, - EntityDataSerializers.BYTE - ); - - public CubozoaEntity(EntityType entityType, Level world) { - super(entityType, world); - } - - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, SpawnGroupData entityData, CompoundTag entityTag) { - SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); - - if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) { - this.entityData.set(VARIANT, (byte) 1); - } - - if (entityTag != null) { - if (entityTag.contains("Variant")) { - this.entityData.set(VARIANT, entityTag.getByte("Variant")); - } - if (entityTag.contains("Scale")) { - this.entityData.set(SCALE, entityTag.getByte("Scale")); - } - } - - this.refreshDimensions(); - return data; - } - - @Override - protected void defineSynchedData() { - super.defineSynchedData(); - this.entityData.define(VARIANT, (byte) 0); - this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16)); - } - - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - tag.putByte("Variant", (byte) getVariant()); - tag.putByte("Scale", getByteScale()); - } - - @Override - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); - if (tag.contains("Variant")) { - this.entityData.set(VARIANT, tag.getByte("Variant")); - } - if (tag.contains("Scale")) { - this.entityData.set(SCALE, tag.getByte("Scale")); - } - } - - @Override - public ItemStack getBucketItemStack() { - ItemStack bucket = EndItems.BUCKET_CUBOZOA.getDefaultInstance(); - CompoundTag tag = bucket.getOrCreateTag(); - tag.putByte("Variant", entityData.get(VARIANT)); - tag.putByte("Scale", entityData.get(SCALE)); - return bucket; - } - - public static AttributeSupplier.Builder createMobAttributes() { - return LivingEntity - .createLivingAttributes() - .add(Attributes.MAX_HEALTH, 2.0) - .add(Attributes.FOLLOW_RANGE, 16.0) - .add(Attributes.MOVEMENT_SPEED, 0.5); - } - - public int getVariant() { - return (int) this.entityData.get(VARIANT); - } - - public byte getByteScale() { - return this.entityData.get(SCALE); - } - - public float getScale() { - return getByteScale() / 32F + 0.75F; - } - - protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { - return dimensions.height * 0.5F; - } - - @Override - protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { - int count = random.nextInt(3); - if (count > 0) { - ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.GELATINE, count)); - this.level.addFreshEntity(drop); - } - } - - @Override - protected SoundEvent getFlopSound() { - return SoundEvents.SALMON_FLOP; - } - - @Override - public void playerTouch(Player player) { - if (player instanceof ServerPlayer && player.hurt(DamageSource.mobAttack(this), 0.5F)) { - if (!this.isSilent()) { - ((ServerPlayer) player).connection.send(new ClientboundGameEventPacket( - ClientboundGameEventPacket.PUFFER_FISH_STING, - 0.0F - )); - } - if (random.nextBoolean()) { - player.addEffect(new MobEffectInstance(MobEffects.POISON, 20, 0)); - } - } - } -} diff --git a/src/main/java/ru/betterend/entity/DragonflyEntity.java b/src/main/java/ru/betterend/entity/DragonflyEntity.java deleted file mode 100644 index 7778cfcc..00000000 --- a/src/main/java/ru/betterend/entity/DragonflyEntity.java +++ /dev/null @@ -1,218 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.AgeableMob; -import net.minecraft.world.entity.Entity; -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.control.FlyingMoveControl; -import net.minecraft.world.entity.ai.control.LookControl; -import net.minecraft.world.entity.ai.goal.BreedGoal; -import net.minecraft.world.entity.ai.goal.FloatGoal; -import net.minecraft.world.entity.ai.goal.FollowParentGoal; -import net.minecraft.world.entity.ai.goal.Goal; -import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; -import net.minecraft.world.entity.ai.navigation.PathNavigation; -import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos; -import net.minecraft.world.entity.ai.util.HoverRandomPos; -import net.minecraft.world.entity.animal.FlyingAnimal; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.BlockPathTypes; -import net.minecraft.world.level.pathfinder.Path; -import net.minecraft.world.phys.Vec3; -import ru.bclib.entity.DespawnableAnimal; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndSounds; - -import java.util.EnumSet; - -public class DragonflyEntity extends DespawnableAnimal implements FlyingAnimal { - public DragonflyEntity(EntityType entityType, Level world) { - super(entityType, world); - this.moveControl = new FlyingMoveControl(this, 20, true); - this.lookControl = new DragonflyLookControl(this); - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.xpReward = 1; - } - - public static AttributeSupplier.Builder createMobAttributes() { - return LivingEntity - .createLivingAttributes() - .add(Attributes.MAX_HEALTH, 8.0D) - .add(Attributes.FOLLOW_RANGE, 16.0D) - .add(Attributes.FLYING_SPEED, 1.0D) - .add(Attributes.MOVEMENT_SPEED, 0.1D); - } - - @Override - public boolean canBeLeashed(Player player) { - return false; - } - - @Override - protected PathNavigation createNavigation(Level world) { - FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) { - public boolean isStableDestination(BlockPos pos) { - BlockState state = this.level.getBlockState(pos); - return state.isAir() || !state.getMaterial().blocksMotion(); - } - - public void tick() { - super.tick(); - } - }; - birdNavigation.setCanOpenDoors(false); - birdNavigation.setCanFloat(false); - birdNavigation.setCanPassDoors(true); - return birdNavigation; - } - - @Override - public float getWalkTargetValue(BlockPos pos, LevelReader world) { - return world.getBlockState(pos).isAir() ? 10.0F : 0.0F; - } - - @Override - protected void registerGoals() { - this.goalSelector.addGoal(1, new FloatGoal(this)); - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); - this.goalSelector.addGoal(3, new FollowParentGoal(this, 1.0D)); - this.goalSelector.addGoal(4, new WanderAroundGoal()); - } - - @Override - public boolean isPushable() { - return false; - } - - @Override - public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { - return false; - } - - @Override - protected Entity.MovementEmission getMovementEmission() { - return Entity.MovementEmission.EVENTS; - } - - @Override - public boolean isFlying() { - return !this.onGround; - } - - @Override - public boolean isNoGravity() { - return true; - } - - @Override - public SoundEvent getAmbientSound() { - return EndSounds.ENTITY_DRAGONFLY; - } - - @Override - protected float getSoundVolume() { - return MHelper.randRange(0.25F, 0.5F, random); - } - - class DragonflyLookControl extends LookControl { - DragonflyLookControl(Mob entity) { - super(entity); - } - - protected boolean resetXRotOnTick() { - return true; - } - } - - class WanderAroundGoal extends Goal { - WanderAroundGoal() { - this.setFlags(EnumSet.of(Goal.Flag.MOVE)); - } - - public boolean canUse() { - return DragonflyEntity.this.navigation.isDone() && DragonflyEntity.this.random.nextInt(10) == 0; - } - - public boolean canContinueToUse() { - return DragonflyEntity.this.navigation.isInProgress(); - } - - public void start() { - Vec3 vec3d = this.getRandomLocation(); - if (vec3d != null) { - BlockPos pos = new BlockPos(vec3d); - try { - Path path = DragonflyEntity.this.navigation.createPath(pos, 1); - if (path != null) { - DragonflyEntity.this.navigation.moveTo(path, 1.0D); - } - } - catch (Exception e) { - } - } - super.start(); - } - - private Vec3 getRandomLocation() { - int h = BlocksHelper.downRay(DragonflyEntity.this.level, DragonflyEntity.this.blockPosition(), 16); - Vec3 rotation = DragonflyEntity.this.getViewVector(0.0F); - Vec3 airPos = HoverRandomPos.getPos(DragonflyEntity.this, 8, 7, rotation.x, rotation.z, 1.5707964F, 3, 1); - if (airPos != null) { - if (isInVoid(airPos)) { - for (int i = 0; i < 8; i++) { - airPos = HoverRandomPos.getPos( - DragonflyEntity.this, - 16, - 7, - rotation.x, - rotation.z, - MHelper.PI2, - 3, - 1 - ); - if (airPos != null && !isInVoid(airPos)) { - return airPos; - } - } - return null; - } - if (h > 5 && airPos.y() >= DragonflyEntity.this.blockPosition().getY()) { - airPos = new Vec3(airPos.x, airPos.y - h * 0.5, airPos.z); - } - return airPos; - } - return AirAndWaterRandomPos.getPos( - DragonflyEntity.this, - 8, - 4, - -2, - rotation.x, - rotation.z, - 1.5707963705062866D - ); - } - - private boolean isInVoid(Vec3 pos) { - int h = BlocksHelper.downRay(DragonflyEntity.this.level, new BlockPos(pos), 128); - return h > 100; - } - } - - @Override - public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { - return EndEntities.DRAGONFLY.create(world); - } -} diff --git a/src/main/java/ru/betterend/entity/EndFishEntity.java b/src/main/java/ru/betterend/entity/EndFishEntity.java deleted file mode 100644 index a89adfd2..00000000 --- a/src/main/java/ru/betterend/entity/EndFishEntity.java +++ /dev/null @@ -1,170 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.core.particles.ParticleTypes; -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.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.damagesource.EntityDamageSource; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.SpawnGroupData; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.animal.AbstractSchoolingFish; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.api.biomes.BiomeAPI; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndItems; - -public class EndFishEntity extends AbstractSchoolingFish { - public static final int VARIANTS_NORMAL = 5; - public static final int VARIANTS_SULPHUR = 3; - public static final int VARIANTS = VARIANTS_NORMAL + VARIANTS_SULPHUR; - private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( - EndFishEntity.class, - EntityDataSerializers.BYTE - ); - private static final EntityDataAccessor SCALE = SynchedEntityData.defineId( - EndFishEntity.class, - EntityDataSerializers.BYTE - ); - - public EndFishEntity(EntityType entityType, Level world) { - super(entityType, world); - } - - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, SpawnGroupData entityData, CompoundTag entityTag) { - SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); - - if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) { - this.entityData.set(VARIANT, (byte) (random.nextInt(VARIANTS_SULPHUR) + VARIANTS_NORMAL)); - } - - if (entityTag != null) { - if (entityTag.contains("Variant")) { - this.entityData.set(VARIANT, entityTag.getByte("variant")); - } - if (entityTag.contains("Scale")) { - this.entityData.set(SCALE, entityTag.getByte("scale")); - } - } - - this.refreshDimensions(); - return data; - } - - @Override - protected void defineSynchedData() { - super.defineSynchedData(); - this.entityData.define(VARIANT, (byte) this.getRandom().nextInt(VARIANTS_NORMAL)); - this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16)); - } - - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - tag.putByte("Variant", (byte) getVariant()); - tag.putByte("Scale", getByteScale()); - } - - @Override - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); - if (tag.contains("Variant")) { - this.entityData.set(VARIANT, tag.getByte("Variant")); - } - if (tag.contains("Scale")) { - this.entityData.set(SCALE, tag.getByte("Scale")); - } - } - - @Override - public ItemStack getBucketItemStack() { - ItemStack bucket = EndItems.BUCKET_END_FISH.getDefaultInstance(); - CompoundTag tag = bucket.getOrCreateTag(); - tag.putByte("variant", entityData.get(VARIANT)); - tag.putByte("scale", entityData.get(SCALE)); - return bucket; - } - - @Override - protected SoundEvent getFlopSound() { - return SoundEvents.TROPICAL_FISH_FLOP; - } - - @Override - protected SoundEvent getAmbientSound() { - return SoundEvents.SALMON_AMBIENT; - } - - @Override - protected SoundEvent getDeathSound() { - return SoundEvents.SALMON_DEATH; - } - - @Override - protected SoundEvent getHurtSound(DamageSource source) { - return SoundEvents.SALMON_HURT; - } - - @Override - public void tick() { - super.tick(); - if (random.nextInt(8) == 0 && getFeetBlockState().is(Blocks.WATER)) { - double x = getX() + random.nextGaussian() * 0.2; - double y = getY() + random.nextGaussian() * 0.2; - double z = getZ() + random.nextGaussian() * 0.2; - level.addParticle(ParticleTypes.BUBBLE, x, y, z, 0, 0, 0); - } - } - - public static AttributeSupplier.Builder createMobAttributes() { - return LivingEntity - .createLivingAttributes() - .add(Attributes.MAX_HEALTH, 2.0) - .add(Attributes.FOLLOW_RANGE, 16.0) - .add(Attributes.MOVEMENT_SPEED, 0.75); - } - - public int getVariant() { - return (int) this.entityData.get(VARIANT); - } - - public byte getByteScale() { - return this.entityData.get(SCALE); - } - - public float getScale() { - return getByteScale() / 32F + 0.75F; - } - - @Override - protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { - Item item = source.isFire() ? EndItems.END_FISH_COOKED : EndItems.END_FISH_RAW; - if (causedByPlayer && source instanceof EntityDamageSource) { - EntityDamageSource damageSource = (EntityDamageSource) source; - ItemStack handItem = ((Player) damageSource.getEntity()).getItemInHand(InteractionHand.MAIN_HAND); - if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FIRE_ASPECT, handItem) > 0) { - item = EndItems.END_FISH_COOKED; - } - } - ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(item)); - this.level.addFreshEntity(drop); - } -} diff --git a/src/main/java/ru/betterend/entity/EndSlimeEntity.java b/src/main/java/ru/betterend/entity/EndSlimeEntity.java deleted file mode 100644 index 155edf2e..00000000 --- a/src/main/java/ru/betterend/entity/EndSlimeEntity.java +++ /dev/null @@ -1,433 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -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.DifficultyInstance; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.SpawnGroupData; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.ai.control.MoveControl; -import net.minecraft.world.entity.ai.goal.Goal; -import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; -import net.minecraft.world.entity.animal.IronGolem; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.monster.Slime; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.biomes.BCLBiome; -import ru.betterend.interfaces.ISlime; -import ru.betterend.registry.EndBiomes; -import ru.betterend.util.GlobalState; - -import java.util.EnumSet; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndSlimeEntity extends Slime { - private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId( - EndSlimeEntity.class, - EntityDataSerializers.BYTE - ); - - public EndSlimeEntity(EntityType entityType, Level world) { - super(entityType, world); - this.moveControl = new EndSlimeMoveControl(this); - } - - protected void registerGoals() { - this.goalSelector.addGoal(1, new SwimmingGoal()); - this.goalSelector.addGoal(2, new FaceTowardTargetGoal()); - this.goalSelector.addGoal(3, new RandomLookGoal()); - this.goalSelector.addGoal(5, new MoveGoal()); - this.targetSelector.addGoal( - 1, - new NearestAttackableTargetGoal(this, Player.class, 10, true, false, (livingEntity) -> { - return Math.abs(livingEntity.getY() - this.getY()) <= 4.0D; - }) - ); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal(this, IronGolem.class, true)); - } - - public static AttributeSupplier.Builder createMobAttributes() { - return LivingEntity - .createLivingAttributes() - .add(Attributes.MAX_HEALTH, 1.0D) - .add(Attributes.ATTACK_DAMAGE, 1.0D) - .add(Attributes.FOLLOW_RANGE, 16.0D) - .add(Attributes.MOVEMENT_SPEED, 0.15D); - } - - @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, SpawnGroupData entityData, CompoundTag entityTag) { - SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag); - BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(blockPosition())); - if (biome == EndBiomes.FOGGY_MUSHROOMLAND) { - this.setMossy(); - } - else if (biome == EndBiomes.MEGALAKE || biome == EndBiomes.MEGALAKE_GROVE) { - this.setLake(); - } - else if (biome == EndBiomes.AMBER_LAND) { - this.setAmber(true); - } - this.refreshDimensions(); - return data; - } - - @Override - protected void defineSynchedData() { - super.defineSynchedData(); - this.entityData.define(VARIANT, (byte) 0); - } - - @Override - public void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - tag.putByte("Variant", (byte) getSlimeType()); - } - - @Override - public void readAdditionalSaveData(CompoundTag tag) { - super.readAdditionalSaveData(tag); - if (tag.contains("Variant")) { - this.entityData.set(VARIANT, tag.getByte("Variant")); - } - } - - @Override - protected ParticleOptions getParticleType() { - return ParticleTypes.PORTAL; - } - - @Override - public void remove(RemovalReason reason) { - int i = this.getSize(); - if (!this.level.isClientSide && i > 1 && this.isDeadOrDying()) { - Component text = this.getCustomName(); - boolean bl = this.isNoAi(); - float f = (float) i / 4.0F; - int j = i / 2; - int k = 2 + this.random.nextInt(3); - int type = this.getSlimeType(); - - for (int l = 0; l < k; ++l) { - float g = ((float) (l % 2) - 0.5F) * f; - float h = ((float) (l / 2) - 0.5F) * f; - EndSlimeEntity slimeEntity = (EndSlimeEntity) this.getType().create(this.level); - if (this.isPersistenceRequired()) { - slimeEntity.setPersistenceRequired(); - } - - slimeEntity.setSlimeType(type); - slimeEntity.setCustomName(text); - slimeEntity.setNoAi(bl); - slimeEntity.setInvulnerable(this.isInvulnerable()); - ((ISlime) slimeEntity).be_setSlimeSize(j, true); - slimeEntity.refreshDimensions(); - slimeEntity.moveTo( - this.getX() + (double) g, - this.getY() + 0.5D, - this.getZ() + (double) h, - this.random.nextFloat() * 360.0F, - 0.0F - ); - this.level.addFreshEntity(slimeEntity); - } - } - - ((ISlime) this).entityRemove(reason); - } - - @Override - protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { - int maxCount = this.getSize(); - int minCount = maxCount >> 1; - if (minCount < 1) { - minCount = 1; - } - if (causedByPlayer && this.lastHurtByPlayer != null) { - int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer); - minCount += looting; - } - int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount; - ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(Items.SLIME_BALL, count)); - this.level.addFreshEntity(drop); - } - - public int getSlimeType() { - return this.entityData.get(VARIANT).intValue(); - } - - public void setSlimeType(int value) { - this.entityData.set(VARIANT, (byte) value); - } - - protected void setMossy() { - setSlimeType(1); - } - - public boolean isMossy() { - return getSlimeType() == 1; - } - - protected void setLake() { - setSlimeType(2); - } - - public boolean isLake() { - return getSlimeType() == 2; - } - - protected void setAmber(boolean mossy) { - this.entityData.set(VARIANT, (byte) 3); - } - - public boolean isAmber() { - return this.entityData.get(VARIANT) == 3; - } - - public boolean isChorus() { - return this.entityData.get(VARIANT) == 0; - } - - public static boolean canSpawn(EntityType entityType, LevelAccessor world, MobSpawnType spawnType, BlockPos pos, RandomSource random) { - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - return false; - } - BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(pos)); - if (biome == EndBiomes.CHORUS_FOREST || biome == EndBiomes.MEGALAKE) { - return true; - } - if (biome == EndBiomes.MEGALAKE_GROVE && random.nextBoolean()) { - return true; - } - return random.nextInt(4) == 0 && isWaterNear(world, pos); - } - - private static boolean isWaterNear(LevelAccessor world, BlockPos pos) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - - for (int x = pos.getX() - 32; x <= pos.getX() + 32; x++) { - POS.setX(x); - for (int z = pos.getZ() - 32; z <= pos.getZ() + 32; z++) { - POS.setZ(z); - for (int y = pos.getY() - 8; y <= pos.getY() + 8; y++) { - POS.setY(y); - if (world.getBlockState(POS).getBlock() == Blocks.WATER) { - return true; - } - } - } - } - return false; - } - - class MoveGoal extends Goal { - public MoveGoal() { - this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); - } - - public boolean canUse() { - if (EndSlimeEntity.this.isPassenger()) { - return false; - } - - float yaw = EndSlimeEntity.this.getYHeadRot(); - float speed = EndSlimeEntity.this.getSpeed(); - if (speed > 0.1) { - float dx = Mth.sin(-yaw * 0.017453292F); - float dz = Mth.cos(-yaw * 0.017453292F); - BlockPos pos = EndSlimeEntity.this.blockPosition().offset(dx * speed * 4, 0, dz * speed * 4); - int down = BlocksHelper.downRay(EndSlimeEntity.this.level, pos, 16); - return down < 5; - } - - return true; - } - - public void tick() { - ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.0D); - } - } - - class SwimmingGoal extends Goal { - public SwimmingGoal() { - this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); - EndSlimeEntity.this.getNavigation().setCanFloat(true); - } - - public boolean canUse() { - return (EndSlimeEntity.this.isInWater() || EndSlimeEntity.this.isInLava()) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl; - } - - public void tick() { - if (EndSlimeEntity.this.getRandom().nextFloat() < 0.8F) { - EndSlimeEntity.this.getJumpControl().jump(); - } - - ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.2D); - } - } - - class RandomLookGoal extends Goal { - private float targetYaw; - private int timer; - - public RandomLookGoal() { - this.setFlags(EnumSet.of(Goal.Flag.LOOK)); - } - - public boolean canUse() { - return EndSlimeEntity.this.getTarget() == null && (EndSlimeEntity.this.onGround || EndSlimeEntity.this.isInWater() || EndSlimeEntity.this - .isInLava() || EndSlimeEntity.this.hasEffect(MobEffects.LEVITATION)) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl; - } - - public void tick() { - if (--this.timer <= 0) { - this.timer = 40 + EndSlimeEntity.this.getRandom().nextInt(60); - this.targetYaw = (float) EndSlimeEntity.this.getRandom().nextInt(360); - } - - ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look(this.targetYaw, false); - } - } - - class FaceTowardTargetGoal extends Goal { - private int ticksLeft; - - public FaceTowardTargetGoal() { - this.setFlags(EnumSet.of(Goal.Flag.LOOK)); - } - - public boolean canUse() { - LivingEntity livingEntity = EndSlimeEntity.this.getTarget(); - if (livingEntity == null) { - return false; - } - else if (!livingEntity.isAlive()) { - return false; - } - else { - return livingEntity instanceof Player && ((Player) livingEntity).getAbilities().invulnerable ? false : EndSlimeEntity.this - .getMoveControl() instanceof EndSlimeMoveControl; - } - } - - public void start() { - this.ticksLeft = 300; - super.start(); - } - - public boolean canContinueToUse() { - LivingEntity livingEntity = EndSlimeEntity.this.getTarget(); - if (livingEntity == null) { - return false; - } - else if (!livingEntity.isAlive()) { - return false; - } - else if (livingEntity instanceof Player && ((Player) livingEntity).getAbilities().invulnerable) { - return false; - } - else { - return --this.ticksLeft > 0; - } - } - - public void tick() { - EndSlimeEntity.this.lookAt(EndSlimeEntity.this.getTarget(), 10.0F, 10.0F); - ((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look( - EndSlimeEntity.this.getYRot(), - EndSlimeEntity.this.isDealsDamage() - ); - } - } - - class EndSlimeMoveControl extends MoveControl { - private float targetYaw; - private int ticksUntilJump; - private boolean jumpOften; - - public EndSlimeMoveControl(EndSlimeEntity slime) { - super(slime); - this.targetYaw = 180.0F * slime.getYRot() / 3.1415927F; - } - - public void look(float targetYaw, boolean jumpOften) { - this.targetYaw = targetYaw; - this.jumpOften = jumpOften; - } - - public void move(double speed) { - this.speedModifier = speed; - this.operation = MoveControl.Operation.MOVE_TO; - } - - public void tick() { - this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.targetYaw, 90.0F)); - this.mob.yHeadRot = this.mob.getYRot(); - this.mob.yBodyRot = this.mob.getYRot(); - if (this.operation != MoveControl.Operation.MOVE_TO) { - this.mob.setZza(0.0F); - } - else { - this.operation = MoveControl.Operation.WAIT; - if (this.mob.isOnGround()) { - this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); - if (this.ticksUntilJump-- <= 0) { - this.ticksUntilJump = EndSlimeEntity.this.getJumpDelay(); - if (this.jumpOften) { - this.ticksUntilJump /= 3; - } - - EndSlimeEntity.this.getJumpControl().jump(); - if (EndSlimeEntity.this.doPlayJumpSound()) { - EndSlimeEntity.this.playSound( - EndSlimeEntity.this.getJumpSound(), - EndSlimeEntity.this.getSoundVolume(), - getJumpSoundPitch() - ); - } - } - else { - EndSlimeEntity.this.xxa = 0.0F; - EndSlimeEntity.this.zza = 0.0F; - this.mob.setSpeed(0.0F); - } - } - else { - this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); - } - - } - } - - private float getJumpSoundPitch() { - float f = EndSlimeEntity.this.isTiny() ? 1.4F : 0.8F; - return ((EndSlimeEntity.this.random.nextFloat() - EndSlimeEntity.this.random.nextFloat()) * 0.2F + 1.0F) * f; - } - } -} diff --git a/src/main/java/ru/betterend/entity/ShadowWalkerEntity.java b/src/main/java/ru/betterend/entity/ShadowWalkerEntity.java deleted file mode 100644 index 5cf84c96..00000000 --- a/src/main/java/ru/betterend/entity/ShadowWalkerEntity.java +++ /dev/null @@ -1,153 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -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.LookAtPlayerGoal; -import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; -import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; -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.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndSounds; - -public class ShadowWalkerEntity extends Monster { - public ShadowWalkerEntity(EntityType entityType, Level world) { - super(entityType, world); - } - - @Override - protected void registerGoals() { - this.goalSelector.addGoal(2, new AttackGoal(this, 1.0D, false)); - this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); - this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, Player.class, true)); - } - - public static AttributeSupplier.Builder createMobAttributes() { - return Monster - .createMonsterAttributes() - .add(Attributes.FOLLOW_RANGE, 35.0) - .add(Attributes.MOVEMENT_SPEED, 0.15) - .add(Attributes.ATTACK_DAMAGE, 4.5) - .add(Attributes.ARMOR, 2.0) - .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); - } - - @Override - public void tick() { - super.tick(); - level.addParticle( - ParticleTypes.ASH, - getX() + random.nextGaussian() * 0.2, - getY() + random.nextGaussian() * 0.5 + 1, - getZ() + random.nextGaussian() * 0.2, - 0, - 0, - 0 - ); - level.addParticle( - ParticleTypes.SMOKE, - getX() + random.nextGaussian() * 0.2, - getY() + random.nextGaussian() * 0.5 + 1, - getZ() + random.nextGaussian() * 0.2, - 0, - 0, - 0 - ); - level.addParticle( - ParticleTypes.ENTITY_EFFECT, - getX() + random.nextGaussian() * 0.2, - getY() + random.nextGaussian() * 0.5 + 1, - getZ() + random.nextGaussian() * 0.2, - 0, - 0, - 0 - ); - } - - @Override - protected SoundEvent getAmbientSound() { - return EndSounds.ENTITY_SHADOW_WALKER; - } - - @Override - protected SoundEvent getHurtSound(DamageSource source) { - return EndSounds.ENTITY_SHADOW_WALKER_DAMAGE; - } - - @Override - protected SoundEvent getDeathSound() { - return EndSounds.ENTITY_SHADOW_WALKER_DEATH; - } - - @Override - protected void playStepSound(BlockPos pos, BlockState state) { - } - - @Override - protected float getSoundVolume() { - return MHelper.randRange(0.25F, 0.5F, random); - } - - @Override - public float getVoicePitch() { - return MHelper.randRange(0.75F, 1.25F, random); - } - - @Override - public boolean doHurtTarget(Entity target) { - boolean attack = super.doHurtTarget(target); - if (attack && target instanceof LivingEntity) { - LivingEntity living = (LivingEntity) target; - if (!(living.hasEffect(MobEffects.BLINDNESS))) { - living.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 60)); - } - } - return attack; - } - - private final class AttackGoal extends MeleeAttackGoal { - private final ShadowWalkerEntity walker; - private int ticks; - - public AttackGoal(ShadowWalkerEntity walker, double speed, boolean pauseWhenMobIdle) { - super(walker, speed, pauseWhenMobIdle); - this.walker = walker; - } - - public void start() { - super.start(); - this.ticks = 0; - } - - public void stop() { - super.stop(); - this.walker.setAggressive(false); - } - - public void tick() { - super.tick(); - ++this.ticks; - if (this.ticks >= 5 && this.getTicksUntilNextAttack() < this.getAttackInterval() / 2) { - this.walker.setAggressive(true); - } - else { - this.walker.setAggressive(false); - } - } - } -} diff --git a/src/main/java/ru/betterend/entity/SilkMothEntity.java b/src/main/java/ru/betterend/entity/SilkMothEntity.java deleted file mode 100644 index f3afc4f3..00000000 --- a/src/main/java/ru/betterend/entity/SilkMothEntity.java +++ /dev/null @@ -1,323 +0,0 @@ -package ru.betterend.entity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.AgeableMob; -import net.minecraft.world.entity.Entity; -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.control.FlyingMoveControl; -import net.minecraft.world.entity.ai.control.LookControl; -import net.minecraft.world.entity.ai.goal.BreedGoal; -import net.minecraft.world.entity.ai.goal.FloatGoal; -import net.minecraft.world.entity.ai.goal.FollowParentGoal; -import net.minecraft.world.entity.ai.goal.Goal; -import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; -import net.minecraft.world.entity.ai.navigation.PathNavigation; -import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos; -import net.minecraft.world.entity.ai.util.HoverRandomPos; -import net.minecraft.world.entity.animal.FlyingAnimal; -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.enchantment.EnchantmentHelper; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.pathfinder.BlockPathTypes; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.Nullable; -import ru.bclib.entity.DespawnableAnimal; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndBlockProperties; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndItems; - -import java.util.EnumSet; - -public class SilkMothEntity extends DespawnableAnimal implements FlyingAnimal { - private BlockPos hivePos; - private BlockPos entrance; - private Level hiveWorld; - - public SilkMothEntity(EntityType entityType, Level world) { - super(entityType, world); - this.moveControl = new FlyingMoveControl(this, 20, true); - this.lookControl = new MothLookControl(this); - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.xpReward = 1; - } - - public static AttributeSupplier.Builder createMobAttributes() { - return LivingEntity - .createLivingAttributes() - .add(Attributes.MAX_HEALTH, 2.0D) - .add(Attributes.FOLLOW_RANGE, 16.0D) - .add(Attributes.FLYING_SPEED, 0.4D) - .add(Attributes.MOVEMENT_SPEED, 0.1D); - } - - public void setHive(Level world, BlockPos hive) { - this.hivePos = hive; - this.hiveWorld = world; - } - - @Override - public boolean canBeLeashed(Player player) { - return false; - } - - @Override - public void addAdditionalSaveData(CompoundTag tag) { - if (hivePos != null) { - tag.put("HivePos", NbtUtils.writeBlockPos(hivePos)); - tag.putString("HiveWorld", hiveWorld.dimension().location().toString()); - } - } - - @Override - public void readAdditionalSaveData(CompoundTag tag) { - if (tag.contains("HivePos")) { - hivePos = NbtUtils.readBlockPos(tag.getCompound("HivePos")); - ResourceLocation worldID = new ResourceLocation(tag.getString("HiveWorld")); - try { - hiveWorld = level.getServer().getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, worldID)); - } - catch (Exception e) { - BetterEnd.LOGGER.warning("Silk Moth Hive World {} is missing!", worldID); - hivePos = null; - } - } - } - - @Override - protected void registerGoals() { - this.goalSelector.addGoal(1, new ReturnToHiveGoal()); - this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); - this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25D)); - this.goalSelector.addGoal(8, new WanderAroundGoal()); - this.goalSelector.addGoal(9, new FloatGoal(this)); - } - - @Override - protected PathNavigation createNavigation(Level world) { - FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) { - public boolean isStableDestination(BlockPos pos) { - BlockState state = this.level.getBlockState(pos); - return state.isAir() || !state.getMaterial().blocksMotion(); - } - - public void tick() { - super.tick(); - } - }; - birdNavigation.setCanOpenDoors(false); - birdNavigation.setCanFloat(false); - birdNavigation.setCanPassDoors(true); - return birdNavigation; - } - - @Override - public boolean isPushable() { - return false; - } - - @Override - public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { - return false; - } - - @Override - protected Entity.MovementEmission getMovementEmission() { - return Entity.MovementEmission.EVENTS; - } - - @Override - public boolean isFlying() { - return !this.onGround; - } - - @Override - public boolean isNoGravity() { - return true; - } - - @Override - public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { - return EndEntities.SILK_MOTH.create(world); - } - - @Override - protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) { - int minCount = 0; - int maxCount = 1; - if (causedByPlayer && this.lastHurtByPlayer != null) { - int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer); - minCount += looting; - maxCount += looting; - if (maxCount > 2) { - maxCount = 2; - } - } - int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount; - ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.SILK_FIBER, count)); - this.level.addFreshEntity(drop); - } - - class MothLookControl extends LookControl { - MothLookControl(Mob entity) { - super(entity); - } - - protected boolean resetXRotOnTick() { - return true; - } - } - - class WanderAroundGoal extends Goal { - WanderAroundGoal() { - this.setFlags(EnumSet.of(Goal.Flag.MOVE)); - } - - @Override - public boolean canUse() { - return SilkMothEntity.this.navigation.isDone() && SilkMothEntity.this.random.nextInt(10) == 0; - } - - @Override - public boolean canContinueToUse() { - return SilkMothEntity.this.navigation.isInProgress(); - } - - @Override - public void start() { - Vec3 vec3d = null; - if (SilkMothEntity.this.hivePos != null && SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level) { - if (SilkMothEntity.this.position().distanceToSqr(SilkMothEntity.this.hivePos.getX(), SilkMothEntity.this.hivePos.getY(), SilkMothEntity.this.hivePos.getZ()) > 16) { - vec3d = SilkMothEntity.this.position().add(random.nextGaussian() * 2, 0, random.nextGaussian() * 2); - } - } - vec3d = vec3d == null ? this.getRandomLocation() : vec3d; - if (vec3d != null) { - try { - SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(new BlockPos(vec3d), 1), 1.0D); - } - catch (Exception e) {} - } - } - - @Nullable - private Vec3 getRandomLocation() { - Vec3 vec3d3 = SilkMothEntity.this.getViewVector(0.0F); - Vec3 vec3d4 = HoverRandomPos.getPos(SilkMothEntity.this, 8, 7, vec3d3.x, vec3d3.z, 1.5707964F, 3, 1); - return vec3d4 != null ? vec3d4 : AirAndWaterRandomPos.getPos( - SilkMothEntity.this, - 8, - 4, - -2, - vec3d3.x, - vec3d3.z, - 1.5707963705062866D - ); - } - } - - class ReturnToHiveGoal extends Goal { - ReturnToHiveGoal() { - this.setFlags(EnumSet.of(Goal.Flag.MOVE)); - } - - @Override - public boolean canUse() { - return SilkMothEntity.this.hivePos != null && - SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level && - SilkMothEntity.this.navigation.isDone() && - SilkMothEntity.this.random.nextInt(8) == 0 && - SilkMothEntity.this.position().distanceToSqr( - SilkMothEntity.this.hivePos.getX(), - SilkMothEntity.this.hivePos.getY(), - SilkMothEntity.this.hivePos.getZ() - ) < 16384; - } - - @Override - public boolean canContinueToUse() { - return SilkMothEntity.this.navigation.isInProgress() && level.getBlockState(entrance) - .isAir() && (level.getBlockState(hivePos) - .is(EndBlocks.SILK_MOTH_NEST) || level - .getBlockState(hivePos) - .is(EndBlocks.SILK_MOTH_HIVE)); - } - - @Override - public void start() { - BlockState state = SilkMothEntity.this.level.getBlockState(SilkMothEntity.this.hivePos); - if (!state.is(EndBlocks.SILK_MOTH_NEST) && !state.is(EndBlocks.SILK_MOTH_HIVE)) { - SilkMothEntity.this.hivePos = null; - return; - } - try { - SilkMothEntity.this.entrance = SilkMothEntity.this.hivePos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING)); - SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(entrance, 1), 1.0D); - } - catch (Exception e) { - } - } - - @Override - public void tick() { - super.tick(); - if (SilkMothEntity.this.entrance == null) { - return; - } - double dx = Math.abs(SilkMothEntity.this.entrance.getX() - SilkMothEntity.this.getX()); - double dy = Math.abs(SilkMothEntity.this.entrance.getY() - SilkMothEntity.this.getY()); - double dz = Math.abs(SilkMothEntity.this.entrance.getZ() - SilkMothEntity.this.getZ()); - if (dx + dy + dz < 1) { - BlockState state = SilkMothEntity.this.level.getBlockState(hivePos); - if (state.is(EndBlocks.SILK_MOTH_NEST) || state.is(EndBlocks.SILK_MOTH_HIVE)) { - int fullness = state.getValue(EndBlockProperties.FULLNESS); - boolean isHive = state.is(EndBlocks.SILK_MOTH_HIVE); - if (fullness < 3 && (isHive || SilkMothEntity.this.random.nextBoolean())) { - fullness += isHive ? MHelper.randRange(1, 2, random) : 1; - if (fullness > 3) { - fullness = 3; - } - BlocksHelper.setWithUpdate( - SilkMothEntity.this.hiveWorld, - SilkMothEntity.this.hivePos, - state.setValue(EndBlockProperties.FULLNESS, fullness) - ); - } - SilkMothEntity.this.level.playSound( - null, - SilkMothEntity.this.entrance, - SoundEvents.BEEHIVE_ENTER, - SoundSource.BLOCKS, - 1, - 1 - ); - SilkMothEntity.this.discard(); - } - else { - SilkMothEntity.this.hivePos = null; - } - } - } - } -} diff --git a/src/main/java/ru/betterend/entity/model/CubozoaEntityModel.java b/src/main/java/ru/betterend/entity/model/CubozoaEntityModel.java deleted file mode 100644 index 624a63fd..00000000 --- a/src/main/java/ru/betterend/entity/model/CubozoaEntityModel.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.betterend.entity.model; - -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.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.RenderType; -import net.minecraft.util.Mth; -import ru.betterend.entity.CubozoaEntity; - -public class CubozoaEntityModel extends EntityModel { - private final static int TENTACLE_COUNT = 4; - - private final ModelPart model; - private final ModelPart[] tentacle_center; - private final ModelPart[] tentacle; - private float scaleY; - private float scaleXZ; - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - PartDefinition bodyPart = modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(0, 17).addBox(-2.0F, -12.5F, -2.0F, 4.0F, 4.0F, 4.0F), - PartPose.offset(0.0F, 24.0F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - "main_cube_r1", - CubeListBuilder.create().texOffs(0, 0).addBox(-5.0F, -7.0F, -5.0F, 10.0F, 7.0F, 10.0F), - PartPose.offsetAndRotation(0.0F, -14.0F, 0.0F, 0.0F, 0.0F, -3.1416F) - ); - - for (int i = 1; i <= TENTACLE_COUNT; i++) { - PartDefinition tentaclePart = bodyPart.addOrReplaceChild( - "tentacle_center_" + i, - CubeListBuilder.create(), - PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.0F, i * 1.5708F, 0.0F) - ); - - tentaclePart.addOrReplaceChild( - "tentacle_" + i, - CubeListBuilder.create().texOffs(16, 17).addBox(-4.0F, 0.0F, 0.0F, 8.0F, 7.0F, 0.0F), - PartPose.offset(0.0F, -7.0F, 4.5F) - ); - } - - return LayerDefinition.create(modelData, 48, 48); - } - - public CubozoaEntityModel(ModelPart modelPart) { - super(RenderType::entityTranslucent); - tentacle = new ModelPart[TENTACLE_COUNT]; - tentacle_center = new ModelPart[TENTACLE_COUNT]; - - model = modelPart.getChild(PartNames.BODY); - for (int i = 1; i <= TENTACLE_COUNT; i++) { - tentacle_center[i - 1] = model.getChild("tentacle_center_" + i); - tentacle[i - 1] = tentacle_center[i - 1].getChild("tentacle_" + i); - } - } - - @Override - public void setupAnim(CubozoaEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { - float sin = Mth.sin(animationProgress * 0.13F); - scaleY = sin * 0.1F + 0.9F; - scaleXZ = Mth.sin(animationProgress * 0.13F + 3.14F) * 0.1F + 0.9F; - - for (int i = 0; i < TENTACLE_COUNT; i++) { - tentacle[i].xRot = sin * 0.15f; - } - } - - @Override - public void renderToBuffer(PoseStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { - matrices.pushPose(); - matrices.scale(scaleXZ, scaleY, scaleXZ); - model.render(matrices, vertices, light, overlay); - matrices.popPose(); - } -} diff --git a/src/main/java/ru/betterend/entity/model/DragonflyEntityModel.java b/src/main/java/ru/betterend/entity/model/DragonflyEntityModel.java deleted file mode 100644 index 7e363571..00000000 --- a/src/main/java/ru/betterend/entity/model/DragonflyEntityModel.java +++ /dev/null @@ -1,131 +0,0 @@ -package ru.betterend.entity.model; - -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.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.RenderType; -import ru.betterend.entity.DragonflyEntity; - -public class DragonflyEntityModel extends EntityModel { - private final ModelPart model; - private final ModelPart head; - private final ModelPart tail; - private final ModelPart tail_2; - private final ModelPart wing_1; - private final ModelPart wing_2; - private final ModelPart wing_3; - private final ModelPart wing_4; - private final ModelPart legs_1; - private final ModelPart legs_2; - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - PartDefinition bodyPart = modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -4.0F, 0.0F, 4.0F, 4.0F, 9.0F), - PartPose.offset(2.0F, 21.5F, -4.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.HEAD, - CubeListBuilder.create().texOffs(17, 0).addBox(-1.5F, -1.5F, -2.5F, 3.0F, 3.0F, 3.0F), - PartPose.offsetAndRotation(-2.0F, -2.0F, 0.0F, 0.3491F, 0.0F, 0.0F) - ); - - PartDefinition tailPart = bodyPart.addOrReplaceChild( - PartNames.TAIL, - CubeListBuilder.create().texOffs(26, 0).addBox(-1.5F, -1.5F, 0.0F, 3.0F, 3.0F, 7.0F), - PartPose.offset(-2.0F, -2.0F, 9.0F) - ); - - tailPart.addOrReplaceChild( - PartNames.TAIL_FIN, - CubeListBuilder.create().texOffs(36, 0).addBox(-1.0F, -1.0F, 0.0F, 2.0F, 2.0F, 10.0F), - PartPose.offset(0.0F, 0.0F, 7.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.LEFT_WING, - CubeListBuilder.create().texOffs(0, 13).addBox(-15.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F), - PartPose.offset(-2.0F, -4.0F, 4.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.RIGHT_WING, - CubeListBuilder.create().mirror().texOffs(0, 13).addBox(0.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F), - PartPose.offset(-2.0F, -4.0F, 4.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.LEFT_WING_BASE, - CubeListBuilder.create().texOffs(4, 17).addBox(-12.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F), - PartPose.offset(-2.0F, -4.0F, 8.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.RIGHT_WING_BASE, - CubeListBuilder.create().mirror().texOffs(4, 17).addBox(0.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F), - PartPose.offset(-2.0F, -4.0F, 8.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.LEFT_LEG, - CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F), - PartPose.offsetAndRotation(-1.0F, 0.0F, 1.0F, 0.0F, 0.0F, -0.5236F) - ); - - bodyPart.addOrReplaceChild( - PartNames.RIGHT_LEG, - CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F), - PartPose.offsetAndRotation(-3.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.5236F) - ); - - return LayerDefinition.create(modelData, 64, 64); - } - - public DragonflyEntityModel(ModelPart modelPart) { - super(RenderType::entityCutout); - - model = modelPart.getChild(PartNames.BODY); - head = model.getChild(PartNames.HEAD); - tail = model.getChild(PartNames.TAIL); - tail_2 = tail.getChild(PartNames.TAIL_FIN); - wing_1 = model.getChild(PartNames.LEFT_WING); - wing_2 = model.getChild(PartNames.RIGHT_WING); - wing_3 = model.getChild(PartNames.LEFT_WING_BASE); - wing_4 = model.getChild(PartNames.RIGHT_WING_BASE); - legs_1 = model.getChild(PartNames.LEFT_LEG); - legs_2 = model.getChild(PartNames.RIGHT_LEG); - } - - @Override - public void setupAnim(DragonflyEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { - float progress = animationProgress * 2F; - - wing_1.zRot = 0.3491F + (float) Math.sin(progress) * 0.3491F; - wing_2.zRot = -wing_1.zRot; - - wing_3.zRot = 0.3491F + (float) Math.cos(progress) * 0.3491F; - wing_4.zRot = -wing_3.zRot; - - progress = animationProgress * 0.05F; - - head.xRot = 0.3491F + (float) Math.sin(progress * 0.7F) * 0.1F; - tail.xRot = (float) Math.cos(progress) * 0.05F - 0.05F; - tail_2.xRot = -tail.xRot * 1.5F; - } - - @Override - public void renderToBuffer(PoseStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { - model.render(matrices, vertices, light, overlay); - } -} diff --git a/src/main/java/ru/betterend/entity/model/EndFishEntityModel.java b/src/main/java/ru/betterend/entity/model/EndFishEntityModel.java deleted file mode 100644 index a6d8b0d8..00000000 --- a/src/main/java/ru/betterend/entity/model/EndFishEntityModel.java +++ /dev/null @@ -1,93 +0,0 @@ -package ru.betterend.entity.model; - -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.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.RenderType; -import ru.betterend.entity.EndFishEntity; - -public class EndFishEntityModel extends EntityModel { - private final ModelPart model; - private final ModelPart fin_top; - private final ModelPart fin_bottom; - private final ModelPart flipper; - private final ModelPart fin_right; - private final ModelPart fin_left; - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - PartDefinition bodyPart = modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -2.0F, -4.0F, 2.0F, 4.0F, 8.0F), - PartPose.offset(0.0F, 20.0F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.TOP_FIN, - CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, -8.0F, 0.0F, 0.0F, 8.0F, 6.0F), - PartPose.offsetAndRotation(0.0F, -2.0F, -4.0F, -0.6981F, 0.0F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.BOTTOM_FIN, - CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, 0.0F, 0.0F, 0.0F, 8.0F, 6.0F), - PartPose.offsetAndRotation(0.0F, 2.0F, -4.0F, 0.6981F, 0.0F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.TAIL_FIN, - CubeListBuilder.create().texOffs(0, 15).addBox(0.0F, -5.0F, 0.0F, 0.0F, 5.0F, 5.0F), - PartPose.offsetAndRotation(0.0F, 0.0F, 2.0F, -0.7854F, 0.0F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.RIGHT_FIN, - CubeListBuilder.create().texOffs(0, 25).addBox(-3.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F), - PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, 0.7854F, 0.0F) - ); - - bodyPart.addOrReplaceChild( - PartNames.LEFT_FIN, - CubeListBuilder.create().mirror().texOffs(0, 25).addBox(0.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F), - PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, -0.7854F, 0.0F) - ); - - return LayerDefinition.create(modelData, 32, 32); - } - - public EndFishEntityModel(ModelPart modelPart) { - super(RenderType::entityCutout); - - model = modelPart.getChild(PartNames.BODY); - fin_top = model.getChild(PartNames.TOP_FIN); - fin_bottom = model.getChild(PartNames.BOTTOM_FIN); - flipper = model.getChild(PartNames.TAIL_FIN); - fin_right = model.getChild(PartNames.RIGHT_FIN); - fin_left = model.getChild(PartNames.LEFT_FIN); - } - - @Override - public void setupAnim(EndFishEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { - float s1 = (float) Math.sin(animationProgress * 0.1); - float s2 = (float) Math.sin(animationProgress * 0.05); - flipper.yRot = s1 * 0.3F; - fin_top.xRot = s2 * 0.02F - 0.6981F; - fin_bottom.xRot = 0.6981F - s2 * 0.02F; - fin_left.yRot = s1 * 0.3F - 0.7854F; - fin_right.yRot = 0.7854F - s1 * 0.3F; - } - - @Override - public void renderToBuffer(PoseStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { - model.render(matrices, vertices, light, overlay); - } -} diff --git a/src/main/java/ru/betterend/entity/model/EndSlimeEntityModel.java b/src/main/java/ru/betterend/entity/model/EndSlimeEntityModel.java deleted file mode 100644 index 82f89b25..00000000 --- a/src/main/java/ru/betterend/entity/model/EndSlimeEntityModel.java +++ /dev/null @@ -1,148 +0,0 @@ -package ru.betterend.entity.model; - -import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.model.ListModel; -import net.minecraft.client.model.geom.EntityModelSet; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.RenderType; -import ru.bclib.util.MHelper; -import ru.betterend.entity.EndSlimeEntity; -import ru.betterend.registry.EndEntitiesRenders; - -public class EndSlimeEntityModel extends ListModel { - private final ModelPart innerCube; - private final ModelPart rightEye; - private final ModelPart leftEye; - private final ModelPart mouth; - private final ModelPart flower; - private final ModelPart crop; - - public static LayerDefinition getShellOnlyTexturedModelData() { - return getTexturedModelData(true); - } - - public static LayerDefinition getCompleteTexturedModelData() { - return getTexturedModelData(false); - } - - private static LayerDefinition getTexturedModelData(boolean onlyShell) { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - if (onlyShell) { - modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, 16.0F, -4.0F, 8.0F, 8.0F, 8.0F), - PartPose.ZERO - ); - } - else { - modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(0, 16).addBox(-3.0F, 17.0F, -3.0F, 6.0F, 6.0F, 6.0F), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - PartNames.RIGHT_EYE, - CubeListBuilder.create().texOffs(32, 0).addBox(-3.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - PartNames.LEFT_EYE, - CubeListBuilder.create().texOffs(32, 4).addBox(1.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - PartNames.MOUTH, - CubeListBuilder.create().texOffs(32, 8).addBox(0.0F, 21.0F, -3.5F, 1.0F, 1.0F, 1.0F), - PartPose.ZERO - ); - - PartDefinition flowerPart = modelPartData.addOrReplaceChild( - "flower", - CubeListBuilder.create(), - PartPose.ZERO - ); - PartDefinition cropPart = modelPartData.addOrReplaceChild("crop", CubeListBuilder.create(), PartPose.ZERO); - - for (int i = 0; i < 6; i++) { - final PartDefinition parent = i < 4 ? flowerPart : cropPart; - final float rot = MHelper.degreesToRadians(i < 4 ? (i * 45F) : ((i - 4) * 90F + 45F)); - - PartDefinition petalRotPart = parent.addOrReplaceChild( - "petalRot_" + i, - CubeListBuilder.create(), - PartPose.offsetAndRotation(0, 0, 0, 0, rot, 0) - ); - - - petalRotPart.addOrReplaceChild( - "petal_" + i, - CubeListBuilder.create().texOffs(40, 0).addBox(0.0F, 0.0F, 0.0F, 8.0F, 8.0F, 0.0F), - PartPose.offset(-4, 8, 0) - ); - } - } - - return LayerDefinition.create(modelData, 64, 32); - } - - public EndSlimeEntityModel(EntityModelSet modelSet, boolean onlyShell) { - super(RenderType::entityCutout); - - ModelPart modelPart = modelSet.bakeLayer(onlyShell ? EndEntitiesRenders.END_SLIME_SHELL_MODEL : EndEntitiesRenders.END_SLIME_MODEL); - - innerCube = modelPart.getChild(PartNames.BODY); - if (!onlyShell) { - rightEye = modelPart.getChild(PartNames.RIGHT_EYE); - leftEye = modelPart.getChild(PartNames.LEFT_EYE); - mouth = modelPart.getChild(PartNames.MOUTH); - flower = modelPart.getChild("flower"); - crop = modelPart.getChild("crop"); - } - else { - rightEye = null; - leftEye = null; - mouth = null; - flower = null; - crop = null; - } - } - - @Override - public void setupAnim(T entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { - } - - public void renderFlower(PoseStack matrices, VertexConsumer vertices, int light, int overlay) { - flower.render(matrices, vertices, light, overlay); - } - - public void renderCrop(PoseStack matrices, VertexConsumer vertices, int light, int overlay) { - crop.render(matrices, vertices, light, overlay); - } - - private boolean isOnlyShell() { - return rightEye == null; - } - - @Override - public Iterable parts() { - if (isOnlyShell()) { - return ImmutableList.of(this.innerCube); - } - else { - return ImmutableList.of(this.innerCube, this.rightEye, this.leftEye, this.mouth); - } - } -} diff --git a/src/main/java/ru/betterend/entity/model/SilkMothEntityModel.java b/src/main/java/ru/betterend/entity/model/SilkMothEntityModel.java deleted file mode 100644 index 5ea45b4b..00000000 --- a/src/main/java/ru/betterend/entity/model/SilkMothEntityModel.java +++ /dev/null @@ -1,170 +0,0 @@ -package ru.betterend.entity.model; - -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.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.RenderType; -import net.minecraft.util.Mth; -import ru.betterend.entity.SilkMothEntity; - -public class SilkMothEntityModel extends EntityModel { - private final ModelPart legsL; - private final ModelPart cube_r1; - private final ModelPart cube_r2; - private final ModelPart cube_r3; - private final ModelPart legsR; - private final ModelPart cube_r4; - private final ModelPart cube_r5; - private final ModelPart cube_r6; - private final ModelPart head_pivot; - private final ModelPart tendril_r_r1; - private final ModelPart tendril_r_r2; - private final ModelPart bb_main; - private final ModelPart wingR_r1; - private final ModelPart wingL_r1; - private final ModelPart abdomen_r1; - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - PartDefinition legsL = modelPartData.addOrReplaceChild( - PartNames.LEFT_LEG, - CubeListBuilder.create().texOffs(0, 0), - PartPose.offsetAndRotation(1.5f, 19.9f, -0.45f, 0.0f, 0.0f, 0.6981f) - ); - - legsL.addOrReplaceChild( - "cube_r1", - CubeListBuilder.create().texOffs(0, 13).addBox(0.0216f, 0.0f, -0.5976f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f) - ); - - legsL.addOrReplaceChild( - "cube_r2", - CubeListBuilder.create().texOffs(0, 15).addBox(0.0f, 0.0f, -0.6f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f) - ); - - legsL.addOrReplaceChild( - "cube_r3", - CubeListBuilder.create().texOffs(0, 14).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f) - ); - - PartDefinition legsR = modelPartData.addOrReplaceChild( - PartNames.RIGHT_LEG, - CubeListBuilder.create().texOffs(0, 0), - PartPose.offsetAndRotation(-1.5f, 19.9f, -0.55f, 0.0f, 3.1416f, -0.6545f) - ); - - legsR.addOrReplaceChild( - "cube_r4", - CubeListBuilder.create().texOffs(0, 10).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f) - ); - - legsR.addOrReplaceChild( - "cube_r5", - CubeListBuilder.create().texOffs(0, 11).addBox(0.0f, 0.0f, -0.4f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f) - ); - - legsR.addOrReplaceChild( - "cube_r6", - CubeListBuilder.create().texOffs(0, 12).addBox(0.0216f, 0.0f, -0.4024f, 3.0f, 0.0f, 1.0f), - PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f) - ); - - PartDefinition head_pivot = modelPartData.addOrReplaceChild( - PartNames.HEAD, - CubeListBuilder.create().texOffs(15, 10).addBox(-1.5f, -1.5f, -2.0f, 3.0f, 3.0f, 3.0f), - PartPose.offset(0.0f, 18.0f, -3.0f) - ); - - head_pivot.addOrReplaceChild( - "tendril_r_r1", - CubeListBuilder.create().mirror().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f), - PartPose.offsetAndRotation(1.0f, -1.15f, -1.0f, 0.0f, 0.0f, 0.3927f) - ); - - head_pivot.addOrReplaceChild( - "tendril_r_r2", - CubeListBuilder.create().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f), - PartPose.offsetAndRotation(-1.0f, -1.15f, -1.0f, 0.0f, 0.0f, -0.3927f) - ); - - PartDefinition bb_main = modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(19, 19).addBox(-2.5f, -8.5f, -3.0f, 5.0f, 5.0f, 3.0f), - PartPose.offset(0.0f, 24.0f, 0.0f) - ); - - bb_main.addOrReplaceChild( - PartNames.RIGHT_WING, - CubeListBuilder.create().mirror().texOffs(0, 5).addBox(-7.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f), - PartPose.offsetAndRotation(-1.5f, -6.5f, 0.5f, 0.0f, 0.0f, 0.3927f) - ); - - bb_main.addOrReplaceChild( - PartNames.LEFT_WING, - CubeListBuilder.create().texOffs(0, 5).addBox(-2.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f), - PartPose.offsetAndRotation(1.5f, -6.5f, 0.5f, 0.0f, 0.0f, -0.3927f) - ); - - bb_main.addOrReplaceChild( - "abdomen_r1", - CubeListBuilder.create().texOffs(0, 10).addBox(-3.0f, -4.0f, -1.0f, 4.0f, 4.0f, 7.0f), - PartPose.offsetAndRotation(1.0f, -3.9f, 0.0f, -0.3927f, 0.0f, 0.0f) - ); - - return LayerDefinition.create(modelData, 64, 64); - } - - public SilkMothEntityModel(ModelPart modelPart) { - super(RenderType::entityCutout); - - legsL = modelPart.getChild(PartNames.LEFT_LEG); - cube_r1 = legsL.getChild("cube_r1"); - cube_r2 = legsL.getChild("cube_r2"); - cube_r3 = legsL.getChild("cube_r3"); - legsR = modelPart.getChild(PartNames.RIGHT_LEG); - cube_r4 = legsR.getChild("cube_r4"); - cube_r5 = legsR.getChild("cube_r5"); - cube_r6 = legsR.getChild("cube_r6"); - head_pivot = modelPart.getChild(PartNames.HEAD); - tendril_r_r1 = head_pivot.getChild("tendril_r_r1"); - tendril_r_r2 = head_pivot.getChild("tendril_r_r2"); - bb_main = modelPart.getChild(PartNames.BODY); - wingR_r1 = bb_main.getChild(PartNames.RIGHT_WING); - wingL_r1 = bb_main.getChild(PartNames.LEFT_WING); - abdomen_r1 = bb_main.getChild("abdomen_r1"); - } - - @Override - public void setupAnim(SilkMothEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { - wingR_r1.zRot = Mth.sin(animationProgress * 2F) * 0.4F + 0.3927F; - wingL_r1.zRot = -wingR_r1.zRot; - head_pivot.xRot = Mth.sin(animationProgress * 0.03F) * 0.1F; - tendril_r_r1.zRot = Mth.sin(animationProgress * 0.07F) * 0.2F + 0.3927F; - tendril_r_r2.zRot = -tendril_r_r1.zRot; - abdomen_r1.xRot = Mth.sin(animationProgress * 0.05F) * 0.1F - 0.3927F; - legsR.zRot = Mth.sin(animationProgress * 0.07F) * 0.1F - 0.6545F; - legsL.zRot = -legsR.zRot; - } - - @Override - public void renderToBuffer(PoseStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { - bb_main.render(matrices, vertices, light, overlay); - head_pivot.render(matrices, vertices, light, overlay); - legsL.render(matrices, vertices, light, overlay); - legsR.render(matrices, vertices, light, overlay); - } -} diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityCubozoa.java b/src/main/java/ru/betterend/entity/render/RendererEntityCubozoa.java deleted file mode 100644 index 334e85a1..00000000 --- a/src/main/java/ru/betterend/entity/render/RendererEntityCubozoa.java +++ /dev/null @@ -1,64 +0,0 @@ -package ru.betterend.entity.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.layers.EyesLayer; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; -import ru.betterend.BetterEnd; -import ru.betterend.entity.CubozoaEntity; -import ru.betterend.entity.model.CubozoaEntityModel; -import ru.betterend.registry.EndEntitiesRenders; - -public class RendererEntityCubozoa extends MobRenderer { - private static final ResourceLocation[] TEXTURE = new ResourceLocation[2]; - private static final RenderType[] GLOW = new RenderType[2]; - - public RendererEntityCubozoa(EntityRendererProvider.Context ctx) { - super(ctx, new CubozoaEntityModel(ctx.bakeLayer(EndEntitiesRenders.CUBOZOA_MODEL)), 0.5f); - this.addLayer(new EyesLayer(this) { - @Override - public RenderType renderType() { - return GLOW[0]; - } - - @Override - public void render(PoseStack matrices, MultiBufferSource vertexConsumers, int light, CubozoaEntity entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { - VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]); - this.getParentModel() - .renderToBuffer(matrices, - vertexConsumer, - 15728640, - OverlayTexture.NO_OVERLAY, - 1.0F, - 1.0F, - 1.0F, - 1.0F - ); - } - }); - } - - @Override - protected void scale(CubozoaEntity entity, PoseStack matrixStack, float f) { - float scale = entity.getScale(); - matrixStack.scale(scale, scale, scale); - } - - @Override - public ResourceLocation getTextureLocation(CubozoaEntity entity) { - return TEXTURE[entity.getVariant()]; - } - - static { - TEXTURE[0] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa.png"); - TEXTURE[1] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur.png"); - - GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_glow.png")); - GLOW[1] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur_glow.png")); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityDragonfly.java b/src/main/java/ru/betterend/entity/render/RendererEntityDragonfly.java deleted file mode 100644 index 7679f989..00000000 --- a/src/main/java/ru/betterend/entity/render/RendererEntityDragonfly.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.entity.render; - -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.layers.EyesLayer; -import net.minecraft.resources.ResourceLocation; -import ru.betterend.BetterEnd; -import ru.betterend.entity.DragonflyEntity; -import ru.betterend.entity.model.DragonflyEntityModel; -import ru.betterend.registry.EndEntitiesRenders; - -public class RendererEntityDragonfly extends MobRenderer { - private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/dragonfly.png"); - private static final RenderType GLOW = RenderType.eyes(BetterEnd.makeID("textures/entity/dragonfly_glow.png")); - - public RendererEntityDragonfly(EntityRendererProvider.Context ctx) { - super(ctx, new DragonflyEntityModel(ctx.bakeLayer(EndEntitiesRenders.DRAGONFLY_MODEL)), 0.5f); - this.addLayer(new EyesLayer(this) { - @Override - public RenderType renderType() { - return GLOW; - } - }); - } - - @Override - public ResourceLocation getTextureLocation(DragonflyEntity entity) { - return TEXTURE; - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityEndFish.java b/src/main/java/ru/betterend/entity/render/RendererEntityEndFish.java deleted file mode 100644 index 95e81065..00000000 --- a/src/main/java/ru/betterend/entity/render/RendererEntityEndFish.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.betterend.entity.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.layers.EyesLayer; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; -import ru.betterend.BetterEnd; -import ru.betterend.entity.EndFishEntity; -import ru.betterend.entity.model.EndFishEntityModel; -import ru.betterend.registry.EndEntitiesRenders; - -public class RendererEntityEndFish extends MobRenderer { - private static final ResourceLocation[] TEXTURE = new ResourceLocation[EndFishEntity.VARIANTS]; - private static final RenderType[] GLOW = new RenderType[EndFishEntity.VARIANTS]; - - public RendererEntityEndFish(EntityRendererProvider.Context ctx) { - super(ctx, new EndFishEntityModel(ctx.bakeLayer(EndEntitiesRenders.END_FISH_MODEL)), 0.5f); - this.addLayer(new EyesLayer(this) { - @Override - public RenderType renderType() { - return GLOW[0]; - } - - @Override - public void render(PoseStack matrices, MultiBufferSource vertexConsumers, int light, EndFishEntity entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { - VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]); - this.getParentModel() - .renderToBuffer(matrices, - vertexConsumer, - 15728640, - OverlayTexture.NO_OVERLAY, - 1.0F, - 1.0F, - 1.0F, - 1.0F - ); - } - }); - } - - @Override - protected void scale(EndFishEntity entity, PoseStack matrixStack, float f) { - float scale = entity.getScale(); - matrixStack.scale(scale, scale, scale); - } - - @Override - public ResourceLocation getTextureLocation(EndFishEntity entity) { - return TEXTURE[entity.getVariant()]; - } - - static { - for (int i = 0; i < EndFishEntity.VARIANTS; i++) { - TEXTURE[i] = BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + ".png"); - GLOW[i] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + "_glow.png")); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityEndSlime.java b/src/main/java/ru/betterend/entity/render/RendererEntityEndSlime.java deleted file mode 100644 index af5379d3..00000000 --- a/src/main/java/ru/betterend/entity/render/RendererEntityEndSlime.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.betterend.entity.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import net.minecraft.client.renderer.entity.layers.EyesLayer; -import net.minecraft.client.renderer.entity.layers.RenderLayer; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import ru.betterend.BetterEnd; -import ru.betterend.entity.EndSlimeEntity; -import ru.betterend.entity.model.EndSlimeEntityModel; - -public class RendererEntityEndSlime extends MobRenderer> { - private static final ResourceLocation TEXTURE[] = new ResourceLocation[4]; - private static final RenderType GLOW[] = new RenderType[4]; - - public RendererEntityEndSlime(EntityRendererProvider.Context ctx) { - super(ctx, new EndSlimeEntityModel<>(ctx.getModelSet(), false), 0.25f); - this.addLayer(new OverlayFeatureRenderer(this, ctx)); - this.addLayer(new EyesLayer>(this) { - @Override - public RenderType renderType() { - return GLOW[0]; - } - - @Override - public void render(PoseStack matrices, MultiBufferSource vertexConsumers, int light, EndSlimeEntity entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { - VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getSlimeType()]); - this.getParentModel() - .renderToBuffer(matrices, - vertexConsumer, - 15728640, - OverlayTexture.NO_OVERLAY, - 1.0F, - 1.0F, - 1.0F, - 1.0F - ); - if (entity.isLake()) { - this.getParentModel().renderFlower(matrices, vertexConsumer, 15728640, OverlayTexture.NO_OVERLAY); - } - } - }); - } - - @Override - public ResourceLocation getTextureLocation(EndSlimeEntity entity) { - return TEXTURE[entity.getSlimeType()]; - } - - @Override - public void render(EndSlimeEntity slimeEntity, float f, float g, PoseStack matrixStack, MultiBufferSource vertexConsumerProvider, int i) { - this.shadowRadius = 0.25F * (float) slimeEntity.getSize(); - super.render(slimeEntity, f, g, matrixStack, vertexConsumerProvider, i); - } - - @Override - protected void scale(EndSlimeEntity slimeEntity, PoseStack matrixStack, float f) { - matrixStack.scale(0.999F, 0.999F, 0.999F); - matrixStack.translate(0.0D, 0.0010000000474974513D, 0.0D); - float h = (float) slimeEntity.getSize(); - float i = Mth.lerp(f, slimeEntity.oSquish, slimeEntity.squish) / (h * 0.5F + 1.0F); - float j = 1.0F / (i + 1.0F); - matrixStack.scale(j * h, 1.0F / j * h, j * h); - } - - private final class OverlayFeatureRenderer extends RenderLayer> { - private final EndSlimeEntityModel modelOrdinal; - private final EndSlimeEntityModel modelLake; - - public OverlayFeatureRenderer(RenderLayerParent> featureRendererContext, EntityRendererProvider.Context ctx) { - super(featureRendererContext); - modelOrdinal = new EndSlimeEntityModel<>(ctx.getModelSet(), true); - modelLake = new EndSlimeEntityModel<>(ctx.getModelSet(), true); - } - - public void render(PoseStack matrixStack, MultiBufferSource vertexConsumerProvider, int i, T livingEntity, float f, float g, float h, float j, float k, float l) { - if (!livingEntity.isInvisible()) { - if (livingEntity.isLake()) { - VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation( - livingEntity))); - this.getParentModel() - .renderFlower(matrixStack, - vertexConsumer, - i, - LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F) - ); - } - else if (livingEntity.isAmber() || livingEntity.isChorus()) { - VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation( - livingEntity))); - this.getParentModel() - .renderCrop(matrixStack, - vertexConsumer, - i, - LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F) - ); - } - - EndSlimeEntityModel model = livingEntity.getSlimeType() == 1 ? modelLake : modelOrdinal; - this.getParentModel().copyPropertiesTo(model); - model.prepareMobModel(livingEntity, f, g, h); - model.setupAnim(livingEntity, f, g, j, k, l); - VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityTranslucent(this.getTextureLocation( - livingEntity))); - model.renderToBuffer( - matrixStack, - vertexConsumer, - i, - LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F), - 1.0F, - 1.0F, - 1.0F, - 1.0F - ); - } - } - } - - static { - TEXTURE[0] = BetterEnd.makeID("textures/entity/end_slime/end_slime.png"); - TEXTURE[1] = BetterEnd.makeID("textures/entity/end_slime/end_slime_mossy.png"); - TEXTURE[2] = BetterEnd.makeID("textures/entity/end_slime/end_slime_lake.png"); - TEXTURE[3] = BetterEnd.makeID("textures/entity/end_slime/end_slime_amber.png"); - GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_glow.png")); - GLOW[1] = GLOW[0]; - GLOW[2] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_lake_glow.png")); - GLOW[3] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_amber_glow.png")); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityShadowWalker.java b/src/main/java/ru/betterend/entity/render/RendererEntityShadowWalker.java deleted file mode 100644 index da3df3d6..00000000 --- a/src/main/java/ru/betterend/entity/render/RendererEntityShadowWalker.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.betterend.entity.render; - -import net.minecraft.client.model.PlayerModel; -import net.minecraft.client.model.geom.ModelLayers; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.HumanoidMobRenderer; -import net.minecraft.resources.ResourceLocation; -import ru.betterend.BetterEnd; -import ru.betterend.entity.ShadowWalkerEntity; - -public class RendererEntityShadowWalker extends HumanoidMobRenderer> { - private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/shadow_walker.png"); - - public RendererEntityShadowWalker(EntityRendererProvider.Context ctx) { - super(ctx, new PlayerModel(ctx.bakeLayer(ModelLayers.PLAYER), false), 0.5F); - //super(entityRenderDispatcher, new PlayerModel(0.0F, false), 0.5F); - } - - @Override - public ResourceLocation getTextureLocation(ShadowWalkerEntity zombieEntity) { - return TEXTURE; - } -} diff --git a/src/main/java/ru/betterend/entity/render/SilkMothEntityRenderer.java b/src/main/java/ru/betterend/entity/render/SilkMothEntityRenderer.java deleted file mode 100644 index 3ee6fed8..00000000 --- a/src/main/java/ru/betterend/entity/render/SilkMothEntityRenderer.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.betterend.entity.render; - -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.resources.ResourceLocation; -import ru.betterend.BetterEnd; -import ru.betterend.entity.SilkMothEntity; -import ru.betterend.entity.model.SilkMothEntityModel; -import ru.betterend.registry.EndEntitiesRenders; - -public class SilkMothEntityRenderer extends MobRenderer { - private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/silk_moth.png"); - - public SilkMothEntityRenderer(EntityRendererProvider.Context ctx) { - super(ctx, new SilkMothEntityModel(ctx.bakeLayer(EndEntitiesRenders.SILK_MOTH_MODEL)), 0.5f); - } - - @Override - public ResourceLocation getTextureLocation(SilkMothEntity entity) { - return TEXTURE; - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/events/ItemTooltipCallback.java b/src/main/java/ru/betterend/events/ItemTooltipCallback.java deleted file mode 100644 index b2d36fb7..00000000 --- a/src/main/java/ru/betterend/events/ItemTooltipCallback.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.betterend.events; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; - -import java.util.List; - -@Environment(EnvType.CLIENT) -public interface ItemTooltipCallback { - /** - * Fired after the game has appended all base tooltip lines to the list. - */ - Event EVENT = EventFactory.createArrayBacked( - ItemTooltipCallback.class, - callbacks -> (player, stack, context, lines) -> { - for (ItemTooltipCallback callback : callbacks) { - callback.getTooltip(player, stack, context, lines); - } - } - ); - - /** - * Called when an item stack's tooltip is rendered. Text added to {@code lines} will be - * rendered with the tooltip. - * - * @param lines the list containing the lines of text displayed on the stack's tooltip - */ - void getTooltip(Player player, ItemStack stack, TooltipFlag context, List lines); -} diff --git a/src/main/java/ru/betterend/events/PlayerAdvancementsCallback.java b/src/main/java/ru/betterend/events/PlayerAdvancementsCallback.java deleted file mode 100644 index 573ac70b..00000000 --- a/src/main/java/ru/betterend/events/PlayerAdvancementsCallback.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.betterend.events; - -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.advancements.Advancement; -import net.minecraft.server.level.ServerPlayer; - -public interface PlayerAdvancementsCallback { - - Event PLAYER_ADVANCEMENT_COMPLETE = EventFactory.createArrayBacked( - PlayerAdvancementsCallback.class, - callbacks -> (player, advancement, criterionName) -> { - for (PlayerAdvancementsCallback event : callbacks) { - event.onAdvancementComplete(player, advancement, criterionName); - } - } - ); - - void onAdvancementComplete(ServerPlayer player, Advancement advancement, String criterionName); -} diff --git a/src/main/java/ru/betterend/integration/EndBiomeIntegration.java b/src/main/java/ru/betterend/integration/EndBiomeIntegration.java deleted file mode 100644 index 023f0e6a..00000000 --- a/src/main/java/ru/betterend/integration/EndBiomeIntegration.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.betterend.integration; - -public interface EndBiomeIntegration { - void addBiomes(); -} diff --git a/src/main/java/ru/betterend/integration/EnderscapeIntegration.java b/src/main/java/ru/betterend/integration/EnderscapeIntegration.java deleted file mode 100644 index 096f5122..00000000 --- a/src/main/java/ru/betterend/integration/EnderscapeIntegration.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.integration; - -import net.minecraft.core.Holder; -import net.minecraft.core.MappedRegistry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.api.tag.TagAPI; -import ru.bclib.integration.ModIntegration; -import ru.bclib.world.features.BCLFeature; - -public class EnderscapeIntegration extends ModIntegration { - public EnderscapeIntegration() { - super("enderscape"); - } - - @Override - public void init() { - Class enderscape = getClass("net.enderscape.Enderscape"); - Class enderscapeIslandsBiome = getClass("net.enderscape.world.biomes.EnderscapeIslandsBiome"); - MappedRegistry biomes = getStaticFieldValue(enderscape, "ENDERSCAPE_BIOME"); - biomes.entrySet().forEach(entry -> { - ResourceKey key = entry.getKey(); - Holder biome = getBiome(key.location().getPath()); - if (enderscapeIslandsBiome.isInstance(entry.getValue())) { - BiomeAPI.registerEndVoidBiome(biome); - } - else { - BiomeAPI.registerEndLandBiome(biome); - } - }); - - BCLFeature scatteredShadowQuartzOre = getFeature("scattered_shadow_quartz_ore", Decoration.UNDERGROUND_DECORATION); - BCLFeature voidNebuliteOre = getFeature("void_nebulite_ore", Decoration.UNDERGROUND_DECORATION); - BCLFeature nebuliteOre = getFeature("nebulite_ore", Decoration.UNDERGROUND_DECORATION); - - BiomeAPI.registerEndBiomeModification((biomeID, biome) -> { - if (!biomeID.getNamespace().equals("enderscape")) { - BiomeAPI.addBiomeFeature(biome, scatteredShadowQuartzOre); - BiomeAPI.addBiomeFeature(biome, voidNebuliteOre); - BiomeAPI.addBiomeFeature(biome, nebuliteOre); - } - }); - - TagAPI.addBlockTag(CommonBlockTags.END_STONES, getBlock("nebulite_ore")); - TagAPI.addBlockTag(CommonBlockTags.END_STONES, getBlock("shadow_quartz_ore")); - } -} diff --git a/src/main/java/ru/betterend/integration/FlamboyantRefabricatedIntegration.java b/src/main/java/ru/betterend/integration/FlamboyantRefabricatedIntegration.java deleted file mode 100644 index c8f45267..00000000 --- a/src/main/java/ru/betterend/integration/FlamboyantRefabricatedIntegration.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.betterend.integration; - -import com.google.common.collect.Maps; -import net.minecraft.world.level.ItemLike; -import ru.bclib.integration.ModIntegration; -import ru.bclib.util.ColorUtil; -import ru.betterend.blocks.HydraluxPetalColoredBlock; -import ru.betterend.complexmaterials.ColoredMaterial; -import ru.betterend.registry.EndBlocks; - -import java.awt.Color; -import java.util.Map; - -public class FlamboyantRefabricatedIntegration extends ModIntegration { - public FlamboyantRefabricatedIntegration() { - super("flamboyant"); - } - - @Override - public void init() { - Map colors = Maps.newHashMap(); - Map dyes = Maps.newHashMap(); - - addColor("fead1d", "amber", colors, dyes); - addColor("bd9a5f", "beige", colors, dyes); - addColor("edeada", "cream", colors, dyes); - addColor("33430e", "dark_green", colors, dyes); - addColor("639920", "forest_green", colors, dyes); - addColor("f0618c", "hot_pink", colors, dyes); - addColor("491c7b", "indigo", colors, dyes); - addColor("65291b", "maroon", colors, dyes); - addColor("2c3969", "navy", colors, dyes); - addColor("827c17", "olive", colors, dyes); - addColor("7bc618", "pale_green", colors, dyes); - addColor("f4a4bd", "pale_pink", colors, dyes); - addColor("f8d45a", "pale_yellow", colors, dyes); - addColor("6bb1cf", "sky_blue", colors, dyes); - addColor("6e8c9c", "slate_gray", colors, dyes); - addColor("b02454", "violet", colors, dyes); - - new ColoredMaterial(HydraluxPetalColoredBlock::new, EndBlocks.HYDRALUX_PETAL_BLOCK, colors, dyes, true); - } - - private void addColor(String hex, String name, Map colors, Map dyes) { - int color = ColorUtil.color(hex); - colors.put(color, name); - dyes.put(color, getItem(name + "_dye")); - - System.out.println(name + " " + color + " " + new Color(color)); - } -} diff --git a/src/main/java/ru/betterend/integration/Integrations.java b/src/main/java/ru/betterend/integration/Integrations.java deleted file mode 100644 index 21a7a9aa..00000000 --- a/src/main/java/ru/betterend/integration/Integrations.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.betterend.integration; - -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import ru.bclib.api.ModIntegrationAPI; -import ru.bclib.integration.ModIntegration; -import ru.bclib.recipes.GridRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.events.PlayerAdvancementsCallback; -import ru.betterend.integration.byg.BYGIntegration; -import ru.betterend.item.GuideBookItem; -import ru.betterend.registry.EndItems; - -public class Integrations { - public static final ModIntegration BYG = ModIntegrationAPI.register(new BYGIntegration()); - public static final ModIntegration NOURISH = ModIntegrationAPI.register(new NourishIntegration()); - public static final ModIntegration FLAMBOYANT_REFABRICATED = ModIntegrationAPI.register(new FlamboyantRefabricatedIntegration()); - public static final ModIntegration ENDERSCAPE = ModIntegrationAPI.register(new EnderscapeIntegration()); - - private static boolean hasHydrogen; - - public static void init() { - if (hasGuideBook()) { - GuideBookItem.register(); - - PlayerAdvancementsCallback.PLAYER_ADVANCEMENT_COMPLETE.register((player, advancement, criterionName) -> { - ResourceLocation advId = new ResourceLocation("minecraft:end/enter_end_gateway"); - if (advId.equals(advancement.getId())) { - player.addItem(new ItemStack(GuideBookItem.GUIDE_BOOK)); - } - }); - - GridRecipe.make(BetterEnd.MOD_ID, "guide_book", GuideBookItem.GUIDE_BOOK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("D", "B", "C") - .addMaterial('D', EndItems.ENDER_DUST) - .addMaterial('B', Items.BOOK) - .addMaterial('C', EndItems.CRYSTAL_SHARDS) - .build(); - } - hasHydrogen = FabricLoader.getInstance().isModLoaded("hydrogen"); - } - - public static boolean hasGuideBook() { - return FabricLoader.getInstance().isModLoaded("patchouli"); - } - - public static boolean hasHydrogen() { - return hasHydrogen; - } -} diff --git a/src/main/java/ru/betterend/integration/NourishIntegration.java b/src/main/java/ru/betterend/integration/NourishIntegration.java deleted file mode 100644 index 133f1ee7..00000000 --- a/src/main/java/ru/betterend/integration/NourishIntegration.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.betterend.integration; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import ru.bclib.api.tag.TagAPI; - -import ru.bclib.integration.ModIntegration; -import ru.betterend.registry.EndItems; - -public class NourishIntegration extends ModIntegration { - public NourishIntegration() { - super("nourish"); - } - - @Override - public void init() { - TagKey fats = getItemTag("fats"); - TagKey fruit = getItemTag("fruit"); - TagKey protein = getItemTag("protein"); - TagKey sweets = getItemTag("sweets"); - - TagAPI.addItemTag(fats, EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED); - TagAPI.addItemTag( - fruit, - EndItems.SHADOW_BERRY_RAW, - EndItems.SHADOW_BERRY_COOKED, - EndItems.BLOSSOM_BERRY, - EndItems.SHADOW_BERRY_JELLY, - EndItems.SWEET_BERRY_JELLY, - EndItems.BLOSSOM_BERRY_JELLY, - EndItems.AMBER_ROOT_RAW, - EndItems.CHORUS_MUSHROOM_RAW, - EndItems.CHORUS_MUSHROOM_COOKED, - EndItems.BOLUX_MUSHROOM_COOKED - ); - TagAPI.addItemTag( - protein, - EndItems.END_FISH_RAW, - EndItems.END_FISH_COOKED, - EndItems.CHORUS_MUSHROOM_COOKED, - EndItems.BOLUX_MUSHROOM_COOKED, - EndItems.CAVE_PUMPKIN_PIE - ); - TagAPI.addItemTag( - sweets, - EndItems.SHADOW_BERRY_JELLY, - EndItems.SWEET_BERRY_JELLY, - EndItems.BLOSSOM_BERRY_JELLY, - EndItems.CAVE_PUMPKIN_PIE - ); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/BYGBlocks.java b/src/main/java/ru/betterend/integration/byg/BYGBlocks.java deleted file mode 100644 index 8d58b147..00000000 --- a/src/main/java/ru/betterend/integration/byg/BYGBlocks.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.betterend.integration.byg; - -import net.minecraft.world.level.block.Block; -import ru.bclib.blocks.BaseVineBlock; -import ru.betterend.blocks.basis.EndWallPlantBlock; -import ru.betterend.registry.EndBlocks; - -public class BYGBlocks { - public static final Block IVIS_MOSS = EndBlocks.registerBlock("ivis_moss", new EndWallPlantBlock()); - public static final Block NIGHTSHADE_MOSS = EndBlocks.registerBlock("nightshade_moss", new EndWallPlantBlock()); - - public static final Block IVIS_VINE = EndBlocks.registerBlock("ivis_vine", new BaseVineBlock()); - - public static void register() { - } -} diff --git a/src/main/java/ru/betterend/integration/byg/BYGIntegration.java b/src/main/java/ru/betterend/integration/byg/BYGIntegration.java deleted file mode 100644 index 429b6f0d..00000000 --- a/src/main/java/ru/betterend/integration/byg/BYGIntegration.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.integration.byg; - -import ru.bclib.integration.ModIntegration; -import ru.betterend.integration.EndBiomeIntegration; - -public class BYGIntegration extends ModIntegration implements EndBiomeIntegration { - public BYGIntegration() { - super("byg"); - } - - @Override - public void init() { - /*Block block = Integrations.BYG.getBlock("ivis_phylium"); - if (block != null) { - TagAPI.addTags(block, CommonBlockTags.END_STONES, CommonBlockTags.GEN_END_STONES); - } - BYGBlocks.register(); - BYGFeatures.register(); - BYGBiomes.register();*/ - } - - @Override - public void addBiomes() { - //BYGBiomes.addBiomes(); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java b/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java deleted file mode 100644 index 9d01f412..00000000 --- a/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.betterend.integration.byg.biomes; - -import ru.betterend.BetterEnd; -import ru.betterend.integration.Integrations; -import ru.betterend.registry.EndBiomes; -import ru.betterend.world.biome.EndBiome; - -public class BYGBiomes { - // New Biomes - public static final EndBiome OLD_BULBIS_GARDENS = EndBiomes.registerSubBiomeIntegration(new OldBulbisGardens()); - public static final EndBiome NIGHTSHADE_REDWOODS = EndBiomes.registerSubBiomeIntegration(new NightshadeRedwoods()); - //public static final EndBiome ETHERIAL_GROVE = EndBiomes.registerSubBiomeIntegration(new EterialGrove()); - - public static void register() { - BetterEnd.LOGGER.info("Registered " + OLD_BULBIS_GARDENS); - } - - public static void addBiomes() { - EndBiomes.addSubBiomeIntegration(OLD_BULBIS_GARDENS, Integrations.BYG.getID("bulbis_gardens")); - EndBiomes.addSubBiomeIntegration(NIGHTSHADE_REDWOODS, Integrations.BYG.getID("nightshade_forest")); - //EndBiomes.addSubBiomeIntegration(ETHERIAL_GROVE, Integrations.BYG.getID("ethereal_islands")); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java b/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java deleted file mode 100644 index 7a4baf67..00000000 --- a/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java +++ /dev/null @@ -1,86 +0,0 @@ -package ru.betterend.integration.byg.biomes; - -import net.minecraft.core.Holder; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSpecialEffects; -import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import ru.bclib.BCLib; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.betterend.integration.Integrations; -import ru.betterend.integration.byg.features.BYGFeatures; -import ru.betterend.registry.EndFeatures; -import ru.betterend.world.biome.EndBiome; - -import java.util.List; - -public class NightshadeRedwoods extends EndBiome.Config { - public NightshadeRedwoods() { - super("nightshade_redwoods"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - Holder biome = Integrations.BYG.getBiome("nightshade_forest"); - BiomeSpecialEffects effects = biome.value().getSpecialEffects(); - - builder.fogColor(140, 108, 47) - .fogDensity(1.5F) - .waterAndFogColor(55, 70, 186) - .foliageColor(122, 17, 155) - .particles( - ParticleTypes.REVERSE_PORTAL, - 0.002F - ) - //TODO: 1.18 surface rules -// .setSurface(biome.getGenerationSettings() -// .getSurfaceBuilder() -// .get()) - .grassColor(48, 13, 89) - .plantsColor(200, 125, 9) - .feature(EndFeatures.END_LAKE_RARE) - .feature(BYGFeatures.NIGHTSHADE_REDWOOD_TREE) - .feature(BYGFeatures.NIGHTSHADE_MOSS_WOOD) - .feature(BYGFeatures.NIGHTSHADE_MOSS); - - if (BCLib.isClient()) { - SoundEvent loop = effects.getAmbientLoopSoundEvent() - .get(); - SoundEvent music = effects.getBackgroundMusic() - .get() - .getEvent(); - SoundEvent additions = effects.getAmbientAdditionsSettings() - .get() - .getSoundEvent(); - SoundEvent mood = effects.getAmbientMoodSettings() - .get() - .getSoundEvent(); - builder.loop(loop) - .music(music) - .additions(additions) - .mood(mood); - } - biome.value().getGenerationSettings() - .features() - .forEach((list) -> { - list.forEach((feature) -> { - builder.feature(Decoration.VEGETAL_DECORATION, feature); - }); - }); - - for (MobCategory group : MobCategory.values()) { - List list = biome.value() - .getMobSettings() - .getMobs(group) - .unwrap(); - list.forEach((entry) -> { - builder.spawn((EntityType) entry.type, 1, entry.minCount, entry.maxCount); - }); - } - } -} diff --git a/src/main/java/ru/betterend/integration/byg/biomes/OldBulbisGardens.java b/src/main/java/ru/betterend/integration/byg/biomes/OldBulbisGardens.java deleted file mode 100644 index 5a1f4524..00000000 --- a/src/main/java/ru/betterend/integration/byg/biomes/OldBulbisGardens.java +++ /dev/null @@ -1,119 +0,0 @@ -package ru.betterend.integration.byg.biomes; - -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSpecialEffects; -import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import ru.bclib.BCLib; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.betterend.integration.Integrations; -import ru.betterend.integration.byg.features.BYGFeatures; -import ru.betterend.registry.EndFeatures; -import ru.betterend.world.biome.EndBiome; - -import java.util.List; -import java.util.function.Supplier; - - -public class OldBulbisGardens extends EndBiome.Config { - public OldBulbisGardens() { - super("old_bulbis_gardens"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - Holder biome = Integrations.BYG.getBiome("bulbis_gardens"); - BiomeSpecialEffects effects = biome.value().getSpecialEffects(); - - Block ivis = Integrations.BYG.getBlock("ivis_phylium"); -// Block origin = biome.getGenerationSettings() -// .getSurfaceBuilderConfig() -// .getTopMaterial() -// .getBlock(); - builder.fogColor(215, 132, 207) - .fogDensity(1.8F) - .waterAndFogColor(40, 0, 56) - .foliageColor(122, 17, 155) - .particles( - ParticleTypes.REVERSE_PORTAL, - 0.002F - ) - //TODO: 1.18 surface rules - //.surface(ivis, origin) - .feature(EndFeatures.END_LAKE_RARE) - .feature(BYGFeatures.OLD_BULBIS_TREE); - - if (BCLib.isClient()) { - SoundEvent loop = effects.getAmbientLoopSoundEvent() - .get(); - SoundEvent music = effects.getBackgroundMusic() - .get() - .getEvent(); - SoundEvent additions = effects.getAmbientAdditionsSettings() - .get() - .getSoundEvent(); - SoundEvent mood = effects.getAmbientMoodSettings() - .get() - .getSoundEvent(); - builder.loop(loop) - .music(music) - .additions(additions) - .mood(mood); - } - - for (MobCategory group : MobCategory.values()) { - List list = biome.value() - .getMobSettings() - .getMobs(group) - .unwrap(); - list.forEach((entry) -> { - builder.spawn((EntityType) entry.type, 1, entry.minCount, entry.maxCount); - }); - } - - List> features = biome.value().getGenerationSettings() - .features(); - HolderSet vegetal = features.get(Decoration.VEGETAL_DECORATION.ordinal()); - if (vegetal.size() > 2) { - Supplier getter; - //TODO: 1.18.2 BRING BACK FEATURE COPY CODE - for(var placed : vegetal){ - System.out.print(placed); - } -// // Trees (first two features) -// // I couldn't process them with conditions, so that's why they are hardcoded (paulevs) -// for (int i = 0; i < 2; i++) { -// getter = vegetal.get(i); -// Holder feature = getter.get(); -// ResourceLocation id = BetterEnd.makeID("obg_feature_" + i); -// feature = Registry.register( -// BuiltinRegistries.PLACED_FEATURE, -// id, -// feature -// ); -// builder.feature(Decoration.VEGETAL_DECORATION, feature); -// } -// // Grasses and other features -// for (int i = 2; i < vegetal.size(); i++) { -// getter = vegetal.get(i); -// Holder feature = getter.get(); -// builder.feature(Decoration.VEGETAL_DECORATION, feature); -// } - } - - builder.feature(EndFeatures.PURPLE_POLYPORE) - .feature(BYGFeatures.IVIS_MOSS_WOOD) - .feature(BYGFeatures.IVIS_MOSS) - .feature(BYGFeatures.IVIS_VINE) - .feature(BYGFeatures.IVIS_SPROUT); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java b/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java deleted file mode 100644 index e83b8388..00000000 --- a/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java +++ /dev/null @@ -1,65 +0,0 @@ -package ru.betterend.integration.byg.features; - -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.features.BCLCommonFeatures; -import ru.bclib.world.features.BCLFeature; -import ru.betterend.BetterEnd; -import ru.betterend.integration.Integrations; -import ru.betterend.integration.byg.BYGBlocks; -import ru.betterend.world.features.SinglePlantFeature; -import ru.betterend.world.features.VineFeature; -import ru.betterend.world.features.WallPlantFeature; -import ru.betterend.world.features.WallPlantOnLogFeature; - -public class BYGFeatures { - public static final BCLFeature OLD_BULBIS_TREE = redisterVegetation( - "old_bulbis_tree", - new OldBulbisTreeFeature(), - 1 - ); - public static final BCLFeature IVIS_SPROUT = redisterVegetation( - "ivis_sprout", - new SinglePlantFeature(Integrations.BYG.getBlock("ivis_sprout"), 6, 2), - 6 - ); - public static final BCLFeature IVIS_VINE = redisterVegetation( - "ivis_vine", - new VineFeature(BYGBlocks.IVIS_VINE, 24), - 5 - ); - public static final BCLFeature IVIS_MOSS = redisterVegetation( - "ivis_moss", - new WallPlantFeature(BYGBlocks.IVIS_MOSS, 6), - 1 - ); - public static final BCLFeature IVIS_MOSS_WOOD = redisterVegetation( - "ivis_moss_wood", - new WallPlantOnLogFeature(BYGBlocks.IVIS_MOSS, 6), - 15 - ); - public static final BCLFeature NIGHTSHADE_MOSS = redisterVegetation( - "nightshade_moss", - new WallPlantFeature(BYGBlocks.NIGHTSHADE_MOSS, 5), - 2 - ); - public static final BCLFeature NIGHTSHADE_MOSS_WOOD = redisterVegetation( - "nightshade_moss_wood", - new WallPlantOnLogFeature(BYGBlocks.NIGHTSHADE_MOSS, 5), - 8 - ); - - public static final BCLFeature NIGHTSHADE_REDWOOD_TREE = redisterVegetation( - "nightshade_redwood_tree", - new NightshadeRedwoodTreeFeature(), - 1 - ); - public static final BCLFeature BIG_ETHER_TREE = redisterVegetation("big_ether_tree", new BigEtherTreeFeature(), 1); - - public static void register() { - } - - private static BCLFeature redisterVegetation(String name, Feature feature, int density) { - return BCLCommonFeatures.makeVegetationFeature(BetterEnd.makeID(name), feature, density); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/features/BigEtherTreeFeature.java b/src/main/java/ru/betterend/integration/byg/features/BigEtherTreeFeature.java deleted file mode 100644 index d559ce4a..00000000 --- a/src/main/java/ru/betterend/integration/byg/features/BigEtherTreeFeature.java +++ /dev/null @@ -1,78 +0,0 @@ -package ru.betterend.integration.byg.features; - -import com.google.common.base.Function; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.integration.Integrations; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BigEtherTreeFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - - BlockState log = Integrations.BYG.getDefaultState("ether_log"); - BlockState wood = Integrations.BYG.getDefaultState("ether_wood"); - Function splinePlacer = (bpos) -> { - return log; - }; - Function replace = (state) -> { - return state.is(CommonBlockTags.END_STONES) || state.getMaterial().equals(Material.PLANT) || state.getMaterial() - .isReplaceable(); - }; - - int height = MHelper.randRange(40, 60, random); - List trunk = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, height / 4); - SplineHelper.offsetParts(trunk, random, 2F, 0, 2F); - SDF sdf = SplineHelper.buildSDF(trunk, 2.3F, 0.8F, splinePlacer); - - int count = height / 15; - for (int i = 1; i < count; i++) { - float splinePos = (float) i / (float) count; - float startAngle = random.nextFloat() * MHelper.PI2; - float length = (1 - splinePos) * height * 0.4F; - int points = (int) (length / 3); - List branch = SplineHelper.makeSpline(0, 0, 0, length, 0, 0, points < 2 ? 2 : points); - SplineHelper.powerOffset(branch, length, 2F); - int rotCount = MHelper.randRange(5, 7, random); - Vector3f start = SplineHelper.getPos(trunk, splinePos * (trunk.size() - 1)); - for (int j = 0; j < rotCount; j++) { - float angle = startAngle + (float) j / rotCount * MHelper.PI2; - List br = SplineHelper.copySpline(branch); - SplineHelper.offsetParts(br, random, 0, 1, 1); - SplineHelper.rotateSpline(br, angle); - - SplineHelper.offset(br, start); - SplineHelper.fillSpline(br, world, wood, pos, replace); - } - } - - sdf.setReplaceFunction((state) -> { - return state.is(CommonBlockTags.END_STONES) || state.getMaterial().equals(Material.PLANT) || state.getMaterial() - .isReplaceable(); - }).addPostProcess((info) -> { - if (info.getState().equals(log) && (!info.getStateUp().equals(log) || !info.getStateDown().equals(log))) { - return wood; - } - return info.getState(); - }).fillRecursive(world, pos); - - return true; - } -} diff --git a/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java b/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java deleted file mode 100644 index d58628ac..00000000 --- a/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java +++ /dev/null @@ -1,199 +0,0 @@ -package ru.betterend.integration.byg.features; - -import com.google.common.base.Function; -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFFlatWave; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.integration.Integrations; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class NightshadeRedwoodTreeFeature extends DefaultFeature { - private static final List BRANCH; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - - BlockState log = Integrations.BYG.getDefaultState("nightshade_log"); - BlockState wood = Integrations.BYG.getDefaultState("nightshade_wood"); - BlockState leaves = Integrations.BYG.getDefaultState("nightshade_leaves"); - BlockState leaves_flower = Integrations.BYG.getDefaultState("flowering_nightshade_leaves"); - - Function splinePlacer = (bpos) -> { - return log; - }; - Function replace = (state) -> { - return state.is(CommonBlockTags.END_STONES) || state.getMaterial().equals(Material.PLANT) || state.getMaterial() - .isReplaceable(); - }; - Function post = (info) -> { - if (info.getState().equals(log) && (!info.getStateUp().equals(log) || !info.getStateDown().equals(log))) { - return wood; - } - return info.getState(); - }; - Function ignore = (state) -> { - return state.equals(log) || state.equals(wood); - }; - - int height = MHelper.randRange(40, 60, random); - List trunk = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, height / 4); - SplineHelper.offsetParts(trunk, random, 0.8F, 0, 0.8F); - - if (!SplineHelper.canGenerate(trunk, pos, world, replace)) { - return false; - } - - int count = height >> 2; - float start = trunk.size() / 3F; - float delta = trunk.size() * 0.6F; - float max = height - 7; - float startAngle = random.nextFloat() * MHelper.PI2; - for (int i = 0; i < count; i++) { - float scale = (float) (count - i) / count * 15; - Vector3f offset = SplineHelper.getPos(trunk, (float) i / count * delta + start); - if (offset.y() > max) { - break; - } - List branch = SplineHelper.copySpline(BRANCH); - SplineHelper.rotateSpline(branch, i * 1.3F + startAngle); - SplineHelper.scale(branch, scale); - SplineHelper.offsetParts(branch, random, 0.3F, 0.3F, 0.3F); - SplineHelper.offset(branch, offset); - SplineHelper.fillSpline(branch, world, wood, pos, replace); - } - - SDF sdf = SplineHelper.buildSDF(trunk, 2.3F, 0.8F, splinePlacer); - SDF roots = new SDFSphere().setRadius(2F).setBlock(log); - roots = new SDFFlatWave().setIntensity(2F) - .setRaysCount(MHelper.randRange(5, 7, random)) - .setAngle(random.nextFloat() * MHelper.PI2) - .setSource(roots); - sdf = new SDFSmoothUnion().setRadius(2F).setSourceA(sdf).setSourceB(roots); - sdf.setReplaceFunction(replace).addPostProcess(post).fillRecursive(world, pos); - Vector3f last = SplineHelper.getPos(trunk, trunk.size() - 1.35F); - for (int y = 0; y < 8; y++) { - BlockPos p = pos.offset(last.x() + 0.5, last.y() + y, last.z() + 0.5); - BlocksHelper.setWithoutUpdate(world, p, y == 4 ? wood : log); - } - - for (int y = 0; y < 16; y++) { - BlockPos p = pos.offset(last.x() + 0.5, last.y() + y, last.z() + 0.5); - if (world.isEmptyBlock(p)) { - BlocksHelper.setWithoutUpdate(world, p, leaves); - } - float radius = (1 - y / 16F) * 3F; - int rad = (int) (radius + 1); - radius *= radius; - for (int x = -rad; x <= rad; x++) { - int x2 = x * x; - for (int z = -rad; z <= rad; z++) { - int z2 = z * z; - if (x2 + z2 < radius - random.nextFloat() * rad) { - BlockPos lp = p.offset(x, 0, z); - if (world.isEmptyBlock(lp)) { - BlocksHelper.setWithoutUpdate(world, lp, leaves); - } - } - } - } - } - - MutableBlockPos mut = new MutableBlockPos(); - Function leavesPost1 = (info) -> { - if (info.getState().equals(log) || info.getState().equals(wood)) { - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }; - Function leavesPost2 = (info) -> { - if (info.getState().getBlock() instanceof LeavesBlock) { - int distance = info.getState().getValue(LeavesBlock.DISTANCE); - if (distance > MHelper.randRange(2, 4, random)) { - return Blocks.AIR.defaultBlockState(); - } - for (Direction d : BlocksHelper.DIRECTIONS) { - int airCount = 0; - if (info.getState(d).isAir()) { - airCount++; - } - if (airCount > 5) { - return Blocks.AIR.defaultBlockState(); - } - } - if (random.nextInt(8) == 0) { - return leaves_flower.setValue(LeavesBlock.DISTANCE, distance); - } - } - return info.getState(); - }; - - SDF canopy = new SDFCappedCone().setRadius1(12F).setRadius2(1f).setHeight(height * 0.3F).setBlock(leaves); - canopy = new SDFDisplacement().setFunction((vec) -> { - return MHelper.randRange(-3F, 3F, random); - }).setSource(canopy); - canopy.addPostProcess(leavesPost1) - .addPostProcess(leavesPost2) - .fillRecursiveIgnore(world, pos.offset(0, height * 0.75, 0), ignore); - - return true; - } - - static { - BRANCH = Lists.newArrayList( - new Vector3f(0, 0, 0), - new Vector3f(0.25F, 0.1F, 0), - new Vector3f(0.40F, 0.2F, 0), - new Vector3f(0.50F, 0.4F, 0), - new Vector3f(0.55F, 0.6F, 0) - ); - } -} diff --git a/src/main/java/ru/betterend/integration/byg/features/OldBulbisTreeFeature.java b/src/main/java/ru/betterend/integration/byg/features/OldBulbisTreeFeature.java deleted file mode 100644 index c8595e49..00000000 --- a/src/main/java/ru/betterend/integration/byg/features/OldBulbisTreeFeature.java +++ /dev/null @@ -1,200 +0,0 @@ -package ru.betterend.integration.byg.features; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import net.minecraft.world.phys.AABB; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.integration.Integrations; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class OldBulbisTreeFeature extends DefaultFeature { - private static final List SPLINE; - private static final List ROOT; - private static final List LEAF; - private static final List SIDE; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - if (!world.getBlockState(pos.below(4)).is(CommonBlockTags.GEN_END_STONES)) return false; - - BlockState stem = Integrations.BYG.getDefaultState("bulbis_stem"); - BlockState wood = Integrations.BYG.getDefaultState("bulbis_wood"); - BlockState cap = Integrations.BYG.getDefaultState(random.nextBoolean() ? "bulbis_shell" : "purple_bulbis_shell"); - BlockState glow = Integrations.BYG.getDefaultState("purple_shroomlight"); - - Function replacement = (state) -> { - if (state.equals(stem) || state.equals(wood) || state.is(CommonBlockTags.END_STONES) || state.getMaterial() - .equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - float size = MHelper.randRange(10, 20, random); - float addSize = MHelper.randRange(1, 1.7F, random); - float addRad = addSize * 0.5F + 0.5F; - int count = (int) (size * 0.15F); - size *= addSize; - float var = MHelper.PI2 / (float) (count * 3); - float start = MHelper.randRange(0, MHelper.PI2, random); - SDF sdf = null; - int x1 = ((pos.getX() >> 4) << 4) - 16; - int z1 = ((pos.getZ() >> 4) << 4) - 16; - AABB limits = new AABB(x1, pos.getY() - 5, z1, x1 + 47, pos.getY() + size * 2, z1 + 47); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; - List spline = SplineHelper.copySpline(SPLINE); - float sizeXZ = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.7F; - SplineHelper.scale(spline, sizeXZ, sizeXZ * 1.5F + MHelper.randRange(0, size * 0.5F, random), sizeXZ); - SplineHelper.offset(spline, new Vector3f(size * random.nextFloat() * 0.3F, 0, 0)); - SplineHelper.rotateSpline(spline, angle); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F);// 1.3F 0.8F - SDF branch = SplineHelper.buildSDF(spline, 2.3F * addRad, 1.3F * addRad, (bpos) -> { - return stem; - }); - - Vector3f vec = spline.get(spline.size() - 1); - float radius = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.35F; - bigSphere(world, pos.offset(vec.x(), vec.y(), vec.z()), radius, cap, glow, wood, replacement, random); - vec = SplineHelper.getPos(spline, 0.3F); - makeRoots(world, pos.offset(vec.x(), vec.y(), vec.z()), size * 0.4F + 5, random, wood, replacement); - - sdf = (sdf == null) ? branch : new SDFUnion().setSourceA(sdf).setSourceB(branch); - } - - sdf.setReplaceFunction(replacement).addPostProcess((info) -> { - if (info.getState().equals(stem) && (!info.getStateUp().equals(stem) || !info.getStateDown() - .equals(stem))) { - return wood; - } - return info.getState(); - }).fillArea(world, pos, limits); - - return true; - } - - private void bigSphere(WorldGenLevel world, BlockPos pos, float radius, BlockState cap, BlockState glow, BlockState wood, Function replacement, RandomSource random) { - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - SDF sphere = new SDFSphere().setRadius(radius).setBlock(cap); - - SDF sphereInner = new SDFSphere().setRadius(radius * 0.53F).setBlock(Blocks.AIR); - sphereInner = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); - }).setSource(sphereInner); - - SDF sphereGlow = new SDFSphere().setRadius(radius * 0.6F).setBlock(glow); - sphereGlow = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1) * 2F; - }).setSource(sphereGlow); - sphereGlow = new SDFSubtraction().setSourceA(sphereGlow).setSourceB(sphereInner); - - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sphereGlow); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sphereInner); - - float offsetY = radius * 1.7F; - sphere = new SDFUnion().setSourceA(sphere).setSourceB(sphereGlow); - sphere = new SDFTranslate().setTranslate(0, offsetY, 0).setSource(sphere); - - int leafCount = (int) (radius * 0.5F) + 2; - for (int i = 0; i < 4; i++) { - float angle = (float) i / 4 * MHelper.PI2; - List spline = SplineHelper.copySpline(LEAF); - SplineHelper.rotateSpline(spline, angle); - SplineHelper.scale(spline, radius * 1.4F); - SplineHelper.fillSplineForce(spline, world, wood, pos, replacement); - - for (int j = 0; j < leafCount; j++) { - float delta = ((float) j / (float) (leafCount - 1)); - float scale = (float) Math.sin(delta * Math.PI) * 0.8F + 0.2F; - float index = Mth.lerp(delta, 1F, 3.9F); - Vector3f point = SplineHelper.getPos(spline, index); - - List side = SplineHelper.copySpline(SIDE); - SplineHelper.rotateSpline(side, angle); - SplineHelper.scale(side, scale * radius); - BlockPos p = pos.offset(point.x() + 0.5F, point.y() + 0.5F, point.z() + 0.5F); - SplineHelper.fillSplineForce(side, world, wood, p, replacement); - } - } - - sphere.fillArea(world, pos, new AABB(pos.above((int) offsetY)).inflate(radius * 1.3F)); - } - - private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, BlockState wood, Function replacement) { - int count = (int) (radius * 1.5F); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(ROOT); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - Vector3f last = branch.get(branch.size() - 1); - if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { - SplineHelper.fillSpline(branch, world, wood, pos, replacement); - } - } - } - - static { - SPLINE = Lists.newArrayList( - new Vector3f(0.00F, 0.00F, 0.00F), - new Vector3f(0.10F, 0.35F, 0.00F), - new Vector3f(0.20F, 0.50F, 0.00F), - new Vector3f(0.30F, 0.55F, 0.00F), - new Vector3f(0.42F, 0.70F, 0.00F), - new Vector3f(0.50F, 1.00F, 0.00F) - ); - - ROOT = Lists.newArrayList( - new Vector3f(0F, 1F, 0), - new Vector3f(0.1F, 0.70F, 0), - new Vector3f(0.3F, 0.30F, 0), - new Vector3f(0.7F, 0.05F, 0), - new Vector3f(0.8F, -0.20F, 0) - ); - SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); - - LEAF = Lists.newArrayList( - new Vector3f(0.00F, 0.0F, 0), - new Vector3f(0.10F, 0.4F, 0), - new Vector3f(0.40F, 0.8F, 0), - new Vector3f(0.75F, 0.9F, 0), - new Vector3f(1.00F, 0.8F, 0) - ); - - SIDE = Lists.newArrayList( - new Vector3f(0, -0.3F, -0.5F), - new Vector3f(0, -0.1F, -0.3F), - new Vector3f(0, 0.0F, 0.0F), - new Vector3f(0, -0.1F, 0.3F), - new Vector3f(0, -0.3F, 0.5F) - ); - } -} diff --git a/src/main/java/ru/betterend/integration/rei/REIContainer.java b/src/main/java/ru/betterend/integration/rei/REIContainer.java deleted file mode 100644 index 5365baf4..00000000 --- a/src/main/java/ru/betterend/integration/rei/REIContainer.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.betterend.integration.rei; - -public class REIContainer implements Runnable { - - @Override - public void run() { - //ContainerInfoHandler.registerContainerInfo(AlloyingRecipe.ID, CraftingContainerInfoWrapper.create(EndStoneSmelterScreenHandler.class)); - } -} diff --git a/src/main/java/ru/betterend/interfaces/BETargetChecker.java b/src/main/java/ru/betterend/interfaces/BETargetChecker.java deleted file mode 100644 index 304c4dc2..00000000 --- a/src/main/java/ru/betterend/interfaces/BETargetChecker.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.betterend.interfaces; - -public interface BETargetChecker { - boolean be_isTarget(); - void be_setTarget(boolean target); -} diff --git a/src/main/java/ru/betterend/interfaces/FallFlyingItem.java b/src/main/java/ru/betterend/interfaces/FallFlyingItem.java deleted file mode 100644 index fbb6bc0a..00000000 --- a/src/main/java/ru/betterend/interfaces/FallFlyingItem.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.betterend.interfaces; - -import net.minecraft.resources.ResourceLocation; - -public interface FallFlyingItem { - ResourceLocation getModelTexture(); - - double getMovementFactor(); -} diff --git a/src/main/java/ru/betterend/interfaces/ISlime.java b/src/main/java/ru/betterend/interfaces/ISlime.java deleted file mode 100644 index feb05e07..00000000 --- a/src/main/java/ru/betterend/interfaces/ISlime.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.betterend.interfaces; - -import net.minecraft.world.entity.Entity; - -public interface ISlime { - public void be_setSlimeSize(int size, boolean heal); - - void entityRemove(Entity.RemovalReason removalReason); -} diff --git a/src/main/java/ru/betterend/interfaces/MultiModelItem.java b/src/main/java/ru/betterend/interfaces/MultiModelItem.java deleted file mode 100644 index 1245197f..00000000 --- a/src/main/java/ru/betterend/interfaces/MultiModelItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.betterend.interfaces; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import ru.betterend.registry.EndItems; - -public interface MultiModelItem { - @Environment(EnvType.CLIENT) - void registerModelPredicate(); - - static void register() { - EndItems.getModItems().forEach(item -> { - if (item instanceof MultiModelItem) { - ((MultiModelItem) item).registerModelPredicate(); - } - }); - } -} diff --git a/src/main/java/ru/betterend/interfaces/PottablePlant.java b/src/main/java/ru/betterend/interfaces/PottablePlant.java deleted file mode 100644 index edb64ccc..00000000 --- a/src/main/java/ru/betterend/interfaces/PottablePlant.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.betterend.interfaces; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.world.level.block.Block; - -public interface PottablePlant { - boolean canPlantOn(Block block); - - default boolean canBePotted() { - return true; - } - - @Environment(EnvType.CLIENT) - default String getPottedState() { - return ""; - } -} diff --git a/src/main/java/ru/betterend/interfaces/PottableTerrain.java b/src/main/java/ru/betterend/interfaces/PottableTerrain.java deleted file mode 100644 index 9bf328ae..00000000 --- a/src/main/java/ru/betterend/interfaces/PottableTerrain.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.betterend.interfaces; - -public interface PottableTerrain { - default boolean canBePotted() { - return true; - } -} diff --git a/src/main/java/ru/betterend/interfaces/TeleportingEntity.java b/src/main/java/ru/betterend/interfaces/TeleportingEntity.java deleted file mode 100644 index 803cf507..00000000 --- a/src/main/java/ru/betterend/interfaces/TeleportingEntity.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.betterend.interfaces; - -import net.minecraft.core.BlockPos; - -public interface TeleportingEntity { - void be_setExitPos(BlockPos pos); - - void be_resetExitPos(); - - boolean be_canTeleport(); -} diff --git a/src/main/java/ru/betterend/item/ArmoredElytra.java b/src/main/java/ru/betterend/item/ArmoredElytra.java deleted file mode 100644 index 3fe282ff..00000000 --- a/src/main/java/ru/betterend/item/ArmoredElytra.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.betterend.item; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.item.ArmorMaterial; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import ru.bclib.items.BaseArmorItem; -import ru.betterend.BetterEnd; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.interfaces.MultiModelItem; -import ru.betterend.registry.EndItems; - -public class ArmoredElytra extends BaseArmorItem implements MultiModelItem, FallFlyingItem { - private final ResourceLocation wingTexture; - private final Item repairItem; - private final double movementFactor; - private final float toughness; - private final int defense; - - public ArmoredElytra(String name, ArmorMaterial material, Item repairItem, int durability, double movementFactor, boolean fireproof) { - super( - material, - EquipmentSlot.CHEST, - fireproof ? EndItems - .makeEndItemSettings() - .durability(durability) - .rarity(Rarity.EPIC) - .fireResistant() : EndItems.makeEndItemSettings().durability(durability).rarity(Rarity.EPIC) - ); - this.wingTexture = BetterEnd.makeID("textures/entity/" + name + ".png"); - this.repairItem = repairItem; - this.movementFactor = movementFactor; - this.defense = (int) ((double) material.getDefenseForSlot(EquipmentSlot.CHEST) / 1.75); - this.toughness = material.getToughness() / 1.75F; - addAttributeModifier( - Attributes.ARMOR, - new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], - "Armor modifier", - defense, - AttributeModifier.Operation.ADDITION - ) - ); - addAttributeModifier( - Attributes.ARMOR_TOUGHNESS, - new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], - "Armor toughness", - toughness, - AttributeModifier.Operation.ADDITION - ) - ); - } - - @Override - public double getMovementFactor() { - return movementFactor; - } - - @Override - @Environment(EnvType.CLIENT) - public ResourceLocation getModelTexture() { - return wingTexture; - } - - @Override - public boolean isValidRepairItem(ItemStack itemStack, ItemStack itemStack2) { - return super.isValidRepairItem(itemStack, itemStack2) || itemStack2.getItem() == repairItem; - } - - @Override - public int getDefense() { - return defense; - } - - @Override - public float getToughness() { - return toughness; - } - - @Override - @Environment(EnvType.CLIENT) - public void registerModelPredicate() { - FabricModelPredicateProviderRegistry.register( - this, - new ResourceLocation("broken"), - (itemStack, clientLevel, livingEntity, id) -> ElytraItem.isFlyEnabled(itemStack) ? 0.0F : 1.0F - ); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteArmor.java b/src/main/java/ru/betterend/item/CrystaliteArmor.java deleted file mode 100644 index 83b64c54..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteArmor.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; - -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import ru.bclib.items.BaseArmorItem; -import ru.betterend.effects.EndStatusEffects; -import ru.betterend.item.material.EndArmorMaterial; - -public class CrystaliteArmor extends BaseArmorItem { - - public final static MutableComponent CHEST_DESC; - public final static MutableComponent BOOTS_DESC; - - public CrystaliteArmor(EquipmentSlot equipmentSlot, Properties settings) { - super(EndArmorMaterial.CRYSTALITE, equipmentSlot, settings); - } - - public static boolean hasFullSet(LivingEntity owner) { - for (ItemStack armorStack : owner.getArmorSlots()) { - if (!(armorStack.getItem() instanceof CrystaliteArmor)) { - return false; - } - } - return true; - } - - public static void applySetEffect(LivingEntity owner) { - if ((owner.tickCount & 63) == 0) { - owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_HEALTH_REGEN)); - } - } - - static { - Style descStyle = Style.EMPTY.applyFormats(ChatFormatting.DARK_AQUA, ChatFormatting.ITALIC); - CHEST_DESC = Component.translatable("tooltip.armor.crystalite_chest"); - CHEST_DESC.setStyle(descStyle); - BOOTS_DESC = Component.translatable("tooltip.armor.crystalite_boots"); - BOOTS_DESC.setStyle(descStyle); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteBoots.java b/src/main/java/ru/betterend/item/CrystaliteBoots.java deleted file mode 100644 index 15a39a7d..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteBoots.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.betterend.item; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Component; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; -import ru.betterend.effects.EndStatusEffects; -import ru.betterend.interfaces.MobEffectApplier; -import ru.betterend.registry.EndItems; - -import java.awt.*; -import java.util.List; - -public class CrystaliteBoots extends CrystaliteArmor implements MobEffectApplier { - - public CrystaliteBoots() { - super(EquipmentSlot.FEET, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); - } - - @Override - public void applyEffect(LivingEntity owner) { - if ((owner.tickCount & 63) == 0) { - owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_MOVE_SPEED)); - } - } - - @Override - @Environment(EnvType.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable Level level, List lines, TooltipFlag tooltip) { - super.appendHoverText(stack, level, lines, tooltip); - lines.add(1, Component.empty()); - lines.add(2, BOOTS_DESC); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteChestplate.java b/src/main/java/ru/betterend/item/CrystaliteChestplate.java deleted file mode 100644 index 2f0295f7..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteChestplate.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.betterend.item; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Component; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; -import ru.betterend.effects.EndStatusEffects; -import ru.betterend.interfaces.MobEffectApplier; -import ru.betterend.registry.EndItems; - -import java.util.List; - -public class CrystaliteChestplate extends CrystaliteArmor implements MobEffectApplier { - - public CrystaliteChestplate() { - super(EquipmentSlot.CHEST, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); - } - - @Override - public void applyEffect(LivingEntity owner) { - owner.addEffect(new MobEffectInstance(EndStatusEffects.CRYSTALITE_DIG_SPEED)); - } - - @Override - @Environment(EnvType.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable Level level, List lines, TooltipFlag tooltip) { - super.appendHoverText(stack, level, lines, tooltip); - lines.add(1, Component.empty()); - lines.add(2, CHEST_DESC); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteElytra.java b/src/main/java/ru/betterend/item/CrystaliteElytra.java deleted file mode 100644 index 78a00940..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteElytra.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.betterend.item; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import ru.betterend.BetterEnd; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.interfaces.MultiModelItem; -import ru.betterend.registry.EndItems; - -public class CrystaliteElytra extends CrystaliteArmor implements MultiModelItem, FallFlyingItem { - - private final ResourceLocation wingTexture; - private final double movementFactor; - private final int defense; - private final float toughness; - - public CrystaliteElytra(int durability, double movementFactor) { - super(EquipmentSlot.CHEST, EndItems.makeEndItemSettings().durability(durability).rarity(Rarity.EPIC)); - this.wingTexture = BetterEnd.makeID("textures/entity/elytra_crystalite.png"); - this.movementFactor = movementFactor; - this.defense = (int) ((double) material.getDefenseForSlot(EquipmentSlot.CHEST) / 1.75); - this.toughness = material.getToughness() / 1.75F; - addAttributeModifier( - Attributes.ARMOR, - new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], - "Armor modifier", - defense, - AttributeModifier.Operation.ADDITION - ) - ); - addAttributeModifier( - Attributes.ARMOR_TOUGHNESS, - new AttributeModifier(ARMOR_MODIFIER_UUID_PER_SLOT[2], - "Armor toughness", - toughness, - AttributeModifier.Operation.ADDITION - ) - ); - } - - @Override - public boolean isValidRepairItem(ItemStack itemStack, ItemStack itemStack2) { - return super.isValidRepairItem(itemStack, itemStack2) || itemStack2.getItem() == EndItems.ENCHANTED_MEMBRANE; - } - - @Override - public double getMovementFactor() { - return movementFactor; - } - - @Override - @Environment(EnvType.CLIENT) - public ResourceLocation getModelTexture() { - return wingTexture; - } - - @Override - public int getDefense() { - return defense; - } - - @Override - public float getToughness() { - return toughness; - } - - @Override - public void registerModelPredicate() { - FabricModelPredicateProviderRegistry.register( - this, - new ResourceLocation("broken"), - (itemStack, clientLevel, livingEntity, i) -> ElytraItem.isFlyEnabled(itemStack) ? 0.0F : 1.0F - ); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteHelmet.java b/src/main/java/ru/betterend/item/CrystaliteHelmet.java deleted file mode 100644 index 34ff61f6..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteHelmet.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.item.Rarity; -import ru.betterend.registry.EndAttributes; -import ru.betterend.registry.EndItems; - -import java.util.UUID; - -public class CrystaliteHelmet extends CrystaliteArmor { - - public CrystaliteHelmet() { - super(EquipmentSlot.HEAD, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); - UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.HEAD.getIndex()]; - addAttributeModifier( - EndAttributes.BLINDNESS_RESISTANCE, - new AttributeModifier(uuid, "Helmet blindness resistance", 1.0, AttributeModifier.Operation.ADDITION) - ); - } -} diff --git a/src/main/java/ru/betterend/item/CrystaliteLeggings.java b/src/main/java/ru/betterend/item/CrystaliteLeggings.java deleted file mode 100644 index d966f848..00000000 --- a/src/main/java/ru/betterend/item/CrystaliteLeggings.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.item.Rarity; -import ru.betterend.registry.EndItems; - -import java.util.UUID; - -public class CrystaliteLeggings extends CrystaliteArmor { - - public CrystaliteLeggings() { - super(EquipmentSlot.LEGS, EndItems.makeEndItemSettings().rarity(Rarity.RARE)); - UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[EquipmentSlot.LEGS.getIndex()]; - addAttributeModifier( - Attributes.MAX_HEALTH, - new AttributeModifier(uuid, "Armor health boost", 4.0, AttributeModifier.Operation.ADDITION) - ); - } -} diff --git a/src/main/java/ru/betterend/item/EnchantedItem.java b/src/main/java/ru/betterend/item/EnchantedItem.java deleted file mode 100644 index fd033403..00000000 --- a/src/main/java/ru/betterend/item/EnchantedItem.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.betterend.item; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.items.ModelProviderItem; -import ru.betterend.registry.EndItems; - -public class EnchantedItem extends ModelProviderItem { - - private final Item source; - - public EnchantedItem(Item source) { - super(EndItems.makeEndItemSettings().rarity(Rarity.RARE).stacksTo(16)); - this.source = source; - } - - @Override - public boolean isFoil(ItemStack stack) { - return true; - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - ResourceLocation sourceId = Registry.ITEM.getKey(source); - return ModelsHelper.createItemModel(sourceId); - } -} diff --git a/src/main/java/ru/betterend/item/EndArmorItem.java b/src/main/java/ru/betterend/item/EndArmorItem.java deleted file mode 100644 index ab8aa11b..00000000 --- a/src/main/java/ru/betterend/item/EndArmorItem.java +++ /dev/null @@ -1,61 +0,0 @@ -package ru.betterend.item; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import net.minecraft.world.entity.EquipmentSlot; -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.ArmorItem; -import net.minecraft.world.item.ArmorMaterial; -import ru.bclib.interfaces.ItemModelProvider; - -import java.util.UUID; - -public class EndArmorItem extends ArmorItem implements ItemModelProvider { - - protected 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") - }; - - protected final Multimap defaultModifiers; - - public EndArmorItem(ArmorMaterial material, EquipmentSlot equipmentSlot, Properties settings) { - super(material, equipmentSlot, settings); - this.defaultModifiers = HashMultimap.create(); - UUID uuid = ARMOR_MODIFIER_UUID_PER_SLOT[equipmentSlot.getIndex()]; - addAttributeModifier( - Attributes.ARMOR, - new AttributeModifier(uuid, "Armor modifier", getDefense(), AttributeModifier.Operation.ADDITION) - ); - addAttributeModifier( - Attributes.ARMOR_TOUGHNESS, - new AttributeModifier(uuid, "Armor toughness", getToughness(), AttributeModifier.Operation.ADDITION) - ); - if (knockbackResistance > 0.0F) { - addAttributeModifier( - Attributes.KNOCKBACK_RESISTANCE, - new AttributeModifier(uuid, - "Armor knockback resistance", - knockbackResistance, - AttributeModifier.Operation.ADDITION - ) - ); - } - } - - @Override - public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentSlot) { - return equipmentSlot == slot ? defaultModifiers : super.getDefaultAttributeModifiers(equipmentSlot); - } - - protected void addAttributeModifier(Attribute attribute, AttributeModifier modifier) { - if (defaultModifiers.containsKey(attribute)) { - defaultModifiers.removeAll(attribute); - } - defaultModifiers.put(attribute, modifier); - } -} diff --git a/src/main/java/ru/betterend/item/EndAttribute.java b/src/main/java/ru/betterend/item/EndAttribute.java deleted file mode 100644 index 03159fea..00000000 --- a/src/main/java/ru/betterend/item/EndAttribute.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.world.entity.ai.attributes.Attribute; - -public class EndAttribute extends Attribute { - - public EndAttribute(String description, double value) { - super(description, value); - } -} diff --git a/src/main/java/ru/betterend/item/EndBucketItem.java b/src/main/java/ru/betterend/item/EndBucketItem.java deleted file mode 100644 index e328ed81..00000000 --- a/src/main/java/ru/betterend/item/EndBucketItem.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.item.MobBucketItem; -import net.minecraft.world.level.material.Fluids; -import ru.bclib.interfaces.ItemModelProvider; -import ru.betterend.registry.EndItems; - -public class EndBucketItem extends MobBucketItem implements ItemModelProvider { - public EndBucketItem(EntityType type) { - super(type, Fluids.WATER, SoundEvents.BUCKET_EMPTY, EndItems.makeEndItemSettings().stacksTo(1)); - } -} diff --git a/src/main/java/ru/betterend/item/EternalCrystalItem.java b/src/main/java/ru/betterend/item/EternalCrystalItem.java deleted file mode 100644 index 9034283d..00000000 --- a/src/main/java/ru/betterend/item/EternalCrystalItem.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.world.item.Rarity; -import ru.bclib.items.ModelProviderItem; -import ru.betterend.registry.EndItems; - -public class EternalCrystalItem extends ModelProviderItem { - public EternalCrystalItem() { - super(EndItems.makeEndItemSettings().stacksTo(16).rarity(Rarity.EPIC)); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/item/GuideBookItem.java b/src/main/java/ru/betterend/item/GuideBookItem.java deleted file mode 100644 index 91971e54..00000000 --- a/src/main/java/ru/betterend/item/GuideBookItem.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.item; - -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import ru.bclib.items.ModelProviderItem; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndItems; -import ru.betterend.util.LangUtil; - -import java.util.List; - -public class GuideBookItem extends ModelProviderItem { - public final static ResourceLocation BOOK_ID = BetterEnd.makeID("guidebook"); - public static final Item GUIDE_BOOK = EndItems.getItemRegistry().register(BOOK_ID, new GuideBookItem()); - - public static void register() { - } - - public GuideBookItem() { - super(EndItems.makeEndItemSettings().stacksTo(1)); - } - - @Override - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { - if (!world.isClientSide && user instanceof ServerPlayer) { - //TODO: reanable Patchouli once it is available for 1.18 - //PatchouliAPI.get().openBookGUI((ServerPlayer) user, BOOK_ID); - return InteractionResultHolder.success(user.getItemInHand(hand)); - } - return InteractionResultHolder.consume(user.getItemInHand(hand)); - } - - @Override - public void appendHoverText(ItemStack stack, Level world, List tooltip, TooltipFlag context) { - tooltip.add(LangUtil.getText("book.betterend", "subtitle") - .withStyle(ChatFormatting.DARK_PURPLE, ChatFormatting.ITALIC)); - } -} diff --git a/src/main/java/ru/betterend/item/material/EndArmorMaterial.java b/src/main/java/ru/betterend/item/material/EndArmorMaterial.java deleted file mode 100644 index fd740dd7..00000000 --- a/src/main/java/ru/betterend/item/material/EndArmorMaterial.java +++ /dev/null @@ -1,88 +0,0 @@ -package ru.betterend.item.material; - -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.util.LazyLoadedValue; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ArmorMaterial; -import net.minecraft.world.item.crafting.Ingredient; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.function.Supplier; - -public enum EndArmorMaterial implements ArmorMaterial { - THALLASIUM("thallasium", 17, new int[] {1, 4, 5, 2}, 12, SoundEvents.ARMOR_EQUIP_IRON, 0.0F, 0.0F, () -> { - return Ingredient.of(EndBlocks.THALLASIUM.ingot); - }), TERMINITE("terminite", 26, new int[] {3, 6, 7, 3}, 14, SoundEvents.ARMOR_EQUIP_IRON, 1.0F, 0.05F, () -> { - return Ingredient.of(EndBlocks.TERMINITE.ingot); - }), AETERNIUM("aeternium", 40, new int[] {4, 7, 9, 4}, 18, SoundEvents.ARMOR_EQUIP_NETHERITE, 3.5F, 0.2F, () -> { - return Ingredient.of(EndItems.AETERNIUM_INGOT); - }), CRYSTALITE("crystalite", 30, new int[] {3, 6, 8, 3}, 24, SoundEvents.ARMOR_EQUIP_DIAMOND, 1.2F, 0.1F, () -> { - return Ingredient.of(EndBlocks.TERMINITE.ingot); - }); - - private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; - private final String name; - private final int durabilityMultiplier; - private final int[] protectionAmounts; - private final int enchantability; - private final SoundEvent equipSound; - private final float toughness; - private final float knockbackResistance; - @SuppressWarnings("deprecation") - private final LazyLoadedValue repairIngredient; - - @SuppressWarnings("deprecation") - private EndArmorMaterial(String name, int durabilityMultiplier, int[] protectionAmounts, int enchantability, SoundEvent equipSound, float toughness, float knockbackResistance, Supplier repairIngredient) { - this.name = name; - this.durabilityMultiplier = durabilityMultiplier; - this.protectionAmounts = protectionAmounts; - this.enchantability = enchantability; - this.equipSound = equipSound; - this.toughness = toughness; - this.knockbackResistance = knockbackResistance; - this.repairIngredient = new LazyLoadedValue<>(repairIngredient); - } - - @Override - public int getDurabilityForSlot(EquipmentSlot slot) { - return BASE_DURABILITY[slot.getIndex()] * this.durabilityMultiplier; - } - - @Override - public int getDefenseForSlot(EquipmentSlot slot) { - return this.protectionAmounts[slot.getIndex()]; - } - - @Override - public int getEnchantmentValue() { - return this.enchantability; - } - - @Override - public SoundEvent getEquipSound() { - return this.equipSound; - } - - @Override - public Ingredient getRepairIngredient() { - return this.repairIngredient.get(); - } - - @Override - public String getName() { - return this.name; - } - - @Override - public float getToughness() { - return this.toughness; - } - - @Override - public float getKnockbackResistance() { - return this.knockbackResistance; - } - -} diff --git a/src/main/java/ru/betterend/item/material/EndToolMaterial.java b/src/main/java/ru/betterend/item/material/EndToolMaterial.java deleted file mode 100644 index ac7f7049..00000000 --- a/src/main/java/ru/betterend/item/material/EndToolMaterial.java +++ /dev/null @@ -1,68 +0,0 @@ -package ru.betterend.item.material; - -import net.minecraft.util.LazyLoadedValue; -import net.minecraft.world.item.Tier; -import net.minecraft.world.item.crafting.Ingredient; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.function.Supplier; - -public enum EndToolMaterial implements Tier { - THALLASIUM(2, 320, 7.0F, 1.5F, 12, () -> { - return Ingredient.of(EndBlocks.THALLASIUM.ingot); - }), TERMINITE(3, 1230, 8.5F, 3.0F, 14, () -> { - return Ingredient.of(EndBlocks.TERMINITE.ingot); - }), AETERNIUM(5, 2196, 10.0F, 4.5F, 18, () -> { - return Ingredient.of(EndItems.AETERNIUM_INGOT); - }); - - private final int durability; - private final float miningSpeed; - private final float attackDamage; - private final int miningLevel; - private final int enchantability; - @SuppressWarnings("deprecation") - private final LazyLoadedValue repairIngredient; - - @SuppressWarnings("deprecation") - private EndToolMaterial(int miningLevel, int durability, float miningSpeed, float attackDamage, int enchantability, Supplier repairIngredient) { - this.durability = durability; - this.miningSpeed = miningSpeed; - this.attackDamage = attackDamage; - this.miningLevel = miningLevel; - this.enchantability = enchantability; - this.repairIngredient = new LazyLoadedValue<>(repairIngredient); - } - - @Override - public int getUses() { - return this.durability; - } - - @Override - public float getSpeed() { - return this.miningSpeed; - } - - @Override - public float getAttackDamageBonus() { - return this.attackDamage; - } - - @Override - public int getLevel() { - return this.miningLevel; - } - - @Override - public int getEnchantmentValue() { - return this.enchantability; - } - - @Override - public Ingredient getRepairIngredient() { - return this.repairIngredient.get(); - } - -} diff --git a/src/main/java/ru/betterend/item/model/ArmoredElytraModel.java b/src/main/java/ru/betterend/item/model/ArmoredElytraModel.java deleted file mode 100644 index 2937ad9f..00000000 --- a/src/main/java/ru/betterend/item/model/ArmoredElytraModel.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.ImmutableList; -import net.minecraft.client.model.AgeableListModel; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartNames; -import net.minecraft.client.model.geom.PartPose; -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.player.AbstractClientPlayer; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.phys.Vec3; - -public class ArmoredElytraModel extends AgeableListModel { - private final ModelPart rightWing; - private final ModelPart leftWing; - - public static LayerDefinition getTexturedModelData() { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - modelPartData.addOrReplaceChild( - PartNames.LEFT_WING, - CubeListBuilder.create().texOffs(22, 0).addBox(-10.0f, 0.0f, 0.0f, 10.0f, 20.0f, 2.0f), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - PartNames.RIGHT_WING, - CubeListBuilder.create().mirror().texOffs(22, 0).addBox(0.0f, 0.0f, 0.0f, 10.0f, 20.0f, 2.0f), - PartPose.ZERO - ); - - return LayerDefinition.create(modelData, 64, 32); - } - - public ArmoredElytraModel(ModelPart modelPart) { - leftWing = modelPart.getChild(PartNames.LEFT_WING); - rightWing = modelPart.getChild(PartNames.RIGHT_WING); - } - - protected Iterable headParts() { - return ImmutableList.of(); - } - - protected Iterable bodyParts() { - return ImmutableList.of(leftWing, rightWing); - } - - public void setupAnim(T livingEntity, float f, float g, float h, float i, float j) { - float rotX = 0.2617994F; - float rotZ = -0.2617994F; - float rotY = 0.0F; - float wingY = 0.0F; - if (livingEntity.isFallFlying()) { - float coef = 1.0F; - Vec3 vec3 = livingEntity.getDeltaMovement(); - if (vec3.y < 0.0D) { - Vec3 normalized = vec3.normalize(); - coef = 1.0F - (float) Math.pow(-normalized.y, 2.5D); - } - rotX = coef * 0.34906584F + (1.0F - coef) * rotX; - rotZ = coef * -1.5707964F + (1.0F - coef) * rotZ; - } - else if (livingEntity.isCrouching()) { - rotX = 0.6981317F; - rotZ = -0.7853982F; - rotY = 0.08726646F; - wingY = 3.0F; - } - - leftWing.x = 5.0F; - leftWing.y = wingY; - if (livingEntity instanceof AbstractClientPlayer) { - AbstractClientPlayer abstractClientPlayer = (AbstractClientPlayer) livingEntity; - abstractClientPlayer.elytraRotX = (float) ((double) abstractClientPlayer.elytraRotX + (double) (rotX - abstractClientPlayer.elytraRotX) * 0.1D); - abstractClientPlayer.elytraRotY = (float) ((double) abstractClientPlayer.elytraRotY + (double) (rotY - abstractClientPlayer.elytraRotY) * 0.1D); - abstractClientPlayer.elytraRotZ = (float) ((double) abstractClientPlayer.elytraRotZ + (double) (rotZ - abstractClientPlayer.elytraRotZ) * 0.1D); - leftWing.xRot = abstractClientPlayer.elytraRotX; - leftWing.yRot = abstractClientPlayer.elytraRotY; - leftWing.zRot = abstractClientPlayer.elytraRotZ; - } - else { - leftWing.xRot = rotX; - leftWing.zRot = rotZ; - leftWing.yRot = rotY; - } - - rightWing.x = -leftWing.x; - rightWing.yRot = -leftWing.yRot; - rightWing.y = leftWing.y; - rightWing.xRot = leftWing.xRot; - rightWing.zRot = -leftWing.zRot; - } -} diff --git a/src/main/java/ru/betterend/item/model/CrystaliteArmorProvider.java b/src/main/java/ru/betterend/item/model/CrystaliteArmorProvider.java deleted file mode 100644 index e38e846d..00000000 --- a/src/main/java/ru/betterend/item/model/CrystaliteArmorProvider.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import ru.betterend.item.CrystaliteArmor; -import ru.betterend.registry.EndItems; -import shadow.fabric.api.client.rendering.v1.ArmorRenderingRegistry; - -@Environment(EnvType.CLIENT) -public class CrystaliteArmorProvider implements ArmorRenderingRegistry.ModelProvider, ArmorRenderingRegistry.TextureProvider { - //TODO: find new registry - private final static ResourceLocation FIRST_LAYER = new ResourceLocation( - "textures/models/armor/crystalite_layer_1.png"); - private final static ResourceLocation SECOND_LAYER = new ResourceLocation( - "textures/models/armor/crystalite_layer_2.png"); - private final static CrystaliteHelmetModel HELMET_MODEL = CrystaliteHelmetModel.createModel(null); - private final static CrystaliteChestplateModel CHEST_MODEL = CrystaliteChestplateModel.createRegularModel(null); - private final static CrystaliteChestplateModel CHEST_MODEL_SLIM = CrystaliteChestplateModel.createThinModel(null); - private final static CrystaliteLeggingsModel LEGGINGS_MODEL = CrystaliteLeggingsModel.createModel(null); - private final static CrystaliteBootsModel BOOTS_MODEL = CrystaliteBootsModel.createModel(null); - - //@Override - public @NotNull ResourceLocation getArmorTexture(LivingEntity entity, ItemStack stack, EquipmentSlot slot, boolean secondLayer, @Nullable String suffix, ResourceLocation defaultTexture) { - if (!isStackValid(stack)) return defaultTexture; - if (secondLayer) return SECOND_LAYER; - return FIRST_LAYER; - } - - //@Override - public @NotNull HumanoidModel getArmorModel(LivingEntity entity, ItemStack stack, EquipmentSlot slot, HumanoidModel defaultModel) { - if (!isStackValid(stack)) return defaultModel; - switch (slot) { - case HEAD: { - return HELMET_MODEL; - } - case CHEST: { - if (entity instanceof AbstractClientPlayer && ((AbstractClientPlayer) entity).getModelName() - .equals("slim")) { - CHEST_MODEL_SLIM.copyPropertiesTo(defaultModel); - return CHEST_MODEL_SLIM; - } - CHEST_MODEL.copyPropertiesTo(defaultModel); - return CHEST_MODEL; - } - case LEGS: { - return LEGGINGS_MODEL; - } - case FEET: { - BOOTS_MODEL.copyPropertiesTo(defaultModel); - return BOOTS_MODEL; - } - default: { - return defaultModel; - } - } - } - - public Iterable getRenderedItems() { - return Lists.newArrayList( - EndItems.CRYSTALITE_HELMET, - EndItems.CRYSTALITE_CHESTPLATE, - EndItems.CRYSTALITE_ELYTRA, - EndItems.CRYSTALITE_LEGGINGS, - EndItems.CRYSTALITE_BOOTS - ); - } - - private boolean isStackValid(ItemStack stack) { - return stack.getItem() instanceof CrystaliteArmor; - } -} diff --git a/src/main/java/ru/betterend/item/model/CrystaliteBootsModel.java b/src/main/java/ru/betterend/item/model/CrystaliteBootsModel.java deleted file mode 100644 index 4bb0b3c5..00000000 --- a/src/main/java/ru/betterend/item/model/CrystaliteBootsModel.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.Lists; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.model.geom.EntityModelSet; -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.RenderType; -import net.minecraft.world.entity.LivingEntity; -import ru.betterend.registry.EndEntitiesRenders; - -import java.util.Collections; - -public class CrystaliteBootsModel extends HumanoidModel { - - public ModelPart leftBoot; - public ModelPart rightBoot; - - public static LayerDefinition getTexturedModelData() { - final float scale = 1.0f; - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - // TODO: see if we need to subclass HumanoidModel - // Humanoid model tries to retrieve all parts in it's constructor, - // so we need to add empty Nodes - modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); - - CubeDeformation deformation = new CubeDeformation(scale + 0.25f); - modelPartData.addOrReplaceChild( - "leftBoot", - CubeListBuilder.create().texOffs(0, 32).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(1.9f, 12.0f, 0.0f) - ); - - modelPartData.addOrReplaceChild( - "rightBoot", - CubeListBuilder.create().texOffs(0, 16).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(-1.9f, 12.0f, 0.0f) - ); - - return LayerDefinition.create(modelData, 64, 48); - } - - public static CrystaliteBootsModel createModel(EntityModelSet entityModelSet) { - return new CrystaliteBootsModel(entityModelSet == null ? getTexturedModelData().bakeRoot() : entityModelSet.bakeLayer( - EndEntitiesRenders.CRYSTALITE_BOOTS)); - } - - public CrystaliteBootsModel(ModelPart modelPart) { - super(modelPart, RenderType::entityTranslucent); - - leftBoot = modelPart.getChild("leftBoot"); - rightBoot = modelPart.getChild("rightBoot"); - } - - @Override - public void copyPropertiesTo(HumanoidModel bipedEntityModel) { - super.copyPropertiesTo(bipedEntityModel); - this.leftBoot.copyFrom(leftLeg); - this.rightBoot.copyFrom(rightLeg); - } - - @Override - protected Iterable headParts() { - return Collections::emptyIterator; - } - - @Override - protected Iterable bodyParts() { - return Lists.newArrayList(leftBoot, rightBoot); - } -} diff --git a/src/main/java/ru/betterend/item/model/CrystaliteChestplateModel.java b/src/main/java/ru/betterend/item/model/CrystaliteChestplateModel.java deleted file mode 100644 index 8752cf20..00000000 --- a/src/main/java/ru/betterend/item/model/CrystaliteChestplateModel.java +++ /dev/null @@ -1,145 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.model.geom.EntityModelSet; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartNames; -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.RenderType; -import net.minecraft.world.entity.HumanoidArm; -import net.minecraft.world.entity.LivingEntity; -import ru.betterend.registry.EndEntitiesRenders; - -import java.util.Collections; - -public class CrystaliteChestplateModel extends HumanoidModel { - - public ModelPart leftShoulder; - public ModelPart rightShoulder; - private final boolean thinArms; - - public static LayerDefinition getRegularTexturedModelData() { - return getTexturedModelData(1.0f, false); - } - - public static LayerDefinition getThinTexturedModelData() { - return getTexturedModelData(1.0f, true); - } - - private static LayerDefinition getTexturedModelData(float scale, boolean thinArms) { - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - // TODO: see if we need to subclass HumanoidModel - // Humanoid model tries to retrieve all parts in it's constructor, - // so we need to add empty Nodes - modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); - // modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); - - CubeDeformation deformation = new CubeDeformation(scale + 0.25F); - PartDefinition body = modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(16, 16).addBox(-4.0f, 0.0f, -2.0f, 8.0f, 12.0f, 4.0f, deformation), - PartPose.ZERO - ); - - if (thinArms) { - deformation = new CubeDeformation(scale + 0.45F); - PartDefinition leftShoulder = modelPartData.addOrReplaceChild( - "leftShoulder", - CubeListBuilder.create() - .mirror() - .texOffs(40, 32) - .addBox(-1.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(5.0f, 2.0f, 0.0f) - ); - - PartDefinition rightShoulder = modelPartData.addOrReplaceChild( - "rightShoulder", - CubeListBuilder.create().texOffs(40, 16).addBox(-3.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(-5.0f, 2.0f, 10.0f) - ); - } - else { - deformation = new CubeDeformation(scale + 0.45F); - PartDefinition leftShoulder = modelPartData.addOrReplaceChild( - "leftShoulder", - CubeListBuilder.create() - .mirror() - .texOffs(40, 32) - .addBox(-1.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(5.0f, 2.0f, 0.0f) - ); - - PartDefinition rightShoulder = modelPartData.addOrReplaceChild( - "rightShoulder", - CubeListBuilder.create().texOffs(40, 16).addBox(-3.0f, -2.5f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(-5.0f, 2.0f, 10.0f) - ); - } - return LayerDefinition.create(modelData, 64, 48); - } - - final ModelPart localBody; - - public static CrystaliteChestplateModel createRegularModel(EntityModelSet entityModelSet) { - return new CrystaliteChestplateModel(entityModelSet == null ? getRegularTexturedModelData().bakeRoot() : entityModelSet - .bakeLayer(EndEntitiesRenders.CRYSTALITE_CHESTPLATE), false); - } - - public static CrystaliteChestplateModel createThinModel(EntityModelSet entityModelSet) { - return new CrystaliteChestplateModel(entityModelSet == null ? getThinTexturedModelData().bakeRoot() : entityModelSet - .bakeLayer(EndEntitiesRenders.CRYSTALITE_CHESTPLATE_THIN), true); - } - - protected CrystaliteChestplateModel(ModelPart modelPart, boolean thinArms) { - super(modelPart, RenderType::entityTranslucent); - this.thinArms = thinArms; - localBody = modelPart.getChild(PartNames.BODY); - leftShoulder = modelPart.getChild("leftShoulder"); - rightShoulder = modelPart.getChild("rightShoulder"); - } - - @Override - public void copyPropertiesTo(HumanoidModel bipedEntityModel) { - super.copyPropertiesTo(bipedEntityModel); - this.leftShoulder.copyFrom(leftArm); - this.rightShoulder.copyFrom(rightArm); - } - - @Override - protected Iterable headParts() { - return Collections::emptyIterator; - } - - @Override - protected Iterable bodyParts() { - return Lists.newArrayList(localBody, leftShoulder, rightShoulder); - } - - @Override - public void translateToHand(HumanoidArm arm, PoseStack matrices) { - ModelPart modelPart = this.getArm(arm); - if (this.thinArms) { - float f = 0.5F * (float) (arm == HumanoidArm.RIGHT ? 1 : -1); - modelPart.x += f; - modelPart.translateAndRotate(matrices); - modelPart.x -= f; - } - else { - modelPart.translateAndRotate(matrices); - } - } -} diff --git a/src/main/java/ru/betterend/item/model/CrystaliteHelmetModel.java b/src/main/java/ru/betterend/item/model/CrystaliteHelmetModel.java deleted file mode 100644 index e70f6f4d..00000000 --- a/src/main/java/ru/betterend/item/model/CrystaliteHelmetModel.java +++ /dev/null @@ -1,73 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.Lists; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.model.geom.EntityModelSet; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartNames; -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.RenderType; -import net.minecraft.world.entity.LivingEntity; -import ru.betterend.registry.EndEntitiesRenders; - -import java.util.Collections; - -@Environment(EnvType.CLIENT) -public class CrystaliteHelmetModel extends HumanoidModel { - final ModelPart myHat; - - public static LayerDefinition getTexturedModelData() { - final float scale = 1.0f; - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - // TODO: see if we need to subclass HumanoidModel - // Humanoid model tries to retrieve all parts in it's constructor, - // so we need to add empty Nodes - modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); - //modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); - - CubeDeformation deformation_hat = new CubeDeformation(scale + 0.5f); - PartDefinition hat = modelPartData.addOrReplaceChild( - PartNames.HAT, - CubeListBuilder.create().texOffs(0, 0).addBox(-4.0f, -8.0f, -4.0f, 8.0f, 8.0f, 8.0f, deformation_hat), - PartPose.ZERO - ); - - return LayerDefinition.create(modelData, 64, 48); - } - - public static CrystaliteHelmetModel createModel(EntityModelSet entityModelSet) { - return new CrystaliteHelmetModel(entityModelSet == null ? getTexturedModelData().bakeRoot() : entityModelSet.bakeLayer( - EndEntitiesRenders.CRYSTALITE_HELMET)); - } - - - public CrystaliteHelmetModel(ModelPart modelPart) { - super(modelPart, RenderType::entityTranslucent); - - myHat = modelPart.getChild(PartNames.HAT); - } - - @Override - protected Iterable headParts() { - return Collections::emptyIterator; - } - - @Override - protected Iterable bodyParts() { - return Lists.newArrayList(myHat); - } -} diff --git a/src/main/java/ru/betterend/item/model/CrystaliteLeggingsModel.java b/src/main/java/ru/betterend/item/model/CrystaliteLeggingsModel.java deleted file mode 100644 index 233efabe..00000000 --- a/src/main/java/ru/betterend/item/model/CrystaliteLeggingsModel.java +++ /dev/null @@ -1,85 +0,0 @@ -package ru.betterend.item.model; - -import com.google.common.collect.Lists; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.model.geom.EntityModelSet; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.PartNames; -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.RenderType; -import net.minecraft.world.entity.LivingEntity; -import ru.betterend.registry.EndEntitiesRenders; - -import java.util.Collections; - -public class CrystaliteLeggingsModel extends HumanoidModel { - public static LayerDefinition getTexturedModelData() { - float scale = 1.0f; - MeshDefinition modelData = new MeshDefinition(); - PartDefinition modelPartData = modelData.getRoot(); - - // TODO: see if we need to subclass HumanoidModel - // Humanoid model tries to retrieve all parts in it's constructor, - // so we need to add empty Nodes - modelPartData.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); - // modelPartData.addOrReplaceChild("body", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("right_arm", CubeListBuilder.create(), PartPose.ZERO); - modelPartData.addOrReplaceChild("left_arm", CubeListBuilder.create(), PartPose.ZERO); - // modelPartData.addOrReplaceChild("right_leg", CubeListBuilder.create(), PartPose.ZERO); - // modelPartData.addOrReplaceChild("left_leg", CubeListBuilder.create(), PartPose.ZERO); - - CubeDeformation deformation = new CubeDeformation(scale); - modelPartData.addOrReplaceChild( - PartNames.BODY, - CubeListBuilder.create().texOffs(16, 16).addBox(-4.0f, 0.0f, -2.0f, 8.0f, 12.0f, 4.0f, deformation), - PartPose.ZERO - ); - - modelPartData.addOrReplaceChild( - PartNames.LEFT_LEG, - CubeListBuilder.create().texOffs(0, 32).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(1.9f, 12.0f, 0.0f) - ); - - modelPartData.addOrReplaceChild( - PartNames.RIGHT_LEG, - CubeListBuilder.create().texOffs(0, 16).addBox(-2.0f, 0.0f, -2.0f, 4.0f, 12.0f, 4.0f, deformation), - PartPose.offset(-1.9f, 12.0f, 0.0f) - ); - - return LayerDefinition.create(modelData, 64, 48); - } - - final ModelPart myBody; - final ModelPart myLeftLeg; - final ModelPart myRightLeg; - - public static CrystaliteLeggingsModel createModel(EntityModelSet entityModelSet) { - return new CrystaliteLeggingsModel(entityModelSet == null ? getTexturedModelData().bakeRoot() : entityModelSet.bakeLayer( - EndEntitiesRenders.CRYSTALITE_LEGGINGS)); - } - - public CrystaliteLeggingsModel(ModelPart modelPart) { - super(modelPart, RenderType::entityTranslucent); - - myBody = modelPart.getChild(PartNames.BODY); - myLeftLeg = modelPart.getChild(PartNames.LEFT_LEG); - myRightLeg = modelPart.getChild(PartNames.RIGHT_LEG); - } - - @Override - protected Iterable headParts() { - return Collections::emptyIterator; - } - - @Override - protected Iterable bodyParts() { - return Lists.newArrayList(myBody, myRightLeg, myLeftLeg); - } -} diff --git a/src/main/java/ru/betterend/item/tool/EndHammerItem.java b/src/main/java/ru/betterend/item/tool/EndHammerItem.java deleted file mode 100644 index c7afccf2..00000000 --- a/src/main/java/ru/betterend/item/tool/EndHammerItem.java +++ /dev/null @@ -1,156 +0,0 @@ -package ru.betterend.item.tool; - -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableMultimap.Builder; -import com.google.common.collect.Multimap; -import io.netty.util.internal.ThreadLocalRandom; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.EquipmentSlot; -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.entity.player.Player; -import net.minecraft.world.item.DiggerItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Tier; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.api.tag.CommonItemTags; - -import ru.bclib.client.models.ModelsHelper; -import ru.bclib.interfaces.ItemModelProvider; -import ru.bclib.interfaces.TagProvider; -import ru.bclib.util.MHelper; - -import java.util.List; -import java.util.UUID; - -public class EndHammerItem extends DiggerItem implements ItemModelProvider, TagProvider { - public final static UUID ATTACK_KNOCKBACK_MODIFIER_ID = Mth.createInsecureUUID(MHelper.RANDOM_SOURCE); - - private final Multimap attributeModifiers; - - public EndHammerItem(Tier material, float attackDamage, float attackSpeed, double knockback, Properties settings) { - super(attackDamage, attackSpeed, material, CommonBlockTags.MINABLE_WITH_HAMMER, settings); - - Builder builder = ImmutableMultimap.builder(); - builder.put( - Attributes.ATTACK_DAMAGE, - new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, - "Weapon modifier", - attackDamage + material.getAttackDamageBonus(), - AttributeModifier.Operation.ADDITION - ) - ); - builder.put( - Attributes.ATTACK_SPEED, - new AttributeModifier(BASE_ATTACK_SPEED_UUID, - "Weapon modifier", - attackSpeed, - AttributeModifier.Operation.ADDITION - ) - ); - builder.put( - Attributes.ATTACK_KNOCKBACK, - new AttributeModifier(ATTACK_KNOCKBACK_MODIFIER_ID, - "Weapon modifier", - knockback, - AttributeModifier.Operation.ADDITION - ) - ); - this.attributeModifiers = builder.build(); - } - - @Override - public boolean canAttackBlock(BlockState state, Level world, BlockPos pos, Player miner) { - return state.getMaterial().equals(Material.STONE) || state.getMaterial().equals(Material.GLASS) || state.is( - Blocks.DIAMOND_BLOCK) || state.is(Blocks.EMERALD_BLOCK) || state.is(Blocks.LAPIS_BLOCK) || state.is(Blocks.REDSTONE_BLOCK); - } - - @Override - public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { - stack.hurtAndBreak(1, attacker, ((entity) -> entity.broadcastBreakEvent(EquipmentSlot.MAINHAND))); - - return true; - } - - @Override - public boolean mineBlock(ItemStack stack, Level world, BlockState state, BlockPos pos, LivingEntity miner) { - if (state.getDestroySpeed(world, pos) != 0.0F) { - stack.hurtAndBreak(1, miner, ((entity) -> entity.broadcastBreakEvent(EquipmentSlot.MAINHAND))); - } - - return true; - } - - @Override - public float getDestroySpeed(ItemStack stack, BlockState state) { - if (state.getMaterial().equals(Material.GLASS)) { - return this.getTier().getSpeed() * 2.0F; - } - if (isCorrectToolForDrops(state)) { - float mult; - if (state.is(Blocks.DIAMOND_BLOCK) || state.is(Blocks.EMERALD_BLOCK) || state.is(Blocks.LAPIS_BLOCK) || state - .is(Blocks.REDSTONE_BLOCK)) { - mult = this.getTier().getSpeed(); - } - else { - mult = this.getTier().getSpeed() / 2.0F; - } - return Math.max(mult, 1.0F); - } - return 1.0F; - } - - @Override - public boolean isCorrectToolForDrops(BlockState state) { - if (state.getMaterial().equals(Material.GLASS)) { - return true; - } - if (!state.is(Blocks.REDSTONE_BLOCK) && !state.is(Blocks.DIAMOND_BLOCK) && !state.is(Blocks.EMERALD_BLOCK) && !state - .is(Blocks.LAPIS_BLOCK) && !state.getMaterial().equals(Material.STONE)) { - return false; - } - int level = this.getTier().getLevel(); - if (state.is(Blocks.IRON_ORE) || state.is(Blocks.LAPIS_BLOCK) || state.is(Blocks.LAPIS_ORE)) { - return level >= 1; - } - if (state.is(Blocks.DIAMOND_BLOCK) && !state.is(Blocks.DIAMOND_ORE) || state.is(Blocks.EMERALD_ORE) || state.is( - Blocks.EMERALD_BLOCK) || state.is(Blocks.GOLD_ORE) || state.is(Blocks.REDSTONE_ORE)) { - return level >= 2; - } - if (state.is(Blocks.OBSIDIAN) || state.is(Blocks.CRYING_OBSIDIAN) || state.is(Blocks.RESPAWN_ANCHOR) || state.is( - Blocks.ANCIENT_DEBRIS)) { - return level >= 3; - } - return true; - } - - @Override - public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { - return slot == EquipmentSlot.MAINHAND ? this.attributeModifiers : super.getDefaultAttributeModifiers(slot); - } - - @Override - @Environment(EnvType.CLIENT) - public BlockModel getItemModel(ResourceLocation resourceLocation) { - return ModelsHelper.createHandheldItem(resourceLocation); - } - - @Override - public void addTags(List> blockTags, List> itemTags) { - itemTags.add(CommonItemTags.HAMMERS); - } -} diff --git a/src/main/java/ru/betterend/item/tool/EndPickaxe.java b/src/main/java/ru/betterend/item/tool/EndPickaxe.java deleted file mode 100644 index cdd1d3fd..00000000 --- a/src/main/java/ru/betterend/item/tool/EndPickaxe.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.betterend.item.tool; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Tier; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.items.tool.BasePickaxeItem; - -public class EndPickaxe extends BasePickaxeItem { - public EndPickaxe(Tier material, int attackDamage, float attackSpeed, Properties settings) { - super(material, attackDamage, attackSpeed, settings); - } - - @Override - public float getDestroySpeed(ItemStack stack, BlockState state) { - if (state.is(Blocks.END_STONE) && this.getTier().getLevel() > 2) { - return this.speed * 3; - } - return super.getDestroySpeed(stack, state); - } -} diff --git a/src/main/java/ru/betterend/mixin/client/BiomeColorsMixin.java b/src/main/java/ru/betterend/mixin/client/BiomeColorsMixin.java deleted file mode 100644 index f88e0c5a..00000000 --- a/src/main/java/ru/betterend/mixin/client/BiomeColorsMixin.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.betterend.mixin.client; - -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BiomeColors; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.BlockAndTintGetter; -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.CallbackInfoReturnable; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.MHelper; -import ru.betterend.client.ClientOptions; -import ru.betterend.registry.EndBlocks; - -import java.awt.Point; -import java.util.Arrays; -import java.util.Comparator; - -@Mixin(BiomeColors.class) -public class BiomeColorsMixin { - private static final int POISON_COLOR = ColorUtil.color(92, 160, 78); - private static final int STREAM_COLOR = ColorUtil.color(105, 213, 244); - private static final Point[] OFFSETS; - private static final boolean HAS_SODIUM; - - @Inject(method = "getAverageWaterColor", at = @At("RETURN"), cancellable = true) - private static void be_getWaterColor(BlockAndTintGetter world, BlockPos pos, CallbackInfoReturnable info) { - if (ClientOptions.useSulfurWaterColor()) { - BlockAndTintGetter view = HAS_SODIUM ? Minecraft.getInstance().level : world; - MutableBlockPos mut = new MutableBlockPos(); - mut.setY(pos.getY()); - for (int i = 0; i < OFFSETS.length; i++) { - mut.setX(pos.getX() + OFFSETS[i].x); - mut.setZ(pos.getZ() + OFFSETS[i].y); - if ((view.getBlockState(mut).is(EndBlocks.BRIMSTONE))) { - info.setReturnValue(i < 4 ? POISON_COLOR : STREAM_COLOR); - return; - } - } - } - } - - static { - HAS_SODIUM = FabricLoader.getInstance().isModLoaded("sodium"); - - int index = 0; - OFFSETS = new Point[20]; - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if ((x != 0 || z != 0) && (Math.abs(x) != 2 || Math.abs(z) != 2)) { - OFFSETS[index++] = new Point(x, z); - } - } - } - Arrays.sort(OFFSETS, Comparator.comparingInt(pos -> MHelper.sqr(pos.x) + MHelper.sqr(pos.y))); - } -} diff --git a/src/main/java/ru/betterend/mixin/client/CapeLayerMixin.java b/src/main/java/ru/betterend/mixin/client/CapeLayerMixin.java deleted file mode 100644 index 8ddbb4cc..00000000 --- a/src/main/java/ru/betterend/mixin/client/CapeLayerMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.mixin.client; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.entity.layers.CapeLayer; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ItemStack; -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 ru.betterend.item.ArmoredElytra; - -@Mixin(CapeLayer.class) -public class CapeLayerMixin { - - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - public void be_checkCustomElytra(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, AbstractClientPlayer abstractClientPlayer, float f, float g, float h, float j, float k, float l, CallbackInfo info) { - ItemStack itemStack = abstractClientPlayer.getItemBySlot(EquipmentSlot.CHEST); - if (itemStack.getItem() instanceof ArmoredElytra) { - info.cancel(); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/client/EndEffectsMixin.java b/src/main/java/ru/betterend/mixin/client/EndEffectsMixin.java deleted file mode 100644 index a215b8ec..00000000 --- a/src/main/java/ru/betterend/mixin/client/EndEffectsMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.renderer.DimensionSpecialEffects.EndEffects; -import net.minecraft.world.phys.Vec3; -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.CallbackInfoReturnable; -import ru.betterend.integration.Integrations; - -@Mixin(value = EndEffects.class, priority = 10) -public class EndEffectsMixin { - @Inject(method = "getBrightnessDependentFogColor", at = @At("HEAD"), cancellable = true) - private void be_restoreBrightness(Vec3 color, float sunHeight, CallbackInfoReturnable info) { - if (Integrations.ENDERSCAPE.modIsInstalled()) { - info.setReturnValue(color.scale(0.15000000596046448D)); - } - } - - @Inject(method = "isFoggyAt", at = @At("HEAD"), cancellable = true) - private void be_restoreFog(int camX, int camY, CallbackInfoReturnable info) { - if (Integrations.ENDERSCAPE.modIsInstalled()) { - info.setReturnValue(false); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java b/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java deleted file mode 100644 index 13232b92..00000000 --- a/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.HumanoidMobRenderer; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.world.entity.Mob; -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 ru.betterend.client.render.ArmoredElytraLayer; - -@Mixin(HumanoidMobRenderer.class) -public abstract class HumanoidMobRendererMixin> extends MobRenderer { - - public HumanoidMobRendererMixin(EntityRendererProvider.Context context, M entityModel, float f) { - super(context, entityModel, f); - } - - @Inject(method = "(Lnet/minecraft/client/renderer/entity/EntityRendererProvider$Context;Lnet/minecraft/client/model/HumanoidModel;FFFF)V", at = @At("TAIL")) - public void be_addCustomLayer(EntityRendererProvider.Context context, M humanoidModel, float f, float g, float h, float i, CallbackInfo ci) { - addLayer(new ArmoredElytraLayer<>(this, context.getModelSet())); - } -} diff --git a/src/main/java/ru/betterend/mixin/client/ItemStackMixin.java b/src/main/java/ru/betterend/mixin/client/ItemStackMixin.java deleted file mode 100644 index e9136846..00000000 --- a/src/main/java/ru/betterend/mixin/client/ItemStackMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -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.CallbackInfoReturnable; -import ru.betterend.events.ItemTooltipCallback; - -import java.util.List; - -@Mixin(ItemStack.class) -public class ItemStackMixin { - @Inject(method = "getTooltipLines", at = @At("RETURN")) - private void be_getTooltip(Player entity, TooltipFlag tooltipContext, CallbackInfoReturnable> info) { - ItemTooltipCallback.EVENT.invoker() - .getTooltip(entity, ItemStack.class.cast(this), tooltipContext, info.getReturnValue()); - } -} diff --git a/src/main/java/ru/betterend/mixin/client/LocalPlayerMixin.java b/src/main/java/ru/betterend/mixin/client/LocalPlayerMixin.java deleted file mode 100644 index 3ea9d1db..00000000 --- a/src/main/java/ru/betterend/mixin/client/LocalPlayerMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -package ru.betterend.mixin.client; - -import com.mojang.authlib.GameProfile; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.ProfilePublicKey; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.betterend.interfaces.FallFlyingItem; - -import org.jetbrains.annotations.Nullable; - -@Mixin(LocalPlayer.class) -public abstract class LocalPlayerMixin extends AbstractClientPlayer { - @Final - @Shadow - public ClientPacketListener connection; - - public LocalPlayerMixin(ClientLevel clientLevel, - GameProfile gameProfile, - @Nullable ProfilePublicKey profilePublicKey) { - super(clientLevel, gameProfile, profilePublicKey); - } - - @Inject(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getItemBySlot(Lnet/minecraft/world/entity/EquipmentSlot;)Lnet/minecraft/world/item/ItemStack;", shift = Shift.AFTER)) - public void be_aiStep(CallbackInfo info) { - ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); - if (itemStack.getItem() instanceof FallFlyingItem && ElytraItem.isFlyEnabled(itemStack) && tryToStartFallFlying()) { - connection.send(new ServerboundPlayerCommandPacket( - LocalPlayer.class.cast(this), - ServerboundPlayerCommandPacket.Action.START_FALL_FLYING - )); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/client/MinecraftClientMixin.java b/src/main/java/ru/betterend/mixin/client/MinecraftClientMixin.java deleted file mode 100644 index 5ad03872..00000000 --- a/src/main/java/ru/betterend/mixin/client/MinecraftClientMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.WinScreen; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.sounds.Music; -import net.minecraft.sounds.Musics; -import net.minecraft.world.level.Level; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.bclib.util.MHelper; - -@Mixin(Minecraft.class) -public class MinecraftClientMixin { - @Shadow - public LocalPlayer player; - - @Shadow - public Screen screen; - - @Final - @Shadow - public Gui gui; - - @Shadow - public ClientLevel level; - - @Inject(method = "getSituationalMusic", at = @At("HEAD"), cancellable = true) - private void be_getEndMusic(CallbackInfoReturnable info) { - if (!(this.screen instanceof WinScreen) && this.player != null) { - if (this.player.level.dimension() == Level.END) { - if (this.gui.getBossOverlay().shouldPlayMusic() && MHelper.lengthSqr( - this.player.getX(), - this.player.getZ() - ) < 250000) { - info.setReturnValue(Musics.END_BOSS); - } - else { - Music sound = this.level.getBiomeManager() - .getNoiseBiomeAtPosition(this.player.blockPosition()) - .value() - .getBackgroundMusic() - .orElse(Musics.END); - info.setReturnValue(sound); - } - info.cancel(); - } - } - } -} diff --git a/src/main/java/ru/betterend/mixin/client/ModelLoaderMixin.java b/src/main/java/ru/betterend/mixin/client/ModelLoaderMixin.java deleted file mode 100644 index 0c89dd50..00000000 --- a/src/main/java/ru/betterend/mixin/client/ModelLoaderMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import ru.betterend.BetterEnd; -import ru.betterend.world.generator.GeneratorOptions; - -@Mixin(ModelBakery.class) -public abstract class ModelLoaderMixin { - @ModifyVariable(method = "loadModel", ordinal = 2, at = @At(value = "INVOKE")) - public ResourceLocation be_switchModel(ResourceLocation id) { - if (GeneratorOptions.changeChorusPlant() && be_changeModel(id)) { - String path = id.getPath().replace("chorus", "custom_chorus"); - id = BetterEnd.makeID(path); - } - return id; - } - - private boolean be_changeModel(ResourceLocation id) { - return id.getNamespace().equals("minecraft") - && id.getPath().startsWith("blockstates/") - && id.getPath().contains("chorus") - && !id.getPath().contains("custom_"); - } -} diff --git a/src/main/java/ru/betterend/mixin/client/MusicTrackerMixin.java b/src/main/java/ru/betterend/mixin/client/MusicTrackerMixin.java deleted file mode 100644 index 3a0afd42..00000000 --- a/src/main/java/ru/betterend/mixin/client/MusicTrackerMixin.java +++ /dev/null @@ -1,106 +0,0 @@ -package ru.betterend.mixin.client; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.sounds.AbstractSoundInstance; -import net.minecraft.client.resources.sounds.SoundInstance; -import net.minecraft.client.sounds.MusicManager; -import net.minecraft.sounds.Music; -import net.minecraft.util.Mth; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.bclib.api.biomes.BiomeAPI; -import ru.betterend.client.ClientOptions; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(MusicManager.class) -public abstract class MusicTrackerMixin { - @Final - @Shadow - private Minecraft minecraft; - - @Final - @Shadow - private RandomSource random; - - @Shadow - private SoundInstance currentMusic; - - @Shadow - private int nextSongDelay; - - private static float volume = 1; - private static float srcVolume = 0; - private static long time; - - @Inject(method = "tick", at = @At("HEAD"), cancellable = true) - public void be_onTick(CallbackInfo info) { - if (ClientOptions.blendBiomeMusic()) { - Music musicSound = minecraft.getSituationalMusic(); - if (be_checkNullSound(musicSound) && volume > 0 && be_shouldChangeSound(musicSound) && be_isCorrectBiome()) { - if (volume > 0) { - if (srcVolume < 0) { - srcVolume = currentMusic.getVolume(); - } - if (currentMusic instanceof AbstractSoundInstance) { - ((AbstractSoundInstanceAccessor) currentMusic).setVolume(volume); - } - minecraft.getSoundManager() - .updateSourceVolume(currentMusic.getSource(), currentMusic.getVolume() * volume); - long t = System.currentTimeMillis(); - if (volume == 1 && time == 0) { - time = t; - } - float delta = (t - time) * 0.0005F; - time = t; - volume -= delta; - if (volume < 0) { - volume = 0; - } - } - if (volume == 0) { - volume = 1; - time = 0; - srcVolume = -1; - this.minecraft.getSoundManager().stop(this.currentMusic); - this.nextSongDelay = Mth.nextInt(this.random, 0, musicSound.getMinDelay() / 2); - this.currentMusic = null; - } - if (this.currentMusic == null && this.nextSongDelay-- <= 0) { - this.startPlaying(musicSound); - } - info.cancel(); - } - else { - volume = 1; - } - } - } - - private boolean be_isCorrectBiome() { - if (minecraft.level == null) { - return false; - } - return BiomeAPI.getRenderBiome(minecraft.level.getBiome(minecraft.player.blockPosition()).value()) instanceof EndBiome; - } - - private boolean be_shouldChangeSound(Music musicSound) { - return currentMusic != null && !musicSound - .getEvent() - .getLocation() - .equals(this.currentMusic.getLocation()) && musicSound.replaceCurrentMusic(); - } - - private boolean be_checkNullSound(Music musicSound) { - return musicSound != null && musicSound.getEvent() != null; - } - - @Shadow - public abstract void startPlaying(Music type); -} diff --git a/src/main/java/ru/betterend/mixin/common/BlockBehaviourMixin.java b/src/main/java/ru/betterend/mixin/common/BlockBehaviourMixin.java deleted file mode 100644 index 674b2f95..00000000 --- a/src/main/java/ru/betterend/mixin/common/BlockBehaviourMixin.java +++ /dev/null @@ -1,46 +0,0 @@ -package ru.betterend.mixin.common; - -import com.google.common.collect.Lists; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -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.CallbackInfoReturnable; -import ru.bclib.util.MHelper; -import ru.betterend.item.tool.EndHammerItem; - -import java.util.List; - -@Mixin(BlockBehaviour.class) -public abstract class BlockBehaviourMixin { - @Inject(method = "getDrops", at = @At("HEAD"), cancellable = true) - public void be_getDroppedStacks(BlockState state, LootContext.Builder builder, CallbackInfoReturnable> info) { - if (state.is(Blocks.GLOWSTONE)) { - ItemStack tool = builder.getParameter(LootContextParams.TOOL); - if (tool != null && tool.getItem() instanceof EndHammerItem) { - int min = 3; - int max = 4; - int count = 0; - int fortune = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool); - if (fortune > 0) { - fortune /= Enchantments.BLOCK_FORTUNE.getMaxLevel(); - min = Mth.clamp(min + fortune, min, max); - if (min == max) { - info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, max))); - } - } - count = MHelper.randRange(min, max, MHelper.RANDOM_SOURCE); - info.setReturnValue(Lists.newArrayList(new ItemStack(Items.GLOWSTONE_DUST, count))); - } - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/ChorusFlowerBlockMixin.java b/src/main/java/ru/betterend/mixin/common/ChorusFlowerBlockMixin.java deleted file mode 100644 index 99588e53..00000000 --- a/src/main/java/ru/betterend/mixin/common/ChorusFlowerBlockMixin.java +++ /dev/null @@ -1,90 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.ChorusFlowerBlock; -import net.minecraft.world.level.block.ChorusPlantBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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 ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.world.generator.GeneratorOptions; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(value = ChorusFlowerBlock.class, priority = 100) -public abstract class ChorusFlowerBlockMixin extends Block { - private static final VoxelShape SHAPE_FULL = Block.box(0, 0, 0, 16, 16, 16); - private static final VoxelShape SHAPE_HALF = Block.box(0, 0, 0, 16, 4, 16); - - public ChorusFlowerBlockMixin(Properties settings) { - super(settings); - } - - @Final - @Shadow - private ChorusPlantBlock plant; - - @Inject(method = "canSurvive", at = @At("HEAD"), cancellable = true) - private void be_canSurvive(BlockState state, LevelReader world, BlockPos pos, CallbackInfoReturnable info) { - if (world.getBlockState(pos.below()).is(EndBlocks.CHORUS_NYLIUM)) { - info.setReturnValue(true); - info.cancel(); - } - } - - @Inject(method = "randomTick", at = @At("HEAD"), cancellable = true) - private void be_randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random, CallbackInfo info) { - if (world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - BlockPos up = pos.above(); - if (world.isEmptyBlock(up) && up.getY() < 256) { - int i = state.getValue(ChorusFlowerBlock.AGE); - if (i < 5) { - this.placeGrownFlower(world, up, i + 1); - BlocksHelper.setWithoutUpdate(world, pos, plant.defaultBlockState().setValue(ChorusPlantBlock.UP, true).setValue(ChorusPlantBlock.DOWN, true)); - info.cancel(); - } - } - } - } - - @Shadow - private void placeGrownFlower(Level world, BlockPos pos, int age) {} - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { - if (GeneratorOptions.changeChorusPlant()) { - return state.getValue(ChorusFlowerBlock.AGE) == 5 ? SHAPE_HALF : SHAPE_FULL; - } - else { - return super.getShape(state, world, pos, context); - } - } - - @Inject(method = "placeDeadFlower", at = @At("HEAD"), cancellable = true) - private void be_placeDeadFlower(Level world, BlockPos pos, CallbackInfo info) { - BlockState down = world.getBlockState(pos.below()); - if (down.is(Blocks.CHORUS_PLANT) || down.is(CommonBlockTags.GEN_END_STONES)) { - world.setBlock(pos, this.defaultBlockState().setValue(BlockStateProperties.AGE_5, 5), 2); - world.levelEvent(1034, pos, 0); - } - info.cancel(); - } -} diff --git a/src/main/java/ru/betterend/mixin/common/ChorusPlantBlockMixin.java b/src/main/java/ru/betterend/mixin/common/ChorusPlantBlockMixin.java deleted file mode 100644 index 89251667..00000000 --- a/src/main/java/ru/betterend/mixin/common/ChorusPlantBlockMixin.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.ChorusPlantBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -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.CallbackInfoReturnable; -import ru.bclib.api.tag.CommonBlockTags; -import ru.betterend.registry.EndBlocks; - -@Mixin(value = ChorusPlantBlock.class, priority = 100) -public abstract class ChorusPlantBlockMixin extends Block { - public ChorusPlantBlockMixin(Properties settings) { - super(settings); - } - - @Inject(method = "getStateForPlacement(Lnet/minecraft/world/item/context/BlockPlaceContext;)Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), cancellable = true) - private void be_getStateForPlacement(BlockPlaceContext ctx, CallbackInfoReturnable info) { - BlockPos pos = ctx.getClickedPos(); - Level world = ctx.getLevel(); - BlockState plant = info.getReturnValue(); - if (ctx.canPlace() && plant.is(Blocks.CHORUS_PLANT) && world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - info.setReturnValue(plant.setValue(BlockStateProperties.DOWN, true)); - } - } - - @Inject(method = "Lnet/minecraft/world/level/block/ChorusPlantBlock;getStateForPlacement" + "(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)" + "Lnet/minecraft/world/level/block/state/BlockState;", at = @At("RETURN"), cancellable = true) - private void be_getStateForPlacement(BlockGetter blockGetter, BlockPos blockPos, CallbackInfoReturnable info) { - BlockState plant = info.getReturnValue(); - if (plant.is(Blocks.CHORUS_PLANT) && blockGetter.getBlockState(blockPos.below()).is(CommonBlockTags.END_STONES)) { - info.setReturnValue(plant.setValue(BlockStateProperties.DOWN, true)); - } - } - - @Inject(method = "canSurvive", at = @At("HEAD"), cancellable = true) - private void be_canSurvive(BlockState state, LevelReader world, BlockPos pos, CallbackInfoReturnable info) { - BlockState down = world.getBlockState(pos.below()); - if (down.is(EndBlocks.CHORUS_NYLIUM) || down.is(Blocks.END_STONE)) { - info.setReturnValue(true); - } - } - - @Inject(method = "updateShape", at = @At("RETURN"), cancellable = true) - private void be_updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor world, BlockPos pos, BlockPos posFrom, CallbackInfoReturnable info) { - BlockState plant = info.getReturnValue(); - if (plant.is(Blocks.CHORUS_PLANT) && world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - plant = plant.setValue(BlockStateProperties.DOWN, true); - info.setReturnValue(plant); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/ChorusPlantFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/ChorusPlantFeatureMixin.java deleted file mode 100644 index e6f2d7f4..00000000 --- a/src/main/java/ru/betterend/mixin/common/ChorusPlantFeatureMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.ChorusFlowerBlock; -import net.minecraft.world.level.block.PipeBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.ChorusPlantFeature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -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.CallbackInfoReturnable; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(ChorusPlantFeature.class) -public class ChorusPlantFeatureMixin { - @Inject(method = "place", at = @At("HEAD"), cancellable = true) - private void be_place(FeaturePlaceContext featureConfig, CallbackInfoReturnable info) { - final RandomSource random = featureConfig.random(); - final BlockPos blockPos = featureConfig.origin(); - final WorldGenLevel structureWorldAccess = featureConfig.level(); - if (structureWorldAccess.isEmptyBlock(blockPos) && structureWorldAccess.getBlockState(blockPos.below()).is(EndBlocks.CHORUS_NYLIUM)) { - ChorusFlowerBlock.generatePlant(structureWorldAccess, blockPos, random, MHelper.randRange(8, 16, random)); - BlockState bottom = structureWorldAccess.getBlockState(blockPos); - if (bottom.is(Blocks.CHORUS_PLANT)) { - BlocksHelper.setWithoutUpdate( - structureWorldAccess, - blockPos, - bottom.setValue(PipeBlock.DOWN, true) - ); - } - info.setReturnValue(true); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EnchantmentMenuMixin.java b/src/main/java/ru/betterend/mixin/common/EnchantmentMenuMixin.java deleted file mode 100644 index 631045d4..00000000 --- a/src/main/java/ru/betterend/mixin/common/EnchantmentMenuMixin.java +++ /dev/null @@ -1,145 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.Registry; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerLevelAccess; -import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.inventory.EnchantmentMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.EnchantmentInstance; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.bclib.api.tag.CommonBlockTags; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(EnchantmentMenu.class) -public abstract class EnchantmentMenuMixin extends AbstractContainerMenu { - @Final - @Shadow - private Container enchantSlots; - - @Final - @Shadow - private ContainerLevelAccess access; - - @Final - @Shadow - private RandomSource random; - - @Final - @Shadow - private DataSlot enchantmentSeed; - - @Shadow - @Final - public int[] costs; - - @Shadow - @Final - public int[] enchantClue; - - @Shadow - @Final - public int[] levelClue; - - protected EnchantmentMenuMixin(MenuType type, int syncId) { - super(type, syncId); - } - - @Inject(method = "slotsChanged", at = @At("HEAD"), cancellable = true) - private void be_slotsChanged(Container inventory, CallbackInfo info) { - if (inventory == this.enchantSlots) { - ItemStack itemStack = inventory.getItem(0); - if (!itemStack.isEmpty() && itemStack.isEnchantable()) { - this.access.execute((world, blockPos) -> { - int i = 0; - - int j; - for (j = -1; j <= 1; ++j) { - for (int k = -1; k <= 1; ++k) { - if ((j != 0 || k != 0) && world.isEmptyBlock(blockPos.offset( - k, - 0, - j - )) && world.isEmptyBlock(blockPos.offset(k, 1, j))) { - if (world.getBlockState(blockPos.offset(k * 2, 0, j * 2)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - - if (world.getBlockState(blockPos.offset(k * 2, 1, j * 2)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - - if (k != 0 && j != 0) { - if (world.getBlockState(blockPos.offset(k * 2, 0, j)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - - if (world.getBlockState(blockPos.offset(k * 2, 1, j)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - - if (world.getBlockState(blockPos.offset(k, 0, j * 2)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - - if (world.getBlockState(blockPos.offset(k, 1, j * 2)).is(CommonBlockTags.BOOKSHELVES)) { - ++i; - } - } - } - } - } - - random.setSeed(enchantmentSeed.get()); - - for (j = 0; j < 3; ++j) { - costs[j] = EnchantmentHelper.getEnchantmentCost(this.random, j, i, itemStack); - enchantClue[j] = -1; - levelClue[j] = -1; - if (costs[j] < j + 1) { - costs[j] = 0; - } - } - - for (j = 0; j < 3; ++j) { - if (this.costs[j] > 0) { - List list = this.getEnchantmentList(itemStack, j, this.costs[j]); - if (list != null && !list.isEmpty()) { - EnchantmentInstance enchantmentLevelEntry = (EnchantmentInstance) list.get(this.random.nextInt( - list.size())); - enchantClue[j] = Registry.ENCHANTMENT.getId(enchantmentLevelEntry.enchantment); - levelClue[j] = enchantmentLevelEntry.level; - } - } - } - - broadcastChanges(); - }); - } - else { - for (int i = 0; i < 3; ++i) { - costs[i] = 0; - enchantClue[i] = -1; - levelClue[i] = -1; - } - } - info.cancel(); - } - } - - @Shadow - private List getEnchantmentList(ItemStack stack, int slot, int level) { - return null; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EndCityFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/EndCityFeatureMixin.java deleted file mode 100644 index 6eed50af..00000000 --- a/src/main/java/ru/betterend/mixin/common/EndCityFeatureMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.WorldgenRandom; -import net.minecraft.world.level.levelgen.XoroshiroRandomSource; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.Structure; -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.structures.EndCityStructure; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.betterend.world.generator.GeneratorOptions; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(EndCityStructure.class) -public class EndCityFeatureMixin { - @Inject(method = "findGenerationPoint", at = @At("HEAD"), cancellable = true) - private void be_findGenerationPoint(Structure.GenerationContext context, - CallbackInfoReturnable> info) { - final ChunkPos pos = context.chunkPos(); - WorldgenRandom chunkRandom = new WorldgenRandom(new XoroshiroRandomSource(pos.x, pos.z)); - - if (GeneratorOptions.useNewGenerator()) { - int chance = GeneratorOptions.getEndCityFailChance(); - if (chance > 0 && chunkRandom.nextInt(chance) != 0) { - info.setReturnValue(Optional.empty()); - info.cancel(); - } - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java b/src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java deleted file mode 100644 index 84fbb60a..00000000 --- a/src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java +++ /dev/null @@ -1,98 +0,0 @@ -package ru.betterend.mixin.common; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.boss.enderdragon.EndCrystal; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.pattern.BlockPattern; -import net.minecraft.world.level.dimension.end.DragonRespawnAnimation; -import net.minecraft.world.level.dimension.end.EndDragonFight; -import net.minecraft.world.phys.AABB; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.bclib.util.BlocksHelper; -import ru.betterend.world.generator.GeneratorOptions; - -import java.util.List; - -@Mixin(EndDragonFight.class) -public class EndDragonFightMixin { - @Shadow - private DragonRespawnAnimation respawnStage; - @Shadow - private boolean dragonKilled; - @Shadow - private BlockPos portalLocation; - @Shadow @Final private static Logger LOGGER; - @Final - @Shadow - private ServerLevel level; - - @Shadow - private BlockPattern.BlockPatternMatch findExitPortal() { - return null; - } - - @Shadow - private void spawnExitPortal(boolean bl) { - } - - @Shadow - private void respawnDragon(List list) { - } - - @Inject(method = "tryRespawn", at = @At("HEAD"), cancellable = true) - private void be_tryRespawnDragon(CallbackInfo info) { - if (GeneratorOptions.replacePortal() && GeneratorOptions.hasDragonFights() && this.dragonKilled && this.respawnStage == null) { - BlockPos blockPos = portalLocation; - if (blockPos == null) { - LOGGER.debug("Tried to respawn, but need to find the portal first."); - BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); - if (blockPatternMatch == null) { - LOGGER.debug("Couldn't find a portal, so we made one."); - spawnExitPortal(true); - } - else { - LOGGER.debug("Found the exit portal & temporarily using it."); - } - } - - List crystals = Lists.newArrayList(); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos central = BlockPos.ZERO.relative(dir, 4); - List crystalList = level.getEntitiesOfClass( - EndCrystal.class, - new AABB(central.below(255).south().west(), central.above(255).north().east()) - ); - - int count = crystalList.size(); - for (int n = 0; n < count; n++) { - EndCrystal crystal = crystalList.get(n); - if (!level.getBlockState(crystal.blockPosition().below()).is(Blocks.BEDROCK)) { - crystalList.remove(n); - count--; - n--; - } - } - - if (crystalList.isEmpty()) { - info.cancel(); - return; - } - - crystals.addAll(crystalList); - } - - LOGGER.debug("Found all crystals, respawning dragon."); - respawnDragon(crystals); - info.cancel(); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EndPodiumFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/EndPodiumFeatureMixin.java deleted file mode 100644 index 8372b1b7..00000000 --- a/src/main/java/ru/betterend/mixin/common/EndPodiumFeatureMixin.java +++ /dev/null @@ -1,91 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.feature.EndPodiumFeature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.bclib.api.WorldDataAPI; -import ru.bclib.util.StructureHelper; -import ru.betterend.BetterEnd; -import ru.betterend.world.generator.GeneratorOptions; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(EndPodiumFeature.class) -public class EndPodiumFeatureMixin { - private static BlockPos be_portalPosition; - - @Final - @Shadow - private boolean active; - - @Inject(method = "place", at = @At("HEAD"), cancellable = true) - private void be_place(FeaturePlaceContext featurePlaceContext, CallbackInfoReturnable info) { - if (!GeneratorOptions.hasPortal()) { - info.setReturnValue(false); - info.cancel(); - } - else if (GeneratorOptions.replacePortal()) { - RandomSource random = featurePlaceContext.random(); - WorldGenLevel world = featurePlaceContext.level(); - BlockPos blockPos = be_updatePortalPos(world); - StructureTemplate structure = StructureHelper.readStructure(BetterEnd.makeID(active ? "portal/end_portal_active" : "portal/end_portal_inactive")); - Vec3i size = structure.getSize(); - blockPos = blockPos.offset(-(size.getX() >> 1), -3, -(size.getZ() >> 1)); - structure.placeInWorld(world, blockPos, blockPos, new StructurePlaceSettings(), random, 2); - info.setReturnValue(true); - info.cancel(); - } - } - - @ModifyVariable(method = "place", ordinal = 0, at = @At("HEAD")) - private FeaturePlaceContext be_setPosOnGround(FeaturePlaceContext featurePlaceContext) { - WorldGenLevel world = featurePlaceContext.level(); - BlockPos pos = be_updatePortalPos(world); - return new FeaturePlaceContext( - Optional.empty(), - world, - featurePlaceContext.chunkGenerator(), - featurePlaceContext.random(), - pos, - featurePlaceContext.config() - ); - } - - private BlockPos be_updatePortalPos(WorldGenLevel world) { - CompoundTag compound = WorldDataAPI.getRootTag(BetterEnd.MOD_ID).getCompound("portal"); - be_portalPosition = NbtUtils.readBlockPos(compound); - - if (be_portalPosition.getY() == 0) { - /*if (GeneratorOptions.useNewGenerator()) { - int y = TerrainGenerator.getHeight(0, 0, world.getLevel().getChunkSource().getGenerator().getBiomeSource()); - be_portalPosition = new BlockPos(0, y, 0); - } - else { - be_portalPosition = new BlockPos(0, 65, 0); - }*/ - int y = world.getHeight(Types.WORLD_SURFACE, 0, 0); - be_portalPosition = new BlockPos(0, y, 0); - WorldDataAPI.getRootTag(BetterEnd.MOD_ID).put("portal", NbtUtils.writeBlockPos(be_portalPosition)); - WorldDataAPI.saveFile(BetterEnd.MOD_ID); - } - - return be_portalPosition; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java b/src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java deleted file mode 100644 index fa21aa5e..00000000 --- a/src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.levelgen.feature.SpikeFeature.EndSpike; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.bclib.api.WorldDataAPI; -import ru.betterend.BetterEnd; -import ru.betterend.world.generator.GeneratorOptions; - -@Mixin(EndSpike.class) -public class EndSpikeMixin { - @Final - @Shadow - private int height; - - @Inject(method = "getHeight", at = @At("HEAD"), cancellable = true) - private void be_getSpikeHeight(CallbackInfoReturnable info) { - if (!GeneratorOptions.isDirectSpikeHeight()) { - int x = getCenterX(); - int z = getCenterZ(); - String pillarID = String.format("%d_%d", x, z); - CompoundTag pillar = WorldDataAPI.getCompoundTag(BetterEnd.MOD_ID, "pillars"); - int minY = pillar.contains(pillarID) ? pillar.getInt(pillarID) : 65; - int maxY = minY + height - 54; - info.setReturnValue(maxY); - } - } - - @Shadow - public int getCenterX() { - return 0; - } - - @Shadow - public int getCenterZ() { - return 0; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EnderManMixin.java b/src/main/java/ru/betterend/mixin/common/EnderManMixin.java deleted file mode 100644 index 0a874e4e..00000000 --- a/src/main/java/ru/betterend/mixin/common/EnderManMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.monster.EnderMan; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -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.CallbackInfoReturnable; -import ru.betterend.effects.EndStatusEffects; -import ru.betterend.registry.EndEnchantments; - -@Mixin(EnderMan.class) -public abstract class EnderManMixin { - @Inject(method = "isLookingAtMe", at = @At("HEAD"), cancellable = true) - private void be_isLookingAtMe(Player player, CallbackInfoReturnable info) { - if (player.isCreative() || player.hasEffect(EndStatusEffects.END_VEIL) || EnchantmentHelper.getItemEnchantmentLevel( - EndEnchantments.END_VEIL, - player.getItemBySlot(EquipmentSlot.HEAD) - ) > 0) { - info.setReturnValue(false); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/EntityMixin.java b/src/main/java/ru/betterend/mixin/common/EntityMixin.java deleted file mode 100644 index 31b3876f..00000000 --- a/src/main/java/ru/betterend/mixin/common/EntityMixin.java +++ /dev/null @@ -1,109 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.portal.PortalInfo; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.betterend.interfaces.TeleportingEntity; - -@Mixin(Entity.class) -public abstract class EntityMixin implements TeleportingEntity { - @Shadow - private float yRot; - @Shadow - private float xRot; - - @Shadow - public Level level; - - @Final - @Shadow - public abstract void unRide(); - - @Shadow - public abstract Vec3 getDeltaMovement(); - - @Shadow - public abstract EntityType getType(); - - @Shadow - protected abstract PortalInfo findDimensionEntryPoint(ServerLevel destination); - - @Shadow - protected abstract void removeAfterChangingDimensions(); - - @Shadow - public abstract boolean isRemoved(); - - private BlockPos exitPos; - - @Inject(method = "changeDimension", at = @At("HEAD"), cancellable = true) - public void be_changeDimension(ServerLevel destination, CallbackInfoReturnable info) { - if (!isRemoved() && be_canTeleport() && level instanceof ServerLevel) { - unRide(); - level.getProfiler().push("changeDimension"); - level.getProfiler().push("reposition"); - PortalInfo teleportTarget = findDimensionEntryPoint(destination); - if (teleportTarget != null) { - level.getProfiler().popPush("reloading"); - Entity entity = getType().create(destination); - if (entity != null) { - entity.restoreFrom(Entity.class.cast(this)); - entity.moveTo( - teleportTarget.pos.x, - teleportTarget.pos.y, - teleportTarget.pos.z, - teleportTarget.yRot, - entity.getXRot() - ); - entity.setDeltaMovement(teleportTarget.speed); - destination.addDuringTeleport(entity); - } - - this.removeAfterChangingDimensions(); - level.getProfiler().pop(); - ((ServerLevel) level).resetEmptyTime(); - destination.resetEmptyTime(); - level.getProfiler().pop(); - be_resetExitPos(); - info.setReturnValue(entity); - } - } - } - - @Inject(method = "findDimensionEntryPoint", at = @At("HEAD"), cancellable = true) - protected void be_findDimensionEntryPoint(ServerLevel destination, CallbackInfoReturnable info) { - if (be_canTeleport()) { - info.setReturnValue(new PortalInfo( - new Vec3(exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5), - getDeltaMovement(), - yRot, - xRot - )); - } - } - - @Override - public void be_setExitPos(BlockPos pos) { - this.exitPos = pos.immutable(); - } - - @Override - public void be_resetExitPos() { - this.exitPos = null; - } - - @Override - public boolean be_canTeleport() { - return this.exitPos != null; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/LivingEntityMixin.java b/src/main/java/ru/betterend/mixin/common/LivingEntityMixin.java deleted file mode 100644 index 44d83418..00000000 --- a/src/main/java/ru/betterend/mixin/common/LivingEntityMixin.java +++ /dev/null @@ -1,290 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.sounds.SoundEvent; -import net.minecraft.tags.EntityTypeTags; -import net.minecraft.util.Mth; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MoverType; -import net.minecraft.world.entity.ai.attributes.AttributeMap; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.animal.FlyingAnimal; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.betterend.BetterEnd; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.interfaces.MobEffectApplier; -import ru.betterend.item.CrystaliteArmor; -import ru.betterend.registry.EndAttributes; - -import java.util.Collection; - -@Mixin(value=LivingEntity.class, priority=200) -public abstract class LivingEntityMixin extends Entity { - - public LivingEntityMixin(EntityType entityType, Level level) { - super(entityType, level); - } - - @Shadow - protected int fallFlyTicks; - - @Shadow - public abstract boolean hasEffect(MobEffect mobEffect); - - @Shadow - public abstract ItemStack getItemBySlot(EquipmentSlot equipmentSlot); - - @Shadow - public abstract void calculateEntityAnimation(LivingEntity livingEntity, boolean b); - - @Shadow - protected abstract SoundEvent getFallDamageSound(int i); - - @Shadow - public abstract boolean isFallFlying(); - - @Shadow - public abstract AttributeMap getAttributes(); - - private Entity lastAttacker; - - @Inject(method = "createLivingAttributes", at = @At("RETURN"), cancellable = true) - private static void be_addLivingAttributes(CallbackInfoReturnable info) { - EndAttributes.addLivingEntityAttributes(info.getReturnValue()); - } - - @Inject(method = "tickEffects", at = @At("HEAD")) - protected void be_applyEffects(CallbackInfo info) { - if (!level.isClientSide()) { - LivingEntity owner = LivingEntity.class.cast(this); - if (CrystaliteArmor.hasFullSet(owner)) { - CrystaliteArmor.applySetEffect(owner); - } - getArmorSlots().forEach(itemStack -> { - if (itemStack.getItem() instanceof MobEffectApplier) { - ((MobEffectApplier) itemStack.getItem()).applyEffect(owner); - } - }); - } - } - - @Inject(method = "canBeAffected", at = @At("HEAD"), cancellable = true) - public void be_canBeAffected(MobEffectInstance mobEffectInstance, CallbackInfoReturnable info) { - try { - if (mobEffectInstance.getEffect() == MobEffects.BLINDNESS && getAttributes().getValue(EndAttributes.BLINDNESS_RESISTANCE) > 0.0) { - info.setReturnValue(false); - } - } - catch (Exception ex) { - BetterEnd.LOGGER.warning("Blindness resistance attribute haven't been registered."); - } - } - - @Inject(method = "hurt", at = @At("HEAD")) - public void be_hurt(DamageSource source, float amount, CallbackInfoReturnable info) { - this.lastAttacker = source.getEntity(); - } - - @ModifyArg(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), index = 0) - private double be_increaseKnockback(double value, double x, double z) { - if (lastAttacker != null && lastAttacker instanceof LivingEntity) { - LivingEntity attacker = (LivingEntity) lastAttacker; - value += this.be_getKnockback(attacker.getMainHandItem().getItem()); - } - return value; - } - - // FlyFallingLib (part of Origin) redirected the call to updateFallFlying, - // so we inject our code before the actual call and cancel the execution if the player is still - // flying. That means we have to replicate all vanilla code that happens after the call to - // updateFallFlying. We do this in vanillaAfterUpdateFallFlying - @Inject(method="aiStep", cancellable = true, at=@At(value="INVOKE", target="Lnet/minecraft/world/entity/LivingEntity;updateFallFlying()V")) - private void be_updateFallFlying_originFix(CallbackInfo info) { - //run be_updateFallFlying instead - if (!BetterEnd.RUNS_FALL_FLYING_LIB) return; - - if (be_updateFallFlyingCommon()) { - vanillaAfterUpdateFallFlying(); - info.cancel(); - } - } - - @Inject(method = "updateFallFlying", at = @At("HEAD"), cancellable = true) - private void be_updateFallFlying(CallbackInfo info) { - //run be_updateFallFlying_originFix instead? - if (BetterEnd.RUNS_FALL_FLYING_LIB) return; - if (be_updateFallFlyingCommon()) { - info.cancel(); - } - } - - private boolean be_updateFallFlyingCommon() { - ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); - if (!level.isClientSide && itemStack.getItem() instanceof FallFlyingItem) { - boolean isFlying = getSharedFlag(7); - if (isFlying && !onGround && !isPassenger() && !hasEffect(MobEffects.LEVITATION)) { - if (ElytraItem.isFlyEnabled(itemStack)) { - int level = 20 + EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, itemStack) * 5; - if ((fallFlyTicks + 1) % level == 0) { - itemStack.hurtAndBreak( - 1, - LivingEntity.class.cast(this), - livingEntity -> livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST) - ); - } - isFlying = true; - } - else { - isFlying = false; - } - } - else { - isFlying = false; - } - setSharedFlag(7, isFlying); - return isFlying; - } - return false; - } - - @Shadow protected abstract void removeFrost(); - @Shadow protected abstract void tryAddFrost(); - @Shadow protected abstract void pushEntities(); - @Shadow protected abstract void checkAutoSpinAttack(AABB aABB, AABB aABB2); - @Shadow protected int autoSpinAttackTicks; - - private void vanillaAfterUpdateFallFlying(){ - LivingEntity self = (LivingEntity)(Object)this; - AABB aABB = this.getBoundingBox(); - self.travel(new Vec3(self.xxa, self.yya, self.zza)); - this.level.getProfiler().pop(); - this.level.getProfiler().push("freezing"); - boolean bl2 = this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES); - int o; - if (!this.level.isClientSide && !self.isDeadOrDying()) { - o = this.getTicksFrozen(); - if (this.isInPowderSnow && this.canFreeze()) { - this.setTicksFrozen(Math.min(this.getTicksRequiredToFreeze(), o + 1)); - } else { - this.setTicksFrozen(Math.max(0, o - 2)); - } - } - - this.removeFrost(); - this.tryAddFrost(); - if (!this.level.isClientSide && this.tickCount % 40 == 0 && this.isFullyFrozen() && this.canFreeze()) { - o = bl2 ? 5 : 1; - this.hurt(DamageSource.FREEZE, (float)o); - } - - this.level.getProfiler().pop(); - this.level.getProfiler().push("push"); - if (this.autoSpinAttackTicks > 0) { - --this.autoSpinAttackTicks; - this.checkAutoSpinAttack(aABB, this.getBoundingBox()); - } - - this.pushEntities(); - this.level.getProfiler().pop(); - if (!this.level.isClientSide && self.isSensitiveToWater() && this.isInWaterRainOrBubble()) { - this.hurt(DamageSource.DROWN, 1.0F); - } - } - - - - @Inject(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isFallFlying()Z", shift = Shift.AFTER), cancellable = true) - public void be_travel(Vec3 vec3, CallbackInfo info) { - ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); - if (isFallFlying() && itemStack.getItem() instanceof FallFlyingItem) { - Vec3 moveDelta = getDeltaMovement(); - if (moveDelta.y > -0.5D) { - fallDistance = 1.0F; - } - - Vec3 lookAngle = getLookAngle(); - double d = 0.08D; - float rotX = getXRot() * 0.017453292F; - double k = Math.sqrt(lookAngle.x * lookAngle.x + lookAngle.z * lookAngle.z); - double l = moveDelta.horizontalDistance(); - double lookLen = lookAngle.length(); - float n = Mth.cos(rotX); - n = (float) (n * n * Math.min(1.0D, lookLen / 0.4D)); - moveDelta = getDeltaMovement().add(0.0D, d * (-1.0D + (double) n * 0.75D), 0.0D); - double coef; - if (moveDelta.y < 0.0D && k > 0.0D) { - coef = moveDelta.y * -0.1D * (double) n; - moveDelta = moveDelta.add(lookAngle.x * coef / k, coef, lookAngle.z * coef / k); - } - - if (rotX < 0.0F && k > 0.0D) { - coef = l * (double) (-Mth.sin(rotX)) * 0.04D; - moveDelta = moveDelta.add(-lookAngle.x * coef / k, coef * 3.2D, -lookAngle.z * coef / k); - } - - if (k > 0.0D) { - moveDelta = moveDelta.add( - (lookAngle.x / k * l - moveDelta.x) * 0.1D, - 0.0D, - (lookAngle.z / k * l - moveDelta.z) * 0.1D - ); - } - moveDelta = moveDelta.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D); - double movementFactor = ((FallFlyingItem) itemStack.getItem()).getMovementFactor(); - moveDelta = moveDelta.multiply(movementFactor, 1.0D, movementFactor); - setDeltaMovement(moveDelta); - move(MoverType.SELF, moveDelta); - if (!level.isClientSide) { - if (horizontalCollision) { - coef = moveDelta.horizontalDistance(); - double r = l - coef; - float dmg = (float) (r * 10.0D - 3.0D); - if (dmg > 0.0F) { - playSound(getFallDamageSound((int) dmg), 1.0F, 1.0F); - hurt(DamageSource.FLY_INTO_WALL, dmg); - } - } - if (onGround) { - setSharedFlag(7, false); - } - } - - calculateEntityAnimation(LivingEntity.class.cast(this), this instanceof FlyingAnimal); - info.cancel(); - } - } - - private double be_getKnockback(Item tool) { - if (tool == null) return 0.0D; - Collection modifiers = tool.getDefaultAttributeModifiers(EquipmentSlot.MAINHAND) - .get(Attributes.ATTACK_KNOCKBACK); - if (modifiers.size() > 0) { - return modifiers.iterator().next().getAmount(); - } - return 0.0D; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/MonsterMixin.java b/src/main/java/ru/betterend/mixin/common/MonsterMixin.java deleted file mode 100644 index c3e9cdcc..00000000 --- a/src/main/java/ru/betterend/mixin/common/MonsterMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.monster.EnderMan; -import net.minecraft.world.entity.monster.Monster; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.phys.AABB; -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.CallbackInfoReturnable; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(Monster.class) -public class MonsterMixin { - @Inject(method = "checkMonsterSpawnRules", at = @At(value = "RETURN"), cancellable = true) - private static void be_checkMonsterSpawnRules(EntityType type, ServerLevelAccessor serverWorldAccess, MobSpawnType spawnReason, BlockPos pos, RandomSource random, CallbackInfoReturnable info) { - boolean canSpawn = info.getReturnValue(); - if (canSpawn && spawnReason == MobSpawnType.NATURAL && type == EntityType.ENDERMAN) { - AABB box = new AABB(pos).inflate(16); - List entities = serverWorldAccess.getEntitiesOfClass(EnderMan.class, box, (entity) -> { - return true; - }); - info.setReturnValue(entities.size() < 6); - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/NoiseChunkAccessor.java b/src/main/java/ru/betterend/mixin/common/NoiseChunkAccessor.java deleted file mode 100644 index 718caa54..00000000 --- a/src/main/java/ru/betterend/mixin/common/NoiseChunkAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.level.levelgen.NoiseChunk; -import net.minecraft.world.level.levelgen.NoiseSettings; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(NoiseChunk.class) -public interface NoiseChunkAccessor { - @Accessor("noiseSettings") - NoiseSettings bnv_getNoiseSettings(); - - @Accessor("cellCountXZ") - int bnv_getCellCountXZ(); - - @Accessor("cellCountY") - int bnv_getCellCountY(); - - @Accessor("firstCellZ") - int bnv_getFirstCellZ(); - - @Accessor("cellNoiseMinY") - int bnv_getCellNoiseMinY(); -} diff --git a/src/main/java/ru/betterend/mixin/common/NoiseChunkMixin.java b/src/main/java/ru/betterend/mixin/common/NoiseChunkMixin.java deleted file mode 100644 index acc1a4dd..00000000 --- a/src/main/java/ru/betterend/mixin/common/NoiseChunkMixin.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.level.levelgen.*; -import net.minecraft.world.level.levelgen.blending.Blender; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import ru.bclib.BCLib; -import ru.betterend.interfaces.BETargetChecker; -import ru.betterend.world.generator.TerrainGenerator; - -import java.util.List; - -@Mixin(NoiseChunk.class) -public class NoiseChunkMixin implements BETargetChecker { - private boolean be_isEndGenerator; - - @Inject(method = "*", at = @At("TAIL")) - private void be_onNoiseChunkInit(int i, - RandomState randomState, - int j, - int k, - NoiseSettings noiseSettings, - DensityFunctions.BeardifierOrMarker beardifierOrMarker, - NoiseGeneratorSettings noiseGeneratorSettings, - Aquifer.FluidPicker fluidPicker, - Blender blender, - CallbackInfo ci) { - var o = BETargetChecker.class.cast(noiseGeneratorSettings); - if (o!= null) be_isEndGenerator = o.be_isTarget(); - else BCLib.LOGGER.warning(noiseGeneratorSettings + " has unknown implementation."); - } - - @Override - public boolean be_isTarget() { - return be_isEndGenerator; - } - - @Override - public void be_setTarget(boolean target) { - be_isEndGenerator = target; - } - - @Shadow @Final private List interpolators; - - @Inject(method = "fillSlice", at = @At("HEAD"), cancellable = true) - private void be_fillSlice(boolean primarySlice, int x, CallbackInfo info) { - if (!be_isTarget()) return; - - info.cancel(); - - NoiseChunkAccessor accessor = NoiseChunkAccessor.class.cast(this); - NoiseSettings noiseSettings = accessor.bnv_getNoiseSettings(); - - final int sizeY = noiseSettings.getCellHeight(); - final int sizeXZ = noiseSettings.getCellWidth(); - final int cellSizeXZ = accessor.bnv_getCellCountXZ() + 1; - final int firstCellZ = accessor.bnv_getFirstCellZ(); - - x *= sizeXZ; - for (int cellXZ = 0; cellXZ < cellSizeXZ; ++cellXZ) { - int z = (firstCellZ + cellXZ) * sizeXZ; - for (NoiseChunk.NoiseInterpolator noiseInterpolator : this.interpolators) { - if (noiseInterpolator instanceof NoiseInterpolatorAccessor interpolator) { - final double[] ds = (primarySlice - ? interpolator.be_getSlice0() - : interpolator.be_getSlice1())[cellXZ]; - TerrainGenerator.fillTerrainDensity(ds, x, z, sizeXZ, sizeY); - } - } - } - } -} diff --git a/src/main/java/ru/betterend/mixin/common/NoiseGeneratorSettingsMixin.java b/src/main/java/ru/betterend/mixin/common/NoiseGeneratorSettingsMixin.java deleted file mode 100644 index 8f3eca58..00000000 --- a/src/main/java/ru/betterend/mixin/common/NoiseGeneratorSettingsMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import org.spongepowered.asm.mixin.Mixin; -import ru.betterend.interfaces.BETargetChecker; - -@Mixin(NoiseGeneratorSettings.class) -public class NoiseGeneratorSettingsMixin implements BETargetChecker { - private boolean be_isTargetGenerator; - - @Override - public boolean be_isTarget() { - return be_isTargetGenerator; - } - - @Override - public void be_setTarget(boolean target) { - be_isTargetGenerator = target; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/PlayerAdvancementsMixin.java b/src/main/java/ru/betterend/mixin/common/PlayerAdvancementsMixin.java deleted file mode 100644 index 06260c1d..00000000 --- a/src/main/java/ru/betterend/mixin/common/PlayerAdvancementsMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.advancements.Advancement; -import net.minecraft.server.PlayerAdvancements; -import net.minecraft.server.level.ServerPlayer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.betterend.events.PlayerAdvancementsCallback; - -@Mixin(PlayerAdvancements.class) -public abstract class PlayerAdvancementsMixin { - @Shadow - private ServerPlayer player; - - @Inject(method = "award", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/AdvancementRewards;grant(Lnet/minecraft/server/level/ServerPlayer;)V", shift = Shift.AFTER)) - public void be_award(Advancement advancement, String criterionName, CallbackInfoReturnable info) { - PlayerAdvancementsCallback.PLAYER_ADVANCEMENT_COMPLETE.invoker() - .onAdvancementComplete(player, - advancement, - criterionName - ); - } -} diff --git a/src/main/java/ru/betterend/mixin/common/PlayerMixin.java b/src/main/java/ru/betterend/mixin/common/PlayerMixin.java deleted file mode 100644 index f86d1ded..00000000 --- a/src/main/java/ru/betterend/mixin/common/PlayerMixin.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -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.CallbackInfoReturnable; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.interfaces.FallFlyingItem; -import ru.betterend.registry.EndBlocks; - -import java.util.Optional; - -@Mixin(value=Player.class, priority=200) -public abstract class PlayerMixin extends LivingEntity { - protected PlayerMixin(EntityType entityType, Level level) { - super(entityType, level); - } - - private static Direction[] horizontal; - - @Inject(method = "findRespawnPositionAndUseSpawnBlock", at = @At(value = "HEAD"), cancellable = true) - private static void be_findRespawnPositionAndUseSpawnBlock(ServerLevel world, BlockPos pos, float f, boolean bl, boolean bl2, CallbackInfoReturnable> info) { - BlockState blockState = world.getBlockState(pos); - if (blockState.is(EndBlocks.RESPAWN_OBELISK)) { - info.setReturnValue(be_obeliskRespawnPosition(world, pos, blockState)); - info.cancel(); - } - } - - @Inject(method = "tryToStartFallFlying", at = @At("HEAD"), cancellable = true) - public void be_tryToStartFlying(CallbackInfoReturnable info) { - if (!onGround && !isFallFlying() && !isInWater() && !hasEffect(MobEffects.LEVITATION)) { - ItemStack itemStack = getItemBySlot(EquipmentSlot.CHEST); - if (itemStack.getItem() instanceof FallFlyingItem && ElytraItem.isFlyEnabled(itemStack)) { - setSharedFlag(7, true); - info.setReturnValue(true); - System.out.println("Started"); - info.cancel(); - } - } - } - - private static Optional be_obeliskRespawnPosition(ServerLevel world, BlockPos pos, BlockState state) { - if (state.getValue(BlockProperties.TRIPLE_SHAPE) == TripleShape.TOP) { - pos = pos.below(2); - } - else if (state.getValue(BlockProperties.TRIPLE_SHAPE) == TripleShape.MIDDLE) { - pos = pos.below(); - } - if (horizontal == null) { - horizontal = BlocksHelper.makeHorizontal(); - } - MHelper.shuffle(horizontal, world.getRandom()); - for (Direction dir : horizontal) { - BlockPos p = pos.relative(dir); - BlockState state2 = world.getBlockState(p); - if (!state2.getMaterial().blocksMotion() && state2.getCollisionShape(world, pos).isEmpty()) { - return Optional.of(Vec3.atLowerCornerOf(p).add(0.5, 0, 0.5)); - } - } - return Optional.empty(); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java b/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java deleted file mode 100644 index d2732fb3..00000000 --- a/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java +++ /dev/null @@ -1,123 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraft.world.level.storage.LevelStorageSource; -import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; -import net.minecraft.world.level.storage.ServerLevelData; -import net.minecraft.world.level.storage.WritableLevelData; -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.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import ru.bclib.BCLib; -import ru.bclib.api.biomes.BiomeAPI; -import ru.betterend.BetterEnd; -import ru.betterend.interfaces.BETargetChecker; -import ru.betterend.registry.EndBlocks; -import ru.betterend.world.generator.GeneratorOptions; -import ru.betterend.world.generator.TerrainGenerator; - -import java.util.List; -import java.util.concurrent.Executor; -import java.util.function.Supplier; - -@Mixin(ServerLevel.class) -public abstract class ServerLevelMixin extends Level { - protected ServerLevelMixin(WritableLevelData writableLevelData, - ResourceKey resourceKey, - Holder holder, - Supplier supplier, - boolean bl, - boolean bl2, - long l, - int i) { - super(writableLevelData, resourceKey, holder, supplier, bl, bl2, l, i); - } - - private final static List> BE_TEST_DIMENSIONS = List.of(BuiltinDimensionTypes.OVERWORLD, BuiltinDimensionTypes.OVERWORLD_CAVES, BuiltinDimensionTypes.NETHER); - @ModifyArg(method = "", at = @At(value = "INVOKE", target="Lnet/minecraft/core/Holder;is(Lnet/minecraft/resources/ResourceKey;)Z")) - ResourceKey be_dragonFight(ResourceKey resourceKey){ - if (!GeneratorOptions.hasDragonFights()) { - //this object would pass the test for the End-Dimension, so make sure we compare against something else to disabled the Dragon-Fight - if (this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) return BuiltinDimensionTypes.OVERWORLD; - } - return resourceKey; - } - - @Inject(method = "*", at = @At("TAIL")) - private void be_onServerWorldInit(MinecraftServer minecraftServer, - Executor executor, - LevelStorageAccess levelStorageAccess, - ServerLevelData serverLevelData, - ResourceKey resourceKey, - LevelStem levelStem, - ChunkProgressListener chunkProgressListener, - boolean bl, - long seed, - List list, - boolean bl2, - CallbackInfo ci) { - ServerLevel level = ServerLevel.class.cast(this); - if (level.dimension() == Level.END) { - final ChunkGenerator chunkGenerator = levelStem.generator(); - if (chunkGenerator instanceof NoiseBasedChunkGenerator) { - Holder sHolder = NoiseBasedChunkGeneratorAccessor.class.cast(chunkGenerator).be_getSettings(); - BETargetChecker.class.cast(sHolder.value()).be_setTarget(true); - - } - TerrainGenerator.initNoise(seed, chunkGenerator.getBiomeSource(), level.getChunkSource().randomState().sampler()); - } - } - - - @Inject(method = "makeObsidianPlatform", at = @At("HEAD"), cancellable = true) - private static void be_createObsidianPlatform(ServerLevel serverLevel, CallbackInfo info) { - if (!GeneratorOptions.generateObsidianPlatform()) { - info.cancel(); - } - else if (GeneratorOptions.changeSpawn()) { - BlockPos blockPos = GeneratorOptions.getSpawn(); - int i = blockPos.getX(); - int j = blockPos.getY() - 2; - int k = blockPos.getZ(); - BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockPosx) -> { - serverLevel.setBlockAndUpdate(blockPosx, Blocks.AIR.defaultBlockState()); - }); - BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockPosx) -> { - serverLevel.setBlockAndUpdate(blockPosx, Blocks.OBSIDIAN.defaultBlockState()); - }); - info.cancel(); - } - } - - @ModifyArg(method = "tickChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) - private BlockState be_modifyTickState(BlockPos pos, BlockState state) { - if (state.is(Blocks.ICE)) { - ResourceLocation biome = BiomeAPI.getBiomeID(getBiome(pos)); - if (biome.getNamespace().equals(BetterEnd.MOD_ID)) { - state = EndBlocks.EMERALD_ICE.defaultBlockState(); - } - } - return state; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/ServerPlayerMixin.java b/src/main/java/ru/betterend/mixin/common/ServerPlayerMixin.java deleted file mode 100644 index bda4175c..00000000 --- a/src/main/java/ru/betterend/mixin/common/ServerPlayerMixin.java +++ /dev/null @@ -1,186 +0,0 @@ -package ru.betterend.mixin.common; - -import com.mojang.authlib.GameProfile; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; -import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; -import net.minecraft.network.protocol.game.ClientboundRespawnPacket; -import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.ServerPlayerGameMode; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.player.ProfilePublicKey; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.BiomeManager; -import net.minecraft.world.level.portal.PortalInfo; -import net.minecraft.world.level.storage.LevelData; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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 ru.betterend.interfaces.TeleportingEntity; -import ru.betterend.world.generator.GeneratorOptions; - -import org.jetbrains.annotations.Nullable; - -@Mixin(ServerPlayer.class) -public abstract class ServerPlayerMixin extends Player implements TeleportingEntity { - @Shadow - public ServerGamePacketListenerImpl connection; - @Final - @Shadow - public ServerPlayerGameMode gameMode; - @Final - @Shadow - public MinecraftServer server; - @Shadow - private boolean isChangingDimension; - @Shadow - private float lastSentHealth; - @Shadow - private int lastSentFood; - @Shadow - private int lastSentExp; - - private BlockPos exitPos; - private int be_teleportDelay = 0; - - public ServerPlayerMixin(Level level, - BlockPos blockPos, - float f, - GameProfile gameProfile, - @Nullable ProfilePublicKey profilePublicKey) { - super(level, blockPos, f, gameProfile, profilePublicKey); - } - - - @Inject(method = "createEndPlatform", at = @At("HEAD"), cancellable = true) - private void be_createEndSpawnPlatform(ServerLevel world, BlockPos centerPos, CallbackInfo info) { - if (!GeneratorOptions.generateObsidianPlatform()) { - info.cancel(); - } - } - - @Inject(method = "findDimensionEntryPoint", at = @At("HEAD"), cancellable = true) - protected void be_getTeleportTarget(ServerLevel destination, CallbackInfoReturnable info) { - if (be_canTeleport()) { - info.setReturnValue(new PortalInfo( - new Vec3(exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5), - getDeltaMovement(), - getYRot(), - getXRot() - )); - } - else if (GeneratorOptions.changeSpawn() && destination.dimension() == Level.END) { - BlockPos spawn = GeneratorOptions.getSpawn(); - Vec3 pos = new Vec3(spawn.getX() + 0.5, spawn.getY(), spawn.getZ() + 0.5); - info.setReturnValue(new PortalInfo(pos, Vec3.ZERO, 90.0F, 0.0F)); - } - } - - @Inject(method = "changeDimension", at = @At("HEAD"), cancellable = true) - public void be_changeDimension(ServerLevel destination, CallbackInfoReturnable info) { - if (be_canTeleport() && level instanceof ServerLevel) { - isChangingDimension = true; - ServerLevel serverWorld = getLevel(); - LevelData worldProperties = destination.getLevelData(); - ServerPlayer player = ServerPlayer.class.cast(this); - connection.send(new ClientboundRespawnPacket( - new Holder.Direct(destination.dimensionType()), - destination.dimension(), - BiomeManager.obfuscateSeed(destination.getSeed()), - gameMode.getGameModeForPlayer(), - gameMode.getPreviousGameModeForPlayer(), - destination.isDebug(), - destination.isFlat(), - true - )); - connection.send(new ClientboundChangeDifficultyPacket( - worldProperties.getDifficulty(), - worldProperties.isDifficultyLocked() - )); - PlayerList playerManager = server.getPlayerList(); - playerManager.sendPlayerPermissionLevel(player); - serverWorld.removePlayerImmediately(player, RemovalReason.CHANGED_DIMENSION); - unsetRemoved(); - PortalInfo teleportTarget = findDimensionEntryPoint(destination); - if (teleportTarget != null) { - serverWorld.getProfiler().push("moving"); - serverWorld.getProfiler().pop(); - serverWorld.getProfiler().push("placing"); - this.level = destination; - destination.addDuringPortalTeleport(player); - setRot(teleportTarget.yRot, teleportTarget.xRot); - moveTo(teleportTarget.pos.x, teleportTarget.pos.y, teleportTarget.pos.z); - serverWorld.getProfiler().pop(); - triggerDimensionChangeTriggers(serverWorld); - gameMode.setLevel(destination); - connection.send(new ClientboundPlayerAbilitiesPacket(getAbilities())); - playerManager.sendLevelInfo(player, destination); - playerManager.sendAllPlayerInfo(player); - - for (MobEffectInstance statusEffectInstance : getActiveEffects()) { - connection.send(new ClientboundUpdateMobEffectPacket(getId(), statusEffectInstance)); - } - - connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); - lastSentExp = -1; - lastSentHealth = -1.0F; - lastSentFood = -1; - } - be_teleportDelay = 100; - be_resetExitPos(); - info.setReturnValue(player); - } - } - - @Inject(method = "tick", at = @At("TAIL")) - public void be_decreaseCooldawn(CallbackInfo info) { - if (be_teleportDelay > 0) be_teleportDelay--; - } - - @Override - public int getDimensionChangingDelay() { - if (be_teleportDelay > 0) { - return be_teleportDelay; - } - return super.getDimensionChangingDelay(); - } - - @Shadow - public abstract ServerLevel getLevel(); - - @Shadow - abstract void triggerDimensionChangeTriggers(ServerLevel origin); - - @Shadow - @Override - protected abstract PortalInfo findDimensionEntryPoint(ServerLevel destination); - - @Override - public void be_setExitPos(BlockPos pos) { - this.exitPos = pos.immutable(); - } - - @Override - public void be_resetExitPos() { - this.exitPos = null; - } - - @Override - public boolean be_canTeleport() { - return this.exitPos != null; - } -} diff --git a/src/main/java/ru/betterend/mixin/common/SlimeMixin.java b/src/main/java/ru/betterend/mixin/common/SlimeMixin.java deleted file mode 100644 index ab9b072c..00000000 --- a/src/main/java/ru/betterend/mixin/common/SlimeMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.monster.Slime; -import net.minecraft.world.level.Level; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import ru.betterend.interfaces.ISlime; - -@Mixin(Slime.class) -public abstract class SlimeMixin extends Entity implements ISlime { - public SlimeMixin(EntityType entityType, Level level) { - super(entityType, level); - } - - @Shadow - public void setSize(int size, boolean heal) { - } - - @Override - public void be_setSlimeSize(int size, boolean heal) { - setSize(size, heal); - } - - @Override - public void entityRemove(Entity.RemovalReason removalReason) { - super.remove(removalReason); - } -} diff --git a/src/main/java/ru/betterend/mixin/common/SpikeFeatureMixin.java b/src/main/java/ru/betterend/mixin/common/SpikeFeatureMixin.java deleted file mode 100644 index a0a73b12..00000000 --- a/src/main/java/ru/betterend/mixin/common/SpikeFeatureMixin.java +++ /dev/null @@ -1,178 +0,0 @@ -package ru.betterend.mixin.common; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.boss.enderdragon.EndCrystal; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.IronBarsBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.SpikeFeature; -import net.minecraft.world.level.levelgen.feature.configurations.SpikeConfiguration; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -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 ru.bclib.api.WorldDataAPI; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.StructureHelper; -import ru.betterend.BetterEnd; -import ru.betterend.world.generator.GeneratorOptions; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -@Mixin(SpikeFeature.class) -public class SpikeFeatureMixin { - @Inject(method = "place", at = @At("HEAD"), cancellable = true) - private void be_place(FeaturePlaceContext featurePlaceContext, CallbackInfoReturnable info) { - if (!GeneratorOptions.hasPillars()) { - info.setReturnValue(false); - } - } - - @Inject(method = "placeSpike", at = @At("HEAD"), cancellable = true) - private void be_placeSpike(ServerLevelAccessor world, RandomSource random, SpikeConfiguration config, SpikeFeature.EndSpike spike, CallbackInfo info) { - int x = spike.getCenterX(); - int z = spike.getCenterZ(); - int radius = spike.getRadius(); - int minY = 0; - - long lx = (long) x; - long lz = (long) z; - if (lx * lx + lz * lz < 10000) { - String pillarID = String.format("%d_%d", x, z); - CompoundTag pillar = WorldDataAPI.getCompoundTag(BetterEnd.MOD_ID, "pillars"); - boolean haveValue = pillar.contains(pillarID); - minY = haveValue ? pillar.getInt(pillarID) : world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z); - if (!haveValue) { - pillar.putInt(pillarID, minY); - WorldDataAPI.saveFile(BetterEnd.MOD_ID); - } - } - else { - minY = world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z); - } - - GeneratorOptions.setDirectSpikeHeight(); - int maxY = minY + spike.getHeight() - 64; - - if (GeneratorOptions.replacePillars() && be_radiusInRange(radius)) { - radius--; - StructureTemplate base = StructureHelper.readStructure(BetterEnd.makeID("pillars/pillar_base_" + radius)); - StructureTemplate top = StructureHelper.readStructure(BetterEnd.makeID("pillars/pillar_top_" + radius + (spike - .isGuarded() ? "_cage" : ""))); - Vec3i side = base.getSize(); - BlockPos pos1 = new BlockPos(x - (side.getX() >> 1), minY - 3, z - (side.getZ() >> 1)); - minY = pos1.getY() + side.getY(); - side = top.getSize(); - BlockPos pos2 = new BlockPos(x - (side.getX() >> 1), maxY, z - (side.getZ() >> 1)); - maxY = pos2.getY(); - - StructurePlaceSettings data = new StructurePlaceSettings(); - base.placeInWorld(world, pos1, pos1, data, random, 2); - top.placeInWorld(world, pos2, pos2, data, random, 2); - - int r2 = radius * radius + 1; - MutableBlockPos mut = new MutableBlockPos(); - for (int px = -radius; px <= radius; px++) { - mut.setX(x + px); - int x2 = px * px; - for (int pz = -radius; pz <= radius; pz++) { - mut.setZ(z + pz); - int z2 = pz * pz; - if (x2 + z2 <= r2) { - for (int py = minY; py < maxY; py++) { - mut.setY(py); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - if ((px == radius || px == -radius || pz == radius || pz == -radius) && random.nextInt( - 24) == 0) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.CRYING_OBSIDIAN); - } - else { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.OBSIDIAN); - } - } - } - } - } - } - } - else { - minY -= 15; - int r2 = radius * radius + 1; - MutableBlockPos mut = new MutableBlockPos(); - for (int px = -radius; px <= radius; px++) { - mut.setX(x + px); - int x2 = px * px; - for (int pz = -radius; pz <= radius; pz++) { - mut.setZ(z + pz); - int z2 = pz * pz; - if (x2 + z2 <= r2) { - for (int py = minY; py < maxY; py++) { - mut.setY(py); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.OBSIDIAN); - } - } - } - } - } - mut.setX(x); - mut.setZ(z); - mut.setY(maxY); - BlocksHelper.setWithoutUpdate(world, mut, Blocks.BEDROCK); - - EndCrystal crystal = EntityType.END_CRYSTAL.create(world.getLevel()); - crystal.setBeamTarget(config.getCrystalBeamTarget()); - crystal.setInvulnerable(config.isCrystalInvulnerable()); - crystal.moveTo(x + 0.5D, maxY + 1, z + 0.5D, random.nextFloat() * 360.0F, 0.0F); - world.addFreshEntity(crystal); - - if (spike.isGuarded()) { - for (int px = -2; px <= 2; ++px) { - boolean bl = Mth.abs(px) == 2; - for (int pz = -2; pz <= 2; ++pz) { - boolean bl2 = Mth.abs(pz) == 2; - for (int py = 0; py <= 3; ++py) { - boolean bl3 = py == 3; - if (bl || bl2 || bl3) { - boolean bl4 = px == -2 || px == 2 || bl3; - boolean bl5 = pz == -2 || pz == 2 || bl3; - BlockState blockState = (BlockState) ((BlockState) ((BlockState) ((BlockState) Blocks.IRON_BARS - .defaultBlockState() - .setValue(IronBarsBlock.NORTH, bl4 && pz != -2)).setValue( - IronBarsBlock.SOUTH, - bl4 && pz != 2 - )).setValue(IronBarsBlock.WEST, bl5 && px != -2)).setValue( - IronBarsBlock.EAST, - bl5 && px != 2 - ); - BlocksHelper.setWithoutUpdate( - world, - mut.set(spike.getCenterX() + px, maxY + py, spike.getCenterZ() + pz), - blockState - ); - } - } - } - } - } - } - - info.cancel(); - } - - private boolean be_radiusInRange(int radius) { - return radius > 1 && radius < 6; - } -} diff --git a/src/main/java/ru/betterend/noise/OpenSimplexNoise.java b/src/main/java/ru/betterend/noise/OpenSimplexNoise.java deleted file mode 100644 index ff24de98..00000000 --- a/src/main/java/ru/betterend/noise/OpenSimplexNoise.java +++ /dev/null @@ -1,2671 +0,0 @@ -package ru.betterend.noise; - -/* - * OpenSimplex Noise in Java. - * by Kurt Spencer - * - * v1.1 (October 5, 2014) - * - Added 2D and 4D implementations. - * - Proper gradient sets for all dimensions, from a - * dimensionally-generalizable scheme with an actual - * rhyme and reason behind it. - * - Removed default permutation array in favor of - * default seed. - * - Changed seed-based constructor to be independent - * of any particular randomization library, so results - * will be the same when ported to other languages. - */ - -public final class OpenSimplexNoise { - private static final double STRETCH_CONSTANT_2D = -0.211324865405187; // (1/Math.sqrt(2+1)-1)/2; - private static final double SQUISH_CONSTANT_2D = 0.366025403784439; // (Math.sqrt(2+1)-1)/2; - private static final double STRETCH_CONSTANT_3D = -1.0 / 6; // (1/Math.sqrt(3+1)-1)/3; - private static final double SQUISH_CONSTANT_3D = 1.0 / 3; // (Math.sqrt(3+1)-1)/3; - private static final double STRETCH_CONSTANT_4D = -0.138196601125011; // (1/Math.sqrt(4+1)-1)/4; - private static final double SQUISH_CONSTANT_4D = 0.309016994374947; // (Math.sqrt(4+1)-1)/4; - - private static final double NORM_CONSTANT_2D = 47; - private static final double NORM_CONSTANT_3D = 103; - private static final double NORM_CONSTANT_4D = 30; - - private static final long DEFAULT_SEED = 0; - - private short[] perm; - private short[] permGradIndex3D; - - public OpenSimplexNoise() { - this(DEFAULT_SEED); - } - - public OpenSimplexNoise(short[] perm) { - this.perm = perm; - permGradIndex3D = new short[256]; - - for (int i = 0; i < 256; i++) { - // Since 3D has 24 gradients, simple bitmask won't work, so - // precompute modulo array. - permGradIndex3D[i] = (short) ((perm[i] % (gradients3D.length / 3)) * 3); - } - } - - // Initializes the class using a permutation array generated from a 64-bit - // seed. - // Generates a proper permutation (i.e. doesn't merely perform N successive - // pair swaps on a base array) - // Uses a simple 64-bit LCG. - public OpenSimplexNoise(long seed) { - perm = new short[256]; - permGradIndex3D = new short[256]; - short[] source = new short[256]; - for (short i = 0; i < 256; i++) { - source[i] = i; - } - seed = seed * 6364136223846793005l + 1442695040888963407l; - seed = seed * 6364136223846793005l + 1442695040888963407l; - seed = seed * 6364136223846793005l + 1442695040888963407l; - for (int i = 255; i >= 0; i--) { - seed = seed * 6364136223846793005l + 1442695040888963407l; - int r = (int) ((seed + 31) % (i + 1)); - if (r < 0) r += (i + 1); - perm[i] = source[r]; - permGradIndex3D[i] = (short) ((perm[i] % (gradients3D.length / 3)) * 3); - source[r] = source[i]; - } - } - - // 2D OpenSimplex Noise. - public double eval(double x, double y) { - - // Place input coordinates onto grid. - double stretchOffset = (x + y) * STRETCH_CONSTANT_2D; - double xs = x + stretchOffset; - double ys = y + stretchOffset; - - // Floor to get grid coordinates of rhombus (stretched square) - // super-cell origin. - int xsb = fastFloor(xs); - int ysb = fastFloor(ys); - - // Skew out to get actual coordinates of rhombus origin. We'll need - // these later. - double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; - double xb = xsb + squishOffset; - double yb = ysb + squishOffset; - - // Compute grid coordinates relative to rhombus origin. - double xins = xs - xsb; - double yins = ys - ysb; - - // Sum those together to get a value that determines which region we're - // in. - double inSum = xins + yins; - - // Positions relative to origin point. - double dx0 = x - xb; - double dy0 = y - yb; - - // We'll be defining these inside the next block and using them - // afterwards. - double dx_ext, dy_ext; - int xsv_ext, ysv_ext; - - double value = 0; - - // Contribution (1,0) - double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; - double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); - } - - // Contribution (0,1) - double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; - double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); - } - - if (inSum <= 1) { // We're inside the triangle (2-Simplex) at (0,0) - double zins = 1 - inSum; - if (zins > xins || zins > yins) { // (0,0) is one of the closest two - // triangular vertices - if (xins > yins) { - xsv_ext = xsb + 1; - ysv_ext = ysb - 1; - dx_ext = dx0 - 1; - dy_ext = dy0 + 1; - } - else { - xsv_ext = xsb - 1; - ysv_ext = ysb + 1; - dx_ext = dx0 + 1; - dy_ext = dy0 - 1; - } - } - else { // (1,0) and (0,1) are the closest two vertices. - xsv_ext = xsb + 1; - ysv_ext = ysb + 1; - dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; - dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; - } - } - else { // We're inside the triangle (2-Simplex) at (1,1) - double zins = 2 - inSum; - if (zins < xins || zins < yins) { // (0,0) is one of the closest two - // triangular vertices - if (xins > yins) { - xsv_ext = xsb + 2; - ysv_ext = ysb + 0; - dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; - dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; - } - else { - xsv_ext = xsb + 0; - ysv_ext = ysb + 2; - dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; - dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; - } - } - else { // (1,0) and (0,1) are the closest two vertices. - dx_ext = dx0; - dy_ext = dy0; - xsv_ext = xsb; - ysv_ext = ysb; - } - xsb += 1; - ysb += 1; - dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; - dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; - } - - // Contribution (0,0) or (1,1) - double attn0 = 2 - dx0 * dx0 - dy0 * dy0; - if (attn0 > 0) { - attn0 *= attn0; - value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); - } - - // Extra Vertex - double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; - if (attn_ext > 0) { - attn_ext *= attn_ext; - value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); - } - - return value / NORM_CONSTANT_2D; - } - - // 3D OpenSimplex Noise. - public double eval(double x, double y, double z) { - - // Place input coordinates on simplectic honeycomb. - double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D; - double xs = x + stretchOffset; - double ys = y + stretchOffset; - double zs = z + stretchOffset; - - // Floor to get simplectic honeycomb coordinates of rhombohedron - // (stretched cube) super-cell origin. - int xsb = fastFloor(xs); - int ysb = fastFloor(ys); - int zsb = fastFloor(zs); - - // Skew out to get actual coordinates of rhombohedron origin. We'll need - // these later. - double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D; - double xb = xsb + squishOffset; - double yb = ysb + squishOffset; - double zb = zsb + squishOffset; - - // Compute simplectic honeycomb coordinates relative to rhombohedral - // origin. - double xins = xs - xsb; - double yins = ys - ysb; - double zins = zs - zsb; - - // Sum those together to get a value that determines which region we're - // in. - double inSum = xins + yins + zins; - - // Positions relative to origin point. - double dx0 = x - xb; - double dy0 = y - yb; - double dz0 = z - zb; - - // We'll be defining these inside the next block and using them - // afterwards. - double dx_ext0, dy_ext0, dz_ext0; - double dx_ext1, dy_ext1, dz_ext1; - int xsv_ext0, ysv_ext0, zsv_ext0; - int xsv_ext1, ysv_ext1, zsv_ext1; - - double value = 0; - if (inSum <= 1) { // We're inside the tetrahedron (3-Simplex) at (0,0,0) - - // Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. - byte aPoint = 0x01; - double aScore = xins; - byte bPoint = 0x02; - double bScore = yins; - if (aScore >= bScore && zins > bScore) { - bScore = zins; - bPoint = 0x04; - } - else if (aScore < bScore && zins > aScore) { - aScore = zins; - aPoint = 0x04; - } - - // Now we determine the two lattice points not part of the - // tetrahedron that may contribute. - // This depends on the closest two tetrahedral vertices, including - // (0,0,0) - double wins = 1 - inSum; - if (wins > aScore || wins > bScore) { // (0,0,0) is one of the - // closest two tetrahedral - // vertices. - byte c = (bScore > aScore ? bPoint : aPoint); // Our other - // closest - // vertex is the - // closest out - // of a and b. - - if ((c & 0x01) == 0) { - xsv_ext0 = xsb - 1; - xsv_ext1 = xsb; - dx_ext0 = dx0 + 1; - dx_ext1 = dx0; - } - else { - xsv_ext0 = xsv_ext1 = xsb + 1; - dx_ext0 = dx_ext1 = dx0 - 1; - } - - if ((c & 0x02) == 0) { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0; - if ((c & 0x01) == 0) { - ysv_ext1 -= 1; - dy_ext1 += 1; - } - else { - ysv_ext0 -= 1; - dy_ext0 += 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1; - } - - if ((c & 0x04) == 0) { - zsv_ext0 = zsb; - zsv_ext1 = zsb - 1; - dz_ext0 = dz0; - dz_ext1 = dz0 + 1; - } - else { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz_ext1 = dz0 - 1; - } - } - else { // (0,0,0) is not one of the closest two tetrahedral - // vertices. - byte c = (byte) (aPoint | bPoint); // Our two extra vertices are - // determined by the closest - // two. - - if ((c & 0x01) == 0) { - xsv_ext0 = xsb; - xsv_ext1 = xsb - 1; - dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D; - dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; - } - else { - xsv_ext0 = xsv_ext1 = xsb + 1; - dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; - dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; - } - - if ((c & 0x02) == 0) { - ysv_ext0 = ysb; - ysv_ext1 = ysb - 1; - dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; - } - else { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; - } - - if ((c & 0x04) == 0) { - zsv_ext0 = zsb; - zsv_ext1 = zsb - 1; - dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; - } - else { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; - } - } - - // Contribution (0,0,0) - double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; - if (attn0 > 0) { - attn0 *= attn0; - value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); - } - - // Contribution (1,0,0) - double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; - double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; - double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); - } - - // Contribution (0,1,0) - double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; - double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; - double dz2 = dz1; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); - } - - // Contribution (0,0,1) - double dx3 = dx2; - double dy3 = dy1; - double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); - } - } - else if (inSum >= 2) { // We're inside the tetrahedron (3-Simplex) at - // (1,1,1) - - // Determine which two tetrahedral vertices are the closest, out of - // (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). - byte aPoint = 0x06; - double aScore = xins; - byte bPoint = 0x05; - double bScore = yins; - if (aScore <= bScore && zins < bScore) { - bScore = zins; - bPoint = 0x03; - } - else if (aScore > bScore && zins < aScore) { - aScore = zins; - aPoint = 0x03; - } - - // Now we determine the two lattice points not part of the - // tetrahedron that may contribute. - // This depends on the closest two tetrahedral vertices, including - // (1,1,1) - double wins = 3 - inSum; - if (wins < aScore || wins < bScore) { // (1,1,1) is one of the - // closest two tetrahedral - // vertices. - byte c = (bScore < aScore ? bPoint : aPoint); // Our other - // closest - // vertex is the - // closest out - // of a and b. - - if ((c & 0x01) != 0) { - xsv_ext0 = xsb + 2; - xsv_ext1 = xsb + 1; - dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D; - dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; - } - else { - xsv_ext0 = xsv_ext1 = xsb; - dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D; - } - - if ((c & 0x02) != 0) { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; - if ((c & 0x01) != 0) { - ysv_ext1 += 1; - dy_ext1 -= 1; - } - else { - ysv_ext0 += 1; - dy_ext0 -= 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D; - } - - if ((c & 0x04) != 0) { - zsv_ext0 = zsb + 1; - zsv_ext1 = zsb + 2; - dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D; - } - else { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D; - } - } - else { // (1,1,1) is not one of the closest two tetrahedral - // vertices. - byte c = (byte) (aPoint & bPoint); // Our two extra vertices are - // determined by the closest - // two. - - if ((c & 0x01) != 0) { - xsv_ext0 = xsb + 1; - xsv_ext1 = xsb + 2; - dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; - dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; - } - else { - xsv_ext0 = xsv_ext1 = xsb; - dx_ext0 = dx0 - SQUISH_CONSTANT_3D; - dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; - } - - if ((c & 0x02) != 0) { - ysv_ext0 = ysb + 1; - ysv_ext1 = ysb + 2; - dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; - } - else { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy0 - SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; - } - - if ((c & 0x04) != 0) { - zsv_ext0 = zsb + 1; - zsv_ext1 = zsb + 2; - dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; - } - else { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz0 - SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; - } - } - - // Contribution (1,1,0) - double dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; - double dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; - double dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); - } - - // Contribution (1,0,1) - double dx2 = dx3; - double dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; - double dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); - } - - // Contribution (0,1,1) - double dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; - double dy1 = dy3; - double dz1 = dz2; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); - } - - // Contribution (1,1,1) - dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; - dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; - dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; - double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; - if (attn0 > 0) { - attn0 *= attn0; - value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); - } - } - else { // We're inside the octahedron (Rectified 3-Simplex) in - // between. - double aScore; - byte aPoint; - boolean aIsFurtherSide; - double bScore; - byte bPoint; - boolean bIsFurtherSide; - - // Decide between point (0,0,1) and (1,1,0) as closest - double p1 = xins + yins; - if (p1 > 1) { - aScore = p1 - 1; - aPoint = 0x03; - aIsFurtherSide = true; - } - else { - aScore = 1 - p1; - aPoint = 0x04; - aIsFurtherSide = false; - } - - // Decide between point (0,1,0) and (1,0,1) as closest - double p2 = xins + zins; - if (p2 > 1) { - bScore = p2 - 1; - bPoint = 0x05; - bIsFurtherSide = true; - } - else { - bScore = 1 - p2; - bPoint = 0x02; - bIsFurtherSide = false; - } - - // The closest out of the two (1,0,0) and (0,1,1) will replace the - // furthest out of the two decided above, if closer. - double p3 = yins + zins; - if (p3 > 1) { - double score = p3 - 1; - if (aScore <= bScore && aScore < score) { - aScore = score; - aPoint = 0x06; - aIsFurtherSide = true; - } - else if (aScore > bScore && bScore < score) { - bScore = score; - bPoint = 0x06; - bIsFurtherSide = true; - } - } - else { - double score = 1 - p3; - if (aScore <= bScore && aScore < score) { - aScore = score; - aPoint = 0x01; - aIsFurtherSide = false; - } - else if (aScore > bScore && bScore < score) { - bScore = score; - bPoint = 0x01; - bIsFurtherSide = false; - } - } - - // Where each of the two closest points are determines how the extra - // two vertices are calculated. - if (aIsFurtherSide == bIsFurtherSide) { - if (aIsFurtherSide) { // Both closest points on (1,1,1) side - - // One of the two extra points is (1,1,1) - dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; - dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; - dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; - xsv_ext0 = xsb + 1; - ysv_ext0 = ysb + 1; - zsv_ext0 = zsb + 1; - - // Other extra point is based on the shared axis. - byte c = (byte) (aPoint & bPoint); - if ((c & 0x01) != 0) { - dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; - xsv_ext1 = xsb + 2; - ysv_ext1 = ysb; - zsv_ext1 = zsb; - } - else if ((c & 0x02) != 0) { - dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; - xsv_ext1 = xsb; - ysv_ext1 = ysb + 2; - zsv_ext1 = zsb; - } - else { - dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; - xsv_ext1 = xsb; - ysv_ext1 = ysb; - zsv_ext1 = zsb + 2; - } - } - else {// Both closest points on (0,0,0) side - - // One of the two extra points is (0,0,0) - dx_ext0 = dx0; - dy_ext0 = dy0; - dz_ext0 = dz0; - xsv_ext0 = xsb; - ysv_ext0 = ysb; - zsv_ext0 = zsb; - - // Other extra point is based on the omitted axis. - byte c = (byte) (aPoint | bPoint); - if ((c & 0x01) == 0) { - dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; - xsv_ext1 = xsb - 1; - ysv_ext1 = ysb + 1; - zsv_ext1 = zsb + 1; - } - else if ((c & 0x02) == 0) { - dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; - dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; - xsv_ext1 = xsb + 1; - ysv_ext1 = ysb - 1; - zsv_ext1 = zsb + 1; - } - else { - dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; - dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; - xsv_ext1 = xsb + 1; - ysv_ext1 = ysb + 1; - zsv_ext1 = zsb - 1; - } - } - } - else { // One point on (0,0,0) side, one point on (1,1,1) side - byte c1, c2; - if (aIsFurtherSide) { - c1 = aPoint; - c2 = bPoint; - } - else { - c1 = bPoint; - c2 = aPoint; - } - - // One contribution is a permutation of (1,1,-1) - if ((c1 & 0x01) == 0) { - dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D; - dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; - dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; - xsv_ext0 = xsb - 1; - ysv_ext0 = ysb + 1; - zsv_ext0 = zsb + 1; - } - else if ((c1 & 0x02) == 0) { - dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; - dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D; - dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; - xsv_ext0 = xsb + 1; - ysv_ext0 = ysb - 1; - zsv_ext0 = zsb + 1; - } - else { - dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; - dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; - dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D; - xsv_ext0 = xsb + 1; - ysv_ext0 = ysb + 1; - zsv_ext0 = zsb - 1; - } - - // One contribution is a permutation of (0,0,2) - dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; - dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; - dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; - xsv_ext1 = xsb; - ysv_ext1 = ysb; - zsv_ext1 = zsb; - if ((c2 & 0x01) != 0) { - dx_ext1 -= 2; - xsv_ext1 += 2; - } - else if ((c2 & 0x02) != 0) { - dy_ext1 -= 2; - ysv_ext1 += 2; - } - else { - dz_ext1 -= 2; - zsv_ext1 += 2; - } - } - - // Contribution (1,0,0) - double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; - double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; - double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); - } - - // Contribution (0,1,0) - double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; - double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; - double dz2 = dz1; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); - } - - // Contribution (0,0,1) - double dx3 = dx2; - double dy3 = dy1; - double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); - } - - // Contribution (1,1,0) - double dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; - double dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; - double dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; - double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; - if (attn4 > 0) { - attn4 *= attn4; - value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); - } - - // Contribution (1,0,1) - double dx5 = dx4; - double dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; - double dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; - double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; - if (attn5 > 0) { - attn5 *= attn5; - value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); - } - - // Contribution (0,1,1) - double dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; - double dy6 = dy4; - double dz6 = dz5; - double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; - if (attn6 > 0) { - attn6 *= attn6; - value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); - } - } - - // First extra vertex - double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; - if (attn_ext0 > 0) { - attn_ext0 *= attn_ext0; - value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); - } - - // Second extra vertex - double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; - if (attn_ext1 > 0) { - attn_ext1 *= attn_ext1; - value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); - } - - return value / NORM_CONSTANT_3D; - } - - // 4D OpenSimplex Noise. - public double eval(double x, double y, double z, double w) { - - // Place input coordinates on simplectic honeycomb. - double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D; - double xs = x + stretchOffset; - double ys = y + stretchOffset; - double zs = z + stretchOffset; - double ws = w + stretchOffset; - - // Floor to get simplectic honeycomb coordinates of rhombo-hypercube - // super-cell origin. - int xsb = fastFloor(xs); - int ysb = fastFloor(ys); - int zsb = fastFloor(zs); - int wsb = fastFloor(ws); - - // Skew out to get actual coordinates of stretched rhombo-hypercube - // origin. We'll need these later. - double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D; - double xb = xsb + squishOffset; - double yb = ysb + squishOffset; - double zb = zsb + squishOffset; - double wb = wsb + squishOffset; - - // Compute simplectic honeycomb coordinates relative to rhombo-hypercube - // origin. - double xins = xs - xsb; - double yins = ys - ysb; - double zins = zs - zsb; - double wins = ws - wsb; - - // Sum those together to get a value that determines which region we're - // in. - double inSum = xins + yins + zins + wins; - - // Positions relative to origin point. - double dx0 = x - xb; - double dy0 = y - yb; - double dz0 = z - zb; - double dw0 = w - wb; - - // We'll be defining these inside the next block and using them - // afterwards. - double dx_ext0, dy_ext0, dz_ext0, dw_ext0; - double dx_ext1, dy_ext1, dz_ext1, dw_ext1; - double dx_ext2, dy_ext2, dz_ext2, dw_ext2; - int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; - int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; - int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; - - double value = 0; - if (inSum <= 1) { // We're inside the pentachoron (4-Simplex) at - // (0,0,0,0) - - // Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) - // are closest. - byte aPoint = 0x01; - double aScore = xins; - byte bPoint = 0x02; - double bScore = yins; - if (aScore >= bScore && zins > bScore) { - bScore = zins; - bPoint = 0x04; - } - else if (aScore < bScore && zins > aScore) { - aScore = zins; - aPoint = 0x04; - } - if (aScore >= bScore && wins > bScore) { - bScore = wins; - bPoint = 0x08; - } - else if (aScore < bScore && wins > aScore) { - aScore = wins; - aPoint = 0x08; - } - - // Now we determine the three lattice points not part of the - // pentachoron that may contribute. - // This depends on the closest two pentachoron vertices, including - // (0,0,0,0) - double uins = 1 - inSum; - if (uins > aScore || uins > bScore) { // (0,0,0,0) is one of the - // closest two pentachoron - // vertices. - byte c = (bScore > aScore ? bPoint : aPoint); // Our other - // closest - // vertex is the - // closest out - // of a and b. - if ((c & 0x01) == 0) { - xsv_ext0 = xsb - 1; - xsv_ext1 = xsv_ext2 = xsb; - dx_ext0 = dx0 + 1; - dx_ext1 = dx_ext2 = dx0; - } - else { - xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; - dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; - } - - if ((c & 0x02) == 0) { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; - dy_ext0 = dy_ext1 = dy_ext2 = dy0; - if ((c & 0x01) == 0x01) { - ysv_ext0 -= 1; - dy_ext0 += 1; - } - else { - ysv_ext1 -= 1; - dy_ext1 += 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; - dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; - } - - if ((c & 0x04) == 0) { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; - dz_ext0 = dz_ext1 = dz_ext2 = dz0; - if ((c & 0x03) != 0) { - if ((c & 0x03) == 0x03) { - zsv_ext0 -= 1; - dz_ext0 += 1; - } - else { - zsv_ext1 -= 1; - dz_ext1 += 1; - } - } - else { - zsv_ext2 -= 1; - dz_ext2 += 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; - dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; - } - - if ((c & 0x08) == 0) { - wsv_ext0 = wsv_ext1 = wsb; - wsv_ext2 = wsb - 1; - dw_ext0 = dw_ext1 = dw0; - dw_ext2 = dw0 + 1; - } - else { - wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; - dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; - } - } - else { // (0,0,0,0) is not one of the closest two pentachoron - // vertices. - byte c = (byte) (aPoint | bPoint); // Our three extra vertices - // are determined by the - // closest two. - - if ((c & 0x01) == 0) { - xsv_ext0 = xsv_ext2 = xsb; - xsv_ext1 = xsb - 1; - dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D; - dx_ext2 = dx0 - SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; - dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x02) == 0) { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; - dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; - dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D; - if ((c & 0x01) == 0x01) { - ysv_ext1 -= 1; - dy_ext1 += 1; - } - else { - ysv_ext2 -= 1; - dy_ext2 += 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; - dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x04) == 0) { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; - dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; - dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D; - if ((c & 0x03) == 0x03) { - zsv_ext1 -= 1; - dz_ext1 += 1; - } - else { - zsv_ext2 -= 1; - dz_ext2 += 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; - dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x08) == 0) { - wsv_ext0 = wsv_ext1 = wsb; - wsv_ext2 = wsb - 1; - dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - SQUISH_CONSTANT_4D; - dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; - dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D; - } - } - - // Contribution (0,0,0,0) - double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; - if (attn0 > 0) { - attn0 *= attn0; - value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); - } - - // Contribution (1,0,0,0) - double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; - double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; - double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; - double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); - } - - // Contribution (0,1,0,0) - double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; - double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; - double dz2 = dz1; - double dw2 = dw1; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); - } - - // Contribution (0,0,1,0) - double dx3 = dx2; - double dy3 = dy1; - double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; - double dw3 = dw1; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); - } - - // Contribution (0,0,0,1) - double dx4 = dx2; - double dy4 = dy1; - double dz4 = dz1; - double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; - double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; - if (attn4 > 0) { - attn4 *= attn4; - value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); - } - } - else if (inSum >= 3) { // We're inside the pentachoron (4-Simplex) at - // (1,1,1,1) - // Determine which two of (1,1,1,0), - // (1,1,0,1), (1,0,1,1), (0,1,1,1) - // are closest. - byte aPoint = 0x0E; - double aScore = xins; - byte bPoint = 0x0D; - double bScore = yins; - if (aScore <= bScore && zins < bScore) { - bScore = zins; - bPoint = 0x0B; - } - else if (aScore > bScore && zins < aScore) { - aScore = zins; - aPoint = 0x0B; - } - if (aScore <= bScore && wins < bScore) { - bScore = wins; - bPoint = 0x07; - } - else if (aScore > bScore && wins < aScore) { - aScore = wins; - aPoint = 0x07; - } - - // Now we determine the three lattice points not part of the - // pentachoron that may contribute. - // This depends on the closest two pentachoron vertices, including - // (0,0,0,0) - double uins = 4 - inSum; - if (uins < aScore || uins < bScore) { // (1,1,1,1) is one of the - // closest two pentachoron - // vertices. - byte c = (bScore < aScore ? bPoint : aPoint); // Our other - // closest - // vertex is the - // closest out - // of a and b. - - if ((c & 0x01) != 0) { - xsv_ext0 = xsb + 2; - xsv_ext1 = xsv_ext2 = xsb + 1; - dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D; - dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; - dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x02) != 0) { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; - dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; - if ((c & 0x01) != 0) { - ysv_ext1 += 1; - dy_ext1 -= 1; - } - else { - ysv_ext0 += 1; - dy_ext0 -= 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; - dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x04) != 0) { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; - dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; - if ((c & 0x03) != 0x03) { - if ((c & 0x03) == 0) { - zsv_ext0 += 1; - dz_ext0 -= 1; - } - else { - zsv_ext1 += 1; - dz_ext1 -= 1; - } - } - else { - zsv_ext2 += 1; - dz_ext2 -= 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; - dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x08) != 0) { - wsv_ext0 = wsv_ext1 = wsb + 1; - wsv_ext2 = wsb + 2; - dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; - dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D; - } - } - else { // (1,1,1,1) is not one of the closest two pentachoron - // vertices. - byte c = (byte) (aPoint & bPoint); // Our three extra vertices - // are determined by the - // closest two. - - if ((c & 0x01) != 0) { - xsv_ext0 = xsv_ext2 = xsb + 1; - xsv_ext1 = xsb + 2; - dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; - dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; - dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; - dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x02) != 0) { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; - dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c & 0x01) != 0) { - ysv_ext2 += 1; - dy_ext2 -= 1; - } - else { - ysv_ext1 += 1; - dy_ext1 -= 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; - dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; - dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x04) != 0) { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; - dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c & 0x03) != 0) { - zsv_ext2 += 1; - dz_ext2 -= 1; - } - else { - zsv_ext1 += 1; - dz_ext1 -= 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; - dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; - dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x08) != 0) { - wsv_ext0 = wsv_ext1 = wsb + 1; - wsv_ext2 = wsb + 2; - dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; - dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; - dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D; - } - } - - // Contribution (1,1,1,0) - double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; - double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; - if (attn4 > 0) { - attn4 *= attn4; - value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); - } - - // Contribution (1,1,0,1) - double dx3 = dx4; - double dy3 = dy4; - double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; - double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); - } - - // Contribution (1,0,1,1) - double dx2 = dx4; - double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; - double dz2 = dz4; - double dw2 = dw3; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); - } - - // Contribution (0,1,1,1) - double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; - double dz1 = dz4; - double dy1 = dy4; - double dw1 = dw3; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); - } - - // Contribution (1,1,1,1) - dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; - dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; - dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; - dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; - double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; - if (attn0 > 0) { - attn0 *= attn0; - value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); - } - } - else if (inSum <= 2) { // We're inside the first dispentachoron - // (Rectified 4-Simplex) - double aScore; - byte aPoint; - boolean aIsBiggerSide = true; - double bScore; - byte bPoint; - boolean bIsBiggerSide = true; - - // Decide between (1,1,0,0) and (0,0,1,1) - if (xins + yins > zins + wins) { - aScore = xins + yins; - aPoint = 0x03; - } - else { - aScore = zins + wins; - aPoint = 0x0C; - } - - // Decide between (1,0,1,0) and (0,1,0,1) - if (xins + zins > yins + wins) { - bScore = xins + zins; - bPoint = 0x05; - } - else { - bScore = yins + wins; - bPoint = 0x0A; - } - - // Closer between (1,0,0,1) and (0,1,1,0) will replace the further - // of a and b, if closer. - if (xins + wins > yins + zins) { - double score = xins + wins; - if (aScore >= bScore && score > bScore) { - bScore = score; - bPoint = 0x09; - } - else if (aScore < bScore && score > aScore) { - aScore = score; - aPoint = 0x09; - } - } - else { - double score = yins + zins; - if (aScore >= bScore && score > bScore) { - bScore = score; - bPoint = 0x06; - } - else if (aScore < bScore && score > aScore) { - aScore = score; - aPoint = 0x06; - } - } - - // Decide if (1,0,0,0) is closer. - double p1 = 2 - inSum + xins; - if (aScore >= bScore && p1 > bScore) { - bScore = p1; - bPoint = 0x01; - bIsBiggerSide = false; - } - else if (aScore < bScore && p1 > aScore) { - aScore = p1; - aPoint = 0x01; - aIsBiggerSide = false; - } - - // Decide if (0,1,0,0) is closer. - double p2 = 2 - inSum + yins; - if (aScore >= bScore && p2 > bScore) { - bScore = p2; - bPoint = 0x02; - bIsBiggerSide = false; - } - else if (aScore < bScore && p2 > aScore) { - aScore = p2; - aPoint = 0x02; - aIsBiggerSide = false; - } - - // Decide if (0,0,1,0) is closer. - double p3 = 2 - inSum + zins; - if (aScore >= bScore && p3 > bScore) { - bScore = p3; - bPoint = 0x04; - bIsBiggerSide = false; - } - else if (aScore < bScore && p3 > aScore) { - aScore = p3; - aPoint = 0x04; - aIsBiggerSide = false; - } - - // Decide if (0,0,0,1) is closer. - double p4 = 2 - inSum + wins; - if (aScore >= bScore && p4 > bScore) { - bScore = p4; - bPoint = 0x08; - bIsBiggerSide = false; - } - else if (aScore < bScore && p4 > aScore) { - aScore = p4; - aPoint = 0x08; - aIsBiggerSide = false; - } - - // Where each of the two closest points are determines how the extra - // three vertices are calculated. - if (aIsBiggerSide == bIsBiggerSide) { - if (aIsBiggerSide) { // Both closest points on the bigger side - byte c1 = (byte) (aPoint | bPoint); - byte c2 = (byte) (aPoint & bPoint); - if ((c1 & 0x01) == 0) { - xsv_ext0 = xsb; - xsv_ext1 = xsb - 1; - dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsb + 1; - dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x02) == 0) { - ysv_ext0 = ysb; - ysv_ext1 = ysb - 1; - dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D; - dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D; - } - else { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x04) == 0) { - zsv_ext0 = zsb; - zsv_ext1 = zsb - 1; - dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D; - dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D; - } - else { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x08) == 0) { - wsv_ext0 = wsb; - wsv_ext1 = wsb - 1; - dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsb + 1; - dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - } - - // One combination is a permutation of (0,0,0,2) based on c2 - xsv_ext2 = xsb; - ysv_ext2 = ysb; - zsv_ext2 = zsb; - wsv_ext2 = wsb; - dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; - dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; - dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; - if ((c2 & 0x01) != 0) { - xsv_ext2 += 2; - dx_ext2 -= 2; - } - else if ((c2 & 0x02) != 0) { - ysv_ext2 += 2; - dy_ext2 -= 2; - } - else if ((c2 & 0x04) != 0) { - zsv_ext2 += 2; - dz_ext2 -= 2; - } - else { - wsv_ext2 += 2; - dw_ext2 -= 2; - } - - } - else { // Both closest points on the smaller side - // One of the two extra points is (0,0,0,0) - xsv_ext2 = xsb; - ysv_ext2 = ysb; - zsv_ext2 = zsb; - wsv_ext2 = wsb; - dx_ext2 = dx0; - dy_ext2 = dy0; - dz_ext2 = dz0; - dw_ext2 = dw0; - - // Other two points are based on the omitted axes. - byte c = (byte) (aPoint | bPoint); - - if ((c & 0x01) == 0) { - xsv_ext0 = xsb - 1; - xsv_ext1 = xsb; - dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsb + 1; - dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x02) == 0) { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; - if ((c & 0x01) == 0x01) { - ysv_ext0 -= 1; - dy_ext0 += 1; - } - else { - ysv_ext1 -= 1; - dy_ext1 += 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x04) == 0) { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; - if ((c & 0x03) == 0x03) { - zsv_ext0 -= 1; - dz_ext0 += 1; - } - else { - zsv_ext1 -= 1; - dz_ext1 += 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c & 0x08) == 0) { - wsv_ext0 = wsb; - wsv_ext1 = wsb - 1; - dw_ext0 = dw0 - SQUISH_CONSTANT_4D; - dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsb + 1; - dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; - } - - } - } - else { // One point on each "side" - byte c1, c2; - if (aIsBiggerSide) { - c1 = aPoint; - c2 = bPoint; - } - else { - c1 = bPoint; - c2 = aPoint; - } - - // Two contributions are the bigger-sided point with each 0 - // replaced with -1. - if ((c1 & 0x01) == 0) { - xsv_ext0 = xsb - 1; - xsv_ext1 = xsb; - dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsb + 1; - dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x02) == 0) { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; - if ((c1 & 0x01) == 0x01) { - ysv_ext0 -= 1; - dy_ext0 += 1; - } - else { - ysv_ext1 -= 1; - dy_ext1 += 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x04) == 0) { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; - if ((c1 & 0x03) == 0x03) { - zsv_ext0 -= 1; - dz_ext0 += 1; - } - else { - zsv_ext1 -= 1; - dz_ext1 += 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x08) == 0) { - wsv_ext0 = wsb; - wsv_ext1 = wsb - 1; - dw_ext0 = dw0 - SQUISH_CONSTANT_4D; - dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsb + 1; - dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; - } - - // One contribution is a permutation of (0,0,0,2) based on the - // smaller-sided point - xsv_ext2 = xsb; - ysv_ext2 = ysb; - zsv_ext2 = zsb; - wsv_ext2 = wsb; - dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; - dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; - dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; - if ((c2 & 0x01) != 0) { - xsv_ext2 += 2; - dx_ext2 -= 2; - } - else if ((c2 & 0x02) != 0) { - ysv_ext2 += 2; - dy_ext2 -= 2; - } - else if ((c2 & 0x04) != 0) { - zsv_ext2 += 2; - dz_ext2 -= 2; - } - else { - wsv_ext2 += 2; - dw_ext2 -= 2; - } - } - - // Contribution (1,0,0,0) - double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; - double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; - double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; - double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); - } - - // Contribution (0,1,0,0) - double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; - double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; - double dz2 = dz1; - double dw2 = dw1; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); - } - - // Contribution (0,0,1,0) - double dx3 = dx2; - double dy3 = dy1; - double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; - double dw3 = dw1; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); - } - - // Contribution (0,0,0,1) - double dx4 = dx2; - double dy4 = dy1; - double dz4 = dz1; - double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; - double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; - if (attn4 > 0) { - attn4 *= attn4; - value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); - } - - // Contribution (1,1,0,0) - double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; - if (attn5 > 0) { - attn5 *= attn5; - value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); - } - - // Contribution (1,0,1,0) - double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; - if (attn6 > 0) { - attn6 *= attn6; - value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); - } - - // Contribution (1,0,0,1) - double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; - if (attn7 > 0) { - attn7 *= attn7; - value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); - } - - // Contribution (0,1,1,0) - double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; - if (attn8 > 0) { - attn8 *= attn8; - value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); - } - - // Contribution (0,1,0,1) - double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; - if (attn9 > 0) { - attn9 *= attn9; - value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); - } - - // Contribution (0,0,1,1) - double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; - if (attn10 > 0) { - attn10 *= attn10; - value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); - } - } - else { // We're inside the second dispentachoron (Rectified 4-Simplex) - double aScore; - byte aPoint; - boolean aIsBiggerSide = true; - double bScore; - byte bPoint; - boolean bIsBiggerSide = true; - - // Decide between (0,0,1,1) and (1,1,0,0) - if (xins + yins < zins + wins) { - aScore = xins + yins; - aPoint = 0x0C; - } - else { - aScore = zins + wins; - aPoint = 0x03; - } - - // Decide between (0,1,0,1) and (1,0,1,0) - if (xins + zins < yins + wins) { - bScore = xins + zins; - bPoint = 0x0A; - } - else { - bScore = yins + wins; - bPoint = 0x05; - } - - // Closer between (0,1,1,0) and (1,0,0,1) will replace the further - // of a and b, if closer. - if (xins + wins < yins + zins) { - double score = xins + wins; - if (aScore <= bScore && score < bScore) { - bScore = score; - bPoint = 0x06; - } - else if (aScore > bScore && score < aScore) { - aScore = score; - aPoint = 0x06; - } - } - else { - double score = yins + zins; - if (aScore <= bScore && score < bScore) { - bScore = score; - bPoint = 0x09; - } - else if (aScore > bScore && score < aScore) { - aScore = score; - aPoint = 0x09; - } - } - - // Decide if (0,1,1,1) is closer. - double p1 = 3 - inSum + xins; - if (aScore <= bScore && p1 < bScore) { - bScore = p1; - bPoint = 0x0E; - bIsBiggerSide = false; - } - else if (aScore > bScore && p1 < aScore) { - aScore = p1; - aPoint = 0x0E; - aIsBiggerSide = false; - } - - // Decide if (1,0,1,1) is closer. - double p2 = 3 - inSum + yins; - if (aScore <= bScore && p2 < bScore) { - bScore = p2; - bPoint = 0x0D; - bIsBiggerSide = false; - } - else if (aScore > bScore && p2 < aScore) { - aScore = p2; - aPoint = 0x0D; - aIsBiggerSide = false; - } - - // Decide if (1,1,0,1) is closer. - double p3 = 3 - inSum + zins; - if (aScore <= bScore && p3 < bScore) { - bScore = p3; - bPoint = 0x0B; - bIsBiggerSide = false; - } - else if (aScore > bScore && p3 < aScore) { - aScore = p3; - aPoint = 0x0B; - aIsBiggerSide = false; - } - - // Decide if (1,1,1,0) is closer. - double p4 = 3 - inSum + wins; - if (aScore <= bScore && p4 < bScore) { - bScore = p4; - bPoint = 0x07; - bIsBiggerSide = false; - } - else if (aScore > bScore && p4 < aScore) { - aScore = p4; - aPoint = 0x07; - aIsBiggerSide = false; - } - - // Where each of the two closest points are determines how the extra - // three vertices are calculated. - if (aIsBiggerSide == bIsBiggerSide) { - if (aIsBiggerSide) { // Both closest points on the bigger side - byte c1 = (byte) (aPoint & bPoint); - byte c2 = (byte) (aPoint | bPoint); - - // Two contributions are permutations of (0,0,0,1) and - // (0,0,0,2) based on c1 - xsv_ext0 = xsv_ext1 = xsb; - ysv_ext0 = ysv_ext1 = ysb; - zsv_ext0 = zsv_ext1 = zsb; - wsv_ext0 = wsv_ext1 = wsb; - dx_ext0 = dx0 - SQUISH_CONSTANT_4D; - dy_ext0 = dy0 - SQUISH_CONSTANT_4D; - dz_ext0 = dz0 - SQUISH_CONSTANT_4D; - dw_ext0 = dw0 - SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D; - dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D; - dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D; - if ((c1 & 0x01) != 0) { - xsv_ext0 += 1; - dx_ext0 -= 1; - xsv_ext1 += 2; - dx_ext1 -= 2; - } - else if ((c1 & 0x02) != 0) { - ysv_ext0 += 1; - dy_ext0 -= 1; - ysv_ext1 += 2; - dy_ext1 -= 2; - } - else if ((c1 & 0x04) != 0) { - zsv_ext0 += 1; - dz_ext0 -= 1; - zsv_ext1 += 2; - dz_ext1 -= 2; - } - else { - wsv_ext0 += 1; - dw_ext0 -= 1; - wsv_ext1 += 2; - dw_ext1 -= 2; - } - - // One contribution is a permutation of (1,1,1,-1) based on - // c2 - xsv_ext2 = xsb + 1; - ysv_ext2 = ysb + 1; - zsv_ext2 = zsb + 1; - wsv_ext2 = wsb + 1; - dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - if ((c2 & 0x01) == 0) { - xsv_ext2 -= 2; - dx_ext2 += 2; - } - else if ((c2 & 0x02) == 0) { - ysv_ext2 -= 2; - dy_ext2 += 2; - } - else if ((c2 & 0x04) == 0) { - zsv_ext2 -= 2; - dz_ext2 += 2; - } - else { - wsv_ext2 -= 2; - dw_ext2 += 2; - } - } - else { // Both closest points on the smaller side - // One of the two extra points is (1,1,1,1) - xsv_ext2 = xsb + 1; - ysv_ext2 = ysb + 1; - zsv_ext2 = zsb + 1; - wsv_ext2 = wsb + 1; - dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; - dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; - dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; - - // Other two points are based on the shared axes. - byte c = (byte) (aPoint & bPoint); - - if ((c & 0x01) != 0) { - xsv_ext0 = xsb + 2; - xsv_ext1 = xsb + 1; - dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsb; - dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x02) != 0) { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c & 0x01) == 0) { - ysv_ext0 += 1; - dy_ext0 -= 1; - } - else { - ysv_ext1 += 1; - dy_ext1 -= 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x04) != 0) { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c & 0x03) == 0) { - zsv_ext0 += 1; - dz_ext0 -= 1; - } - else { - zsv_ext1 += 1; - dz_ext1 -= 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c & 0x08) != 0) { - wsv_ext0 = wsb + 1; - wsv_ext1 = wsb + 2; - dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsb; - dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; - } - } - } - else { // One point on each "side" - byte c1, c2; - if (aIsBiggerSide) { - c1 = aPoint; - c2 = bPoint; - } - else { - c1 = bPoint; - c2 = aPoint; - } - - // Two contributions are the bigger-sided point with each 1 - // replaced with 2. - if ((c1 & 0x01) != 0) { - xsv_ext0 = xsb + 2; - xsv_ext1 = xsb + 1; - dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; - dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - } - else { - xsv_ext0 = xsv_ext1 = xsb; - dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x02) != 0) { - ysv_ext0 = ysv_ext1 = ysb + 1; - dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c1 & 0x01) == 0) { - ysv_ext0 += 1; - dy_ext0 -= 1; - } - else { - ysv_ext1 += 1; - dy_ext1 -= 1; - } - } - else { - ysv_ext0 = ysv_ext1 = ysb; - dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x04) != 0) { - zsv_ext0 = zsv_ext1 = zsb + 1; - dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - if ((c1 & 0x03) == 0) { - zsv_ext0 += 1; - dz_ext0 -= 1; - } - else { - zsv_ext1 += 1; - dz_ext1 -= 1; - } - } - else { - zsv_ext0 = zsv_ext1 = zsb; - dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; - } - - if ((c1 & 0x08) != 0) { - wsv_ext0 = wsb + 1; - wsv_ext1 = wsb + 2; - dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; - } - else { - wsv_ext0 = wsv_ext1 = wsb; - dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; - } - - // One contribution is a permutation of (1,1,1,-1) based on the - // smaller-sided point - xsv_ext2 = xsb + 1; - ysv_ext2 = ysb + 1; - zsv_ext2 = zsb + 1; - wsv_ext2 = wsb + 1; - dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - if ((c2 & 0x01) == 0) { - xsv_ext2 -= 2; - dx_ext2 += 2; - } - else if ((c2 & 0x02) == 0) { - ysv_ext2 -= 2; - dy_ext2 += 2; - } - else if ((c2 & 0x04) == 0) { - zsv_ext2 -= 2; - dz_ext2 += 2; - } - else { - wsv_ext2 -= 2; - dw_ext2 += 2; - } - } - - // Contribution (1,1,1,0) - double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; - double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; - double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; - if (attn4 > 0) { - attn4 *= attn4; - value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); - } - - // Contribution (1,1,0,1) - double dx3 = dx4; - double dy3 = dy4; - double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; - double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; - double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; - if (attn3 > 0) { - attn3 *= attn3; - value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); - } - - // Contribution (1,0,1,1) - double dx2 = dx4; - double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; - double dz2 = dz4; - double dw2 = dw3; - double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; - if (attn2 > 0) { - attn2 *= attn2; - value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); - } - - // Contribution (0,1,1,1) - double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; - double dz1 = dz4; - double dy1 = dy4; - double dw1 = dw3; - double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; - if (attn1 > 0) { - attn1 *= attn1; - value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); - } - - // Contribution (1,1,0,0) - double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; - if (attn5 > 0) { - attn5 *= attn5; - value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); - } - - // Contribution (1,0,1,0) - double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; - if (attn6 > 0) { - attn6 *= attn6; - value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); - } - - // Contribution (1,0,0,1) - double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; - if (attn7 > 0) { - attn7 *= attn7; - value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); - } - - // Contribution (0,1,1,0) - double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; - double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; - if (attn8 > 0) { - attn8 *= attn8; - value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); - } - - // Contribution (0,1,0,1) - double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; - if (attn9 > 0) { - attn9 *= attn9; - value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); - } - - // Contribution (0,0,1,1) - double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; - double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; - double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; - double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; - if (attn10 > 0) { - attn10 *= attn10; - value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); - } - } - - // First extra vertex - double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; - if (attn_ext0 > 0) { - attn_ext0 *= attn_ext0; - value += attn_ext0 * attn_ext0 * extrapolate( - xsv_ext0, - ysv_ext0, - zsv_ext0, - wsv_ext0, - dx_ext0, - dy_ext0, - dz_ext0, - dw_ext0 - ); - } - - // Second extra vertex - double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; - if (attn_ext1 > 0) { - attn_ext1 *= attn_ext1; - value += attn_ext1 * attn_ext1 * extrapolate( - xsv_ext1, - ysv_ext1, - zsv_ext1, - wsv_ext1, - dx_ext1, - dy_ext1, - dz_ext1, - dw_ext1 - ); - } - - // Third extra vertex - double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; - if (attn_ext2 > 0) { - attn_ext2 *= attn_ext2; - value += attn_ext2 * attn_ext2 * extrapolate( - xsv_ext2, - ysv_ext2, - zsv_ext2, - wsv_ext2, - dx_ext2, - dy_ext2, - dz_ext2, - dw_ext2 - ); - } - - return value / NORM_CONSTANT_4D; - } - - private double extrapolate(int xsb, int ysb, double dx, double dy) { - int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; - return gradients2D[index] * dx + gradients2D[index + 1] * dy; - } - - private double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) { - int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; - return gradients3D[index] * dx + gradients3D[index + 1] * dy + gradients3D[index + 2] * dz; - } - - private double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) { - int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; - return gradients4D[index] * dx + gradients4D[index + 1] * dy + gradients4D[index + 2] * dz + gradients4D[index + 3] * dw; - } - - private static int fastFloor(double x) { - int xi = (int) x; - return x < xi ? xi - 1 : xi; - } - - // Gradients for 2D. They approximate the directions to the - // vertices of an octagon from the center. - private static byte[] gradients2D = new byte[] {5, 2, 2, 5, -5, 2, -2, 5, 5, -2, 2, -5, -5, -2, -2, -5,}; - - // Gradients for 3D. They approximate the directions to the - // vertices of a rhombicuboctahedron from the center, skewed so - // that the triangular and square facets can be inscribed inside - // circles of the same radius. - private static byte[] gradients3D = new byte[] { - -11, - 4, - 4, - -4, - 11, - 4, - -4, - 4, - 11, - 11, - 4, - 4, - 4, - 11, - 4, - 4, - 4, - 11, - -11, - -4, - 4, - -4, - -11, - 4, - -4, - -4, - 11, - 11, - -4, - 4, - 4, - -11, - 4, - 4, - -4, - 11, - -11, - 4, - -4, - -4, - 11, - -4, - -4, - 4, - -11, - 11, - 4, - -4, - 4, - 11, - -4, - 4, - 4, - -11, - -11, - -4, - -4, - -4, - -11, - -4, - -4, - -4, - -11, - 11, - -4, - -4, - 4, - -11, - -4, - 4, - -4, - -11, - }; - - // Gradients for 4D. They approximate the directions to the - // vertices of a disprismatotesseractihexadecachoron from the center, - // skewed so that the tetrahedral and cubic facets can be inscribed inside - // spheres of the same radius. - private static byte[] gradients4D = new byte[] { - 3, - 1, - 1, - 1, - 1, - 3, - 1, - 1, - 1, - 1, - 3, - 1, - 1, - 1, - 1, - 3, - -3, - 1, - 1, - 1, - -1, - 3, - 1, - 1, - -1, - 1, - 3, - 1, - -1, - 1, - 1, - 3, - 3, - -1, - 1, - 1, - 1, - -3, - 1, - 1, - 1, - -1, - 3, - 1, - 1, - -1, - 1, - 3, - -3, - -1, - 1, - 1, - -1, - -3, - 1, - 1, - -1, - -1, - 3, - 1, - -1, - -1, - 1, - 3, - 3, - 1, - -1, - 1, - 1, - 3, - -1, - 1, - 1, - 1, - -3, - 1, - 1, - 1, - -1, - 3, - -3, - 1, - -1, - 1, - -1, - 3, - -1, - 1, - -1, - 1, - -3, - 1, - -1, - 1, - -1, - 3, - 3, - -1, - -1, - 1, - 1, - -3, - -1, - 1, - 1, - -1, - -3, - 1, - 1, - -1, - -1, - 3, - -3, - -1, - -1, - 1, - -1, - -3, - -1, - 1, - -1, - -1, - -3, - 1, - -1, - -1, - -1, - 3, - 3, - 1, - 1, - -1, - 1, - 3, - 1, - -1, - 1, - 1, - 3, - -1, - 1, - 1, - 1, - -3, - -3, - 1, - 1, - -1, - -1, - 3, - 1, - -1, - -1, - 1, - 3, - -1, - -1, - 1, - 1, - -3, - 3, - -1, - 1, - -1, - 1, - -3, - 1, - -1, - 1, - -1, - 3, - -1, - 1, - -1, - 1, - -3, - -3, - -1, - 1, - -1, - -1, - -3, - 1, - -1, - -1, - -1, - 3, - -1, - -1, - -1, - 1, - -3, - 3, - 1, - -1, - -1, - 1, - 3, - -1, - -1, - 1, - 1, - -3, - -1, - 1, - 1, - -1, - -3, - -3, - 1, - -1, - -1, - -1, - 3, - -1, - -1, - -1, - 1, - -3, - -1, - -1, - 1, - -1, - -3, - 3, - -1, - -1, - -1, - 1, - -3, - -1, - -1, - 1, - -1, - -3, - -1, - 1, - -1, - -1, - -3, - -3, - -1, - -1, - -1, - -1, - -3, - -1, - -1, - -1, - -1, - -3, - -1, - -1, - -1, - -1, - -3, - }; -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/FireflyParticle.java b/src/main/java/ru/betterend/particle/FireflyParticle.java deleted file mode 100644 index 80505a3e..00000000 --- a/src/main/java/ru/betterend/particle/FireflyParticle.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class FireflyParticle extends SimpleAnimatedParticle { - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected FireflyParticle(ClientLevel world, double x, double y, double z, SpriteSet sprites, double r, double g, double b) { - super(world, x, y, z, sprites, 0); - setSprite(sprites.get(random)); - this.lifetime = MHelper.randRange(150, 300, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setFadeColor(15916745); - this.setSpriteFromAge(sprites); - this.setAlpha(0); - - preVX = random.nextGaussian() * 0.02; - preVY = random.nextGaussian() * 0.02; - preVZ = random.nextGaussian() * 0.02; - - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - - @Override - public void tick() { - int ticks = this.age & 31; - if (ticks == 0) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - double delta = (double) ticks / 31.0; - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - if (this.age <= 60) { - this.setAlpha(this.age / 60F); - } - else if (this.age > lifetime - 60) { - this.setAlpha((lifetime - this.age) / 60F); - } - - super.tick(); - } - - @Environment(EnvType.CLIENT) - public static class FireflyParticleFactory implements ParticleProvider { - private final SpriteSet sprites; - - public FireflyParticleFactory(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new FireflyParticle(world, x, y, z, sprites, 1, 1, 1); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/InfusionParticle.java b/src/main/java/ru/betterend/particle/InfusionParticle.java deleted file mode 100644 index 35cc2cf8..00000000 --- a/src/main/java/ru/betterend/particle/InfusionParticle.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.client.particle.TextureSheetParticle; - -public class InfusionParticle extends TextureSheetParticle { - - private final SpriteSet spriteProvider; - - public InfusionParticle(ClientLevel clientWorld, double x, double y, double z, double velocityX, double velocityY, double velocityZ, float[] palette, SpriteSet spriteProvider) { - super(clientWorld, x, y, z, 0.0, 0.0, 0.0); - this.setSpriteFromAge(spriteProvider); - this.spriteProvider = spriteProvider; - this.setColor(palette[0], palette[1], palette[2]); - this.setAlpha(palette[3]); - this.xd = velocityX * 0.1D; - this.yd = velocityY * 0.1D; - this.zd = velocityZ * 0.1D; - this.lifetime = (int) (3.0F / (this.random.nextFloat() * 0.9F + 0.1F)); - this.quadSize *= 0.9F; - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Override - public void tick() { - this.xo = this.x; - this.yo = this.y; - this.zo = this.z; - if (this.age++ >= this.lifetime) { - this.remove(); - } - else { - this.setSpriteFromAge(spriteProvider); - double velocityX = 2.0D * this.xd * this.random.nextDouble(); - double velocityY = 3.0D * this.yd * this.random.nextDouble(); - double velocityZ = 2.0D * this.zd * this.random.nextDouble(); - this.move(velocityX, velocityY, velocityZ); - } - } - - @Environment(EnvType.CLIENT) - public static class InfusionFactory implements ParticleProvider { - private final SpriteSet spriteProvider; - - public InfusionFactory(SpriteSet spriteProvider) { - this.spriteProvider = spriteProvider; - } - - public Particle createParticle(InfusionParticleType particleType, ClientLevel clientWorld, double d, double e, double f, double g, double h, double i) { - return new InfusionParticle(clientWorld, d, e, f, g, h, i, particleType.getPalette(), this.spriteProvider); - } - } -} diff --git a/src/main/java/ru/betterend/particle/InfusionParticleType.java b/src/main/java/ru/betterend/particle/InfusionParticleType.java deleted file mode 100644 index 73e473f2..00000000 --- a/src/main/java/ru/betterend/particle/InfusionParticleType.java +++ /dev/null @@ -1,78 +0,0 @@ -package ru.betterend.particle; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.serialization.Codec; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.commands.arguments.item.ItemInput; -import net.minecraft.commands.arguments.item.ItemParser; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.Registry; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.item.ItemStack; -import ru.bclib.util.ColorUtil; -import ru.betterend.registry.EndParticles; - -public class InfusionParticleType extends ParticleType implements ParticleOptions { - public static final Codec CODEC = ItemStack.CODEC.xmap(itemStack -> new InfusionParticleType( - EndParticles.INFUSION, - itemStack - ), infusionParticleType -> infusionParticleType.itemStack); - - @SuppressWarnings("deprecation") - public static final ParticleOptions.Deserializer PARAMETERS_FACTORY = new ParticleOptions.Deserializer() { - public InfusionParticleType fromCommand(ParticleType particleType, StringReader stringReader) throws CommandSyntaxException { - stringReader.expect(' '); - ItemParser.ItemResult itemResult = ItemParser.parseForItem(HolderLookup.forRegistry(Registry.ITEM), stringReader); - ItemStack itemStack = new ItemInput(itemResult.item(), itemResult.nbt()).createItemStack(1, false); - - return new InfusionParticleType(particleType, itemStack); - } - - public InfusionParticleType fromNetwork(ParticleType particleType, FriendlyByteBuf packetByteBuf) { - return new InfusionParticleType(particleType, packetByteBuf.readItem()); - } - }; - - private final ParticleType type; - private final ItemStack itemStack; - - public InfusionParticleType(ParticleType particleType, ItemStack stack) { - super(true, PARAMETERS_FACTORY); - this.type = particleType; - this.itemStack = stack; - } - - public InfusionParticleType(ItemStack stack) { - this(EndParticles.INFUSION, stack); - } - - @Environment(EnvType.CLIENT) - public float[] getPalette() { - int color = ColorUtil.extractColor(itemStack.getItem()); - return ColorUtil.toFloatArray(color); - } - - @Override - public ParticleType getType() { - return this.type; - } - - @Override - public void writeToNetwork(FriendlyByteBuf buffer) { - buffer.writeItem(itemStack); - } - - @Override - public String writeToString() { - return Registry.PARTICLE_TYPE.getKey(this).toString(); - } - - @Override - public Codec codec() { - return CODEC; - } -} diff --git a/src/main/java/ru/betterend/particle/ParticleBlackSpore.java b/src/main/java/ru/betterend/particle/ParticleBlackSpore.java deleted file mode 100644 index dee3e30b..00000000 --- a/src/main/java/ru/betterend/particle/ParticleBlackSpore.java +++ /dev/null @@ -1,92 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleBlackSpore extends SimpleAnimatedParticle { - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected ParticleBlackSpore(ClientLevel world, double x, double y, double z, double r, double g, double b, SpriteSet sprites) { - super(world, x, y, z, sprites, 0); - setSprite(sprites.get(random)); - - this.lifetime = MHelper.randRange(30, 60, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setColor(1, 1, 1); - this.setAlpha(0); - - preVX = random.nextGaussian() * 0.015; - preVY = 0; - preVZ = random.nextGaussian() * 0.015; - - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextFloat() * 0.02 + 0.01; - nextVZ = random.nextGaussian() * 0.015; - } - - @Override - public void tick() { - int ticks = this.age & 15; - if (ticks == 0) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextFloat() * 0.02 + 0.01; - nextVZ = random.nextGaussian() * 0.015; - } - double delta = (double) ticks / 15.0; - - if (this.age <= 15) { - this.setAlpha(this.age / 15F); - } - else if (this.age >= this.lifetime - 15) { - this.setAlpha((this.lifetime - this.age) / 15F); - } - - if (this.age >= this.lifetime) { - this.remove(); - } - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class FactoryBlackSpore implements ParticleProvider { - - private final SpriteSet sprites; - - public FactoryBlackSpore(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleBlackSpore(world, x, y, z, 1, 1, 1, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleGeyser.java b/src/main/java/ru/betterend/particle/ParticleGeyser.java deleted file mode 100644 index 6da20d09..00000000 --- a/src/main/java/ru/betterend/particle/ParticleGeyser.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.client.particle.TextureSheetParticle; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.particles.SimpleParticleType; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleGeyser extends TextureSheetParticle { - private MutableBlockPos mut = new MutableBlockPos(); - private boolean changeDir = false; - private boolean check = true; - - protected ParticleGeyser(ClientLevel world, double x, double y, double z, double vx, double vy, double vz, SpriteSet sprites) { - super(world, x, y, z, vx, vy, vz); - pickSprite(sprites); - this.lifetime = MHelper.randRange(400, 800, random); - this.quadSize = MHelper.randRange(0.5F, 1.0F, random); - this.xd = vx; - this.zd = vz; - this.yo = y - 0.125; - } - - @Override - public void tick() { - - if (this.yo == this.y || this.age > this.lifetime) { - this.remove(); - } - else { - if (this.age >= this.lifetime - 200) { - this.setAlpha((this.lifetime - this.age) / 200F); - } - - this.quadSize += 0.005F; - this.yd = 0.125; - - if (changeDir) { - changeDir = false; - check = false; - this.xd += MHelper.randRange(-0.2, 0.2, random); - this.zd += MHelper.randRange(-0.2, 0.2, random); - } - else if (check) { - changeDir = level.getBlockState(mut.set(x, y, z)).getFluidState().isEmpty(); - this.xd = 0; - this.zd = 0; - } - } - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class FactoryGeyser implements ParticleProvider { - - private final SpriteSet sprites; - - public FactoryGeyser(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleGeyser(world, x, y, z, 0, 0.125, 0, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleGlowingSphere.java b/src/main/java/ru/betterend/particle/ParticleGlowingSphere.java deleted file mode 100644 index c4f1d349..00000000 --- a/src/main/java/ru/betterend/particle/ParticleGlowingSphere.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleGlowingSphere extends SimpleAnimatedParticle { - private int ticks; - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected ParticleGlowingSphere(ClientLevel world, double x, double y, double z, SpriteSet sprites, double r, double g, double b) { - super(world, x, y, z, sprites, 0); - setSprite(sprites.get(random)); - this.lifetime = MHelper.randRange(150, 300, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setFadeColor(15916745); - this.setSpriteFromAge(sprites); - - preVX = random.nextGaussian() * 0.02; - preVY = random.nextGaussian() * 0.02; - preVZ = random.nextGaussian() * 0.02; - - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - - @Override - public void tick() { - ticks++; - if (ticks > 30) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - ticks = 0; - } - double delta = (double) ticks / 30.0; - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Environment(EnvType.CLIENT) - public static class FactoryGlowingSphere implements ParticleProvider { - - private final SpriteSet sprites; - - public FactoryGlowingSphere(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleGlowingSphere(world, x, y, z, sprites, 1, 1, 1); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleJungleSpore.java b/src/main/java/ru/betterend/particle/ParticleJungleSpore.java deleted file mode 100644 index 0488b778..00000000 --- a/src/main/java/ru/betterend/particle/ParticleJungleSpore.java +++ /dev/null @@ -1,70 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleJungleSpore extends SimpleAnimatedParticle { - - protected ParticleJungleSpore(ClientLevel world, double x, double y, double z, SpriteSet sprites, double r, double g, double b) { - super(world, x, y, z, sprites, 0); - setSprite(sprites.get(random)); - this.lifetime = MHelper.randRange(150, 300, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setFadeColor(15916745); - this.setSpriteFromAge(sprites); - this.setAlpha(0); - } - - @Override - public void tick() { - super.tick(); - - int ticks = this.age % 30; - if (ticks == 0) { - this.xd = random.nextGaussian() * 0.02; - this.yd = random.nextFloat() * 0.02 + 0.02; - this.zd = random.nextGaussian() * 0.02; - ticks = 0; - } - - if (this.age <= 30) { - float delta = ticks / 30F; - this.setAlpha(delta); - } - else if (this.age >= this.lifetime) { - this.setAlpha(0); - } - else if (this.age >= this.lifetime - 30) { - this.setAlpha((this.lifetime - this.age) / 30F); - } - else { - this.setAlpha(1); - } - - this.yd -= 0.001F; - this.xd *= 0.99F; - this.zd *= 0.99F; - } - - @Environment(EnvType.CLIENT) - public static class FactoryJungleSpore implements ParticleProvider { - private final SpriteSet sprites; - - public FactoryJungleSpore(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleJungleSpore(world, x, y, z, sprites, 1, 1, 1); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleSnowflake.java b/src/main/java/ru/betterend/particle/ParticleSnowflake.java deleted file mode 100644 index bcc46243..00000000 --- a/src/main/java/ru/betterend/particle/ParticleSnowflake.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.client.particle.TextureSheetParticle; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleSnowflake extends TextureSheetParticle { - private int ticks; - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected ParticleSnowflake(ClientLevel world, double x, double y, double z, double r, double g, double b, SpriteSet sprites) { - super(world, x, y, z, r, g, b); - pickSprite(sprites); - - this.lifetime = MHelper.randRange(150, 300, random); - this.quadSize = MHelper.randRange(0.05F, 0.2F, random); - this.setAlpha(0F); - - preVX = random.nextGaussian() * 0.015; - preVY = random.nextGaussian() * 0.015; - preVZ = random.nextGaussian() * 0.015; - - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextGaussian() * 0.015; - nextVZ = random.nextGaussian() * 0.015; - } - - @Override - public void tick() { - ticks++; - if (ticks > 200) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextGaussian() * 0.015; - nextVZ = random.nextGaussian() * 0.015; - if (random.nextInt(4) == 0) { - nextVY = Math.abs(nextVY); - } - ticks = 0; - } - double delta = (double) ticks / 200.0; - - if (this.age <= 40) { - this.setAlpha(this.age / 40F); - } - else if (this.age >= this.lifetime - 40) { - this.setAlpha((this.lifetime - this.age) / 40F); - } - - if (this.age >= this.lifetime) { - this.remove(); - } - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class FactorySnowflake implements ParticleProvider { - - private final SpriteSet sprites; - - public FactorySnowflake(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleSnowflake(world, x, y, z, 1, 1, 1, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleSulphur.java b/src/main/java/ru/betterend/particle/ParticleSulphur.java deleted file mode 100644 index 1cb57527..00000000 --- a/src/main/java/ru/betterend/particle/ParticleSulphur.java +++ /dev/null @@ -1,97 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.client.particle.TextureSheetParticle; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class ParticleSulphur extends TextureSheetParticle { - private int ticks; - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected ParticleSulphur(ClientLevel world, double x, double y, double z, double r, double g, double b, SpriteSet sprites) { - super(world, x, y, z, r, g, b); - pickSprite(sprites); - - this.lifetime = MHelper.randRange(150, 300, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setColor(1, 1, 1); - this.setAlpha(0); - - preVX = random.nextGaussian() * 0.015; - preVY = random.nextGaussian() * 0.015; - preVZ = random.nextGaussian() * 0.015; - - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextGaussian() * 0.015; - nextVZ = random.nextGaussian() * 0.015; - } - - @Override - public void tick() { - ticks++; - if (ticks > 200) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextGaussian() * 0.015; - nextVZ = random.nextGaussian() * 0.015; - if (random.nextInt(4) == 0) { - nextVY = Math.abs(nextVY); - } - ticks = 0; - } - double delta = (double) ticks / 200.0; - - if (this.age <= 40) { - this.setAlpha(this.age / 40F); - } - else if (this.age >= this.lifetime - 40) { - this.setAlpha((this.lifetime - this.age) / 40F); - } - - if (this.age >= this.lifetime) { - this.remove(); - } - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class FactorySulphur implements ParticleProvider { - - private final SpriteSet sprites; - - public FactorySulphur(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleSulphur(world, x, y, z, 1, 1, 1, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/ParticleTenaneaPetal.java b/src/main/java/ru/betterend/particle/ParticleTenaneaPetal.java deleted file mode 100644 index b0ca71f3..00000000 --- a/src/main/java/ru/betterend/particle/ParticleTenaneaPetal.java +++ /dev/null @@ -1,111 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.client.particle.TextureSheetParticle; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.interfaces.CustomColorProvider; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; - -@Environment(EnvType.CLIENT) -public class ParticleTenaneaPetal extends TextureSheetParticle { - private static BlockColor provider; - - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected ParticleTenaneaPetal(ClientLevel world, double x, double y, double z, double r, double g, double b, SpriteSet sprites) { - super(world, x, y, z, r, g, b); - pickSprite(sprites); - - if (provider == null) { - CustomColorProvider block = (CustomColorProvider) EndBlocks.TENANEA_FLOWERS; - provider = block.getProvider(); - } - int color = provider.getColor(null, null, new BlockPos(x, y, z), 0); - this.rCol = ((color >> 16) & 255) / 255F; - this.gCol = ((color >> 8) & 255) / 255F; - this.bCol = ((color) & 255) / 255F; - - this.lifetime = MHelper.randRange(120, 200, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setAlpha(0); - - preVX = 0; - preVY = 0; - preVZ = 0; - - nextVX = random.nextGaussian() * 0.02; - nextVY = -random.nextDouble() * 0.02 - 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - - @Override - public int getLightColor(float tint) { - return 15728880; - } - - @Override - public void tick() { - int ticks = this.age & 63; - if (ticks == 0) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.02; - nextVY = -random.nextDouble() * 0.02 - 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - double delta = (double) ticks / 63.0; - - if (this.age <= 40) { - this.setAlpha(this.age / 40F); - } - else if (this.age >= this.lifetime - 40) { - this.setAlpha((this.lifetime - this.age) / 40F); - } - - if (this.age >= this.lifetime) { - this.remove(); - } - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class FactoryTenaneaPetal implements ParticleProvider { - - private final SpriteSet sprites; - - public FactoryTenaneaPetal(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new ParticleTenaneaPetal(world, x, y, z, 1, 1, 1, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/particle/PaticlePortalSphere.java b/src/main/java/ru/betterend/particle/PaticlePortalSphere.java deleted file mode 100644 index 76ba79f2..00000000 --- a/src/main/java/ru/betterend/particle/PaticlePortalSphere.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -public class PaticlePortalSphere extends SimpleAnimatedParticle { - private int ticks; - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - public PaticlePortalSphere(ClientLevel world, double x, double y, double z, SpriteSet spriteProvider) { - super(world, x, y, z, spriteProvider, 0); - setSprite(spriteProvider.get(random)); - this.lifetime = MHelper.randRange(20, 80, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setColor(0xFEBBD5); - this.setFadeColor(0xBBFEE4); - this.setSpriteFromAge(spriteProvider); - - preVX = random.nextGaussian() * 0.02; - preVY = random.nextGaussian() * 0.02; - preVZ = random.nextGaussian() * 0.02; - - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - } - - @Override - public void tick() { - ticks++; - if (ticks > 30) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.02; - nextVY = random.nextGaussian() * 0.02; - nextVZ = random.nextGaussian() * 0.02; - ticks = 0; - } - double delta = (double) ticks / 30.0; - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Environment(EnvType.CLIENT) - public static class FactoryPortalSphere implements ParticleProvider { - - private final SpriteSet sprites; - - public FactoryPortalSphere(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new PaticlePortalSphere(world, x, y, z, sprites); - } - } -} diff --git a/src/main/java/ru/betterend/particle/SmaragdantParticle.java b/src/main/java/ru/betterend/particle/SmaragdantParticle.java deleted file mode 100644 index 946bca07..00000000 --- a/src/main/java/ru/betterend/particle/SmaragdantParticle.java +++ /dev/null @@ -1,92 +0,0 @@ -package ru.betterend.particle; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.util.Mth; -import ru.bclib.util.MHelper; - -@Environment(EnvType.CLIENT) -public class SmaragdantParticle extends SimpleAnimatedParticle { - private double preVX; - private double preVY; - private double preVZ; - private double nextVX; - private double nextVY; - private double nextVZ; - - protected SmaragdantParticle(ClientLevel world, double x, double y, double z, double r, double g, double b, SpriteSet sprites) { - super(world, x, y, z, sprites, 0); - setSprite(sprites.get(random)); - - this.lifetime = MHelper.randRange(60, 120, random); - this.quadSize = MHelper.randRange(0.05F, 0.15F, random); - this.setColor(1, 1, 1); - this.setAlpha(0); - - preVX = random.nextGaussian() * 0.01; - preVY = random.nextGaussian() * 0.01; - preVZ = random.nextGaussian() * 0.01; - - nextVX = random.nextGaussian() * 0.01; - nextVY = random.nextGaussian() * 0.01; - nextVZ = random.nextGaussian() * 0.01; - } - - @Override - public void tick() { - int ticks = this.age & 31; - if (ticks == 0) { - preVX = nextVX; - preVY = nextVY; - preVZ = nextVZ; - nextVX = random.nextGaussian() * 0.015; - nextVY = random.nextFloat() * 0.02 + 0.01; - nextVZ = random.nextGaussian() * 0.015; - } - double delta = (double) ticks / 31.0; - - if (this.age <= 31) { - this.setAlpha(this.age / 31F); - } - else if (this.age >= this.lifetime - 31) { - this.setAlpha((this.lifetime - this.age) / 31F); - } - - if (this.age >= this.lifetime) { - this.remove(); - } - - this.xd = Mth.lerp(delta, preVX, nextVX); - this.yd = Mth.lerp(delta, preVY, nextVY); - this.zd = Mth.lerp(delta, preVZ, nextVZ); - - super.tick(); - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; - } - - @Environment(EnvType.CLIENT) - public static class SmaragdantParticleFactory implements ParticleProvider { - - private final SpriteSet sprites; - - public SmaragdantParticleFactory(SpriteSet sprites) { - this.sprites = sprites; - } - - @Override - public Particle createParticle(SimpleParticleType type, ClientLevel world, double x, double y, double z, double vX, double vY, double vZ) { - return new SmaragdantParticle(world, x, y, z, 1, 1, 1, sprites); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/recipe/AlloyingRecipes.java b/src/main/java/ru/betterend/recipe/AlloyingRecipes.java deleted file mode 100644 index ea228cf6..00000000 --- a/src/main/java/ru/betterend/recipe/AlloyingRecipes.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.betterend.recipe; - -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Blocks; -import ru.betterend.recipe.builders.AlloyingRecipe; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; -import ru.betterend.registry.EndTags; - -public class AlloyingRecipes { - public static void register() { - AlloyingRecipe.Builder.create("additional_iron") - .setInput(EndTags.ALLOYING_IRON, EndTags.ALLOYING_IRON) - .setOutput(Items.IRON_INGOT, 3) - .setExpiriense(2.1F) - .build(); - AlloyingRecipe.Builder.create("additional_gold") - .setInput(EndTags.ALLOYING_GOLD, EndTags.ALLOYING_GOLD) - .setOutput(Items.GOLD_INGOT, 3) - .setExpiriense(3F) - .build(); - AlloyingRecipe.Builder.create("additional_copper") - .setInput(EndTags.ALLOYING_COPPER, EndTags.ALLOYING_COPPER) - .setOutput(Items.COPPER_INGOT, 3) - .setExpiriense(3F) - .build(); - AlloyingRecipe.Builder.create("additional_netherite") - .setInput(Blocks.ANCIENT_DEBRIS, Blocks.ANCIENT_DEBRIS) - .setOutput(Items.NETHERITE_SCRAP, 3) - .setExpiriense(6F) - .setSmeltTime(1000) - .build(); - AlloyingRecipe.Builder.create("terminite_ingot") - .setInput(Items.IRON_INGOT, EndItems.ENDER_DUST) - .setOutput(EndBlocks.TERMINITE.ingot, 1) - .setExpiriense(2.5F) - .setSmeltTime(450) - .build(); - AlloyingRecipe.Builder.create("aeternium_ingot") - .setInput(EndBlocks.TERMINITE.ingot, Items.NETHERITE_INGOT) - .setOutput(EndItems.AETERNIUM_INGOT, 1) - .setExpiriense(4.5F) - .setSmeltTime(850) - .build(); - AlloyingRecipe.Builder.create("terminite_ingot_thallasium") - .setInput(EndBlocks.THALLASIUM.ingot, EndItems.ENDER_DUST) - .setOutput(EndBlocks.TERMINITE.ingot, 1) - .setExpiriense(2.5F) - .setSmeltTime(450) - .build(); - } -} diff --git a/src/main/java/ru/betterend/recipe/AnvilRecipes.java b/src/main/java/ru/betterend/recipe/AnvilRecipes.java deleted file mode 100644 index 55bc83d4..00000000 --- a/src/main/java/ru/betterend/recipe/AnvilRecipes.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.betterend.recipe; - -import net.minecraft.world.item.Items; -import ru.bclib.recipes.AnvilRecipe; -import ru.betterend.config.Configs; -import ru.betterend.item.material.EndToolMaterial; -import ru.betterend.registry.EndItems; - -public class AnvilRecipes { - public static void register() { - AnvilRecipe.create("ender_pearl_to_dust") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(Items.ENDER_PEARL) - .setOutput(EndItems.ENDER_DUST) - .setToolLevel(4) - .setDamage(5) - .build(); - AnvilRecipe.create("ender_shard_to_dust") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.ENDER_SHARD) - .setOutput(EndItems.ENDER_DUST) - .setToolLevel(0) - .setDamage(3) - .build(); - - int anvilLevel = EndToolMaterial.AETERNIUM.getLevel(); - AnvilRecipe.create("aeternium_axe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_AXE_HEAD) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_pickaxe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_PICKAXE_HEAD) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_shovel_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_SHOVEL_HEAD) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_hoe_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_HOE_HEAD) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_hammer_head") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_HAMMER_HEAD) - .setAnvilLevel(anvilLevel) - .setToolLevel(EndToolMaterial.THALLASIUM.getLevel()) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_sword_blade") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_SWORD_BLADE) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - AnvilRecipe.create("aeternium_forged_plate") - .checkConfig(Configs.RECIPE_CONFIG) - .setInput(EndItems.AETERNIUM_INGOT) - .setOutput(EndItems.AETERNIUM_FORGED_PLATE) - .setAnvilLevel(anvilLevel) - .setToolLevel(anvilLevel) - .setDamage(6) - .build(); - } -} diff --git a/src/main/java/ru/betterend/recipe/CraftingRecipes.java b/src/main/java/ru/betterend/recipe/CraftingRecipes.java deleted file mode 100644 index 92e9227f..00000000 --- a/src/main/java/ru/betterend/recipe/CraftingRecipes.java +++ /dev/null @@ -1,483 +0,0 @@ -package ru.betterend.recipe; - -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.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.api.tag.CommonItemTags; -import ru.bclib.recipes.GridRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class CraftingRecipes { - - public static void register() { - GridRecipe.make(BetterEnd.MOD_ID, "ender_perl_to_block", EndBlocks.ENDER_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("OO", "OO") - .addMaterial('O', Items.ENDER_PEARL) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "ender_block_to_perl", Items.ENDER_PEARL) - .checkConfig(Configs.RECIPE_CONFIG) - .addMaterial('#', EndBlocks.ENDER_BLOCK) - .setOutputCount(4) - .setList("#") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "end_stone_smelter", EndBlocks.END_STONE_SMELTER) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("T#T", "V V", "T#T") - .addMaterial('#', Blocks.END_STONE_BRICKS) - .addMaterial('T', EndBlocks.THALLASIUM.ingot) - .addMaterial('V', CommonItemTags.FURNACES) - .build(); - - registerPedestal( - "andesite_pedestal", - EndBlocks.ANDESITE_PEDESTAL, - Blocks.POLISHED_ANDESITE_SLAB, - Blocks.POLISHED_ANDESITE - ); - registerPedestal( - "diorite_pedestal", - EndBlocks.DIORITE_PEDESTAL, - Blocks.POLISHED_DIORITE_SLAB, - Blocks.POLISHED_DIORITE - ); - registerPedestal( - "granite_pedestal", - EndBlocks.GRANITE_PEDESTAL, - Blocks.POLISHED_GRANITE_SLAB, - Blocks.POLISHED_GRANITE - ); - registerPedestal("quartz_pedestal", EndBlocks.QUARTZ_PEDESTAL, Blocks.QUARTZ_SLAB, Blocks.QUARTZ_PILLAR); - registerPedestal("purpur_pedestal", EndBlocks.PURPUR_PEDESTAL, Blocks.PURPUR_SLAB, Blocks.PURPUR_PILLAR); - - GridRecipe.make(BetterEnd.MOD_ID, "infusion_pedestal", EndBlocks.INFUSION_PEDESTAL) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape(" Y ", "O#O", " # ") - .addMaterial('O', Items.ENDER_PEARL) - .addMaterial('Y', Items.ENDER_EYE) - .addMaterial('#', Blocks.OBSIDIAN) - .build(); - - String material = "aeternium"; - GridRecipe.make(BetterEnd.MOD_ID, material + "_block", EndBlocks.AETERNIUM_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("III", "III", "III") - .addMaterial('I', EndItems.AETERNIUM_INGOT) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, material + "_block_to_ingot", EndItems.AETERNIUM_INGOT) - .checkConfig(Configs.RECIPE_CONFIG) - .addMaterial('#', EndBlocks.AETERNIUM_BLOCK) - .setOutputCount(9) - .setList("#") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "blue_vine_seed_dye", Items.BLUE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.BLUE_VINE_SEED) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "creeping_moss_dye", Items.CYAN_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CREEPING_MOSS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "umbrella_moss_dye", Items.YELLOW_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.UMBRELLA_MOSS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "umbrella_moss_tall_dye", Items.YELLOW_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(2) - .setList("#") - .addMaterial('#', EndBlocks.UMBRELLA_MOSS_TALL) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "shadow_plant_dye", Items.BLACK_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.SHADOW_PLANT) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "paper", Items.PAPER) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###") - .addMaterial('#', EndItems.END_LILY_LEAF_DRIED) - .setOutputCount(3) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "aurora_block", EndBlocks.AURORA_CRYSTAL) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndItems.CRYSTAL_SHARDS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "lotus_block", EndBlocks.END_LOTUS.getLog()) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndBlocks.END_LOTUS_STEM) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "needlegrass_stick", Items.STICK) - .setList("#") - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(2) - .addMaterial('#', EndBlocks.NEEDLEGRASS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_seeds", EndBlocks.SHADOW_BERRY) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .setOutputCount(4) - .addMaterial('#', EndItems.SHADOW_BERRY_RAW) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "purple_polypore_dye", Items.PURPLE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.PURPLE_POLYPORE) - .build(); - - registerLantern("end_stone_lantern", EndBlocks.END_STONE_LANTERN, Blocks.END_STONE_BRICK_SLAB); - registerLantern("andesite_lantern", EndBlocks.ANDESITE_LANTERN, Blocks.ANDESITE_SLAB); - registerLantern("diorite_lantern", EndBlocks.DIORITE_LANTERN, Blocks.DIORITE_SLAB); - registerLantern("granite_lantern", EndBlocks.GRANITE_LANTERN, Blocks.GRANITE_SLAB); - registerLantern("quartz_lantern", EndBlocks.QUARTZ_LANTERN, Blocks.QUARTZ_SLAB); - registerLantern("purpur_lantern", EndBlocks.PURPUR_LANTERN, Blocks.PURPUR_SLAB); - registerLantern("blackstone_lantern", EndBlocks.BLACKSTONE_LANTERN, Blocks.BLACKSTONE_SLAB); - - GridRecipe.make(BetterEnd.MOD_ID, "amber_gem", EndItems.AMBER_GEM) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndItems.RAW_AMBER) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "amber_block", EndBlocks.AMBER_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndItems.AMBER_GEM) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "amber_gem_block", EndItems.AMBER_GEM) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setList("#") - .addMaterial('#', EndBlocks.AMBER_BLOCK) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "iron_bulb_lantern", EndBlocks.IRON_BULB_LANTERN) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("C", "I", "#") - .addMaterial('C', Items.CHAIN) - .addMaterial('I', Items.IRON_INGOT) - .addMaterial('#', EndItems.GLOWING_BULB) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "twisted_moss_dye", Items.PINK_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.TWISTED_MOSS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "byshy_grass_dye", Items.MAGENTA_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.BUSHY_GRASS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "tail_moss_dye", Items.GRAY_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.TAIL_MOSS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "petal_block", EndBlocks.HYDRALUX_PETAL_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndItems.HYDRALUX_PETAL) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "petal_white_dye", Items.WHITE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndItems.HYDRALUX_PETAL) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "sweet_berry_jelly", EndItems.SWEET_BERRY_JELLY) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("JWSB") - .addMaterial('J', EndItems.GELATINE) - .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) - .addMaterial('S', Items.SUGAR) - .addMaterial('B', Items.SWEET_BERRIES) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_jelly", EndItems.SHADOW_BERRY_JELLY) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("JWSB") - .addMaterial('J', EndItems.GELATINE) - .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) - .addMaterial('S', Items.SUGAR) - .addMaterial('B', EndItems.SHADOW_BERRY_COOKED) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "shadow_berry_jelly", EndItems.BLOSSOM_BERRY_JELLY) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("JWSB") - .addMaterial('J', EndItems.GELATINE) - .addMaterial('W', PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)) - .addMaterial('S', Items.SUGAR) - .addMaterial('B', EndItems.BLOSSOM_BERRY) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "sulphur_gunpowder", Items.GUNPOWDER) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("SCB") - .addMaterial('S', EndItems.CRYSTALLINE_SULPHUR) - .addMaterial('C', Items.COAL, Items.CHARCOAL) - .addMaterial('B', Items.BONE_MEAL) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "dense_emerald_ice", EndBlocks.DENSE_EMERALD_ICE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndBlocks.EMERALD_ICE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "ancient_emerald_ice", EndBlocks.ANCIENT_EMERALD_ICE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "###", "###") - .addMaterial('#', EndBlocks.DENSE_EMERALD_ICE) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "charnia_cyan_dye", Items.CYAN_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_CYAN) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charnia_green_dye", Items.GREEN_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_GREEN) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charnia_light_blue_dye", Items.LIGHT_BLUE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_LIGHT_BLUE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charnia_orange_dye", Items.ORANGE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_ORANGE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charnia_purple_dye", Items.PURPLE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_PURPLE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charnia_red_dye", Items.RED_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.CHARNIA_RED) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "respawn_obelisk", EndBlocks.RESPAWN_OBELISK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("CSC", "CSC", "AAA") - .addMaterial('C', EndBlocks.AURORA_CRYSTAL) - .addMaterial('S', EndItems.ETERNAL_CRYSTAL) - .addMaterial('A', EndBlocks.AMBER_BLOCK) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "twisted_umbrella_moss_dye", Items.PURPLE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("#") - .addMaterial('#', EndBlocks.TWISTED_UMBRELLA_MOSS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "twisted_umbrella_moss_dye_tall", Items.PURPLE_DYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(2) - .setList("#") - .addMaterial('#', EndBlocks.TWISTED_UMBRELLA_MOSS_TALL) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "leather_to_stripes", EndItems.LEATHER_STRIPE) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("L") - .addMaterial('L', Items.LEATHER) - .setOutputCount(3) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "stripes_to_leather", Items.LEATHER) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("SSS") - .addMaterial('S', EndItems.LEATHER_STRIPE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "leather_wrapped_stick", EndItems.LEATHER_WRAPPED_STICK) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("SL") - .addMaterial('S', Items.STICK) - .addMaterial('L', EndItems.LEATHER_STRIPE) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "fiber_string", Items.STRING) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(6) - .setShape("#", "#", "#") - .addMaterial('#', EndItems.SILK_FIBER) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "ender_eye_amber", Items.ENDER_EYE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("SAS", "APA", "SAS") - .addMaterial('S', EndItems.CRYSTAL_SHARDS) - .addMaterial('A', EndItems.AMBER_GEM) - .addMaterial('P', Items.ENDER_PEARL) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "iron_chandelier", EndBlocks.IRON_CHANDELIER) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("I#I", " # ") - .addMaterial('#', Items.IRON_INGOT) - .addMaterial('I', EndItems.LUMECORN_ROD) - .setGroup("end_metal_chandelier") - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "gold_chandelier", EndBlocks.GOLD_CHANDELIER) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("I#I", " # ") - .addMaterial('#', Items.GOLD_INGOT) - .addMaterial('I', EndItems.LUMECORN_ROD) - .setGroup("end_metal_chandelier") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "missing_tile", EndBlocks.MISSING_TILE) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setShape("#P", "P#") - .addMaterial('#', EndBlocks.VIOLECITE.stone, EndBlocks.VIOLECITE.bricks, EndBlocks.VIOLECITE.tiles) - .addMaterial('P', Blocks.PURPUR_BLOCK) - .build(); - - registerHammer("iron", Items.IRON_INGOT, EndItems.IRON_HAMMER); - registerHammer("golden", Items.GOLD_INGOT, EndItems.GOLDEN_HAMMER); - registerHammer("diamond", Items.DIAMOND, EndItems.DIAMOND_HAMMER); - - GridRecipe.make(BetterEnd.MOD_ID, "charcoal_block", EndBlocks.CHARCOAL_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "###", "###") - .addMaterial('#', Items.CHARCOAL) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "charcoal_from_block", Items.CHARCOAL) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(9) - .setList("#") - .addMaterial('#', EndBlocks.CHARCOAL_BLOCK) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "end_stone_furnace", EndBlocks.END_STONE_FURNACE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "# #", "###") - .addMaterial('#', Blocks.END_STONE) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "filalux_lantern", EndBlocks.FILALUX_LANTERN) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###", "###", "###") - .addMaterial('#', EndBlocks.FILALUX) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "silk_moth_hive", EndBlocks.SILK_MOTH_HIVE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("#L#", "LML", "#L#") - .addMaterial('#', EndBlocks.TENANEA.getBlock("planks")) - .addMaterial('L', EndBlocks.TENANEA_LEAVES) - .addMaterial('M', EndItems.SILK_MOTH_MATRIX) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "cave_pumpkin_pie", EndItems.CAVE_PUMPKIN_PIE) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("SBS", "BPB", "SBS") - .addMaterial('P', EndBlocks.CAVE_PUMPKIN) - .addMaterial('B', EndItems.BLOSSOM_BERRY, EndItems.SHADOW_BERRY_RAW) - .addMaterial('S', Items.SUGAR) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "cave_pumpkin_seeds", EndBlocks.CAVE_PUMPKIN_SEED) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(4) - .setList("#") - .addMaterial('#', EndBlocks.CAVE_PUMPKIN) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block", EndBlocks.NEON_CACTUS_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("##", "##") - .addMaterial('#', EndBlocks.NEON_CACTUS) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block_slab", EndBlocks.NEON_CACTUS_BLOCK_SLAB) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###") - .setOutputCount(6) - .addMaterial('#', EndBlocks.NEON_CACTUS_BLOCK) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "neon_cactus_block_stairs", EndBlocks.NEON_CACTUS_BLOCK_STAIRS) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("# ", "## ", "###") - .setOutputCount(4) - .addMaterial('#', EndBlocks.NEON_CACTUS_BLOCK) - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "sugar_from_root", Items.SUGAR) - .checkConfig(Configs.RECIPE_CONFIG) - .setList("###") - .addMaterial('#', EndItems.AMBER_ROOT_RAW) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "endstone_flower_pot", EndBlocks.ENDSTONE_FLOWER_POT) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(3) - .setShape("# #", " # ") - .addMaterial('#', Blocks.END_STONE_BRICKS) - .setGroup("end_pots") - .build(); - - GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_block", EndBlocks.DRAGON_BONE_BLOCK) - .checkConfig(Configs.RECIPE_CONFIG) - .setOutputCount(8) - .setShape("###", "#D#", "###") - .addMaterial('#', Blocks.BONE_BLOCK) - .addMaterial('D', Items.DRAGON_BREATH) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_slab", EndBlocks.DRAGON_BONE_SLAB) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("###") - .setOutputCount(6) - .addMaterial('#', EndBlocks.DRAGON_BONE_BLOCK) - .build(); - GridRecipe.make(BetterEnd.MOD_ID, "dragon_bone_stairs", EndBlocks.DRAGON_BONE_STAIRS) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("# ", "## ", "###") - .setOutputCount(4) - .addMaterial('#', EndBlocks.DRAGON_BONE_BLOCK) - .build(); - } - - private static void registerLantern(String name, Block lantern, Block slab) { - GridRecipe.make(BetterEnd.MOD_ID, name, lantern) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("S", "#", "S") - .addMaterial('#', EndItems.CRYSTAL_SHARDS) - .addMaterial('S', slab) - .setGroup("end_stone_lanterns") - .build(); - } - - public static void registerPedestal(String name, Block pedestal, Block slab, Block pillar) { - GridRecipe.make(BetterEnd.MOD_ID, name, pedestal) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("S", "#", "S") - .addMaterial('S', slab) - .addMaterial('#', pillar) - .setOutputCount(2) - .build(); - } - - private static void registerHammer(String name, Item material, Item result) { - GridRecipe.make(BetterEnd.MOD_ID, name + "_hammer", result) - .checkConfig(Configs.RECIPE_CONFIG) - .setShape("I I", "I#I", " # ") - .addMaterial('I', material) - .addMaterial('#', Items.STICK) - .build(); - } -} diff --git a/src/main/java/ru/betterend/recipe/FurnaceRecipes.java b/src/main/java/ru/betterend/recipe/FurnaceRecipes.java deleted file mode 100644 index 0b3446bd..00000000 --- a/src/main/java/ru/betterend/recipe/FurnaceRecipes.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.betterend.recipe; - -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.recipes.FurnaceRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class FurnaceRecipes { - public static void register() { - FurnaceRecipe.make( - BetterEnd.MOD_ID, - "end_lily_leaf_dried", - EndItems.END_LILY_LEAF, - EndItems.END_LILY_LEAF_DRIED - ).checkConfig(Configs.RECIPE_CONFIG).build(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "end_glass", EndBlocks.ENDSTONE_DUST, Blocks.GLASS) - .checkConfig(Configs.RECIPE_CONFIG) - .build(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "end_berry", EndItems.SHADOW_BERRY_RAW, EndItems.SHADOW_BERRY_COOKED) - .checkConfig(Configs.RECIPE_CONFIG) - .buildFoodlike(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "end_fish", EndItems.END_FISH_RAW, EndItems.END_FISH_COOKED) - .checkConfig(Configs.RECIPE_CONFIG) - .buildFoodlike(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "slime_ball", EndBlocks.JELLYSHROOM_CAP_PURPLE, Items.SLIME_BALL) - .checkConfig(Configs.RECIPE_CONFIG) - .build(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "menger_sponge", EndBlocks.MENGER_SPONGE_WET, EndBlocks.MENGER_SPONGE) - .checkConfig(Configs.RECIPE_CONFIG) - .build(); - FurnaceRecipe.make( - BetterEnd.MOD_ID, - "chorus_mushroom", - EndItems.CHORUS_MUSHROOM_RAW, - EndItems.CHORUS_MUSHROOM_COOKED - ).checkConfig(Configs.RECIPE_CONFIG).buildFoodlike(); - FurnaceRecipe.make(BetterEnd.MOD_ID, "bolux_mushroom", EndBlocks.BOLUX_MUSHROOM, EndItems.BOLUX_MUSHROOM_COOKED) - .checkConfig(Configs.RECIPE_CONFIG) - .buildFoodlike(); - } -} diff --git a/src/main/java/ru/betterend/recipe/InfusionRecipes.java b/src/main/java/ru/betterend/recipe/InfusionRecipes.java deleted file mode 100644 index 93ce4fce..00000000 --- a/src/main/java/ru/betterend/recipe/InfusionRecipes.java +++ /dev/null @@ -1,614 +0,0 @@ -package ru.betterend.recipe; - -import net.minecraft.world.item.EnchantedBookItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentInstance; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.block.Blocks; -import ru.betterend.recipe.builders.InfusionRecipe; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class InfusionRecipes { - public static void register() { - InfusionRecipe.Builder.create("runed_flavolite") - .setInput(EndBlocks.FLAVOLITE.polished) - .setOutput(EndBlocks.FLAVOLITE_RUNED) - .addCatalyst(0, EndItems.CRYSTAL_SHARDS) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(100) - .build(); - - InfusionRecipe.Builder.create("eternal_crystal") - .setInput(Items.END_CRYSTAL) - .setOutput(EndItems.ETERNAL_CRYSTAL) - .addCatalyst(0, EndItems.CRYSTAL_SHARDS) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .addCatalyst(1, EndItems.ENDER_SHARD) - .addCatalyst(3, EndItems.ENDER_SHARD) - .addCatalyst(5, EndItems.ENDER_SHARD) - .addCatalyst(7, EndItems.ENDER_SHARD) - .setTime(250) - .build(); - - InfusionRecipe.Builder.create("crystalite_helmet") - .setInput(EndBlocks.TERMINITE.helmet) - .setOutput(EndItems.CRYSTALITE_HELMET) - .addCatalyst(0, EndItems.AMBER_GEM) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(150) - .build(); - InfusionRecipe.Builder.create("crystalite_chestplate") - .setInput(EndBlocks.TERMINITE.chestplate) - .setOutput(EndItems.CRYSTALITE_CHESTPLATE) - .addCatalyst(0, EndItems.AMBER_GEM) - .addCatalyst(1, EndItems.CRYSTAL_SHARDS) - .addCatalyst(3, EndItems.CRYSTAL_SHARDS) - .addCatalyst(5, EndItems.CRYSTAL_SHARDS) - .addCatalyst(7, EndItems.CRYSTAL_SHARDS) - .setTime(300) - .build(); - InfusionRecipe.Builder.create("crystalite_leggings") - .setInput(EndBlocks.TERMINITE.leggings) - .setOutput(EndItems.CRYSTALITE_LEGGINGS) - .addCatalyst(0, EndItems.AMBER_GEM) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(225) - .build(); - InfusionRecipe.Builder.create("crystalite_boots") - .setInput(EndBlocks.TERMINITE.boots) - .setOutput(EndItems.CRYSTALITE_BOOTS) - .addCatalyst(0, EndItems.AMBER_GEM) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(150) - .build(); - - InfusionRecipe.Builder.create("crystalite_elytra") - .setInput(Items.ELYTRA) - .setOutput(EndItems.CRYSTALITE_ELYTRA) - .addCatalyst(0, EndItems.AMBER_GEM) - .addCatalyst(1, EndItems.CRYSTAL_SHARDS) - .addCatalyst(2, EndItems.ENCHANTED_MEMBRANE) - .addCatalyst(3, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.ENCHANTED_MEMBRANE) - .addCatalyst(5, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.ENCHANTED_MEMBRANE) - .addCatalyst(7, EndItems.CRYSTAL_SHARDS) - .setTime(500) - .build(); - - InfusionRecipe.Builder.create("enchanted_petal") - .setInput(EndItems.HYDRALUX_PETAL) - .setOutput(EndItems.ENCHANTED_PETAL) - .addCatalyst(0, EndItems.CRYSTAL_SHARDS) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(75) - .build(); - InfusionRecipe.Builder.create("enchanted_membrane") - .setInput(Items.PHANTOM_MEMBRANE) - .setOutput(EndItems.ENCHANTED_MEMBRANE) - .addCatalyst(0, EndItems.CRYSTAL_SHARDS) - .addCatalyst(2, EndItems.CRYSTAL_SHARDS) - .addCatalyst(4, EndItems.CRYSTAL_SHARDS) - .addCatalyst(6, EndItems.CRYSTAL_SHARDS) - .setTime(75) - .build(); - - InfusionRecipe.Builder.create("protection_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.ALL_DAMAGE_PROTECTION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(4, Items.TURTLE_HELMET) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("fire_protection_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FIRE_PROTECTION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.BLAZE_ROD) - .addCatalyst(4, Items.BLAZE_ROD) - .addCatalyst(6, Items.BLAZE_ROD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("feather_falling_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FALL_PROTECTION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.FEATHER) - .addCatalyst(4, Items.FEATHER) - .addCatalyst(6, Items.FEATHER) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("blast_protection_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.BLAST_PROTECTION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.OBSIDIAN) - .addCatalyst(4, Blocks.OBSIDIAN) - .addCatalyst(6, Blocks.OBSIDIAN) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("projectile_protection_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.PROJECTILE_PROTECTION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.SCUTE) - .addCatalyst(4, Items.SHIELD) - .addCatalyst(6, Items.SCUTE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("respiration_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.RESPIRATION, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.NAUTILUS_SHELL) - .addCatalyst(4, Items.NAUTILUS_SHELL) - .addCatalyst(6, Items.NAUTILUS_SHELL) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("aqua_affinity_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.AQUA_AFFINITY, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.PRISMARINE_CRYSTALS) - .addCatalyst(4, Items.PRISMARINE_CRYSTALS) - .addCatalyst(6, Items.PRISMARINE_CRYSTALS) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("thorns_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.THORNS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.CACTUS) - .addCatalyst(4, Blocks.CACTUS) - .addCatalyst(6, Blocks.CACTUS) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("depth_strider_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.DEPTH_STRIDER, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.LILY_PAD) - .addCatalyst(4, EndBlocks.END_LILY_SEED) - .addCatalyst(6, Blocks.LILY_PAD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("frost_walker_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FROST_WALKER, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(4, EndBlocks.ANCIENT_EMERALD_ICE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("soul_speed_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.SOUL_SPEED, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) - .addCatalyst(4, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) - .addCatalyst(6, Blocks.SOUL_SAND, Blocks.SOUL_SOIL) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("sharpness_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.SHARPNESS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(4, Items.NETHERITE_SCRAP) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("smite_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.SMITE, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.SUNFLOWER) - .addCatalyst(4, Items.GOLD_INGOT) - .addCatalyst(6, Blocks.SUNFLOWER) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("bane_of_arthropods_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.BANE_OF_ARTHROPODS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.FERMENTED_SPIDER_EYE) - .addCatalyst(4, Items.IRON_INGOT) - .addCatalyst(6, Items.FERMENTED_SPIDER_EYE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("knockback_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.KNOCKBACK, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.REDSTONE) - .addCatalyst(4, Blocks.PISTON) - .addCatalyst(6, Items.REDSTONE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("fire_aspect_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FIRE_ASPECT, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.BLAZE_POWDER) - .addCatalyst(4, Items.MAGMA_CREAM) - .addCatalyst(6, Items.BLAZE_POWDER) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("looting_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.MOB_LOOTING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.EMERALD) - .addCatalyst(4, Items.GOLD_INGOT) - .addCatalyst(6, Items.EMERALD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("sweeping_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.SWEEPING_EDGE, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.GOLDEN_SWORD) - .addCatalyst(4, Items.IRON_SWORD) - .addCatalyst(6, Items.GOLDEN_SWORD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("efficiency_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.BLOCK_EFFICIENCY, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, EndItems.AMBER_GEM) - .addCatalyst(4, EndItems.AMBER_GEM) - .addCatalyst(6, EndItems.AMBER_GEM) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("silk_touch_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.SILK_TOUCH, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Blocks.COBWEB) - .addCatalyst(4, EndItems.ETERNAL_CRYSTAL) - .addCatalyst(6, Blocks.COBWEB) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - InfusionRecipe.Builder.create("unbreaking_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.UNBREAKING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.DIAMOND) - .addCatalyst(4, Items.DIAMOND) - .addCatalyst(6, Items.DIAMOND) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("fortune_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.BLOCK_FORTUNE, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.EMERALD) - .addCatalyst(4, Items.RABBIT_FOOT) - .addCatalyst(6, Items.EMERALD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("power_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.POWER_ARROWS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, EndItems.AMBER_GEM) - .addCatalyst(4, Items.DIAMOND_SWORD) - .addCatalyst(6, EndItems.AMBER_GEM) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("punch_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.PUNCH_ARROWS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.POPPED_CHORUS_FRUIT) - .addCatalyst(4, Items.SPECTRAL_ARROW) - .addCatalyst(6, Items.POPPED_CHORUS_FRUIT) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("flame_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FLAMING_ARROWS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.BLAZE_POWDER) - .addCatalyst(4, Items.SPECTRAL_ARROW) - .addCatalyst(6, Items.BLAZE_POWDER) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("infinity_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.INFINITY_ARROWS, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.SPECTRAL_ARROW) - .addCatalyst(4, EndItems.ETERNAL_CRYSTAL) - .addCatalyst(6, Items.SPECTRAL_ARROW) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - InfusionRecipe.Builder.create("luck_of_sea_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FISHING_LUCK, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.EMERALD) - .addCatalyst(4, Items.FISHING_ROD) - .addCatalyst(6, Items.EMERALD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("lure_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.FISHING_SPEED, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.GOLD_NUGGET) - .addCatalyst(4, Items.FISHING_ROD) - .addCatalyst(6, Items.GOLD_NUGGET) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("loyalty_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.LOYALTY, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.ENDER_EYE) - .addCatalyst(4, Items.HEART_OF_THE_SEA) - .addCatalyst(6, Items.ENDER_EYE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - InfusionRecipe.Builder.create("impaling_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.IMPALING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.PRISMARINE_SHARD) - .addCatalyst(4, Items.IRON_SWORD) - .addCatalyst(6, Items.PRISMARINE_SHARD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("riptide_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.RIPTIDE, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.LEAD) - .addCatalyst(4, Items.HEART_OF_THE_SEA) - .addCatalyst(6, Items.LEAD) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - InfusionRecipe.Builder.create("channeling_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.CHANNELING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.CHAIN) - .addCatalyst(4, Items.HEART_OF_THE_SEA) - .addCatalyst(6, Items.CHAIN) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - InfusionRecipe.Builder.create("multishot_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.MULTISHOT, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.ARROW) - .addCatalyst(4, Items.SPECTRAL_ARROW) - .addCatalyst(6, Items.ARROW) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("quick_charge_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.QUICK_CHARGE, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.QUARTZ) - .addCatalyst(4, Items.GLOWSTONE_DUST) - .addCatalyst(6, Items.QUARTZ) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("piercing_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.PIERCING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.GLOWSTONE_DUST) - .addCatalyst(4, Items.SPECTRAL_ARROW) - .addCatalyst(6, Items.GLOWSTONE_DUST) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(300) - .build(); - InfusionRecipe.Builder.create("mending_book") - .setInput(Items.BOOK) - .setOutput(createEnchantedBook(Enchantments.MENDING, 1)) - .addCatalyst(0, EndItems.ENCHANTED_PETAL) - .addCatalyst(2, Items.EXPERIENCE_BOTTLE) - .addCatalyst(4, Blocks.ANVIL) - .addCatalyst(6, Items.EXPERIENCE_BOTTLE) - .addCatalyst(1, Items.LAPIS_LAZULI) - .addCatalyst(3, Items.LAPIS_LAZULI) - .addCatalyst(5, Items.LAPIS_LAZULI) - .addCatalyst(7, Items.LAPIS_LAZULI) - .setGroup("enchantment") - .setTime(375) - .build(); - } - - private static ItemStack createEnchantedBook(Enchantment enchantment, int level) { - ItemStack book = new ItemStack(Items.ENCHANTED_BOOK); - EnchantedBookItem.addEnchantment(book, new EnchantmentInstance(enchantment, level)); - return book; - } -} diff --git a/src/main/java/ru/betterend/recipe/SmithingRecipes.java b/src/main/java/ru/betterend/recipe/SmithingRecipes.java deleted file mode 100644 index 7f50dba1..00000000 --- a/src/main/java/ru/betterend/recipe/SmithingRecipes.java +++ /dev/null @@ -1,109 +0,0 @@ -package ru.betterend.recipe; - -import net.minecraft.world.item.Items; -import ru.bclib.recipes.SmithingTableRecipe; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class SmithingRecipes { - - public static void register() { - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_sword_handle") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_SWORD_HANDLE) - .setBase(EndBlocks.TERMINITE.ingot) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_sword") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_SWORD) - .setBase(EndItems.AETERNIUM_SWORD_BLADE) - .setAddition(EndItems.AETERNIUM_SWORD_HANDLE) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_pickaxe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_PICKAXE) - .setBase(EndItems.AETERNIUM_PICKAXE_HEAD) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_axe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_AXE) - .setBase(EndItems.AETERNIUM_AXE_HEAD) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_shovel") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_SHOVEL) - .setBase(EndItems.AETERNIUM_SHOVEL_HEAD) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_hoe") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_HOE) - .setBase(EndItems.AETERNIUM_HOE_HEAD) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_hammer") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_HAMMER) - .setBase(EndItems.AETERNIUM_HAMMER_HEAD) - .setAddition(EndItems.LEATHER_WRAPPED_STICK) - .build(); - - SmithingTableRecipe.create(BetterEnd.MOD_ID, "netherite_hammer") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.NETHERITE_HAMMER) - .setBase(EndItems.DIAMOND_HAMMER) - .setAddition(Items.NETHERITE_INGOT) - .build(); - - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_helmet") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_HELMET) - .setBase(EndBlocks.TERMINITE.helmet) - .setAddition(EndItems.AETERNIUM_FORGED_PLATE) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_chestplate") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_CHESTPLATE) - .setBase(EndBlocks.TERMINITE.chestplate) - .setAddition(EndItems.AETERNIUM_FORGED_PLATE) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_leggings") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_LEGGINGS) - .setBase(EndBlocks.TERMINITE.leggings) - .setAddition(EndItems.AETERNIUM_FORGED_PLATE) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "aeternium_boots") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.AETERNIUM_BOOTS) - .setBase(EndBlocks.TERMINITE.boots) - .setAddition(EndItems.AETERNIUM_FORGED_PLATE) - .build(); - - SmithingTableRecipe.create(BetterEnd.MOD_ID, "thallasium_anvil_updrade") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndBlocks.TERMINITE.anvilBlock.asItem()) - .setBase(EndBlocks.THALLASIUM.anvilBlock.asItem()) - .setAddition(EndBlocks.TERMINITE.block) - .build(); - SmithingTableRecipe.create(BetterEnd.MOD_ID, "terminite_anvil_updrade") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndBlocks.AETERNIUM_ANVIL.asItem()) - .setBase(EndBlocks.TERMINITE.anvilBlock.asItem()) - .setAddition(EndItems.AETERNIUM_INGOT) - .build(); - - SmithingTableRecipe.create(BetterEnd.MOD_ID, "armored_elytra") - .checkConfig(Configs.RECIPE_CONFIG) - .setResult(EndItems.ARMORED_ELYTRA) - .setBase(Items.ELYTRA) - .setAddition(EndItems.AETERNIUM_INGOT) - .build(); - } -} diff --git a/src/main/java/ru/betterend/recipe/builders/AlloyingRecipe.java b/src/main/java/ru/betterend/recipe/builders/AlloyingRecipe.java deleted file mode 100644 index 3838c14d..00000000 --- a/src/main/java/ru/betterend/recipe/builders/AlloyingRecipe.java +++ /dev/null @@ -1,290 +0,0 @@ -package ru.betterend.recipe.builders; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.NonNullList; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.Container; -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.Recipe; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.Level; -import ru.bclib.interfaces.UnknownReceipBookCategory; -import ru.bclib.recipes.BCLRecipeManager; -import ru.bclib.util.ItemUtil; -import ru.bclib.util.RecipeHelper; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.registry.EndBlocks; - -public class AlloyingRecipe implements Recipe, UnknownReceipBookCategory { - public final static String GROUP = "alloying"; - public final static RecipeType TYPE = BCLRecipeManager.registerType(BetterEnd.MOD_ID, GROUP); - public final static Serializer SERIALIZER = BCLRecipeManager.registerSerializer( - BetterEnd.MOD_ID, - GROUP, - new Serializer() - ); - - protected final RecipeType type; - protected final ResourceLocation id; - protected final Ingredient primaryInput; - protected final Ingredient secondaryInput; - protected final ItemStack output; - protected final String group; - protected final float experience; - protected final int smeltTime; - - public AlloyingRecipe(ResourceLocation id, String group, Ingredient primaryInput, Ingredient secondaryInput, ItemStack output, float experience, int smeltTime) { - this.group = group; - this.id = id; - this.primaryInput = primaryInput; - this.secondaryInput = secondaryInput; - this.output = output; - this.experience = experience; - this.smeltTime = smeltTime; - this.type = TYPE; - } - - public float getExperience() { - return this.experience; - } - - public int getSmeltTime() { - return this.smeltTime; - } - - @Override - public NonNullList getIngredients() { - NonNullList defaultedList = NonNullList.create(); - defaultedList.add(primaryInput); - defaultedList.add(secondaryInput); - - return defaultedList; - } - - @Override - public boolean matches(Container inv, Level world) { - return this.primaryInput.test(inv.getItem(0)) && this.secondaryInput.test(inv.getItem(1)) || this.primaryInput.test( - inv.getItem(1)) && this.secondaryInput.test(inv.getItem(0)); - } - - @Override - public ItemStack assemble(Container inv) { - return this.output.copy(); - } - - @Override - public boolean canCraftInDimensions(int width, int height) { - return true; - } - - @Override - public ItemStack getResultItem() { - return this.output; - } - - @Override - public ResourceLocation getId() { - return this.id; - } - - @Override - public RecipeSerializer getSerializer() { - return SERIALIZER; - } - - @Override - public RecipeType getType() { - return this.type; - } - - @Override - @Environment(EnvType.CLIENT) - public String getGroup() { - return this.group; - } - - @Environment(EnvType.CLIENT) - public ItemStack getToastSymbol() { - return new ItemStack(EndBlocks.END_STONE_SMELTER); - } - - public static class Builder { - private final static Builder INSTANCE = new Builder(); - private static boolean exist; - - public static Builder create(ResourceLocation id) { - INSTANCE.id = id; - INSTANCE.group = String.format("%s_%s", GROUP, id); - INSTANCE.primaryInput = null; - INSTANCE.secondaryInput = null; - INSTANCE.output = null; - INSTANCE.experience = 0.0F; - INSTANCE.smeltTime = 350; - exist = Configs.RECIPE_CONFIG.getBoolean("alloying", id.getPath(), true); - - return INSTANCE; - } - - public static Builder create(String id) { - return create(BetterEnd.makeID(id)); - } - - private ResourceLocation id; - private Ingredient primaryInput; - private Ingredient secondaryInput; - private ItemStack output; - private String group; - private float experience; - private int smeltTime; - private boolean alright = true; - - private Builder() { - } - - public Builder setGroup(String group) { - this.group = group; - return this; - } - - public Builder setPrimaryInput(ItemLike... inputs) { - for (ItemLike item : inputs) { - this.alright &= RecipeHelper.exists(item); - } - this.primaryInput = Ingredient.of(inputs); - return this; - } - - public Builder setSecondaryInput(ItemLike... inputs) { - for (ItemLike item : inputs) { - this.alright &= RecipeHelper.exists(item); - } - this.secondaryInput = Ingredient.of(inputs); - return this; - } - - public Builder setPrimaryInput(TagKey input) { - this.primaryInput = Ingredient.of(input); - return this; - } - - public Builder setSecondaryInput(TagKey input) { - this.secondaryInput = Ingredient.of(input); - return this; - } - - public Builder setInput(ItemLike primaryInput, ItemLike secondaryInput) { - this.setPrimaryInput(primaryInput); - this.setSecondaryInput(secondaryInput); - return this; - } - - public Builder setInput(TagKey primaryInput, TagKey secondaryInput) { - this.setPrimaryInput(primaryInput); - this.setSecondaryInput(secondaryInput); - return this; - } - - public Builder setOutput(ItemLike output, int amount) { - this.alright &= RecipeHelper.exists(output); - this.output = new ItemStack(output, amount); - return this; - } - - public Builder setExpiriense(float amount) { - this.experience = amount; - return this; - } - - public Builder setSmeltTime(int time) { - this.smeltTime = time; - return this; - } - - public void build() { - if (exist) { - if (primaryInput == null) { - BetterEnd.LOGGER.warning( - "Primary input for Alloying recipe can't be 'null', recipe {} will be ignored!", - id - ); - return; - } - if (secondaryInput == null) { - BetterEnd.LOGGER.warning( - "Secondary input for Alloying can't be 'null', recipe {} will be ignored!", - id - ); - return; - } - if (output == null) { - BetterEnd.LOGGER.warning("Output for Alloying can't be 'null', recipe {} will be ignored!", id); - return; - } - if (BCLRecipeManager.getRecipe(TYPE, id) != null) { - BetterEnd.LOGGER.warning("Can't add Alloying recipe! Id {} already exists!", id); - return; - } - if (!alright) { - BetterEnd.LOGGER.debug("Can't add Alloying recipe {}! Ingeredient or output not exists.", id); - return; - } - BCLRecipeManager.addRecipe( - TYPE, - new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime) - ); - } - } - } - - public static class Serializer implements RecipeSerializer { - @Override - public AlloyingRecipe fromJson(ResourceLocation id, JsonObject json) { - JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients"); - Ingredient primaryInput = Ingredient.fromJson(ingredients.get(0)); - Ingredient secondaryInput = Ingredient.fromJson(ingredients.get(1)); - String group = GsonHelper.getAsString(json, "group", ""); - JsonObject result = GsonHelper.getAsJsonObject(json, "result"); - ItemStack output = ItemUtil.fromJsonRecipe(result); - if (output == null) { - throw new IllegalStateException("Output item does not exists!"); - } - float experience = GsonHelper.getAsFloat(json, "experience", 0.0F); - int smeltTime = GsonHelper.getAsInt(json, "smelttime", 350); - - return new AlloyingRecipe(id, group, primaryInput, secondaryInput, output, experience, smeltTime); - } - - @Override - public AlloyingRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf packetBuffer) { - String group = packetBuffer.readUtf(32767); - Ingredient primary = Ingredient.fromNetwork(packetBuffer); - Ingredient secondary = Ingredient.fromNetwork(packetBuffer); - ItemStack output = packetBuffer.readItem(); - float experience = packetBuffer.readFloat(); - int smeltTime = packetBuffer.readVarInt(); - - return new AlloyingRecipe(id, group, primary, secondary, output, experience, smeltTime); - } - - @Override - public void toNetwork(FriendlyByteBuf packetBuffer, AlloyingRecipe recipe) { - packetBuffer.writeUtf(recipe.group); - recipe.primaryInput.toNetwork(packetBuffer); - recipe.secondaryInput.toNetwork(packetBuffer); - packetBuffer.writeItem(recipe.output); - packetBuffer.writeFloat(recipe.experience); - packetBuffer.writeVarInt(recipe.smeltTime); - } - } -} diff --git a/src/main/java/ru/betterend/recipe/builders/InfusionRecipe.java b/src/main/java/ru/betterend/recipe/builders/InfusionRecipe.java deleted file mode 100644 index 2dfb6d34..00000000 --- a/src/main/java/ru/betterend/recipe/builders/InfusionRecipe.java +++ /dev/null @@ -1,280 +0,0 @@ -package ru.betterend.recipe.builders; - -import com.google.gson.JsonObject; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.TagParser; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -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.level.ItemLike; -import net.minecraft.world.level.Level; -import ru.bclib.interfaces.UnknownReceipBookCategory; -import ru.bclib.recipes.BCLRecipeManager; -import ru.bclib.util.ItemUtil; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.rituals.InfusionRitual; - -import java.util.Arrays; - -public class InfusionRecipe implements Recipe, UnknownReceipBookCategory { - public final static String GROUP = "infusion"; - public final static RecipeType TYPE = BCLRecipeManager.registerType(BetterEnd.MOD_ID, GROUP); - public final static Serializer SERIALIZER = BCLRecipeManager.registerSerializer( - BetterEnd.MOD_ID, - GROUP, - new Serializer() - ); - - private final ResourceLocation id; - private final Ingredient[] catalysts; - private Ingredient input; - private ItemStack output; - private int time = 1; - private String group; - - private InfusionRecipe(ResourceLocation id) { - this(id, null, null); - } - - private InfusionRecipe(ResourceLocation id, Ingredient input, ItemStack output) { - this.id = id; - this.input = input; - this.output = output; - this.catalysts = new Ingredient[8]; - Arrays.fill(catalysts, Ingredient.EMPTY); - } - - public int getInfusionTime() { - return this.time; - } - - @Override - public boolean matches(InfusionRitual inv, Level world) { - boolean valid = this.input.test(inv.getItem(0)); - if (!valid) return false; - for (int i = 0; i < 8; i++) { - valid &= this.catalysts[i].test(inv.getItem(i + 1)); - } - return valid; - } - - @Override - public ItemStack assemble(InfusionRitual ritual) { - return output.copy(); - } - - @Override - public boolean canCraftInDimensions(int width, int height) { - return true; - } - - @Override - public NonNullList getIngredients() { - NonNullList defaultedList = NonNullList.create(); - defaultedList.add(input); - defaultedList.addAll(Arrays.asList(catalysts)); - return defaultedList; - } - - @Override - public ItemStack getResultItem() { - return this.output; - } - - @Override - public ResourceLocation getId() { - return this.id; - } - - @Override - @Environment(EnvType.CLIENT) - public String getGroup() { - return this.group; - } - - @Override - public RecipeSerializer getSerializer() { - return SERIALIZER; - } - - @Override - public RecipeType getType() { - return TYPE; - } - - public static class Builder { - private final static Builder INSTANCE = new Builder(); - private static boolean exist; - - public static Builder create(String id) { - return create(BetterEnd.makeID(id)); - } - - public static Builder create(ResourceLocation id) { - INSTANCE.id = id; - INSTANCE.input = null; - INSTANCE.output = null; - INSTANCE.time = 1; - exist = Configs.RECIPE_CONFIG.getBoolean("infusion", id.getPath(), true); - - Arrays.fill(INSTANCE.catalysts, Ingredient.EMPTY); - - return INSTANCE; - } - - private final Ingredient[] catalysts = new Ingredient[8]; - private ResourceLocation id; - private Ingredient input; - private ItemStack output; - private String group; - private int time = 1; - - private Builder() { - Arrays.fill(catalysts, Ingredient.EMPTY); - } - - public Builder setGroup(String group) { - this.group = group; - return this; - } - - public Builder setInput(ItemLike input) { - this.input = Ingredient.of(input); - return this; - } - - public Builder setOutput(ItemLike output) { - this.output = new ItemStack(output); - this.output.setCount(1); - return this; - } - - public Builder setOutput(ItemStack output) { - this.output = output; - this.output.setCount(1); - return this; - } - - public Builder setTime(int time) { - this.time = time; - return this; - } - - public Builder addCatalyst(int slot, ItemLike... items) { - if (slot > 7) return this; - this.catalysts[slot] = Ingredient.of(items); - return this; - } - - public void build() { - if (exist) { - if (input == null) { - BetterEnd.LOGGER.warning( - "Input for Infusion recipe can't be 'null', recipe {} will be ignored!", - id - ); - return; - } - if (output == null) { - BetterEnd.LOGGER.warning( - "Output for Infusion recipe can't be 'null', recipe {} will be ignored!", - id - ); - return; - } - InfusionRecipe recipe = new InfusionRecipe(id, input, output); - recipe.group = group != null ? group : GROUP; - recipe.time = time; - int empty = 0; - for (int i = 0; i < catalysts.length; i++) { - if (catalysts[i].isEmpty()) empty++; - else recipe.catalysts[i] = catalysts[i]; - } - if (empty == catalysts.length) { - BetterEnd.LOGGER.warning("At least one catalyst must be non empty, recipe {} will be ignored!", id); - return; - } - BCLRecipeManager.addRecipe(TYPE, recipe); - } - } - } - - public static class Serializer implements RecipeSerializer { - @Override - public InfusionRecipe fromJson(ResourceLocation id, JsonObject json) { - InfusionRecipe recipe = new InfusionRecipe(id); - recipe.input = Ingredient.fromJson(json.get("input")); - JsonObject result = GsonHelper.getAsJsonObject(json, "result"); - recipe.output = ItemUtil.fromJsonRecipe(result); - if (recipe.output == null) { - throw new IllegalStateException("Output item does not exists!"); - } - if (result.has("nbt")) { - try { - String nbtData = GsonHelper.getAsString(result, "nbt"); - CompoundTag nbt = TagParser.parseTag(nbtData); - recipe.output.setTag(nbt); - } - catch (CommandSyntaxException ex) { - BetterEnd.LOGGER.warning("Error parse nbt data for output.", ex); - } - } - recipe.group = GsonHelper.getAsString(json, "group", GROUP); - recipe.time = GsonHelper.getAsInt(json, "time", 1); - - JsonObject catalysts = GsonHelper.getAsJsonObject(json, "catalysts"); - ItemStack catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north", "")); - recipe.catalysts[0] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_east", "")); - recipe.catalysts[1] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "east", "")); - recipe.catalysts[2] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_east", "")); - recipe.catalysts[3] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south", "")); - recipe.catalysts[4] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "south_west", "")); - recipe.catalysts[5] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "west", "")); - recipe.catalysts[6] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - catalyst = ItemUtil.fromStackString(GsonHelper.getAsString(catalysts, "north_west", "")); - recipe.catalysts[7] = (catalyst != null && !catalyst.isEmpty()) ? Ingredient.of(catalyst.getItem()) : Ingredient.EMPTY; - - return recipe; - } - - @Override - public InfusionRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) { - InfusionRecipe recipe = new InfusionRecipe(id); - recipe.input = Ingredient.fromNetwork(buffer); - recipe.output = buffer.readItem(); - recipe.group = buffer.readUtf(); - recipe.time = buffer.readVarInt(); - for (int i = 0; i < 8; i++) { - recipe.catalysts[i] = Ingredient.fromNetwork(buffer); - } - return recipe; - } - - @Override - public void toNetwork(FriendlyByteBuf buffer, InfusionRecipe recipe) { - recipe.input.toNetwork(buffer); - buffer.writeItem(recipe.output); - buffer.writeUtf(recipe.group); - buffer.writeVarInt(recipe.time); - for (int i = 0; i < 8; i++) { - recipe.catalysts[i].toNetwork(buffer); - } - } - } -} diff --git a/src/main/java/ru/betterend/registry/EndAttributes.java b/src/main/java/ru/betterend/registry/EndAttributes.java deleted file mode 100644 index 8262d5ba..00000000 --- a/src/main/java/ru/betterend/registry/EndAttributes.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.betterend.registry; - -import net.minecraft.core.Registry; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import ru.betterend.BetterEnd; -import ru.betterend.item.EndAttribute; - -public class EndAttributes { - public final static Attribute BLINDNESS_RESISTANCE = registerAttribute("generic.blindness_resistance", 0.0, true); - - public static Attribute registerAttribute(String name, double value, boolean syncable) { - return Registry.register( - Registry.ATTRIBUTE, - BetterEnd.makeID(name), - new EndAttribute("attribute.name." + name, value).setSyncable(syncable) - ); - } - - public static AttributeSupplier.Builder addLivingEntityAttributes(AttributeSupplier.Builder builder) { - return builder.add(EndAttributes.BLINDNESS_RESISTANCE); - } -} - - diff --git a/src/main/java/ru/betterend/registry/EndBiomes.java b/src/main/java/ru/betterend/registry/EndBiomes.java deleted file mode 100644 index f1dfa640..00000000 --- a/src/main/java/ru/betterend/registry/EndBiomes.java +++ /dev/null @@ -1,183 +0,0 @@ -package ru.betterend.registry; - -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.biome.Biome; -import ru.bclib.api.LifeCycleAPI; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.world.biomes.BCLBiome; -import ru.bclib.world.generator.BiomePicker; -import ru.bclib.world.generator.map.hex.HexBiomeMap; -import ru.betterend.config.Configs; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.biome.air.BiomeIceStarfield; -import ru.betterend.world.biome.cave.EmptyAuroraCaveBiome; -import ru.betterend.world.biome.cave.EmptyEndCaveBiome; -import ru.betterend.world.biome.cave.EmptySmaragdantCaveBiome; -import ru.betterend.world.biome.cave.EndCaveBiome; -import ru.betterend.world.biome.cave.JadeCaveBiome; -import ru.betterend.world.biome.cave.LushAuroraCaveBiome; -import ru.betterend.world.biome.cave.LushSmaragdantCaveBiome; -import ru.betterend.world.biome.land.AmberLandBiome; -import ru.betterend.world.biome.land.BlossomingSpiresBiome; -import ru.betterend.world.biome.land.ChorusForestBiome; -import ru.betterend.world.biome.land.CrystalMountainsBiome; -import ru.betterend.world.biome.land.DragonGraveyardsBiome; -import ru.betterend.world.biome.land.DryShrublandBiome; -import ru.betterend.world.biome.land.DustWastelandsBiome; -import ru.betterend.world.biome.land.FoggyMushroomlandBiome; -import ru.betterend.world.biome.land.GlowingGrasslandsBiome; -import ru.betterend.world.biome.land.LanternWoodsBiome; -import ru.betterend.world.biome.land.MegalakeBiome; -import ru.betterend.world.biome.land.MegalakeGroveBiome; -import ru.betterend.world.biome.land.NeonOasisBiome; -import ru.betterend.world.biome.land.PaintedMountainsBiome; -import ru.betterend.world.biome.land.ShadowForestBiome; -import ru.betterend.world.biome.land.SulphurSpringsBiome; -import ru.betterend.world.biome.land.UmbraValleyBiome; -import ru.betterend.world.biome.land.UmbrellaJungleBiome; -import ru.betterend.world.generator.BiomeType; -import ru.betterend.world.generator.GeneratorOptions; - -public class EndBiomes { - public static final BiomeAPI.Dimension END_CAVE = new BiomeAPI.Dimension(BiomeAPI.Dimension.END); - - public static BiomePicker CAVE_BIOMES = null; - private static HexBiomeMap caveBiomeMap; - private static long lastSeed; - - // Better End Land - public static final EndBiome FOGGY_MUSHROOMLAND = registerBiome(new FoggyMushroomlandBiome(), BiomeType.LAND); - public static final EndBiome CHORUS_FOREST = registerBiome(new ChorusForestBiome(), BiomeType.LAND); - public static final EndBiome DUST_WASTELANDS = registerBiome(new DustWastelandsBiome(), BiomeType.LAND); - public static final EndBiome MEGALAKE = registerBiome(new MegalakeBiome(), BiomeType.LAND); - public static final EndBiome MEGALAKE_GROVE = registerSubBiome(new MegalakeGroveBiome(), MEGALAKE); - public static final EndBiome CRYSTAL_MOUNTAINS = registerBiome(new CrystalMountainsBiome(), BiomeType.LAND); - public static final EndBiome PAINTED_MOUNTAINS = registerSubBiome(new PaintedMountainsBiome(), DUST_WASTELANDS); - public static final EndBiome SHADOW_FOREST = registerBiome(new ShadowForestBiome(), BiomeType.LAND); - public static final EndBiome AMBER_LAND = registerBiome(new AmberLandBiome(), BiomeType.LAND); - public static final EndBiome BLOSSOMING_SPIRES = registerBiome(new BlossomingSpiresBiome(), BiomeType.LAND); - public static final EndBiome SULPHUR_SPRINGS = registerBiome(new SulphurSpringsBiome(), BiomeType.LAND); - public static final EndBiome UMBRELLA_JUNGLE = registerBiome(new UmbrellaJungleBiome(), BiomeType.LAND); - public static final EndBiome GLOWING_GRASSLANDS = registerBiome(new GlowingGrasslandsBiome(), BiomeType.LAND); - public static final EndBiome DRAGON_GRAVEYARDS = registerBiome(new DragonGraveyardsBiome(), BiomeType.LAND); - public static final EndBiome DRY_SHRUBLAND = registerBiome(new DryShrublandBiome(), BiomeType.LAND); - public static final EndBiome LANTERN_WOODS = registerBiome(new LanternWoodsBiome(), BiomeType.LAND); - public static final EndBiome NEON_OASIS = registerSubBiome(new NeonOasisBiome(), DUST_WASTELANDS); - public static final EndBiome UMBRA_VALLEY = registerBiome(new UmbraValleyBiome(), BiomeType.LAND); - - // Better End Void - public static final EndBiome ICE_STARFIELD = registerBiome(new BiomeIceStarfield(), BiomeType.VOID); - - // Better End Caves - public static final EndCaveBiome EMPTY_END_CAVE = registerCaveBiome(new EmptyEndCaveBiome()); - public static final EndCaveBiome EMPTY_SMARAGDANT_CAVE = registerCaveBiome(new EmptySmaragdantCaveBiome()); - public static final EndCaveBiome LUSH_SMARAGDANT_CAVE = registerCaveBiome(new LushSmaragdantCaveBiome()); - public static final EndCaveBiome EMPTY_AURORA_CAVE = registerCaveBiome(new EmptyAuroraCaveBiome()); - public static final EndCaveBiome LUSH_AURORA_CAVE = registerCaveBiome(new LushAuroraCaveBiome()); - public static final EndCaveBiome JADE_CAVE = registerCaveBiome(new JadeCaveBiome()); - - public static void register() { - LifeCycleAPI.onLevelLoad(EndBiomes::onWorldLoad); - } - - private static void onWorldLoad(ServerLevel level, long seed, Registry registry) { - if (CAVE_BIOMES==null || CAVE_BIOMES.biomeRegistry != registry) { - CAVE_BIOMES = new BiomePicker(registry); - registry.stream() - .filter(biome -> registry.getResourceKey(biome).isPresent()) - .map(biome -> registry.getOrCreateHolder(registry.getResourceKey(biome).get())) - .map(biome -> biome.unwrapKey().orElseThrow().location()) - .filter(id -> BiomeAPI.wasRegisteredAs(id, END_CAVE)) - .map(id -> BiomeAPI.getBiome(id)) - .filter(bcl -> bcl != null) - .forEach(bcl -> CAVE_BIOMES.addBiome(bcl)); - - CAVE_BIOMES.rebuild(); - caveBiomeMap = null; - } - - if (caveBiomeMap == null || lastSeed != seed) { - caveBiomeMap = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeCaves(), CAVE_BIOMES); - lastSeed = seed; - } - } - - /** - * Put existing {@link EndBiome} as a sub-biome into selected parent. - * - * @param biomeConfig - {@link EndBiome.Config} instance - * @param parent - {@link EndBiome} to be linked with - * @return registered {@link EndBiome} - */ - public static EndBiome registerSubBiome(EndBiome.Config biomeConfig, EndBiome parent) { - final EndBiome biome = EndBiome.create(biomeConfig); - - if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { - BiomeAPI.registerSubBiome(parent, biome); - } - return biome; - } - - /** - * Registers {@link EndBiome} and adds it into worldgen. - * - * @param biomeConfig - {@link EndBiome.Config} instance - * @param type - {@link BiomeType} - * @return registered {@link EndBiome} - */ - public static EndBiome registerBiome(EndBiome.Config biomeConfig, BiomeType type) { - final EndBiome biome = EndBiome.create(biomeConfig); - if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { - if (type == BiomeType.LAND) { - BiomeAPI.registerEndLandBiome(biome); - } - else { - BiomeAPI.registerEndVoidBiome(biome); - } - } - return biome; - } - - /** - * Put integration sub-biome {@link EndBiome} into subbiomes list and registers it. - * - * @param biomeConfig - {@link EndBiome.Config} instance - * @return registered {@link EndBiome} - */ - public static EndBiome registerSubBiomeIntegration(EndBiome.Config biomeConfig) { - EndBiome biome = EndBiome.create(biomeConfig); - if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { - BiomeAPI.registerBiome(biome, BiomeAPI.Dimension.END); - } - return biome; - } - - /** - * Link integration sub-biome with parent. - * - * @param biome - {@link EndBiome} instance - * @param parent - {@link ResourceLocation} parent id - */ - public static void addSubBiomeIntegration(EndBiome biome, ResourceLocation parent) { - if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { - BCLBiome parentBiome = BiomeAPI.getBiome(parent); - if (parentBiome != null && !parentBiome.containsSubBiome(biome)) { - parentBiome.addSubBiome(biome); - } - } - } - - public static EndCaveBiome registerCaveBiome(EndCaveBiome.Config biomeConfig) { - final EndCaveBiome biome = EndCaveBiome.create(biomeConfig); - if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) { - BiomeAPI.registerBiome(biome, END_CAVE); - } - return biome; - } - - public static BiomePicker.ActualBiome getCaveBiome(int x, int z) { - return caveBiomeMap.getBiome(x, 5, z); - } -} diff --git a/src/main/java/ru/betterend/registry/EndBlockEntities.java b/src/main/java/ru/betterend/registry/EndBlockEntities.java deleted file mode 100644 index 6b90487d..00000000 --- a/src/main/java/ru/betterend/registry/EndBlockEntities.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; -import net.minecraft.core.Registry; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndStoneSmelter; -import ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.blocks.entities.BlockEntityHydrothermalVent; -import ru.betterend.blocks.entities.EndStoneSmelterBlockEntity; -import ru.betterend.blocks.entities.EternalPedestalEntity; -import ru.betterend.blocks.entities.InfusionPedestalEntity; -import ru.betterend.blocks.entities.PedestalBlockEntity; - -public class EndBlockEntities { - public final static BlockEntityType END_STONE_SMELTER = registerBlockEntity( - EndStoneSmelter.ID, - FabricBlockEntityTypeBuilder.create(EndStoneSmelterBlockEntity::new, EndBlocks.END_STONE_SMELTER) - ); - public final static BlockEntityType PEDESTAL = registerBlockEntity( - "pedestal", - FabricBlockEntityTypeBuilder.create(PedestalBlockEntity::new, getPedestals()) - ); - public final static BlockEntityType ETERNAL_PEDESTAL = registerBlockEntity( - "eternal_pedestal", - FabricBlockEntityTypeBuilder.create(EternalPedestalEntity::new, EndBlocks.ETERNAL_PEDESTAL) - ); - public final static BlockEntityType INFUSION_PEDESTAL = registerBlockEntity( - "infusion_pedestal", - FabricBlockEntityTypeBuilder.create(InfusionPedestalEntity::new, EndBlocks.INFUSION_PEDESTAL) - ); - public final static BlockEntityType HYDROTHERMAL_VENT = registerBlockEntity( - "hydrother_malvent", - FabricBlockEntityTypeBuilder.create(BlockEntityHydrothermalVent::new, EndBlocks.HYDROTHERMAL_VENT) - ); - - public static BlockEntityType registerBlockEntity(String id, FabricBlockEntityTypeBuilder builder) { - return Registry.register(Registry.BLOCK_ENTITY_TYPE, BetterEnd.makeID(id), builder.build(null)); - - //return Registry.register(Registry.BLOCK_ENTITY_TYPE, BetterEnd.makeID(id), builder.build(null)); - } - - public static void register() { - } - - static Block[] getPedestals() { - return EndBlocks.getModBlocks() - .stream() - .filter(block -> block instanceof PedestalBlock && !((PedestalBlock) block).hasUniqueEntity()) - .toArray(Block[]::new); - } -} diff --git a/src/main/java/ru/betterend/registry/EndBlockEntityRenders.java b/src/main/java/ru/betterend/registry/EndBlockEntityRenders.java deleted file mode 100644 index b4a10e53..00000000 --- a/src/main/java/ru/betterend/registry/EndBlockEntityRenders.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; -import ru.betterend.client.render.PedestalItemRenderer; - -@Environment(EnvType.CLIENT) -public class EndBlockEntityRenders { - public static void register() { - BlockEntityRendererRegistry.register(EndBlockEntities.PEDESTAL, PedestalItemRenderer::new); - BlockEntityRendererRegistry.register(EndBlockEntities.ETERNAL_PEDESTAL, PedestalItemRenderer::new); - BlockEntityRendererRegistry.register(EndBlockEntities.INFUSION_PEDESTAL, PedestalItemRenderer::new); - } -} diff --git a/src/main/java/ru/betterend/registry/EndBlocks.java b/src/main/java/ru/betterend/registry/EndBlocks.java deleted file mode 100644 index 41f7c536..00000000 --- a/src/main/java/ru/betterend/registry/EndBlocks.java +++ /dev/null @@ -1,553 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.MaterialColor; -import org.jetbrains.annotations.NotNull; -import ru.bclib.blocks.BaseFurnaceBlock; -import ru.bclib.blocks.BaseOreBlock; -import ru.bclib.blocks.BasePathBlock; -import ru.bclib.blocks.BaseRotatedPillarBlock; -import ru.bclib.blocks.BaseSlabBlock; -import ru.bclib.blocks.BaseStairsBlock; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.blocks.SimpleLeavesBlock; -import ru.bclib.blocks.StalactiteBlock; -import ru.bclib.registry.BlockRegistry; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.AeterniumAnvil; -import ru.betterend.blocks.AeterniumBlock; -import ru.betterend.blocks.AmaranitaCapBlock; -import ru.betterend.blocks.AmaranitaHymenophoreBlock; -import ru.betterend.blocks.AmaranitaStemBlock; -import ru.betterend.blocks.AmberBlock; -import ru.betterend.blocks.AncientEmeraldIceBlock; -import ru.betterend.blocks.AuroraCrystalBlock; -import ru.betterend.blocks.BlueVineBlock; -import ru.betterend.blocks.BlueVineLanternBlock; -import ru.betterend.blocks.BlueVineSeedBlock; -import ru.betterend.blocks.BoluxMushroomBlock; -import ru.betterend.blocks.BrimstoneBlock; -import ru.betterend.blocks.BubbleCoralBlock; -import ru.betterend.blocks.BulbVineBlock; -import ru.betterend.blocks.BulbVineLanternBlock; -import ru.betterend.blocks.BulbVineLanternColoredBlock; -import ru.betterend.blocks.BulbVineSeedBlock; -import ru.betterend.blocks.CavePumpkinBlock; -import ru.betterend.blocks.CavePumpkinVineBlock; -import ru.betterend.blocks.ChandelierBlock; -import ru.betterend.blocks.CharcoalBlock; -import ru.betterend.blocks.CharniaBlock; -import ru.betterend.blocks.ChorusGrassBlock; -import ru.betterend.blocks.DenseEmeraldIceBlock; -import ru.betterend.blocks.DenseSnowBlock; -import ru.betterend.blocks.DragonTreeSaplingBlock; -import ru.betterend.blocks.EmeraldIceBlock; -import ru.betterend.blocks.EndLilyBlock; -import ru.betterend.blocks.EndLilySeedBlock; -import ru.betterend.blocks.EndLotusFlowerBlock; -import ru.betterend.blocks.EndLotusLeafBlock; -import ru.betterend.blocks.EndLotusSeedBlock; -import ru.betterend.blocks.EndLotusStemBlock; -import ru.betterend.blocks.EndPortalBlock; -import ru.betterend.blocks.EndStoneSmelter; -import ru.betterend.blocks.EnderBlock; -import ru.betterend.blocks.EndstoneDustBlock; -import ru.betterend.blocks.EternalPedestal; -import ru.betterend.blocks.FilaluxBlock; -import ru.betterend.blocks.FilaluxLanternBlock; -import ru.betterend.blocks.FilaluxWingsBlock; -import ru.betterend.blocks.FlamaeaBlock; -import ru.betterend.blocks.FlammalixBlock; -import ru.betterend.blocks.FlowerPotBlock; -import ru.betterend.blocks.GlowingHymenophoreBlock; -import ru.betterend.blocks.GlowingMossBlock; -import ru.betterend.blocks.GlowingPillarLuminophorBlock; -import ru.betterend.blocks.GlowingPillarRootsBlock; -import ru.betterend.blocks.GlowingPillarSeedBlock; -import ru.betterend.blocks.HelixTreeLeavesBlock; -import ru.betterend.blocks.HelixTreeSaplingBlock; -import ru.betterend.blocks.HydraluxBlock; -import ru.betterend.blocks.HydraluxPetalBlock; -import ru.betterend.blocks.HydraluxPetalColoredBlock; -import ru.betterend.blocks.HydraluxSaplingBlock; -import ru.betterend.blocks.HydrothermalVentBlock; -import ru.betterend.blocks.InfusionPedestal; -import ru.betterend.blocks.JellyshroomCapBlock; -import ru.betterend.blocks.LacugroveSaplingBlock; -import ru.betterend.blocks.LanceleafBlock; -import ru.betterend.blocks.LanceleafSeedBlock; -import ru.betterend.blocks.LargeAmaranitaBlock; -import ru.betterend.blocks.LucerniaSaplingBlock; -import ru.betterend.blocks.LumecornBlock; -import ru.betterend.blocks.LumecornSeedBlock; -import ru.betterend.blocks.MengerSpongeBlock; -import ru.betterend.blocks.MengerSpongeWetBlock; -import ru.betterend.blocks.MissingTileBlock; -import ru.betterend.blocks.MossyDragonBoneBlock; -import ru.betterend.blocks.MossyGlowshroomCapBlock; -import ru.betterend.blocks.MossyGlowshroomSaplingBlock; -import ru.betterend.blocks.MossyObsidian; -import ru.betterend.blocks.MurkweedBlock; -import ru.betterend.blocks.NeedlegrassBlock; -import ru.betterend.blocks.NeonCactusBlock; -import ru.betterend.blocks.NeonCactusPlantBlock; -import ru.betterend.blocks.PallidiumBlock; -import ru.betterend.blocks.PedestalVanilla; -import ru.betterend.blocks.PondAnemoneBlock; -import ru.betterend.blocks.PythadendronSaplingBlock; -import ru.betterend.blocks.RespawnObeliskBlock; -import ru.betterend.blocks.RunedFlavolite; -import ru.betterend.blocks.ShadowBerryBlock; -import ru.betterend.blocks.ShadowGrassBlock; -import ru.betterend.blocks.SilkMothHiveBlock; -import ru.betterend.blocks.SilkMothNestBlock; -import ru.betterend.blocks.SmallAmaranitaBlock; -import ru.betterend.blocks.SmallJellyshroomBlock; -import ru.betterend.blocks.SmaragdantCrystalBlock; -import ru.betterend.blocks.SmaragdantCrystalShardBlock; -import ru.betterend.blocks.SulphurCrystalBlock; -import ru.betterend.blocks.TenaneaFlowersBlock; -import ru.betterend.blocks.TenaneaSaplingBlock; -import ru.betterend.blocks.TerrainPlantBlock; -import ru.betterend.blocks.TwistedUmbrellaMossBlock; -import ru.betterend.blocks.TwistedUmbrellaMossTallBlock; -import ru.betterend.blocks.UmbrellaMossBlock; -import ru.betterend.blocks.UmbrellaMossTallBlock; -import ru.betterend.blocks.UmbrellaTreeClusterBlock; -import ru.betterend.blocks.UmbrellaTreeClusterEmptyBlock; -import ru.betterend.blocks.UmbrellaTreeMembraneBlock; -import ru.betterend.blocks.UmbrellaTreeSaplingBlock; -import ru.betterend.blocks.VentBubbleColumnBlock; -import ru.betterend.blocks.basis.EndTerrainBlock; -import ru.betterend.blocks.basis.EndTripleTerrain; -import ru.betterend.blocks.basis.EndUnderwaterWallPlantBlock; -import ru.betterend.blocks.basis.EndWallMushroom; -import ru.betterend.blocks.basis.EndWallPlantBlock; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.blocks.basis.PottableCropBlock; -import ru.betterend.blocks.basis.PottableLeavesBlock; -import ru.betterend.blocks.basis.StoneLanternBlock; -import ru.betterend.complexmaterials.ColoredMaterial; -import ru.betterend.complexmaterials.CrystalSubblocksMaterial; -import ru.betterend.complexmaterials.EndWoodenComplexMaterial; -import ru.betterend.complexmaterials.MetalMaterial; -import ru.betterend.complexmaterials.StoneMaterial; -import ru.betterend.config.Configs; -import ru.betterend.item.material.EndArmorMaterial; -import ru.betterend.item.material.EndToolMaterial; -import ru.betterend.tab.CreativeTabs; - -import java.util.List; - -public class EndBlocks { - private static final BlockRegistry REGISTRY = new BlockRegistry(CreativeTabs.TAB_BLOCKS, Configs.BLOCK_CONFIG); - - // Terrain // - public static final Block ENDSTONE_DUST = registerBlock("endstone_dust", new EndstoneDustBlock()); - public static final Block END_MYCELIUM = registerBlock("end_mycelium", new EndTerrainBlock(MaterialColor.COLOR_LIGHT_BLUE)); - public static final Block END_MOSS = registerBlock("end_moss", new EndTerrainBlock(MaterialColor.COLOR_CYAN)); - public static final Block CHORUS_NYLIUM = registerBlock("chorus_nylium", new EndTerrainBlock(MaterialColor.COLOR_MAGENTA)); - public static final Block CAVE_MOSS = registerBlock("cave_moss", new EndTripleTerrain(MaterialColor.COLOR_PURPLE)); - public static final Block CRYSTAL_MOSS = registerBlock("crystal_moss", new EndTerrainBlock(MaterialColor.COLOR_PINK)); - public static final Block SHADOW_GRASS = registerBlock("shadow_grass", new ShadowGrassBlock()); - public static final Block PINK_MOSS = registerBlock("pink_moss", new EndTerrainBlock(MaterialColor.COLOR_PINK)); - public static final Block AMBER_MOSS = registerBlock("amber_moss", new EndTerrainBlock(MaterialColor.COLOR_ORANGE)); - public static final Block JUNGLE_MOSS = registerBlock("jungle_moss", new EndTerrainBlock(MaterialColor.COLOR_GREEN)); - public static final Block SANGNUM = registerBlock("sangnum", new EndTerrainBlock(MaterialColor.COLOR_RED)); - public static final Block RUTISCUS = registerBlock("rutiscus", new EndTerrainBlock(MaterialColor.COLOR_ORANGE)); - public static final Block PALLIDIUM_FULL = registerBlock("pallidium_full", new PallidiumBlock("full", null)); - public static final Block PALLIDIUM_HEAVY = registerBlock("pallidium_heavy", new PallidiumBlock("heavy", PALLIDIUM_FULL)); - public static final Block PALLIDIUM_THIN = registerBlock("pallidium_thin", new PallidiumBlock("thin", PALLIDIUM_HEAVY)); - public static final Block PALLIDIUM_TINY = registerBlock("pallidium_tiny", new PallidiumBlock("tiny", PALLIDIUM_THIN)); - - // Roads // - public static final Block END_MYCELIUM_PATH = registerBlock("end_mycelium_path", new BasePathBlock(END_MYCELIUM)); - public static final Block END_MOSS_PATH = registerBlock("end_moss_path", new BasePathBlock(END_MOSS)); - public static final Block CHORUS_NYLIUM_PATH = registerBlock("chorus_nylium_path", new BasePathBlock(CHORUS_NYLIUM)); - public static final Block CAVE_MOSS_PATH = registerBlock("cave_moss_path", new BasePathBlock(CAVE_MOSS)); - public static final Block CRYSTAL_MOSS_PATH = registerBlock("crystal_moss_path", new BasePathBlock(CRYSTAL_MOSS)); - public static final Block SHADOW_GRASS_PATH = registerBlock("shadow_grass_path", new BasePathBlock(SHADOW_GRASS)); - public static final Block PINK_MOSS_PATH = registerBlock("pink_moss_path", new BasePathBlock(PINK_MOSS)); - public static final Block AMBER_MOSS_PATH = registerBlock("amber_moss_path", new BasePathBlock(AMBER_MOSS)); - public static final Block JUNGLE_MOSS_PATH = registerBlock("jungle_moss_path", new BasePathBlock(JUNGLE_MOSS)); - public static final Block SANGNUM_PATH = registerBlock("sangnum_path", new BasePathBlock(SANGNUM)); - public static final Block RUTISCUS_PATH = registerBlock("rutiscus_path", new BasePathBlock(RUTISCUS)); - - public static final Block MOSSY_OBSIDIAN = registerBlock("mossy_obsidian", new MossyObsidian()); - public static final Block DRAGON_BONE_BLOCK = registerBlock("dragon_bone_block", new BaseRotatedPillarBlock(Blocks.BONE_BLOCK)); - public static final Block DRAGON_BONE_STAIRS = registerBlock("dragon_bone_stairs", new BaseStairsBlock(DRAGON_BONE_BLOCK)); - public static final Block DRAGON_BONE_SLAB = registerBlock("dragon_bone_slab", new BaseSlabBlock(DRAGON_BONE_BLOCK)); - public static final Block MOSSY_DRAGON_BONE = registerBlock("mossy_dragon_bone", new MossyDragonBoneBlock()); - - // Rocks // - public static final StoneMaterial FLAVOLITE = new StoneMaterial("flavolite", MaterialColor.SAND); - public static final StoneMaterial VIOLECITE = new StoneMaterial("violecite", MaterialColor.COLOR_PURPLE); - public static final StoneMaterial SULPHURIC_ROCK = new StoneMaterial("sulphuric_rock", MaterialColor.COLOR_BROWN); - public static final StoneMaterial VIRID_JADESTONE = new StoneMaterial("virid_jadestone", MaterialColor.COLOR_GREEN); - public static final StoneMaterial AZURE_JADESTONE = new StoneMaterial("azure_jadestone", MaterialColor.COLOR_LIGHT_BLUE); - public static final StoneMaterial SANDY_JADESTONE = new StoneMaterial("sandy_jadestone", MaterialColor.COLOR_YELLOW); - public static final StoneMaterial UMBRALITH = new StoneMaterial("umbralith", MaterialColor.DEEPSLATE); - public static final Block BRIMSTONE = registerBlock("brimstone", new BrimstoneBlock()); - public static final Block SULPHUR_CRYSTAL = registerBlock("sulphur_crystal", new SulphurCrystalBlock()); - public static final Block MISSING_TILE = registerBlock("missing_tile", new MissingTileBlock()); - public static final Block ENDSTONE_FLOWER_POT = registerBlock("endstone_flower_pot", new FlowerPotBlock(Blocks.END_STONE)); - - public static final Block FLAVOLITE_RUNED = registerBlock("flavolite_runed", new RunedFlavolite(false)); - public static final Block FLAVOLITE_RUNED_ETERNAL = registerBlock("flavolite_runed_eternal", new RunedFlavolite(true)); - - public static final Block ANDESITE_PEDESTAL = registerBlock("andesite_pedestal", new PedestalVanilla(Blocks.ANDESITE)); - public static final Block DIORITE_PEDESTAL = registerBlock("diorite_pedestal", new PedestalVanilla(Blocks.DIORITE)); - public static final Block GRANITE_PEDESTAL = registerBlock("granite_pedestal", new PedestalVanilla(Blocks.GRANITE)); - public static final Block QUARTZ_PEDESTAL = registerBlock("quartz_pedestal", new PedestalVanilla(Blocks.QUARTZ_BLOCK)); - public static final Block PURPUR_PEDESTAL = registerBlock("purpur_pedestal", new PedestalVanilla(Blocks.PURPUR_BLOCK)); - - public static final Block HYDROTHERMAL_VENT = registerBlock("hydrothermal_vent", new HydrothermalVentBlock()); - public static final Block VENT_BUBBLE_COLUMN = registerEndBlockOnly("vent_bubble_column", new VentBubbleColumnBlock()); - - public static final Block DENSE_SNOW = registerBlock("dense_snow", new DenseSnowBlock()); - public static final Block EMERALD_ICE = registerBlock("emerald_ice", new EmeraldIceBlock()); - public static final Block DENSE_EMERALD_ICE = registerBlock("dense_emerald_ice", new DenseEmeraldIceBlock()); - public static final Block ANCIENT_EMERALD_ICE = registerBlock("ancient_emerald_ice", new AncientEmeraldIceBlock()); - - public static final Block END_STONE_STALACTITE = registerBlock("end_stone_stalactite", new StalactiteBlock(Blocks.END_STONE)); - public static final Block END_STONE_STALACTITE_CAVEMOSS = registerBlock("end_stone_stalactite_cavemoss", new StalactiteBlock(CAVE_MOSS)); - - // Wooden Materials And Trees // - public static final Block MOSSY_GLOWSHROOM_SAPLING = registerBlock("mossy_glowshroom_sapling", new MossyGlowshroomSaplingBlock()); - public static final Block MOSSY_GLOWSHROOM_CAP = registerBlock("mossy_glowshroom_cap", new MossyGlowshroomCapBlock()); - public static final Block MOSSY_GLOWSHROOM_HYMENOPHORE = registerBlock("mossy_glowshroom_hymenophore", new GlowingHymenophoreBlock()); - public static final Block MOSSY_GLOWSHROOM_FUR = registerBlock("mossy_glowshroom_fur", new FurBlock(MOSSY_GLOWSHROOM_SAPLING, 15, 16, true)); - public static final EndWoodenComplexMaterial MOSSY_GLOWSHROOM = new EndWoodenComplexMaterial( - "mossy_glowshroom", - MaterialColor.COLOR_GRAY, - MaterialColor.WOOD - ).init(); - - public static final Block PYTHADENDRON_SAPLING = registerBlock("pythadendron_sapling", new PythadendronSaplingBlock()); - public static final Block PYTHADENDRON_LEAVES = registerBlock("pythadendron_leaves", new PottableLeavesBlock(PYTHADENDRON_SAPLING, MaterialColor.COLOR_MAGENTA)); - public static final EndWoodenComplexMaterial PYTHADENDRON = new EndWoodenComplexMaterial( - "pythadendron", - MaterialColor.COLOR_MAGENTA, - MaterialColor.COLOR_PURPLE - ).init(); - - public static final Block END_LOTUS_SEED = registerBlock("end_lotus_seed", new EndLotusSeedBlock()); - public static final Block END_LOTUS_STEM = registerBlock("end_lotus_stem", new EndLotusStemBlock()); - public static final Block END_LOTUS_LEAF = registerEndBlockOnly("end_lotus_leaf", new EndLotusLeafBlock()); - public static final Block END_LOTUS_FLOWER = registerEndBlockOnly("end_lotus_flower", new EndLotusFlowerBlock()); - public static final EndWoodenComplexMaterial END_LOTUS = new EndWoodenComplexMaterial( - "end_lotus", - MaterialColor.COLOR_LIGHT_BLUE, - MaterialColor.COLOR_CYAN - ).init(); - - public static final Block LACUGROVE_SAPLING = registerBlock("lacugrove_sapling", new LacugroveSaplingBlock()); - public static final Block LACUGROVE_LEAVES = registerBlock("lacugrove_leaves", new PottableLeavesBlock(LACUGROVE_SAPLING, MaterialColor.COLOR_CYAN)); - public static final EndWoodenComplexMaterial LACUGROVE = new EndWoodenComplexMaterial( - "lacugrove", - MaterialColor.COLOR_BROWN, - MaterialColor.COLOR_YELLOW - ).init(); - - public static final Block DRAGON_TREE_SAPLING = registerBlock("dragon_tree_sapling", new DragonTreeSaplingBlock()); - public static final Block DRAGON_TREE_LEAVES = registerBlock("dragon_tree_leaves", new PottableLeavesBlock(DRAGON_TREE_SAPLING, MaterialColor.COLOR_MAGENTA)); - public static final EndWoodenComplexMaterial DRAGON_TREE = new EndWoodenComplexMaterial( - "dragon_tree", - MaterialColor.COLOR_BLACK, - MaterialColor.COLOR_MAGENTA - ).init(); - - public static final Block TENANEA_SAPLING = registerBlock("tenanea_sapling", new TenaneaSaplingBlock()); - public static final Block TENANEA_LEAVES = registerBlock("tenanea_leaves", new PottableLeavesBlock(TENANEA_SAPLING, MaterialColor.COLOR_PINK)); - public static final Block TENANEA_FLOWERS = registerBlock("tenanea_flowers", new TenaneaFlowersBlock()); - public static final Block TENANEA_OUTER_LEAVES = registerBlock("tenanea_outer_leaves", new FurBlock(TENANEA_SAPLING, 32)); - public static final EndWoodenComplexMaterial TENANEA = new EndWoodenComplexMaterial( - "tenanea", - MaterialColor.COLOR_BROWN, - MaterialColor.COLOR_PINK - ).init(); - - public static final Block HELIX_TREE_SAPLING = registerBlock("helix_tree_sapling", new HelixTreeSaplingBlock()); - public static final Block HELIX_TREE_LEAVES = registerBlock("helix_tree_leaves", new HelixTreeLeavesBlock()); - public static final EndWoodenComplexMaterial HELIX_TREE = new EndWoodenComplexMaterial( - "helix_tree", - MaterialColor.COLOR_GRAY, - MaterialColor.COLOR_ORANGE - ).init(); - - public static final Block UMBRELLA_TREE_SAPLING = registerBlock("umbrella_tree_sapling", new UmbrellaTreeSaplingBlock()); - public static final Block UMBRELLA_TREE_MEMBRANE = registerBlock("umbrella_tree_membrane", new UmbrellaTreeMembraneBlock()); - public static final Block UMBRELLA_TREE_CLUSTER = registerBlock("umbrella_tree_cluster", new UmbrellaTreeClusterBlock()); - public static final Block UMBRELLA_TREE_CLUSTER_EMPTY = registerBlock("umbrella_tree_cluster_empty", new UmbrellaTreeClusterEmptyBlock()); - public static final EndWoodenComplexMaterial UMBRELLA_TREE = new EndWoodenComplexMaterial( - "umbrella_tree", - MaterialColor.COLOR_BLUE, - MaterialColor.COLOR_GREEN - ).init(); - - public static final Block JELLYSHROOM_CAP_PURPLE = registerBlock("jellyshroom_cap_purple", new JellyshroomCapBlock(217, 142, 255, 164, 0, 255)); - public static final EndWoodenComplexMaterial JELLYSHROOM = new EndWoodenComplexMaterial( - "jellyshroom", - MaterialColor.COLOR_PURPLE, - MaterialColor.COLOR_LIGHT_BLUE - ).init(); - - public static final Block LUCERNIA_SAPLING = registerBlock("lucernia_sapling", new LucerniaSaplingBlock()); - public static final Block LUCERNIA_LEAVES = registerBlock("lucernia_leaves", new PottableLeavesBlock(LUCERNIA_SAPLING, MaterialColor.COLOR_ORANGE)); - public static final Block LUCERNIA_OUTER_LEAVES = registerBlock("lucernia_outer_leaves", new FurBlock(LUCERNIA_SAPLING, 32)); - public static final EndWoodenComplexMaterial LUCERNIA = new EndWoodenComplexMaterial( - "lucernia", - MaterialColor.COLOR_ORANGE, - MaterialColor.COLOR_ORANGE - ).init(); - - // Small Plants // - public static final Block UMBRELLA_MOSS = registerBlock("umbrella_moss", new UmbrellaMossBlock()); - public static final Block UMBRELLA_MOSS_TALL = registerBlock("umbrella_moss_tall", new UmbrellaMossTallBlock()); - public static final Block CREEPING_MOSS = registerBlock("creeping_moss", new GlowingMossBlock(11)); - public static final Block CHORUS_GRASS = registerBlock("chorus_grass", new ChorusGrassBlock()); - public static final Block CAVE_GRASS = registerBlock("cave_grass", new TerrainPlantBlock(CAVE_MOSS)); - public static final Block CRYSTAL_GRASS = registerBlock("crystal_grass", new TerrainPlantBlock(CRYSTAL_MOSS)); - public static final Block SHADOW_PLANT = registerBlock("shadow_plant", new TerrainPlantBlock(SHADOW_GRASS)); - public static final Block BUSHY_GRASS = registerBlock("bushy_grass", new TerrainPlantBlock(PINK_MOSS)); - public static final Block AMBER_GRASS = registerBlock("amber_grass", new TerrainPlantBlock(AMBER_MOSS)); - public static final Block TWISTED_UMBRELLA_MOSS = registerBlock("twisted_umbrella_moss", new TwistedUmbrellaMossBlock()); - public static final Block TWISTED_UMBRELLA_MOSS_TALL = registerBlock("twisted_umbrella_moss_tall", new TwistedUmbrellaMossTallBlock()); - public static final Block JUNGLE_GRASS = registerBlock("jungle_grass", new TerrainPlantBlock(JUNGLE_MOSS)); - public static final Block BLOOMING_COOKSONIA = registerBlock("blooming_cooksonia", new TerrainPlantBlock(END_MOSS)); - public static final Block SALTEAGO = registerBlock("salteago", new TerrainPlantBlock(END_MOSS)); - public static final Block VAIOLUSH_FERN = registerBlock("vaiolush_fern", new TerrainPlantBlock(END_MOSS)); - public static final Block FRACTURN = registerBlock("fracturn", new TerrainPlantBlock(END_MOSS)); - public static final Block CLAWFERN = registerBlock("clawfern", new TerrainPlantBlock(SANGNUM, MOSSY_OBSIDIAN, MOSSY_DRAGON_BONE)); - public static final Block GLOBULAGUS = registerBlock("globulagus", new TerrainPlantBlock(SANGNUM, MOSSY_OBSIDIAN, MOSSY_DRAGON_BONE)); - public static final Block ORANGO = registerBlock("orango", new TerrainPlantBlock(RUTISCUS)); - public static final Block AERIDIUM = registerBlock("aeridium", new TerrainPlantBlock(RUTISCUS)); - public static final Block LUTEBUS = registerBlock("lutebus", new TerrainPlantBlock(RUTISCUS)); - public static final Block LAMELLARIUM = registerBlock("lamellarium", new TerrainPlantBlock(RUTISCUS)); - public static final Block INFLEXIA = registerBlock("inflexia", new TerrainPlantBlock(PALLIDIUM_FULL, PALLIDIUM_HEAVY, PALLIDIUM_THIN, PALLIDIUM_TINY)); - public static final Block FLAMMALIX = registerBlock("flammalix", new FlammalixBlock()); - - public static final Block BLUE_VINE_SEED = registerBlock("blue_vine_seed", new BlueVineSeedBlock()); - public static final Block BLUE_VINE = registerEndBlockOnly("blue_vine", new BlueVineBlock()); - public static final Block BLUE_VINE_LANTERN = registerBlock("blue_vine_lantern", new BlueVineLanternBlock()); - public static final Block BLUE_VINE_FUR = registerBlock("blue_vine_fur", new FurBlock(BLUE_VINE_SEED, 15, 3, false)); - - public static final Block LANCELEAF_SEED = registerBlock("lanceleaf_seed", new LanceleafSeedBlock()); - public static final Block LANCELEAF = registerEndBlockOnly("lanceleaf", new LanceleafBlock()); - - public static final Block GLOWING_PILLAR_SEED = registerBlock("glowing_pillar_seed", new GlowingPillarSeedBlock()); - public static final Block GLOWING_PILLAR_ROOTS = registerEndBlockOnly("glowing_pillar_roots", new GlowingPillarRootsBlock()); - public static final Block GLOWING_PILLAR_LUMINOPHOR = registerBlock("glowing_pillar_luminophor", new GlowingPillarLuminophorBlock()); - public static final Block GLOWING_PILLAR_LEAVES = registerBlock("glowing_pillar_leaves", new FurBlock(GLOWING_PILLAR_SEED, 15, 3, false)); - - public static final Block SMALL_JELLYSHROOM = registerBlock("small_jellyshroom", new SmallJellyshroomBlock()); - public static final Block BOLUX_MUSHROOM = registerBlock("bolux_mushroom", new BoluxMushroomBlock()); - - public static final Block LUMECORN_SEED = registerBlock("lumecorn_seed", new LumecornSeedBlock()); - public static final Block LUMECORN = registerEndBlockOnly("lumecorn", new LumecornBlock()); - - public static final Block SMALL_AMARANITA_MUSHROOM = registerBlock("small_amaranita_mushroom", new SmallAmaranitaBlock()); - public static final Block LARGE_AMARANITA_MUSHROOM = registerEndBlockOnly("large_amaranita_mushroom", new LargeAmaranitaBlock()); - public static final Block AMARANITA_STEM = registerBlock("amaranita_stem", new AmaranitaStemBlock()); - public static final Block AMARANITA_HYPHAE = registerBlock("amaranita_hyphae", new AmaranitaStemBlock()); - public static final Block AMARANITA_HYMENOPHORE = registerBlock("amaranita_hymenophore", new AmaranitaHymenophoreBlock()); - public static final Block AMARANITA_LANTERN = registerBlock("amaranita_lantern", new GlowingHymenophoreBlock()); - public static final Block AMARANITA_FUR = registerBlock("amaranita_fur", new FurBlock(SMALL_AMARANITA_MUSHROOM, 15, 4, true)); - public static final Block AMARANITA_CAP = registerBlock("amaranita_cap", new AmaranitaCapBlock()); - - public static final Block NEON_CACTUS = registerBlock("neon_cactus", new NeonCactusPlantBlock()); - public static final Block NEON_CACTUS_BLOCK = registerBlock("neon_cactus_block", new NeonCactusBlock()); - public static final Block NEON_CACTUS_BLOCK_STAIRS = registerBlock("neon_cactus_stairs", new BaseStairsBlock(NEON_CACTUS_BLOCK)); - public static final Block NEON_CACTUS_BLOCK_SLAB = registerBlock("neon_cactus_slab", new BaseSlabBlock(NEON_CACTUS_BLOCK)); - - // Crops - public static final Block SHADOW_BERRY = registerBlock("shadow_berry", new ShadowBerryBlock()); - public static final Block BLOSSOM_BERRY = registerBlock("blossom_berry_seed", new PottableCropBlock(EndItems.BLOSSOM_BERRY, PINK_MOSS)); - public static final Block AMBER_ROOT = registerBlock("amber_root_seed", new PottableCropBlock(EndItems.AMBER_ROOT_RAW, AMBER_MOSS)); - public static final Block CHORUS_MUSHROOM = registerBlock("chorus_mushroom_seed", new PottableCropBlock(EndItems.CHORUS_MUSHROOM_RAW, CHORUS_NYLIUM)); - //public static final Block PEARLBERRY = registerBlock("pearlberry_seed", new PottableCropBlock(EndItems.BLOSSOM_BERRY, END_MOSS, END_MYCELIUM)); - public static final Block CAVE_PUMPKIN_SEED = registerBlock("cave_pumpkin_seed", new CavePumpkinVineBlock()); - public static final Block CAVE_PUMPKIN = registerBlock("cave_pumpkin", new CavePumpkinBlock()); - - // Water plants - public static final Block BUBBLE_CORAL = registerBlock("bubble_coral", new BubbleCoralBlock()); - public static final Block MENGER_SPONGE = registerBlock("menger_sponge", new MengerSpongeBlock()); - public static final Block MENGER_SPONGE_WET = registerBlock("menger_sponge_wet", new MengerSpongeWetBlock()); - public static final Block CHARNIA_RED = registerBlock("charnia_red", new CharniaBlock()); - public static final Block CHARNIA_PURPLE = registerBlock("charnia_purple", new CharniaBlock()); - public static final Block CHARNIA_ORANGE = registerBlock("charnia_orange", new CharniaBlock()); - public static final Block CHARNIA_LIGHT_BLUE = registerBlock("charnia_light_blue", new CharniaBlock()); - public static final Block CHARNIA_CYAN = registerBlock("charnia_cyan", new CharniaBlock()); - public static final Block CHARNIA_GREEN = registerBlock("charnia_green", new CharniaBlock()); - - public static final Block END_LILY = registerEndBlockOnly("end_lily", new EndLilyBlock()); - public static final Block END_LILY_SEED = registerBlock("end_lily_seed", new EndLilySeedBlock()); - - public static final Block HYDRALUX_SAPLING = registerBlock("hydralux_sapling", new HydraluxSaplingBlock()); - public static final Block HYDRALUX = registerEndBlockOnly("hydralux", new HydraluxBlock()); - public static final Block HYDRALUX_PETAL_BLOCK = registerBlock("hydralux_petal_block", new HydraluxPetalBlock()); - public static final ColoredMaterial HYDRALUX_PETAL_BLOCK_COLORED = new ColoredMaterial(HydraluxPetalColoredBlock::new, HYDRALUX_PETAL_BLOCK, true); - - public static final Block POND_ANEMONE = registerBlock("pond_anemone", new PondAnemoneBlock()); - - public static final Block FLAMAEA = registerBlock("flamaea", new FlamaeaBlock()); - - public static final Block CAVE_BUSH = registerBlock("cave_bush", new SimpleLeavesBlock(MaterialColor.COLOR_MAGENTA)); - - public static final Block MURKWEED = registerBlock("murkweed", new MurkweedBlock()); - public static final Block NEEDLEGRASS = registerBlock("needlegrass", new NeedlegrassBlock()); - - // Wall Plants // - public static final Block PURPLE_POLYPORE = registerBlock("purple_polypore", new EndWallMushroom(13)); - public static final Block AURANT_POLYPORE = registerBlock("aurant_polypore", new EndWallMushroom(13)); - public static final Block TAIL_MOSS = registerBlock("tail_moss", new EndWallPlantBlock()); - public static final Block CYAN_MOSS = registerBlock("cyan_moss", new EndWallPlantBlock()); - public static final Block TWISTED_MOSS = registerBlock("twisted_moss", new EndWallPlantBlock()); - public static final Block TUBE_WORM = registerBlock("tube_worm", new EndUnderwaterWallPlantBlock()); - public static final Block BULB_MOSS = registerBlock("bulb_moss", new EndWallPlantBlock(12)); - public static final Block JUNGLE_FERN = registerBlock("jungle_fern", new EndWallPlantBlock()); - public static final Block RUSCUS = registerBlock("ruscus", new EndWallPlantBlock()); - - // Vines // - public static final Block DENSE_VINE = registerBlock("dense_vine", new BaseVineBlock(15, true)); - public static final Block TWISTED_VINE = registerBlock("twisted_vine", new BaseVineBlock()); - public static final Block BULB_VINE_SEED = registerBlock("bulb_vine_seed", new BulbVineSeedBlock()); - public static final Block BULB_VINE = registerBlock("bulb_vine", new BulbVineBlock()); - public static final Block JUNGLE_VINE = registerBlock("jungle_vine", new BaseVineBlock()); - public static final Block RUBINEA = registerBlock("rubinea", new BaseVineBlock()); - public static final Block MAGNULA = registerBlock("magnula", new BaseVineBlock()); - public static final Block FILALUX = registerBlock("filalux", new FilaluxBlock()); - public static final Block FILALUX_WINGS = registerBlock("filalux_wings", new FilaluxWingsBlock()); - public static final Block FILALUX_LANTERN = registerBlock("filalux_lantern", new FilaluxLanternBlock()); - - // Mob-Related - public static final Block SILK_MOTH_NEST = registerBlock("silk_moth_nest", new SilkMothNestBlock()); - public static final Block SILK_MOTH_HIVE = registerBlock("silk_moth_hive", new SilkMothHiveBlock()); - - // Ores // - public static final Block ENDER_ORE = registerBlock("ender_ore", new BaseOreBlock(()->EndItems.ENDER_SHARD, 1, 3, 5)); - public static final Block AMBER_ORE = registerBlock("amber_ore", new BaseOreBlock(()->EndItems.RAW_AMBER, 1, 2, 4)); - - // Materials // - public static final MetalMaterial THALLASIUM = MetalMaterial.makeNormal( - "thallasium", - MaterialColor.COLOR_BLUE, - EndToolMaterial.THALLASIUM, - EndArmorMaterial.THALLASIUM - ); - public static final MetalMaterial TERMINITE = MetalMaterial.makeOreless( - "terminite", - MaterialColor.WARPED_WART_BLOCK, - 7F, - 9F, - EndToolMaterial.TERMINITE, - EndArmorMaterial.TERMINITE - ); - public static final Block AETERNIUM_BLOCK = registerBlock("aeternium_block", new AeterniumBlock()); - public static final Block CHARCOAL_BLOCK = registerBlock("charcoal_block", new CharcoalBlock()); - - public static final Block ENDER_BLOCK = registerBlock("ender_block", new EnderBlock()); - public static final Block AURORA_CRYSTAL = registerBlock("aurora_crystal", new AuroraCrystalBlock()); - public static final Block AMBER_BLOCK = registerBlock("amber_block", new AmberBlock()); - public static final Block SMARAGDANT_CRYSTAL_SHARD = registerBlock( - "smaragdant_crystal_shard", - new SmaragdantCrystalShardBlock() - ); - public static final Block SMARAGDANT_CRYSTAL = registerBlock("smaragdant_crystal", new SmaragdantCrystalBlock()); - public static final CrystalSubblocksMaterial SMARAGDANT_SUBBLOCKS = new CrystalSubblocksMaterial( - "smaragdant_crystal", - SMARAGDANT_CRYSTAL - ); - - public static final Block RESPAWN_OBELISK = registerBlock("respawn_obelisk", new RespawnObeliskBlock()); - - // Lanterns - public static final Block ANDESITE_LANTERN = registerBlock( - "andesite_lantern", - new StoneLanternBlock(Blocks.ANDESITE) - ); - public static final Block DIORITE_LANTERN = registerBlock("diorite_lantern", new StoneLanternBlock(Blocks.DIORITE)); - public static final Block GRANITE_LANTERN = registerBlock("granite_lantern", new StoneLanternBlock(Blocks.GRANITE)); - public static final Block QUARTZ_LANTERN = registerBlock( - "quartz_lantern", - new StoneLanternBlock(Blocks.QUARTZ_BLOCK) - ); - public static final Block PURPUR_LANTERN = registerBlock( - "purpur_lantern", - new StoneLanternBlock(Blocks.PURPUR_BLOCK) - ); - public static final Block END_STONE_LANTERN = registerBlock( - "end_stone_lantern", - new StoneLanternBlock(Blocks.END_STONE) - ); - public static final Block BLACKSTONE_LANTERN = registerBlock( - "blackstone_lantern", - new StoneLanternBlock(Blocks.BLACKSTONE) - ); - - public static final Block IRON_BULB_LANTERN = registerBlock("iron_bulb_lantern", new BulbVineLanternBlock()); - public static final ColoredMaterial IRON_BULB_LANTERN_COLORED = new ColoredMaterial( - BulbVineLanternColoredBlock::new, - IRON_BULB_LANTERN, - false - ); - - public static final Block IRON_CHANDELIER = EndBlocks.registerBlock( - "iron_chandelier", - new ChandelierBlock(Blocks.GOLD_BLOCK) - ); - public static final Block GOLD_CHANDELIER = EndBlocks.registerBlock( - "gold_chandelier", - new ChandelierBlock(Blocks.GOLD_BLOCK) - ); - - // Blocks With Entity // - public static final Block END_STONE_FURNACE = registerBlock( - "end_stone_furnace", - new BaseFurnaceBlock(Blocks.END_STONE) - ); - public static final Block END_STONE_SMELTER = registerBlock("end_stone_smelter", new EndStoneSmelter()); - public static final Block ETERNAL_PEDESTAL = registerBlock("eternal_pedestal", new EternalPedestal()); - public static final Block INFUSION_PEDESTAL = registerBlock("infusion_pedestal", new InfusionPedestal()); - public static final Block AETERNIUM_ANVIL = registerBlock("aeternium_anvil", new AeterniumAnvil()); - - // Technical - public static final Block END_PORTAL_BLOCK = registerEndBlockOnly("end_portal_block", new EndPortalBlock()); - - public static List getModBlocks() { - return BlockRegistry.getModBlocks(BetterEnd.MOD_ID); - } - - public static List getModBlockItems() { - return BlockRegistry.getModBlockItems(BetterEnd.MOD_ID); - } - - public static Block registerBlock(ResourceLocation id, Block block) { - if (!Configs.BLOCK_CONFIG.getBooleanRoot(id.getPath(), true)) { - return block; - } - getBlockRegistry().register(id, block); - return block; - } - - public static Block registerBlock(String name, Block block) { - return registerBlock(BetterEnd.makeID(name), block); - } - - public static Block registerEndBlockOnly(String name, Block block) { - return getBlockRegistry().registerBlockOnly(BetterEnd.makeID(name), block); - } - - public static FabricItemSettings makeBlockItemSettings() { - return getBlockRegistry().makeItemSettings(); - } - - @NotNull - public static BlockRegistry getBlockRegistry() { - return REGISTRY; - } -} diff --git a/src/main/java/ru/betterend/registry/EndEnchantments.java b/src/main/java/ru/betterend/registry/EndEnchantments.java deleted file mode 100644 index 6d7c5a38..00000000 --- a/src/main/java/ru/betterend/registry/EndEnchantments.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.betterend.registry; - -import net.minecraft.core.Registry; -import net.minecraft.world.item.enchantment.Enchantment; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.effects.enchantment.EndVeilEnchantment; - -public class EndEnchantments { - public final static Enchantment END_VEIL = registerEnchantment("end_veil", new EndVeilEnchantment()); - - public static Enchantment registerEnchantment(String name, Enchantment enchantment) { - if (!Configs.ENCHANTMENT_CONFIG.getBooleanRoot(name, true)) { - return enchantment; - } - return Registry.register(Registry.ENCHANTMENT, BetterEnd.makeID(name), enchantment); - } - - public static void register() {} -} diff --git a/src/main/java/ru/betterend/registry/EndEntities.java b/src/main/java/ru/betterend/registry/EndEntities.java deleted file mode 100644 index 8a0bb785..00000000 --- a/src/main/java/ru/betterend/registry/EndEntities.java +++ /dev/null @@ -1,140 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; -import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityDimensions; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EntityType.EntityFactory; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import ru.bclib.api.spawning.SpawnRuleBuilder; -import ru.bclib.util.ColorUtil; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.entity.CubozoaEntity; -import ru.betterend.entity.DragonflyEntity; -import ru.betterend.entity.EndFishEntity; -import ru.betterend.entity.EndSlimeEntity; -import ru.betterend.entity.ShadowWalkerEntity; -import ru.betterend.entity.SilkMothEntity; - -public class EndEntities { - public static final EntityType DRAGONFLY = register( - "dragonfly", - MobCategory.AMBIENT, - 0.6F, - 0.5F, - DragonflyEntity::new, - DragonflyEntity.createMobAttributes(), - true, - ColorUtil.color(32, 42, 176), - ColorUtil.color(115, 225, 249) - ); - public static final EntityType END_SLIME = register( - "end_slime", - MobCategory.MONSTER, - 2F, - 2F, - EndSlimeEntity::new, - EndSlimeEntity.createMobAttributes(), - false, - ColorUtil.color(28, 28, 28), - ColorUtil.color(99, 11, 99) - ); - public static final EntityType END_FISH = register( - "end_fish", - MobCategory.WATER_AMBIENT, - 0.5F, - 0.5F, - EndFishEntity::new, - EndFishEntity.createMobAttributes(), - true, - ColorUtil.color(3, 50, 76), - ColorUtil.color(120, 206, 255) - ); - public static final EntityType SHADOW_WALKER = register( - "shadow_walker", - MobCategory.MONSTER, - 0.6F, - 1.95F, - ShadowWalkerEntity::new, - ShadowWalkerEntity.createMobAttributes(), - true, - ColorUtil.color(30, 30, 30), - ColorUtil.color(5, 5, 5) - ); - public static final EntityType CUBOZOA = register( - "cubozoa", - MobCategory.WATER_AMBIENT, - 0.6F, - 1F, - CubozoaEntity::new, - CubozoaEntity.createMobAttributes(), - true, - ColorUtil.color(151, 77, 181), - ColorUtil.color(93, 176, 238) - ); - public static final EntityType SILK_MOTH = register( - "silk_moth", - MobCategory.AMBIENT, - 0.6F, - 0.6F, - SilkMothEntity::new, - SilkMothEntity.createMobAttributes(), - true, - ColorUtil.color(198, 138, 204), - ColorUtil.color(242, 220, 236) - ); - - public static void register() { - // Air // - SpawnRuleBuilder.start(DRAGONFLY).aboveGround(2).maxNearby(8).buildNoRestrictions(Types.MOTION_BLOCKING); - SpawnRuleBuilder.start(SILK_MOTH).aboveGround(2).maxNearby(4).buildNoRestrictions(Types.MOTION_BLOCKING); - - // Land // - SpawnRuleBuilder - .start(END_SLIME) - .notPeaceful() - .maxNearby(4, 64) - .onlyOnValidBlocks() - .customRule(EndSlimeEntity::canSpawn) - .buildNoRestrictions(Types.MOTION_BLOCKING); - - SpawnRuleBuilder.start(SHADOW_WALKER).vanillaHostile().onlyOnValidBlocks().maxNearby(8, 64).buildNoRestrictions(Types.MOTION_BLOCKING); - - // Water // - SpawnRuleBuilder.start(END_FISH).maxNearby(8, 64).buildInWater(Types.MOTION_BLOCKING); - SpawnRuleBuilder.start(CUBOZOA).maxNearby(8, 64).buildInWater(Types.MOTION_BLOCKING); - } - - protected static EntityType register(String name, MobCategory group, float width, float height, EntityFactory entity) { - ResourceLocation id = BetterEnd.makeID(name); - EntityType type = FabricEntityTypeBuilder - .create(group, entity) - .dimensions(EntityDimensions.fixed(width, height)) - .build(); - if (Configs.ENTITY_CONFIG.getBooleanRoot(id.getPath(), true)) { - return Registry.register(Registry.ENTITY_TYPE, id, type); - } - return type; - } - - private static EntityType register(String name, MobCategory group, float width, float height, EntityFactory entity, Builder attributes, boolean fixedSize, int eggColor, int dotsColor) { - ResourceLocation id = BetterEnd.makeID(name); - EntityType type = FabricEntityTypeBuilder - .create(group, entity) - .dimensions(fixedSize ? EntityDimensions.fixed(width, height) : EntityDimensions.scalable(width, height)) - .build(); - if (Configs.ENTITY_CONFIG.getBooleanRoot(id.getPath(), true)) { - FabricDefaultAttributeRegistry.register(type, attributes); - EndItems.registerEndEgg("spawn_egg_" + name, type, eggColor, dotsColor); - return Registry.register(Registry.ENTITY_TYPE, BetterEnd.makeID(name), type); - } - return type; - } -} diff --git a/src/main/java/ru/betterend/registry/EndEntitiesRenders.java b/src/main/java/ru/betterend/registry/EndEntitiesRenders.java deleted file mode 100644 index ce16a082..00000000 --- a/src/main/java/ru/betterend/registry/EndEntitiesRenders.java +++ /dev/null @@ -1,75 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; -import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; -import net.minecraft.client.model.geom.ModelLayerLocation; -import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; -import net.minecraft.client.renderer.entity.MobRenderer; -import net.minecraft.world.entity.EntityType; -import ru.betterend.BetterEnd; -import ru.betterend.entity.model.CubozoaEntityModel; -import ru.betterend.entity.model.DragonflyEntityModel; -import ru.betterend.entity.model.EndFishEntityModel; -import ru.betterend.entity.model.EndSlimeEntityModel; -import ru.betterend.entity.model.SilkMothEntityModel; -import ru.betterend.entity.render.RendererEntityCubozoa; -import ru.betterend.entity.render.RendererEntityDragonfly; -import ru.betterend.entity.render.RendererEntityEndFish; -import ru.betterend.entity.render.RendererEntityEndSlime; -import ru.betterend.entity.render.RendererEntityShadowWalker; -import ru.betterend.entity.render.SilkMothEntityRenderer; -import ru.betterend.item.model.ArmoredElytraModel; -import ru.betterend.item.model.CrystaliteBootsModel; -import ru.betterend.item.model.CrystaliteChestplateModel; -import ru.betterend.item.model.CrystaliteHelmetModel; -import ru.betterend.item.model.CrystaliteLeggingsModel; - -import java.util.function.Function; - -public class EndEntitiesRenders { - public static final ModelLayerLocation DRAGONFLY_MODEL = registerMain("dragonfly"); - public static final ModelLayerLocation END_SLIME_SHELL_MODEL = registerMain("endslime_shell"); - public static final ModelLayerLocation END_SLIME_MODEL = registerMain("endslime"); - public static final ModelLayerLocation END_FISH_MODEL = registerMain("endfish"); - public static final ModelLayerLocation CUBOZOA_MODEL = registerMain("cubozoa"); - public static final ModelLayerLocation SILK_MOTH_MODEL = registerMain("silkmoth"); - public static final ModelLayerLocation TEST_MODEL = registerMain("test"); - - public static final ModelLayerLocation ARMORED_ELYTRA = registerMain("armored_elytra"); - public static final ModelLayerLocation CRYSTALITE_CHESTPLATE = registerMain("crystalite_chestplate"); - public static final ModelLayerLocation CRYSTALITE_CHESTPLATE_THIN = registerMain("crystalite_chestplate_thin"); - public static final ModelLayerLocation CRYSTALITE_HELMET = registerMain("crystalite_helmet"); - public static final ModelLayerLocation CRYSTALITE_LEGGINGS = registerMain("crystalite_leggings"); - public static final ModelLayerLocation CRYSTALITE_BOOTS = registerMain("crystalite_boots"); - - public static void register() { - register(EndEntities.DRAGONFLY, RendererEntityDragonfly::new); - register(EndEntities.END_SLIME, RendererEntityEndSlime::new); - register(EndEntities.END_FISH, RendererEntityEndFish::new); - register(EndEntities.SHADOW_WALKER, RendererEntityShadowWalker::new); - register(EndEntities.CUBOZOA, RendererEntityCubozoa::new); - register(EndEntities.SILK_MOTH, SilkMothEntityRenderer::new); - - EntityModelLayerRegistry.registerModelLayer(DRAGONFLY_MODEL, DragonflyEntityModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(END_SLIME_SHELL_MODEL, EndSlimeEntityModel::getShellOnlyTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(END_SLIME_MODEL, EndSlimeEntityModel::getCompleteTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(END_FISH_MODEL, EndFishEntityModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CUBOZOA_MODEL, CubozoaEntityModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(SILK_MOTH_MODEL, SilkMothEntityModel::getTexturedModelData); - - EntityModelLayerRegistry.registerModelLayer(ARMORED_ELYTRA, ArmoredElytraModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_CHESTPLATE, CrystaliteChestplateModel::getRegularTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_CHESTPLATE_THIN, CrystaliteChestplateModel::getThinTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_HELMET, CrystaliteHelmetModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_LEGGINGS, CrystaliteLeggingsModel::getTexturedModelData); - EntityModelLayerRegistry.registerModelLayer(CRYSTALITE_BOOTS, CrystaliteBootsModel::getTexturedModelData); - } - - private static void register(EntityType type, Function renderer) { - EntityRendererRegistry.register(type, (context) -> renderer.apply(context)); - } - - private static ModelLayerLocation registerMain(String id) { - return new ModelLayerLocation(BetterEnd.makeID(id), "main"); - } -} diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java deleted file mode 100644 index 7849105b..00000000 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ /dev/null @@ -1,400 +0,0 @@ -package ru.betterend.registry; - -import com.google.common.collect.Lists; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.levelgen.GenerationStep; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import net.minecraft.world.level.levelgen.VerticalAnchor; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.placement.CountPlacement; -import net.minecraft.world.level.levelgen.placement.HeightRangePlacement; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.features.BCLCommonFeatures; -import ru.bclib.api.features.BCLFeatureBuilder; -import ru.bclib.util.JsonFactory; -import ru.bclib.world.biomes.BCLBiome; -import ru.bclib.world.features.BCLFeature; -import ru.bclib.world.features.DefaultFeature; -import ru.bclib.world.features.ListFeature.StructureInfo; -import ru.bclib.world.features.NBTFeature.TerrainMerge; -import ru.betterend.BetterEnd; -import ru.betterend.complexmaterials.StoneMaterial; -import ru.betterend.config.Configs; -import ru.betterend.world.biome.cave.EndCaveBiome; -import ru.betterend.world.biome.land.UmbraValleyBiome; -import ru.betterend.world.features.BiomeIslandFeature; -import ru.betterend.world.features.BlueVineFeature; -import ru.betterend.world.features.BuildingListFeature; -import ru.betterend.world.features.CavePumpkinFeature; -import ru.betterend.world.features.CharniaFeature; -import ru.betterend.world.features.CrashedShipFeature; -import ru.betterend.world.features.DoublePlantFeature; -import ru.betterend.world.features.EndLilyFeature; -import ru.betterend.world.features.EndLotusFeature; -import ru.betterend.world.features.EndLotusLeafFeature; -import ru.betterend.world.features.FilaluxFeature; -import ru.betterend.world.features.GlowPillarFeature; -import ru.betterend.world.features.HydraluxFeature; -import ru.betterend.world.features.LanceleafFeature; -import ru.betterend.world.features.MengerSpongeFeature; -import ru.betterend.world.features.NeonCactusFeature; -import ru.betterend.world.features.SilkMothNestFeature; -import ru.betterend.world.features.SingleInvertedScatterFeature; -import ru.betterend.world.features.SinglePlantFeature; -import ru.betterend.world.features.UnderwaterPlantFeature; -import ru.betterend.world.features.VineFeature; -import ru.betterend.world.features.WallPlantFeature; -import ru.betterend.world.features.WallPlantOnLogFeature; -import ru.betterend.world.features.bushes.BushFeature; -import ru.betterend.world.features.bushes.BushWithOuterFeature; -import ru.betterend.world.features.bushes.LargeAmaranitaFeature; -import ru.betterend.world.features.bushes.Lumecorn; -import ru.betterend.world.features.bushes.TenaneaBushFeature; -import ru.betterend.world.features.terrain.ArchFeature; -import ru.betterend.world.features.terrain.BigAuroraCrystalFeature; -import ru.betterend.world.features.terrain.DesertLakeFeature; -import ru.betterend.world.features.terrain.EndLakeFeature; -import ru.betterend.world.features.terrain.FallenPillarFeature; -import ru.betterend.world.features.terrain.FloatingSpireFeature; -import ru.betterend.world.features.terrain.GeyserFeature; -import ru.betterend.world.features.terrain.IceStarFeature; -import ru.betterend.world.features.terrain.ObsidianBoulderFeature; -import ru.betterend.world.features.terrain.ObsidianPillarBasementFeature; -import ru.betterend.world.features.terrain.OreLayerFeature; -import ru.betterend.world.features.terrain.SingleBlockFeature; -import ru.betterend.world.features.terrain.SmaragdantCrystalFeature; -import ru.betterend.world.features.terrain.SpireFeature; -import ru.betterend.world.features.terrain.StalactiteFeature; -import ru.betterend.world.features.terrain.SulphurHillFeature; -import ru.betterend.world.features.terrain.SulphuricCaveFeature; -import ru.betterend.world.features.terrain.SulphuricLakeFeature; -import ru.betterend.world.features.terrain.SurfaceVentFeature; -import ru.betterend.world.features.terrain.ThinArchFeature; -import ru.betterend.world.features.terrain.caves.RoundCaveFeature; -import ru.betterend.world.features.terrain.caves.TunelCaveFeature; -import ru.betterend.world.features.trees.DragonTreeFeature; -import ru.betterend.world.features.trees.GiganticAmaranitaFeature; -import ru.betterend.world.features.trees.HelixTreeFeature; -import ru.betterend.world.features.trees.JellyshroomFeature; -import ru.betterend.world.features.trees.LacugroveFeature; -import ru.betterend.world.features.trees.LucerniaFeature; -import ru.betterend.world.features.trees.MossyGlowshroomFeature; -import ru.betterend.world.features.trees.PythadendronTreeFeature; -import ru.betterend.world.features.trees.TenaneaFeature; -import ru.betterend.world.features.trees.UmbrellaTreeFeature; - -import java.io.InputStream; -import java.util.List; - -public class EndFeatures { - // Trees // - public static final BCLFeature MOSSY_GLOWSHROOM = redisterVegetation("mossy_glowshroom", new MossyGlowshroomFeature(), 2); - public static final BCLFeature PYTHADENDRON_TREE = redisterVegetation("pythadendron_tree", new PythadendronTreeFeature(), 1); - public static final BCLFeature LACUGROVE = redisterVegetation("lacugrove", new LacugroveFeature(), 4); - public static final BCLFeature DRAGON_TREE = redisterVegetation("dragon_tree", new DragonTreeFeature(), 2); - public static final BCLFeature TENANEA = redisterVegetation("tenanea", new TenaneaFeature(), 2); - public static final BCLFeature HELIX_TREE = redisterVegetation("helix_tree", new HelixTreeFeature(), 1); - public static final BCLFeature UMBRELLA_TREE = redisterVegetation("umbrella_tree", new UmbrellaTreeFeature(), 2); - public static final BCLFeature JELLYSHROOM = redisterVegetation("jellyshroom", new JellyshroomFeature(), 2); - public static final BCLFeature GIGANTIC_AMARANITA = redisterVegetation("gigantic_amaranita", new GiganticAmaranitaFeature(), 1); - public static final BCLFeature LUCERNIA = redisterVegetation("lucernia", new LucerniaFeature(), 3); - - // Bushes // - public static final BCLFeature PYTHADENDRON_BUSH = redisterVegetation("pythadendron_bush", new BushFeature(EndBlocks.PYTHADENDRON_LEAVES, EndBlocks.PYTHADENDRON.getBark()), 3); - public static final BCLFeature DRAGON_TREE_BUSH = redisterVegetation("dragon_tree_bush", new BushFeature(EndBlocks.DRAGON_TREE_LEAVES, EndBlocks.DRAGON_TREE.getBark()), 5); - public static final BCLFeature TENANEA_BUSH = redisterVegetation("tenanea_bush", new TenaneaBushFeature(), 6); - public static final BCLFeature LUMECORN = redisterVegetation("lumecorn", new Lumecorn(), 5); - public static final BCLFeature LARGE_AMARANITA = redisterVegetation("large_amaranita", new LargeAmaranitaFeature(), 5); - public static final BCLFeature LUCERNIA_BUSH = redisterVegetation("lucernia_bush", new BushWithOuterFeature(EndBlocks.LUCERNIA_LEAVES, EndBlocks.LUCERNIA_OUTER_LEAVES, EndBlocks.LUCERNIA.getBark()), 10); - public static final BCLFeature LUCERNIA_BUSH_RARE = redisterVegetation("lucernia_bush_rare", new BushWithOuterFeature(EndBlocks.LUCERNIA_LEAVES, EndBlocks.LUCERNIA_OUTER_LEAVES, EndBlocks.LUCERNIA.getBark()), 1); - public static final BCLFeature NEON_CACTUS = redisterVegetation("neon_cactus", new NeonCactusFeature(), 2); - - // Plants // - public static final BCLFeature UMBRELLA_MOSS = redisterVegetation("umbrella_moss", new DoublePlantFeature(EndBlocks.UMBRELLA_MOSS, EndBlocks.UMBRELLA_MOSS_TALL, 5), 3); - public static final BCLFeature CREEPING_MOSS = redisterVegetation("creeping_moss", new SinglePlantFeature(EndBlocks.CREEPING_MOSS, 5), 3); - public static final BCLFeature BLUE_VINE = redisterVegetation("blue_vine", new BlueVineFeature(), 1); - public static final BCLFeature CHORUS_GRASS = redisterVegetation("chorus_grass", new SinglePlantFeature(EndBlocks.CHORUS_GRASS, 4), 3); - public static final BCLFeature CRYSTAL_GRASS = redisterVegetation("crystal_grass", new SinglePlantFeature(EndBlocks.CRYSTAL_GRASS, 8, false), 5); - public static final BCLFeature SHADOW_PLANT = redisterVegetation("shadow_plant", new SinglePlantFeature(EndBlocks.SHADOW_PLANT, 6), 5); - public static final BCLFeature MURKWEED = redisterVegetation("murkweed", new SinglePlantFeature(EndBlocks.MURKWEED, 3), 2); - public static final BCLFeature NEEDLEGRASS = redisterVegetation("needlegrass", new SinglePlantFeature(EndBlocks.NEEDLEGRASS, 3), 1); - public static final BCLFeature SHADOW_BERRY = redisterVegetation("shadow_berry", new SinglePlantFeature(EndBlocks.SHADOW_BERRY, 2), 1); - public static final BCLFeature BUSHY_GRASS = redisterVegetation("bushy_grass", new SinglePlantFeature(EndBlocks.BUSHY_GRASS, 8, false), 10); - public static final BCLFeature BUSHY_GRASS_WG = redisterVegetation("bushy_grass_wg", new SinglePlantFeature(EndBlocks.BUSHY_GRASS, 5), 8); - public static final BCLFeature AMBER_GRASS = redisterVegetation("amber_grass", new SinglePlantFeature(EndBlocks.AMBER_GRASS, 6), 7); - public static final BCLFeature LANCELEAF = redisterVegetation("lanceleaf", new LanceleafFeature(), 2); - public static final BCLFeature GLOW_PILLAR = redisterVegetation("glow_pillar", new GlowPillarFeature(), 1); - public static final BCLFeature TWISTED_UMBRELLA_MOSS = redisterVegetation("twisted_umbrella_moss", new DoublePlantFeature(EndBlocks.TWISTED_UMBRELLA_MOSS, EndBlocks.TWISTED_UMBRELLA_MOSS_TALL, 6), 3); - public static final BCLFeature JUNGLE_GRASS = redisterVegetation("jungle_grass", new SinglePlantFeature(EndBlocks.JUNGLE_GRASS, 7, 3), 6); - public static final BCLFeature SMALL_JELLYSHROOM_FLOOR = redisterVegetation("small_jellyshroom_floor", new SinglePlantFeature(EndBlocks.SMALL_JELLYSHROOM, 5, 5), 2); - public static final BCLFeature BLOSSOM_BERRY = redisterVegetation("blossom_berry", new SinglePlantFeature(EndBlocks.BLOSSOM_BERRY, 3, 3), 2); - public static final BCLFeature BLOOMING_COOKSONIA = redisterVegetation("blooming_cooksonia", new SinglePlantFeature(EndBlocks.BLOOMING_COOKSONIA, 5), 5); - public static final BCLFeature SALTEAGO = redisterVegetation("salteago", new SinglePlantFeature(EndBlocks.SALTEAGO, 5), 5); - public static final BCLFeature VAIOLUSH_FERN = redisterVegetation("vaiolush_fern", new SinglePlantFeature(EndBlocks.VAIOLUSH_FERN, 5), 5); - public static final BCLFeature FRACTURN = redisterVegetation("fracturn", new SinglePlantFeature(EndBlocks.FRACTURN, 5), 5); - public static final BCLFeature UMBRELLA_MOSS_RARE = redisterVegetation("umbrella_moss_rare", new SinglePlantFeature(EndBlocks.UMBRELLA_MOSS, 3), 2); - public static final BCLFeature CREEPING_MOSS_RARE = redisterVegetation("creeping_moss_rare", new SinglePlantFeature(EndBlocks.CREEPING_MOSS, 3), 2); - public static final BCLFeature TWISTED_UMBRELLA_MOSS_RARE = redisterVegetation("twisted_umbrella_moss_rare", new SinglePlantFeature(EndBlocks.TWISTED_UMBRELLA_MOSS, 3), 2); - public static final BCLFeature ORANGO = redisterVegetation("orango", new SinglePlantFeature(EndBlocks.ORANGO, 5), 6); - public static final BCLFeature AERIDIUM = redisterVegetation("aeridium", new SinglePlantFeature(EndBlocks.AERIDIUM, 5, 4), 5); - public static final BCLFeature LUTEBUS = redisterVegetation("lutebus", new SinglePlantFeature(EndBlocks.LUTEBUS, 5, 2), 5); - public static final BCLFeature LAMELLARIUM = redisterVegetation("lamellarium", new SinglePlantFeature(EndBlocks.LAMELLARIUM, 5), 6); - public static final BCLFeature SMALL_AMARANITA = redisterVegetation("small_amaranita", new SinglePlantFeature(EndBlocks.SMALL_AMARANITA_MUSHROOM, 5, 5), 4); - public static final BCLFeature GLOBULAGUS = redisterVegetation("globulagus", new SinglePlantFeature(EndBlocks.GLOBULAGUS, 5, 3), 6); - public static final BCLFeature CLAWFERN = redisterVegetation("clawfern", new SinglePlantFeature(EndBlocks.CLAWFERN, 5, 4), 5); - public static final BCLFeature BOLUX_MUSHROOM = redisterVegetation("bolux_mushroom", new SinglePlantFeature(EndBlocks.BOLUX_MUSHROOM, 5, 5), 2); - public static final BCLFeature CHORUS_MUSHROOM = redisterVegetation("chorus_mushroom", new SinglePlantFeature(EndBlocks.CHORUS_MUSHROOM, 3, 5), 1); - public static final BCLFeature AMBER_ROOT = redisterVegetation("amber_root", new SinglePlantFeature(EndBlocks.AMBER_ROOT, 5, 5), 1); - //public static final BCLFeature PEARLBERRY = redisterVegetation("pearlberry", new SinglePlantFeature(EndBlocks.PEARLBERRY, 5, 5), 1); - public static final BCLFeature INFLEXIA = redisterVegetation("inflexia", new SinglePlantFeature(EndBlocks.INFLEXIA, 7, false, 3), 16); - public static final BCLFeature FLAMMALIX = redisterVegetation("flammalix", new SinglePlantFeature(EndBlocks.FLAMMALIX, 3, false, 7), 5); - - // Vines // - public static final BCLFeature DENSE_VINE = redisterVegetation("dense_vine", new VineFeature(EndBlocks.DENSE_VINE, 24), 3); - public static final BCLFeature TWISTED_VINE = redisterVegetation("twisted_vine", new VineFeature(EndBlocks.TWISTED_VINE, 24), 1); - public static final BCLFeature BULB_VINE = redisterVegetation("bulb_vine", new VineFeature(EndBlocks.BULB_VINE, 24), 3); - public static final BCLFeature JUNGLE_VINE = redisterVegetation("jungle_vine", new VineFeature(EndBlocks.JUNGLE_VINE, 24), 5); - - // Ceil plants - public static final BCLFeature SMALL_JELLYSHROOM_CEIL = redisterVegetation("small_jellyshroom_ceil", new SingleInvertedScatterFeature(EndBlocks.SMALL_JELLYSHROOM, 8), 8); - - // Wall Plants // - public static final BCLFeature PURPLE_POLYPORE = redisterVegetation("purple_polypore", new WallPlantOnLogFeature(EndBlocks.PURPLE_POLYPORE, 3), 5); - public static final BCLFeature AURANT_POLYPORE = redisterVegetation("aurant_polypore", new WallPlantOnLogFeature(EndBlocks.AURANT_POLYPORE, 3), 5); - public static final BCLFeature TAIL_MOSS = redisterVegetation("tail_moss", new WallPlantFeature(EndBlocks.TAIL_MOSS, 3), 15); - public static final BCLFeature CYAN_MOSS = redisterVegetation("cyan_moss", new WallPlantFeature(EndBlocks.CYAN_MOSS, 3), 15); - public static final BCLFeature TAIL_MOSS_WOOD = redisterVegetation("tail_moss_wood", new WallPlantOnLogFeature(EndBlocks.TAIL_MOSS, 4), 25); - public static final BCLFeature CYAN_MOSS_WOOD = redisterVegetation("cyan_moss_wood", new WallPlantOnLogFeature(EndBlocks.CYAN_MOSS, 4), 25); - public static final BCLFeature TWISTED_MOSS = redisterVegetation("twisted_moss", new WallPlantFeature(EndBlocks.TWISTED_MOSS, 6), 15); - public static final BCLFeature TWISTED_MOSS_WOOD = redisterVegetation("twisted_moss_wood", new WallPlantOnLogFeature(EndBlocks.TWISTED_MOSS, 6), 25); - public static final BCLFeature BULB_MOSS = redisterVegetation("bulb_moss", new WallPlantFeature(EndBlocks.BULB_MOSS, 6), 1); - public static final BCLFeature BULB_MOSS_WOOD = redisterVegetation("bulb_moss_wood", new WallPlantOnLogFeature(EndBlocks.BULB_MOSS, 6), 15); - public static final BCLFeature SMALL_JELLYSHROOM_WALL = redisterVegetation("small_jellyshroom_wall", new WallPlantFeature(EndBlocks.SMALL_JELLYSHROOM, 4), 4); - public static final BCLFeature SMALL_JELLYSHROOM_WOOD = redisterVegetation("small_jellyshroom_wood", new WallPlantOnLogFeature(EndBlocks.SMALL_JELLYSHROOM, 4), 8); - public static final BCLFeature JUNGLE_FERN_WOOD = redisterVegetation("jungle_fern_wood", new WallPlantOnLogFeature(EndBlocks.JUNGLE_FERN, 3), 12); - public static final BCLFeature RUSCUS = redisterVegetation("ruscus", new WallPlantFeature(EndBlocks.RUSCUS, 6), 10); - public static final BCLFeature RUSCUS_WOOD = redisterVegetation("ruscus_wood", new WallPlantOnLogFeature(EndBlocks.RUSCUS, 6), 10); - - // Sky plants - public static final BCLFeature FILALUX = redisterVegetation("filalux", new FilaluxFeature(), 1); - - // Water // - public static final BCLFeature BUBBLE_CORAL = redisterVegetation("bubble_coral", new UnderwaterPlantFeature(EndBlocks.BUBBLE_CORAL, 6), 10); - public static final BCLFeature BUBBLE_CORAL_RARE = redisterVegetation("bubble_coral_rare", new UnderwaterPlantFeature(EndBlocks.BUBBLE_CORAL, 3), 4); - public static final BCLFeature END_LILY = redisterVegetation("end_lily", new EndLilyFeature(6), 10); - public static final BCLFeature END_LILY_RARE = redisterVegetation("end_lily_rare", new EndLilyFeature(3), 4); - public static final BCLFeature END_LOTUS = redisterVegetation("end_lotus", new EndLotusFeature(7), 5); - public static final BCLFeature END_LOTUS_LEAF = redisterVegetation("end_lotus_leaf", new EndLotusLeafFeature(20), 25); - public static final BCLFeature HYDRALUX = redisterVegetation("hydralux", new HydraluxFeature(5), 5); - public static final BCLFeature POND_ANEMONE = redisterVegetation("pond_anemone", new UnderwaterPlantFeature(EndBlocks.POND_ANEMONE, 6), 10); - - public static final BCLFeature CHARNIA_RED = redisterVegetation("charnia_red", new CharniaFeature(EndBlocks.CHARNIA_RED), 10); - public static final BCLFeature CHARNIA_PURPLE = redisterVegetation("charnia_purple", new CharniaFeature(EndBlocks.CHARNIA_PURPLE), 10); - public static final BCLFeature CHARNIA_CYAN = redisterVegetation("charnia_cyan", new CharniaFeature(EndBlocks.CHARNIA_CYAN), 10); - public static final BCLFeature CHARNIA_LIGHT_BLUE = redisterVegetation("charnia_light_blue", new CharniaFeature(EndBlocks.CHARNIA_LIGHT_BLUE), 10); - public static final BCLFeature CHARNIA_ORANGE = redisterVegetation("charnia_orange", new CharniaFeature(EndBlocks.CHARNIA_ORANGE), 10); - public static final BCLFeature CHARNIA_GREEN = redisterVegetation("charnia_green", new CharniaFeature(EndBlocks.CHARNIA_GREEN), 10); - public static final BCLFeature MENGER_SPONGE = redisterVegetation("menger_sponge", new MengerSpongeFeature(5), 1); - public static final BCLFeature CHARNIA_RED_RARE = redisterVegetation("charnia_red_rare", new CharniaFeature(EndBlocks.CHARNIA_RED),2); - public static final BCLFeature BIOME_ISLAND = BCLFeatureBuilder.start(BetterEnd.makeID("overworld_island"), new BiomeIslandFeature()).decoration(Decoration.RAW_GENERATION).build(); - public static final BCLFeature FLAMAEA = redisterVegetation("flamaea", new SinglePlantFeature(EndBlocks.FLAMAEA, 12, false, 5), 20); - - // Terrain // - public static final BCLFeature END_LAKE = registerLake("end_lake", new EndLakeFeature(), 4); - public static final BCLFeature END_LAKE_NORMAL = registerLake("end_lake_normal", new EndLakeFeature(), 20); - public static final BCLFeature END_LAKE_RARE = registerLake("end_lake_rare", new EndLakeFeature(), 40); - public static final BCLFeature DESERT_LAKE = registerLake("desert_lake", new DesertLakeFeature(), 8); - public static final BCLFeature ROUND_CAVE = registerRawGen("round_cave", new RoundCaveFeature(), 2); - public static final BCLFeature SPIRE = registerRawGen("spire", new SpireFeature(), 4); - public static final BCLFeature FLOATING_SPIRE = registerRawGen("floating_spire", new FloatingSpireFeature(), 8); - public static final BCLFeature GEYSER = registerRawGen("geyser", new GeyserFeature(), 8); - public static final BCLFeature SULPHURIC_LAKE = registerLake("sulphuric_lake", new SulphuricLakeFeature(), 8); - public static final BCLFeature SULPHURIC_CAVE = BCLCommonFeatures.makeCountFeature(BetterEnd.makeID("sulphuric_cave"), Decoration.RAW_GENERATION, new SulphuricCaveFeature(), 2); - public static final BCLFeature ICE_STAR = registerRawGen("ice_star", new IceStarFeature(5, 15, 10, 25), 15); - public static final BCLFeature ICE_STAR_SMALL = registerRawGen("ice_star_small", new IceStarFeature(3, 5, 7, 12), 8); - public static final BCLFeature SURFACE_VENT = registerChanced("surface_vent", new SurfaceVentFeature(), 4); - public static final BCLFeature SULPHUR_HILL = registerChanced("sulphur_hill", new SulphurHillFeature(), 8); - public static final BCLFeature OBSIDIAN_PILLAR_BASEMENT = registerChanced("obsidian_pillar_basement", new ObsidianPillarBasementFeature(), 8); - public static final BCLFeature OBSIDIAN_BOULDER = registerChanced("obsidian_boulder", new ObsidianBoulderFeature(), 10); - public static final BCLFeature FALLEN_PILLAR = registerChanced("fallen_pillar", new FallenPillarFeature(), 20); - public static final BCLFeature TUNEL_CAVE = BCLCommonFeatures.makeChunkFeature(BetterEnd.makeID("tunel_cave"), Decoration.RAW_GENERATION, new TunelCaveFeature()); - public static final BCLFeature UMBRALITH_ARCH = registerChanced("umbralith_arch", new ArchFeature( - EndBlocks.UMBRALITH.stone, - pos -> UmbraValleyBiome.getSurface(pos.getX(), pos.getZ()).defaultBlockState() - ), 10); - public static final BCLFeature THIN_UMBRALITH_ARCH = registerChanced("thin_umbralith_arch", new ThinArchFeature(EndBlocks.UMBRALITH.stone), 15); - - // Ores // - public static final BCLFeature THALLASIUM_ORE = registerOre("thallasium_ore", EndBlocks.THALLASIUM.ore, 24, 8); - public static final BCLFeature ENDER_ORE = registerOre("ender_ore", EndBlocks.ENDER_ORE, 12, 4); - public static final BCLFeature AMBER_ORE = registerOre("amber_ore", EndBlocks.AMBER_ORE, 60, 6); - public static final BCLFeature DRAGON_BONE_BLOCK_ORE = registerOre("dragon_bone_ore", EndBlocks.DRAGON_BONE_BLOCK, 24, 8); - public static final BCLFeature VIOLECITE_LAYER = registerLayer("violecite_layer", EndBlocks.VIOLECITE, 15, 16, 128, 8); - public static final BCLFeature FLAVOLITE_LAYER = registerLayer("flavolite_layer", EndBlocks.FLAVOLITE, 12, 16, 128, 6); - - // Buildings - public static final BCLFeature CRASHED_SHIP = registerChanced("crashed_ship", new CrashedShipFeature(), 500); - - // Mobs - public static final BCLFeature SILK_MOTH_NEST = registerChanced("silk_moth_nest", new SilkMothNestFeature(), 2); - - // Caves - public static final DefaultFeature SMARAGDANT_CRYSTAL = new SmaragdantCrystalFeature(); - public static final DefaultFeature SMARAGDANT_CRYSTAL_SHARD = new SingleBlockFeature(EndBlocks.SMARAGDANT_CRYSTAL_SHARD); - public static final DefaultFeature BIG_AURORA_CRYSTAL = new BigAuroraCrystalFeature(); - public static final DefaultFeature CAVE_BUSH = new BushFeature(EndBlocks.CAVE_BUSH, EndBlocks.CAVE_BUSH); - public static final DefaultFeature CAVE_GRASS = new SingleBlockFeature(EndBlocks.CAVE_GRASS); - public static final DefaultFeature RUBINEA = new VineFeature(EndBlocks.RUBINEA, 8); - public static final DefaultFeature MAGNULA = new VineFeature(EndBlocks.MAGNULA, 8); - public static final DefaultFeature END_STONE_STALACTITE = new StalactiteFeature( - true, - EndBlocks.END_STONE_STALACTITE, - Blocks.END_STONE - ); - public static final DefaultFeature END_STONE_STALAGMITE = new StalactiteFeature( - false, - EndBlocks.END_STONE_STALACTITE, - Blocks.END_STONE - ); - public static final DefaultFeature END_STONE_STALACTITE_CAVEMOSS = new StalactiteFeature( - true, - EndBlocks.END_STONE_STALACTITE_CAVEMOSS, - Blocks.END_STONE, - EndBlocks.CAVE_MOSS - ); - public static final DefaultFeature END_STONE_STALAGMITE_CAVEMOSS = new StalactiteFeature( - false, - EndBlocks.END_STONE_STALACTITE_CAVEMOSS, - EndBlocks.CAVE_MOSS - ); - public static final DefaultFeature CAVE_PUMPKIN = new CavePumpkinFeature(); - - private static BCLFeature redisterVegetation(String name, Feature feature, int density) { - ResourceLocation id = BetterEnd.makeID(name); - return BCLFeatureBuilder.start(id, feature).countLayersMax(density).onlyInBiome().build(); - } - - private static BCLFeature registerRawGen(String name, Feature feature, int chance) { - return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), Decoration.RAW_GENERATION, feature, chance); - } - - private static BCLFeature registerLake(String name, Feature feature, int chance) { - return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), Decoration.LAKES, feature, chance); - } - - private static BCLFeature registerChanced(String name, Feature feature, int chance) { - return BCLCommonFeatures.makeChancedFeature(BetterEnd.makeID(name), Decoration.SURFACE_STRUCTURES, feature, chance); - } - - private static BCLFeature registerOre(String name, Block blockOre, int veins, int veinSize) { - return BCLCommonFeatures.makeOreFeature(BetterEnd.makeID(name), blockOre, Blocks.END_STONE, veins, veinSize, 0, HeightRangePlacement.uniform(VerticalAnchor.bottom(), VerticalAnchor.absolute(128)), false); - } - - private static BCLFeature registerLayer(String name, Block block, float radius, int minY, int maxY, int count) { - OreLayerFeature layer = new OreLayerFeature(block.defaultBlockState(), radius, minY, maxY); - return BCLFeatureBuilder - .start(BetterEnd.makeID(name), layer) - .decoration( GenerationStep.Decoration.UNDERGROUND_ORES) - .modifier(CountPlacement.of(count)) - .build(); - } - - private static BCLFeature registerLayer(String name, StoneMaterial material, float radius, int minY, int maxY, int count) { - return registerLayer(name, material.stone, radius, minY, maxY, count); - } - - public static void addBiomeFeatures(ResourceLocation id, Holder biome) { - BiomeAPI.addBiomeFeature(biome, FLAVOLITE_LAYER); - BiomeAPI.addBiomeFeature(biome, THALLASIUM_ORE); - BiomeAPI.addBiomeFeature(biome, ENDER_ORE); - BiomeAPI.addBiomeFeature(biome, CRASHED_SHIP); - - BCLBiome bclbiome = BiomeAPI.getBiome(id); - BCLFeature feature = getBiomeStructures(bclbiome); - if (feature != null) { - BiomeAPI.addBiomeFeature(biome, feature); - } - - if (id.getNamespace().equals(BetterEnd.MOD_ID)) { - return; - } - - boolean hasCaves = bclbiome.getCustomData("has_caves", true) && !(bclbiome instanceof EndCaveBiome); - //TODO: 1.19 Test Cave generation - if (hasCaves && !BiomeAPI.wasRegisteredAsEndVoidBiome(id) /*!BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(id)*/) { - if (Configs.BIOME_CONFIG.getBoolean(id, "hasCaves", true)) { - BiomeAPI.addBiomeFeature(biome, ROUND_CAVE); - BiomeAPI.addBiomeFeature(biome, TUNEL_CAVE); - } - } - } - - private static BCLFeature getBiomeStructures(BCLBiome biome) { - String ns = biome.getID().getNamespace(); - String nm = biome.getID().getPath(); - ResourceLocation id = new ResourceLocation(ns, nm + "_structures"); - - if (BuiltinRegistries.PLACED_FEATURE.containsKey(id)) { - PlacedFeature placed = BuiltinRegistries.PLACED_FEATURE.get(id); - Feature feature = Registry.FEATURE.get(id); - return BCLFeatureBuilder - .start(id, feature) - .decoration(Decoration.SURFACE_STRUCTURES) - .modifier(placed.placement()) - .build(placed.feature().value().config()); - } - - String path = "/data/" + ns + "/structures/biome/" + nm + "/"; - InputStream inputstream = EndFeatures.class.getResourceAsStream(path + "structures.json"); - if (inputstream != null) { - JsonObject obj = JsonFactory.getJsonObject(inputstream); - JsonArray structures = obj.getAsJsonArray("structures"); - if (structures != null) { - List list = Lists.newArrayList(); - structures.forEach((entry) -> { - JsonObject e = entry.getAsJsonObject(); - String structure = path + e.get("nbt").getAsString() + ".nbt"; - TerrainMerge terrainMerge = TerrainMerge.getFromString(e.get("terrainMerge").getAsString()); - int offsetY = e.get("offsetY").getAsInt(); - list.add(new StructureInfo(structure, offsetY, terrainMerge)); - }); - if (!list.isEmpty()) { - return BCLCommonFeatures.makeChancedFeature( - new ResourceLocation(ns, nm + "_structures"), - Decoration.SURFACE_STRUCTURES, - new BuildingListFeature(list, Blocks.END_STONE.defaultBlockState()), - 10 - ); - } - } - } - return null; - } - - public static BCLBiomeBuilder addDefaultFeatures(BCLBiomeBuilder builder, boolean hasCaves) { - builder.feature(FLAVOLITE_LAYER); - builder.feature(THALLASIUM_ORE); - builder.feature(ENDER_ORE); - builder.feature(CRASHED_SHIP); - - if (hasCaves) { - builder.feature(ROUND_CAVE); - builder.feature(TUNEL_CAVE); - } - - return builder; - } - - public static void register() {} -} diff --git a/src/main/java/ru/betterend/registry/EndItems.java b/src/main/java/ru/betterend/registry/EndItems.java deleted file mode 100644 index 1bcdb454..00000000 --- a/src/main/java/ru/betterend/registry/EndItems.java +++ /dev/null @@ -1,200 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.food.Foods; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.TieredItem; -import net.minecraft.world.item.Tiers; -import org.jetbrains.annotations.NotNull; -import ru.bclib.items.BaseArmorItem; -import ru.bclib.items.ModelProviderItem; -import ru.bclib.items.tool.BaseAxeItem; -import ru.bclib.items.tool.BaseHoeItem; -import ru.bclib.items.tool.BaseShovelItem; -import ru.bclib.items.tool.BaseSwordItem; -import ru.bclib.registry.ItemRegistry; -import ru.betterend.BetterEnd; -import ru.betterend.config.Configs; -import ru.betterend.item.ArmoredElytra; -import ru.betterend.item.CrystaliteBoots; -import ru.betterend.item.CrystaliteChestplate; -import ru.betterend.item.CrystaliteElytra; -import ru.betterend.item.CrystaliteHelmet; -import ru.betterend.item.CrystaliteLeggings; -import ru.betterend.item.EnchantedItem; -import ru.betterend.item.EndArmorItem; -import ru.betterend.item.EndBucketItem; -import ru.betterend.item.EternalCrystalItem; -import ru.betterend.item.material.EndArmorMaterial; -import ru.betterend.item.material.EndToolMaterial; -import ru.betterend.item.tool.EndHammerItem; -import ru.betterend.item.tool.EndPickaxe; -import ru.betterend.tab.CreativeTabs; - -import java.util.List; - -public class EndItems { - private static final ItemRegistry REGISTRY = new ItemRegistry(CreativeTabs.TAB_ITEMS, Configs.ITEM_CONFIG); - - // Materials // - public final static Item ENDER_DUST = registerEndItem("ender_dust"); - public final static Item ENDER_SHARD = registerEndItem("ender_shard"); - public final static Item AETERNIUM_INGOT = registerEndItem("aeternium_ingot", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_FORGED_PLATE = registerEndItem("aeternium_forged_plate", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item END_LILY_LEAF = registerEndItem("end_lily_leaf"); - public final static Item END_LILY_LEAF_DRIED = registerEndItem("end_lily_leaf_dried"); - public final static Item CRYSTAL_SHARDS = registerEndItem("crystal_shards"); - public final static Item RAW_AMBER = registerEndItem("raw_amber"); - public final static Item AMBER_GEM = registerEndItem("amber_gem"); - public final static Item GLOWING_BULB = registerEndItem("glowing_bulb"); - public final static Item CRYSTALLINE_SULPHUR = registerEndItem("crystalline_sulphur"); - public final static Item HYDRALUX_PETAL = registerEndItem("hydralux_petal"); - public final static Item GELATINE = registerEndItem("gelatine"); - public static final Item ETERNAL_CRYSTAL = registerEndItem("eternal_crystal", new EternalCrystalItem()); - public final static Item ENCHANTED_PETAL = registerEndItem("enchanted_petal", new EnchantedItem(HYDRALUX_PETAL)); - public final static Item LEATHER_STRIPE = registerEndItem("leather_stripe"); - public final static Item LEATHER_WRAPPED_STICK = registerEndItem("leather_wrapped_stick"); - public final static Item SILK_FIBER = registerEndItem("silk_fiber"); - public final static Item LUMECORN_ROD = registerEndItem("lumecorn_rod"); - public final static Item SILK_MOTH_MATRIX = registerEndItem("silk_moth_matrix"); - public final static Item ENCHANTED_MEMBRANE = registerEndItem( - "enchanted_membrane", - new EnchantedItem(Items.PHANTOM_MEMBRANE) - ); - - // Music Discs - public final static Item MUSIC_DISC_STRANGE_AND_ALIEN = registerEndDisc( - "music_disc_strange_and_alien", - 0, - EndSounds.RECORD_STRANGE_AND_ALIEN - ); - public final static Item MUSIC_DISC_GRASPING_AT_STARS = registerEndDisc( - "music_disc_grasping_at_stars", - 0, - EndSounds.RECORD_GRASPING_AT_STARS - ); - public final static Item MUSIC_DISC_ENDSEEKER = registerEndDisc( - "music_disc_endseeker", - 0, - EndSounds.RECORD_ENDSEEKER - ); - public final static Item MUSIC_DISC_EO_DRACONA = registerEndDisc( - "music_disc_eo_dracona", - 0, - EndSounds.RECORD_EO_DRACONA - ); - - // Armor // - public static final Item AETERNIUM_HELMET = registerEndItem("aeternium_helmet", new BaseArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.HEAD, makeEndItemSettings().fireResistant())); - public static final Item AETERNIUM_CHESTPLATE = registerEndItem("aeternium_chestplate", new BaseArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.CHEST, makeEndItemSettings().fireResistant())); - public static final Item AETERNIUM_LEGGINGS = registerEndItem("aeternium_leggings", new BaseArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.LEGS, makeEndItemSettings().fireResistant())); - public static final Item AETERNIUM_BOOTS = registerEndItem("aeternium_boots", new BaseArmorItem(EndArmorMaterial.AETERNIUM, EquipmentSlot.FEET, makeEndItemSettings().fireResistant())); - public static final Item CRYSTALITE_HELMET = registerEndItem("crystalite_helmet", new CrystaliteHelmet()); - public static final Item CRYSTALITE_CHESTPLATE = registerEndItem("crystalite_chestplate", new CrystaliteChestplate()); - public static final Item CRYSTALITE_LEGGINGS = registerEndItem("crystalite_leggings", new CrystaliteLeggings()); - public static final Item CRYSTALITE_BOOTS = registerEndItem("crystalite_boots", new CrystaliteBoots()); - public static final Item ARMORED_ELYTRA = registerEndItem("elytra_armored", new ArmoredElytra("elytra_armored", EndArmorMaterial.AETERNIUM, Items.PHANTOM_MEMBRANE, 900, 0.975D, true)); - public static final Item CRYSTALITE_ELYTRA = registerEndItem("elytra_crystalite", new CrystaliteElytra(650, 0.99D)); - - // Tools // - public static final TieredItem AETERNIUM_SHOVEL = registerEndTool("aeternium_shovel", new BaseShovelItem(EndToolMaterial.AETERNIUM, 1.5F, -3.0F, makeEndItemSettings().fireResistant())); - public static final TieredItem AETERNIUM_SWORD = registerEndTool("aeternium_sword", new BaseSwordItem(EndToolMaterial.AETERNIUM, 3, -2.4F, makeEndItemSettings().fireResistant())); - public static final TieredItem AETERNIUM_PICKAXE = registerEndTool("aeternium_pickaxe", new EndPickaxe(EndToolMaterial.AETERNIUM, 1, -2.8F, makeEndItemSettings().fireResistant())); - public static final TieredItem AETERNIUM_AXE = registerEndTool("aeternium_axe", new BaseAxeItem(EndToolMaterial.AETERNIUM, 5.0F, -3.0F, makeEndItemSettings().fireResistant())); - public static final TieredItem AETERNIUM_HOE = registerEndTool("aeternium_hoe", new BaseHoeItem(EndToolMaterial.AETERNIUM, -3, 0.0F, makeEndItemSettings().fireResistant())); - public static final TieredItem AETERNIUM_HAMMER = registerEndTool("aeternium_hammer", new EndHammerItem(EndToolMaterial.AETERNIUM, 6.0F, -3.0F, 0.3D, makeEndItemSettings().fireResistant())); - - // Toolparts // - public final static Item AETERNIUM_SHOVEL_HEAD = registerEndItem("aeternium_shovel_head", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_PICKAXE_HEAD = registerEndItem("aeternium_pickaxe_head", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_AXE_HEAD = registerEndItem("aeternium_axe_head", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_HOE_HEAD = registerEndItem("aeternium_hoe_head", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_HAMMER_HEAD = registerEndItem("aeternium_hammer_head", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_SWORD_BLADE = registerEndItem("aeternium_sword_blade", new ModelProviderItem(makeEndItemSettings().fireResistant())); - public final static Item AETERNIUM_SWORD_HANDLE = registerEndItem("aeternium_sword_handle", new ModelProviderItem(makeEndItemSettings().fireResistant())); - - // ITEM_HAMMERS // - public static final TieredItem IRON_HAMMER = registerEndTool("iron_hammer", new EndHammerItem(Tiers.IRON, 5.0F, -3.2F, 0.2D, makeEndItemSettings())); - public static final TieredItem GOLDEN_HAMMER = registerEndTool("golden_hammer", new EndHammerItem(Tiers.GOLD, 4.5F, -3.4F, 0.3D, makeEndItemSettings())); - public static final TieredItem DIAMOND_HAMMER = registerEndTool("diamond_hammer", new EndHammerItem(Tiers.DIAMOND, 5.5F, -3.1F, 0.2D, makeEndItemSettings())); - public static final TieredItem NETHERITE_HAMMER = registerEndTool("netherite_hammer", new EndHammerItem(Tiers.NETHERITE, 5.0F, -3.0F, 0.2D, makeEndItemSettings().fireResistant())); - - // Food // - public final static Item SHADOW_BERRY_RAW = registerEndFood("shadow_berry_raw", 4, 0.5F); - public final static Item SHADOW_BERRY_COOKED = registerEndFood("shadow_berry_cooked", 6, 0.7F); - public final static Item END_FISH_RAW = registerEndFood("end_fish_raw", Foods.SALMON); - public final static Item END_FISH_COOKED = registerEndFood("end_fish_cooked", Foods.COOKED_SALMON); - public final static Item BUCKET_END_FISH = registerEndItem("bucket_end_fish", new EndBucketItem(EndEntities.END_FISH)); - public final static Item BUCKET_CUBOZOA = registerEndItem("bucket_cubozoa", new EndBucketItem(EndEntities.CUBOZOA)); - public final static Item SWEET_BERRY_JELLY = registerEndFood("sweet_berry_jelly", 8, 0.7F); - public final static Item SHADOW_BERRY_JELLY = registerEndFood("shadow_berry_jelly", 6, 0.8F, new MobEffectInstance(MobEffects.NIGHT_VISION, 400)); - public final static Item BLOSSOM_BERRY_JELLY = registerEndFood("blossom_berry_jelly", 8, 0.7F); - public final static Item BLOSSOM_BERRY = registerEndFood("blossom_berry", Foods.APPLE); - public final static Item AMBER_ROOT_RAW = registerEndFood("amber_root_raw", 2, 0.8F); - public final static Item CHORUS_MUSHROOM_RAW = registerEndFood("chorus_mushroom_raw", 3, 0.5F); - public final static Item CHORUS_MUSHROOM_COOKED = registerEndFood("chorus_mushroom_cooked", Foods.MUSHROOM_STEW); - public final static Item BOLUX_MUSHROOM_COOKED = registerEndFood("bolux_mushroom_cooked", Foods.MUSHROOM_STEW); - public final static Item CAVE_PUMPKIN_PIE = registerEndFood("cave_pumpkin_pie", Foods.PUMPKIN_PIE); - - // Drinks // - public final static Item UMBRELLA_CLUSTER_JUICE = registerEndDrink("umbrella_cluster_juice", 5, 0.7F); - - public static List getModItems() { - return REGISTRY.getModItems(BetterEnd.MOD_ID); - } - - public static Item registerEndDisc(String name, int power, SoundEvent sound) { - return getItemRegistry().registerDisc(BetterEnd.makeID(name), power, sound); - } - - public static Item registerEndItem(String name) { - return getItemRegistry().register(BetterEnd.makeID(name)); - } - - public static Item registerEndItem(String name, Item item) { - if (item instanceof EndArmorItem) { - return getItemRegistry().register(BetterEnd.makeID(name), item, "armour"); - } - return getItemRegistry().register(BetterEnd.makeID(name), item); - } - - public static TieredItem registerEndTool(String name, TieredItem item) { - if (!Configs.ITEM_CONFIG.getBoolean("tools", name, true)) { - return item; - } - return (TieredItem)getItemRegistry().registerTool(BetterEnd.makeID(name), item); - } - - public static Item registerEndEgg(String name, EntityType type, int background, int dots) { - return getItemRegistry().registerEgg(BetterEnd.makeID(name), type, background, dots); - } - - public static Item registerEndFood(String name, int hunger, float saturation, MobEffectInstance... effects) { - return getItemRegistry().registerFood(BetterEnd.makeID(name), hunger, saturation, effects); - } - - public static Item registerEndFood(String name, FoodProperties foodComponent) { - return getItemRegistry().registerFood(BetterEnd.makeID(name), foodComponent); - } - - public static Item registerEndDrink(String name, int hunger, float saturation) { - return getItemRegistry().registerDrink(BetterEnd.makeID(name), hunger, saturation); - } - - public static FabricItemSettings makeEndItemSettings() { - return getItemRegistry().makeItemSettings(); - } - - @NotNull - public static ItemRegistry getItemRegistry() { - return REGISTRY; - } -} diff --git a/src/main/java/ru/betterend/registry/EndModelProviders.java b/src/main/java/ru/betterend/registry/EndModelProviders.java deleted file mode 100644 index bf43f23e..00000000 --- a/src/main/java/ru/betterend/registry/EndModelProviders.java +++ /dev/null @@ -1,17 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import ru.betterend.item.model.CrystaliteArmorProvider; -import shadow.fabric.api.client.rendering.v1.ArmorRenderingRegistry; - -@Environment(EnvType.CLIENT) -public class EndModelProviders { - - public final static CrystaliteArmorProvider CRYSTALITE_PROVIDER = new CrystaliteArmorProvider(); - - public final static void register() { - ArmorRenderingRegistry.registerModel(CRYSTALITE_PROVIDER, CRYSTALITE_PROVIDER.getRenderedItems()); - ArmorRenderingRegistry.registerTexture(CRYSTALITE_PROVIDER, CRYSTALITE_PROVIDER.getRenderedItems()); - } -} diff --git a/src/main/java/ru/betterend/registry/EndParticles.java b/src/main/java/ru/betterend/registry/EndParticles.java deleted file mode 100644 index eef59ab0..00000000 --- a/src/main/java/ru/betterend/registry/EndParticles.java +++ /dev/null @@ -1,66 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; -import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; -import net.minecraft.core.Registry; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.core.particles.SimpleParticleType; -import ru.betterend.BetterEnd; -import ru.betterend.particle.FireflyParticle; -import ru.betterend.particle.InfusionParticle; -import ru.betterend.particle.InfusionParticleType; -import ru.betterend.particle.ParticleBlackSpore; -import ru.betterend.particle.ParticleGeyser; -import ru.betterend.particle.ParticleGlowingSphere; -import ru.betterend.particle.ParticleJungleSpore; -import ru.betterend.particle.ParticleSnowflake; -import ru.betterend.particle.ParticleSulphur; -import ru.betterend.particle.ParticleTenaneaPetal; -import ru.betterend.particle.PaticlePortalSphere; -import ru.betterend.particle.SmaragdantParticle; - -public class EndParticles { - public static final SimpleParticleType GLOWING_SPHERE = register("glowing_sphere"); - public static final SimpleParticleType PORTAL_SPHERE = register("portal_sphere"); - public static final ParticleType INFUSION = register( - "infusion", - FabricParticleTypes.complex(InfusionParticleType.PARAMETERS_FACTORY) - ); - public static final SimpleParticleType SULPHUR_PARTICLE = register("sulphur_particle"); - public static final SimpleParticleType GEYSER_PARTICLE = registerFar("geyser_particle"); - public static final SimpleParticleType SNOWFLAKE = register("snowflake"); - public static final SimpleParticleType AMBER_SPHERE = register("amber_sphere"); - public static final SimpleParticleType BLACK_SPORE = register("black_spore"); - public static final SimpleParticleType TENANEA_PETAL = register("tenanea_petal"); - public static final SimpleParticleType JUNGLE_SPORE = register("jungle_spore"); - public static final SimpleParticleType FIREFLY = register("firefly"); - public static final SimpleParticleType SMARAGDANT = register("smaragdant_particle"); - - public static void register() { - ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); - ParticleFactoryRegistry.getInstance().register(PORTAL_SPHERE, PaticlePortalSphere.FactoryPortalSphere::new); - ParticleFactoryRegistry.getInstance().register(INFUSION, InfusionParticle.InfusionFactory::new); - ParticleFactoryRegistry.getInstance().register(SULPHUR_PARTICLE, ParticleSulphur.FactorySulphur::new); - ParticleFactoryRegistry.getInstance().register(GEYSER_PARTICLE, ParticleGeyser.FactoryGeyser::new); - ParticleFactoryRegistry.getInstance().register(SNOWFLAKE, ParticleSnowflake.FactorySnowflake::new); - ParticleFactoryRegistry.getInstance().register(AMBER_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); - ParticleFactoryRegistry.getInstance().register(BLACK_SPORE, ParticleBlackSpore.FactoryBlackSpore::new); - ParticleFactoryRegistry.getInstance().register(TENANEA_PETAL, ParticleTenaneaPetal.FactoryTenaneaPetal::new); - ParticleFactoryRegistry.getInstance().register(JUNGLE_SPORE, ParticleJungleSpore.FactoryJungleSpore::new); - ParticleFactoryRegistry.getInstance().register(FIREFLY, FireflyParticle.FireflyParticleFactory::new); - ParticleFactoryRegistry.getInstance().register(SMARAGDANT, SmaragdantParticle.SmaragdantParticleFactory::new); - } - - private static SimpleParticleType register(String name) { - return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple()); - } - - private static SimpleParticleType registerFar(String name) { - return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple(true)); - } - - private static ParticleType register(String name, ParticleType type) { - return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), type); - } -} diff --git a/src/main/java/ru/betterend/registry/EndPortals.java b/src/main/java/ru/betterend/registry/EndPortals.java deleted file mode 100644 index 2d3d905e..00000000 --- a/src/main/java/ru/betterend/registry/EndPortals.java +++ /dev/null @@ -1,161 +0,0 @@ -package ru.betterend.registry; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import ru.bclib.util.ColorUtil; -import ru.bclib.util.JsonFactory; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; - -import java.io.File; - -public class EndPortals { - - public final static ResourceLocation OVERWORLD_ID = Level.OVERWORLD.location(); - - private static PortalInfo[] portals; - - public static void loadPortals() { - File file = new File(FabricLoader.getInstance().getConfigDir().toString(), "betterend/portals.json"); - JsonObject json; - if (!file.exists()) { - file.getParentFile().mkdirs(); - json = makeDefault(file); - } - else { - json = JsonFactory.getJsonObject(file); - } - if (!json.has("portals") || !json.get("portals").isJsonArray()) { - json = makeDefault(file); - } - JsonArray array = json.get("portals").getAsJsonArray(); - if (array.size() == 0) { - json = makeDefault(file); - array = json.get("portals").getAsJsonArray(); - } - portals = new PortalInfo[array.size()]; - for (int i = 0; i < portals.length; i++) { - portals[i] = new PortalInfo(array.get(i).getAsJsonObject()); - } - } - - public static int getCount() { - return MHelper.max(portals.length - 1, 1); - } - - public static ServerLevel getWorld(MinecraftServer server, int portalId) { - if (portalId < 0 || portalId >= portals.length) { - return server.overworld(); - } - return portals[portalId].getWorld(server); - } - - public static ResourceLocation getWorldId(int portalId) { - if (portalId < 0 || portalId >= portals.length) { - return OVERWORLD_ID; - } - return portals[portalId].dimension; - } - - public static int getPortalIdByItem(ResourceLocation item) { - for (int i = 0; i < portals.length; i++) { - if (portals[i].item.equals(item)) { - return i; - } - } - return 0; - } - - public static int getPortalIdByWorld(ResourceLocation world) { - for (int i = 0; i < portals.length; i++) { - if (portals[i].dimension.equals(world)) { - return i; - } - } - return 0; - } - - public static int getColor(int state) { - return portals[state].color; - } - - public static boolean isAvailableItem(ResourceLocation item) { - for (PortalInfo portal : portals) { - if (portal.item.equals(item)) { - return true; - } - } - return false; - } - - private static JsonObject makeDefault(File file) { - JsonObject jsonObject = new JsonObject(); - JsonFactory.storeJson(file, jsonObject); - JsonArray array = new JsonArray(); - jsonObject.add("portals", array); - array.add(makeDefault().toJson()); - JsonFactory.storeJson(file, jsonObject); - return jsonObject; - } - - private static PortalInfo makeDefault() { - return new PortalInfo( - new ResourceLocation("minecraft:overworld"), - BetterEnd.makeID("eternal_crystal"), - 255, - 255, - 255 - ); - } - - private static class PortalInfo { - private final ResourceLocation dimension; - private final ResourceLocation item; - private final int color; - private ServerLevel world; - - PortalInfo(JsonObject obj) { - this( - new ResourceLocation(JsonFactory.getString(obj, "dimension", "minecraft:overworld")), - new ResourceLocation(JsonFactory.getString(obj, "item", "betterend:eternal_crystal")), - JsonFactory.getInt(obj, "colorRed", 255), - JsonFactory.getInt(obj, "colorGreen", 255), - JsonFactory.getInt(obj, "colorBlue", 255) - ); - } - - PortalInfo(ResourceLocation dimension, ResourceLocation item, int r, int g, int b) { - this.dimension = dimension; - this.item = item; - this.color = ColorUtil.color(r, g, b); - } - - ServerLevel getWorld(MinecraftServer server) { - if (world != null) { - return world; - } - for (ServerLevel world : server.getAllLevels()) { - if (world.dimension().location().equals(dimension)) { - this.world = world; - return world; - } - } - return server.overworld(); - } - - JsonObject toJson() { - JsonObject obj = new JsonObject(); - obj.addProperty("dimension", dimension.toString()); - obj.addProperty("item", item.toString()); - obj.addProperty("colorRed", (color >> 16) & 255); - obj.addProperty("colorGreen", (color >> 8) & 255); - obj.addProperty("colorBlue", color & 255); - return obj; - } - } -} diff --git a/src/main/java/ru/betterend/registry/EndScreens.java b/src/main/java/ru/betterend/registry/EndScreens.java deleted file mode 100644 index a0464bc1..00000000 --- a/src/main/java/ru/betterend/registry/EndScreens.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.betterend.registry; - -import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; -import ru.betterend.client.gui.EndStoneSmelterScreen; -import ru.betterend.client.gui.EndStoneSmelterScreenHandler; - -public class EndScreens { - public static void register() { - ScreenRegistry.register(EndStoneSmelterScreenHandler.HANDLER_TYPE, EndStoneSmelterScreen::new); - } -} diff --git a/src/main/java/ru/betterend/registry/EndSounds.java b/src/main/java/ru/betterend/registry/EndSounds.java deleted file mode 100644 index 354d11a0..00000000 --- a/src/main/java/ru/betterend/registry/EndSounds.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.registry; - -import net.minecraft.core.Registry; -import net.minecraft.sounds.SoundEvent; -import ru.betterend.BetterEnd; - -public class EndSounds { - // Music - public static final SoundEvent MUSIC_FOREST = register("music", "forest"); - public static final SoundEvent MUSIC_WATER = register("music", "water"); - public static final SoundEvent MUSIC_DARK = register("music", "dark"); - public static final SoundEvent MUSIC_OPENSPACE = register("music", "openspace"); - public static final SoundEvent MUSIC_CAVES = register("music", "caves"); - - // Ambient - public static final SoundEvent AMBIENT_FOGGY_MUSHROOMLAND = register("ambient", "foggy_mushroomland"); - public static final SoundEvent AMBIENT_CHORUS_FOREST = register("ambient", "chorus_forest"); - public static final SoundEvent AMBIENT_MEGALAKE = register("ambient", "megalake"); - public static final SoundEvent AMBIENT_DUST_WASTELANDS = register("ambient", "dust_wastelands"); - public static final SoundEvent AMBIENT_MEGALAKE_GROVE = register("ambient", "megalake_grove"); - public static final SoundEvent AMBIENT_BLOSSOMING_SPIRES = register("ambient", "blossoming_spires"); - public static final SoundEvent AMBIENT_SULPHUR_SPRINGS = register("ambient", "sulphur_springs"); - public static final SoundEvent AMBIENT_UMBRELLA_JUNGLE = register("ambient", "umbrella_jungle"); - public static final SoundEvent AMBIENT_GLOWING_GRASSLANDS = register("ambient", "glowing_grasslands"); - public static final SoundEvent AMBIENT_CAVES = register("ambient", "caves"); - public static final SoundEvent AMBIENT_AMBER_LAND = register("ambient", "amber_land"); - public static final SoundEvent UMBRA_VALLEY = register("ambient", "umbra_valley"); - - // Entity - public static final SoundEvent ENTITY_DRAGONFLY = register("entity", "dragonfly"); - public static final SoundEvent ENTITY_SHADOW_WALKER = register("entity", "shadow_walker"); - public static final SoundEvent ENTITY_SHADOW_WALKER_DAMAGE = register("entity", "shadow_walker_damage"); - public static final SoundEvent ENTITY_SHADOW_WALKER_DEATH = register("entity", "shadow_walker_death"); - - // Records - public static final SoundEvent RECORD_STRANGE_AND_ALIEN = register("record", "strange_and_alien"); - public static final SoundEvent RECORD_GRASPING_AT_STARS = register("record", "grasping_at_stars"); - public static final SoundEvent RECORD_ENDSEEKER = register("record", "endseeker"); - public static final SoundEvent RECORD_EO_DRACONA = register("record", "eo_dracona"); - - public static void register() { - } - - private static SoundEvent register(String type, String id) { - id = "betterend." + type + "." + id; - return Registry.register(Registry.SOUND_EVENT, id, new SoundEvent(BetterEnd.makeID(id))); - } -} diff --git a/src/main/java/ru/betterend/registry/EndStructures.java b/src/main/java/ru/betterend/registry/EndStructures.java deleted file mode 100644 index 4e9903d3..00000000 --- a/src/main/java/ru/betterend/registry/EndStructures.java +++ /dev/null @@ -1,95 +0,0 @@ -package ru.betterend.registry; - -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; -import ru.bclib.api.tag.TagAPI; -import ru.bclib.world.structures.BCLStructure; -import ru.betterend.BetterEnd; -import ru.betterend.world.structures.features.EternalPortalStructure; -import ru.betterend.world.structures.features.GiantIceStarStructure; -import ru.betterend.world.structures.features.GiantMossyGlowshroomStructure; -import ru.betterend.world.structures.features.MegaLakeSmallStructure; -import ru.betterend.world.structures.features.MegaLakeStructure; -import ru.betterend.world.structures.features.MountainStructure; -import ru.betterend.world.structures.features.PaintedMountainStructure; -import ru.betterend.world.structures.piece.CavePiece; -import ru.betterend.world.structures.piece.CrystalMountainPiece; -import ru.betterend.world.structures.piece.LakePiece; -import ru.betterend.world.structures.piece.NBTPiece; -import ru.betterend.world.structures.piece.PaintedMountainPiece; -import ru.betterend.world.structures.piece.VoxelPiece; - -public class EndStructures { - public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new); - public static final StructurePieceType MOUNTAIN_PIECE = register("mountain_piece", CrystalMountainPiece::new); - public static final StructurePieceType CAVE_PIECE = register("cave_piece", CavePiece::new); - public static final StructurePieceType LAKE_PIECE = register("lake_piece", LakePiece::new); - public static final StructurePieceType PAINTED_MOUNTAIN_PIECE = register("painted_mountain_piece", PaintedMountainPiece::new); - public static final StructurePieceType NBT_PIECE = register("nbt_piece", NBTPiece::new); - - public static final BCLStructure GIANT_MOSSY_GLOWSHROOM = new BCLStructure<>( - BetterEnd.makeID("giant_mossy_glowshroom"), - GiantMossyGlowshroomStructure::new, - Decoration.SURFACE_STRUCTURES, - 16, - 8 - ); - public static final BCLStructure MEGALAKE = new BCLStructure<>( - BetterEnd.makeID("megalake"), - MegaLakeStructure::new, - Decoration.RAW_GENERATION, - 4, - 1 - ); - public static final BCLStructure MEGALAKE_SMALL = new BCLStructure<>( - BetterEnd.makeID("megalake_small"), - MegaLakeSmallStructure::new, - Decoration.RAW_GENERATION, - 4, - 1 - ); - public static final BCLStructure MOUNTAIN = new BCLStructure<>( - BetterEnd.makeID("mountain"), - MountainStructure::new, - Decoration.RAW_GENERATION, - 3, - 2 - ); - public static final BCLStructure PAINTED_MOUNTAIN = new BCLStructure<>( - BetterEnd.makeID("painted_mountain"), - PaintedMountainStructure::new, - Decoration.RAW_GENERATION, - 3, - 2 - ); - public static final BCLStructure ETERNAL_PORTAL = new BCLStructure<>( - BetterEnd.makeID("eternal_portal"), - EternalPortalStructure::new, - Decoration.SURFACE_STRUCTURES, - 16, - 6 - ); - public static final BCLStructure GIANT_ICE_STAR = new BCLStructure<>( - BetterEnd.makeID("giant_ice_star"), - GiantIceStarStructure::new, - Decoration.SURFACE_STRUCTURES, - 16, - 8 - ); - - public static void register() {} - - private static StructurePieceType register(String id, StructurePieceType pieceType) { - return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType); - } - - public static void addBiomeStructures(ResourceLocation biomeID, Holder biome) { - if (!biomeID.getPath().contains("mountain") && !biomeID.getPath().contains("lake")) { - TagAPI.addBiomeTag(ETERNAL_PORTAL.biomeTag, biome.value()); - } - } -} diff --git a/src/main/java/ru/betterend/registry/EndTags.java b/src/main/java/ru/betterend/registry/EndTags.java deleted file mode 100644 index 57900c29..00000000 --- a/src/main/java/ru/betterend/registry/EndTags.java +++ /dev/null @@ -1,152 +0,0 @@ -package ru.betterend.registry; - -import com.google.common.collect.Lists; -import net.fabricmc.fabric.mixin.object.builder.AbstractBlockAccessor; -import net.fabricmc.fabric.mixin.object.builder.AbstractBlockSettingsAccessor; -import net.minecraft.core.Registry; -import net.minecraft.tags.TagKey; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.BonemealAPI; -import ru.bclib.api.ComposterAPI; -import ru.bclib.api.tag.*; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.blocks.SimpleLeavesBlock; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.basis.EndTerrainBlock; -import ru.betterend.blocks.basis.PedestalBlock; -import ru.betterend.item.tool.EndHammerItem; -import ru.betterend.world.biome.EndBiome; - -import java.util.List; - -public class EndTags { - // Table with common (c) tags: - // https://fabricmc.net/wiki/tutorial:tags - - // Block Tags - public static final TagKey PEDESTALS = TagAPI.makeBlockTag(BetterEnd.MOD_ID, "pedestal"); - - // Item Tags - public static final TagKey ALLOYING_IRON = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_iron"); - public static final TagKey ALLOYING_GOLD = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_gold"); - public static final TagKey ALLOYING_COPPER = TagAPI.makeItemTag(BetterEnd.MOD_ID, "alloying_copper"); - - public static void register() { - addEndGround(EndBlocks.THALLASIUM.ore); - addEndGround(EndBlocks.ENDSTONE_DUST); - addEndGround(EndBlocks.AMBER_ORE); - - EndBlocks.getModBlocks().forEach(block -> { - Properties properties = ((AbstractBlockAccessor) block).getSettings(); - Material material = ((AbstractBlockSettingsAccessor) properties).getMaterial(); - final Item item = block.asItem(); - - if (material.equals(Material.STONE) || material.equals(Material.METAL) || material.equals(Material.HEAVY_METAL)) { - TagAPI.addBlockTag(NamedMineableTags.PICKAXE, block); - } - else if (material.equals(Material.WOOD)) { - TagAPI.addBlockTag(NamedMineableTags.AXE, block); - } - else if (material.equals(Material.LEAVES) || material.equals(Material.PLANT) || material.equals(Material.WATER_PLANT) || material.equals(Material.SPONGE)) { - TagAPI.addBlockTag(NamedMineableTags.HOE, block); - } - else if (material.equals(Material.SAND)) { - TagAPI.addBlockTag(NamedMineableTags.SHOVEL, block); - } - - if (block instanceof EndTerrainBlock) { - addEndGround(block); - TagAPI.addBlockTag(NamedBlockTags.NYLIUM, block); - BonemealAPI.addSpreadableBlock(block, Blocks.END_STONE); - } - else if (block instanceof LeavesBlock || block instanceof SimpleLeavesBlock) { - TagAPI.addBlockTag(NamedBlockTags.LEAVES, block); - ComposterAPI.allowCompost(0.3f, item); - } - else if (block instanceof BaseVineBlock) { - TagAPI.addBlockTag(NamedBlockTags.CLIMBABLE, block); - } - else if (block instanceof PedestalBlock) { - TagAPI.addBlockTag(PEDESTALS, block); - } - - Material mat = block.defaultBlockState().getMaterial(); - if (mat.equals(Material.PLANT) || mat.equals(Material.REPLACEABLE_PLANT)) { - ComposterAPI.allowCompost(0.1F, item); - } - }); - addEndGround(EndBlocks.CAVE_MOSS); - TagAPI.addBlockTag(NamedBlockTags.NYLIUM, EndBlocks.CAVE_MOSS); - BonemealAPI.addSpreadableBlock(EndBlocks.CAVE_MOSS, Blocks.END_STONE); - BonemealAPI.addSpreadableBlock(EndBlocks.MOSSY_OBSIDIAN, Blocks.OBSIDIAN); - BonemealAPI.addSpreadableBlock(EndBlocks.MOSSY_DRAGON_BONE, EndBlocks.DRAGON_BONE_BLOCK); - - List ITEM_HAMMERS = Lists.newArrayList(); - EndItems.getModItems().forEach(item -> { - if (item.isEdible()) { - FoodProperties food = item.getFoodProperties(); - if (food != null) { - float compost = food.getNutrition() * food.getSaturationModifier() * 0.18F; - ComposterAPI.allowCompost(compost, item); - } - } - if (item instanceof EndHammerItem) { - ITEM_HAMMERS.add(item); - } - }); - - TagAPI.addBlockTag( - CommonBlockTags.END_STONES, - EndBlocks.ENDER_ORE, - EndBlocks.BRIMSTONE - ); - TagAPI.addBlockTag(CommonBlockTags.END_STONES, EndBlocks.BRIMSTONE); - TagAPI.addBlockTag(NamedBlockTags.ANVIL, EndBlocks.AETERNIUM_ANVIL); - TagAPI.addBlockTag(NamedBlockTags.BEACON_BASE_BLOCKS, EndBlocks.AETERNIUM_BLOCK); - TagAPI.addItemTag(NamedItemTags.BEACON_PAYMENT_ITEMS, EndItems.AETERNIUM_INGOT); - TagAPI.addBlockTag( - CommonBlockTags.DRAGON_IMMUNE, - EndBlocks.ENDER_ORE, - EndBlocks.ETERNAL_PEDESTAL, - EndBlocks.FLAVOLITE_RUNED_ETERNAL, - EndBlocks.FLAVOLITE_RUNED - ); - TagAPI.addItemTag(CommonItemTags.IRON_INGOTS, EndBlocks.THALLASIUM.ingot); - - TagAPI.addItemTag(ALLOYING_IRON, Items.IRON_ORE, Items.DEEPSLATE_IRON_ORE, Items.RAW_IRON); - TagAPI.addItemTag(ALLOYING_GOLD, Items.GOLD_ORE, Items.DEEPSLATE_GOLD_ORE, Items.RAW_GOLD); - TagAPI.addItemTag(ALLOYING_COPPER, Items.COPPER_ORE, Items.DEEPSLATE_COPPER_ORE, Items.RAW_COPPER); - } - - public static void addEndGround(Block bl){ - TagAPI.addBlockTag(CommonBlockTags.END_STONES, bl); - } - - public static void addBiomeSurfaceToEndGroup(EndBiome b){ - addEndGround(b.getTopMaterial().getBlock()); - addEndGround(b.getAltTopMaterial().getBlock()); - addEndGround(b.getUnderMaterial().getBlock()); - } - - // TODO make getter for biome top blocks - public static void addTerrainTags(Registry biomeRegistry) { - /*biomeRegistry.forEach((biome) -> { - if (biome.getBiomeCategory() == BiomeCategory.THEEND) { - SurfaceBuilderConfiguration config = biome.getGenerationSettings().getSurfaceBuilderConfig(); - Block under = config.getUnderMaterial().getBlock(); - Block surface = config.getTopMaterial().getBlock(); - TagAPI.addTag(CommonBlockTags.GEN_END_STONES, under, surface); - TagAPI.addTag(CommonBlockTags.END_STONES, surface); - } - }); - TagAPI.BLOCK_END_STONES.getValues().forEach(TagAPI::addEndGround);*/ - } -} diff --git a/src/main/java/ru/betterend/rituals/EternalRitual.java b/src/main/java/ru/betterend/rituals/EternalRitual.java deleted file mode 100644 index 2aced2fb..00000000 --- a/src/main/java/ru/betterend/rituals/EternalRitual.java +++ /dev/null @@ -1,779 +0,0 @@ -package ru.betterend.rituals; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.core.particles.BlockParticleOption; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.LegacyRandomSource; -import net.minecraft.world.level.material.Material; -import org.jetbrains.annotations.Nullable; -import ru.bclib.blocks.BlockProperties; -import ru.betterend.BetterEnd; -import ru.betterend.blocks.EndPortalBlock; -import ru.betterend.blocks.RunedFlavolite; -import ru.betterend.blocks.entities.EternalPedestalEntity; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndPortals; - -import java.awt.Point; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; -import java.util.function.Predicate; - -public class EternalRitual { - private final static Set STRUCTURE_MAP = Sets.newHashSet( - new Point(-4, -5), - new Point(-4, 5), - new Point(-6, 0), - new Point(4, -5), - new Point(4, 5), - new Point(6, 0) - ); - private final static Set FRAME_MAP = Sets.newHashSet( - new Point(0, 0), - new Point(0, 6), - new Point(1, 0), - new Point(1, 6), - new Point(2, 1), - new Point(2, 5), - new Point(3, 2), - new Point(3, 3), - new Point(3, 4) - ); - private final static Set PORTAL_MAP = Sets.newHashSet( - new Point(0, 0), - new Point(0, 1), - new Point(0, 2), - new Point(0, 3), - new Point(0, 4), - new Point(1, 0), - new Point(1, 1), - new Point(1, 2), - new Point(1, 3), - new Point(1, 4), - new Point(2, 1), - new Point(2, 2), - new Point(2, 3) - ); - private final static Set BASE_MAP = Sets.newHashSet( - new Point(3, 0), - new Point(2, 0), - new Point(2, 1), - new Point(1, 1), - new Point(1, 2), - new Point(0, 1), - new Point(0, 2) - ); - - private final static Block BASE = EndBlocks.FLAVOLITE.tiles; - private final static Block PEDESTAL = EndBlocks.ETERNAL_PEDESTAL; - private final static Block FRAME = EndBlocks.FLAVOLITE_RUNED_ETERNAL; - private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK; - private final static BooleanProperty ACTIVE = BlockProperties.ACTIVE; - - public final static int SEARCH_RADIUS = calculateSearchSteps(48); - - private Level world; - private Direction.Axis axis; - private ResourceLocation targetWorldId; - private BlockPos center; - private BlockPos exit; - private boolean active = false; - - public EternalRitual(Level world) { - this.world = world; - } - - public EternalRitual(Level world, BlockPos initial) { - this(world); - this.configure(initial); - } - - public void setWorld(Level world) { - this.world = world; - } - - @Nullable - public ResourceLocation getTargetWorldId() { - return targetWorldId; - } - - private boolean isInvalid() { - return world == null || world.isClientSide() || center == null || axis == null; - } - - public void checkStructure() { - if (isInvalid()) return; - Direction moveX, moveY; - if (Direction.Axis.X == axis) { - moveX = Direction.EAST; - moveY = Direction.NORTH; - } - else { - moveX = Direction.SOUTH; - moveY = Direction.EAST; - } - boolean valid = checkFrame(world, center.below()); - Item item = null; - for (Point pos : STRUCTURE_MAP) { - BlockPos.MutableBlockPos checkPos = center.mutable(); - checkPos.move(moveX, pos.x).move(moveY, pos.y); - valid &= isActive(checkPos); - if (valid) { - EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(checkPos); - if (pedestal != null) { - Item pItem = pedestal.getItem(0).getItem(); - if (item == null) { - item = pItem; - } - else if (!item.equals(pItem)) { - valid = false; - } - } - } - } - if (valid && item != null) { - activatePortal(item); - } - } - - private boolean checkFrame(Level world, BlockPos framePos) { - Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; - boolean valid = true; - for (Point point : FRAME_MAP) { - BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - BlockState state = world.getBlockState(pos); - valid &= state.getBlock() instanceof RunedFlavolite; - pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - state = world.getBlockState(pos); - valid &= state.getBlock() instanceof RunedFlavolite; - } - return valid; - } - - public boolean isActive() { - return active; - } - - private void activatePortal(Item keyItem) { - if (active) return; - ResourceLocation itemId = Registry.ITEM.getKey(keyItem); - int portalId = EndPortals.getPortalIdByItem(itemId); - Level targetWorld = getTargetWorld(portalId); - ResourceLocation worldId = targetWorld.dimension().location(); - try { - if (exit == null) { - initPortal(worldId, portalId); - } - else { - if (!worldId.equals(targetWorldId)) { - initPortal(worldId, portalId); - } - else if (!checkFrame(targetWorld, exit.below())) { - Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; - generatePortal(targetWorld, exit, portalAxis, portalId); - } - activatePortal(targetWorld, exit, portalId); - } - activatePortal(world, center, portalId); - doEffects((ServerLevel) world, center); - active = true; - } - catch (Exception ex) { - BetterEnd.LOGGER.error("Create End portals error.", ex); - removePortal(targetWorld, exit); - removePortal(world, center); - active = false; - } - } - - private void initPortal(ResourceLocation worldId, int portalId) { - targetWorldId = worldId; - exit = findPortalPos(portalId); - } - - private void doEffects(ServerLevel serverWorld, BlockPos center) { - Direction moveX, moveY; - if (Direction.Axis.X == axis) { - moveX = Direction.EAST; - moveY = Direction.NORTH; - } - else { - moveX = Direction.SOUTH; - moveY = Direction.EAST; - } - for (Point pos : STRUCTURE_MAP) { - BlockPos.MutableBlockPos p = center.mutable(); - p.move(moveX, pos.x).move(moveY, pos.y); - serverWorld.sendParticles( - ParticleTypes.PORTAL, - p.getX() + 0.5, - p.getY() + 1.5, - p.getZ() + 0.5, - 20, - 0, - 0, - 0, - 1 - ); - serverWorld.sendParticles( - ParticleTypes.REVERSE_PORTAL, - p.getX() + 0.5, - p.getY() + 1.5, - p.getZ() + 0.5, - 20, - 0, - 0, - 0, - 0.3 - ); - } - serverWorld.playSound(null, center, SoundEvents.END_PORTAL_SPAWN, SoundSource.NEUTRAL, 16, 1); - } - - private void activatePortal(Level world, BlockPos center, int portalId) { - BlockPos framePos = center.below(); - Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; - BlockState frame = FRAME.defaultBlockState().setValue(ACTIVE, true); - FRAME_MAP.forEach(point -> { - BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - BlockState state = world.getBlockState(pos); - if (state.hasProperty(ACTIVE) && !state.getValue(ACTIVE)) { - world.setBlockAndUpdate(pos, frame); - } - pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - state = world.getBlockState(pos); - if (state.hasProperty(ACTIVE) && !state.getValue(ACTIVE)) { - world.setBlockAndUpdate(pos, frame); - } - }); - Direction.Axis portalAxis = Direction.Axis.X == axis ? Direction.Axis.Z : Direction.Axis.X; - BlockState portal = PORTAL.defaultBlockState() - .setValue(EndPortalBlock.AXIS, portalAxis) - .setValue(EndPortalBlock.PORTAL, portalId); - ParticleOptions effect = new BlockParticleOption(ParticleTypes.BLOCK, portal); - ServerLevel serverWorld = (ServerLevel) world; - - PORTAL_MAP.forEach(point -> { - BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - if (!world.getBlockState(pos).is(PORTAL)) { - world.setBlockAndUpdate(pos, portal); - serverWorld.sendParticles( - effect, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - 10, - 0.5, - 0.5, - 0.5, - 0.1 - ); - serverWorld.sendParticles( - ParticleTypes.REVERSE_PORTAL, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - 10, - 0.5, - 0.5, - 0.5, - 0.3 - ); - } - pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - if (!world.getBlockState(pos).is(PORTAL)) { - world.setBlockAndUpdate(pos, portal); - serverWorld.sendParticles( - effect, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - 10, - 0.5, - 0.5, - 0.5, - 0.1 - ); - serverWorld.sendParticles( - ParticleTypes.REVERSE_PORTAL, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - 10, - 0.5, - 0.5, - 0.5, - 0.3 - ); - } - }); - } - - public void disablePortal(int state) { - if (!active || isInvalid()) return; - removePortal(getTargetWorld(state), exit); - removePortal(world, center); - } - - private void removePortal(Level world, BlockPos center) { - BlockPos framePos = center.below(); - Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; - FRAME_MAP.forEach(point -> { - BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - BlockState state = world.getBlockState(pos); - if (state.is(FRAME) && state.getValue(ACTIVE)) { - world.setBlockAndUpdate(pos, state.setValue(ACTIVE, false)); - } - pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - state = world.getBlockState(pos); - if (state.is(FRAME) && state.getValue(ACTIVE)) { - world.setBlockAndUpdate(pos, state.setValue(ACTIVE, false)); - } - }); - PORTAL_MAP.forEach(point -> { - BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - if (world.getBlockState(pos).is(PORTAL)) { - world.removeBlock(pos, false); - } - pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - if (world.getBlockState(pos).is(PORTAL)) { - world.removeBlock(pos, false); - } - }); - this.active = false; - } - - @Nullable - private BlockPos findFrame(Level world, BlockPos.MutableBlockPos startPos) { - List foundPos = findAllBlockPos( - world, - startPos, - (SEARCH_RADIUS >> 4) + 1, - FRAME, - blockState -> blockState.is(FRAME) && !blockState.getValue(ACTIVE) - ); - for (BlockPos.MutableBlockPos testPos : foundPos) { - if (checkFrame(world, testPos)) { - return testPos; - } - } - return null; - } - - private BlockPos findPortalPos(int portalId) { - MinecraftServer server = world.getServer(); - ServerLevel targetWorld = (ServerLevel) getTargetWorld(portalId); - Registry registry = Objects.requireNonNull(server) - .registryAccess() - .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - double multiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale(); - BlockPos.MutableBlockPos basePos = center.mutable() - .set(center.getX() / multiplier, - center.getY(), - center.getZ() / multiplier - ); - BlockPos framePos = findFrame(targetWorld, basePos.mutable()); - if (framePos != null) { - return framePos.above(); - } - Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X; - int worldCeil = targetWorld.getHeight() - 1; - if (checkIsAreaValid(targetWorld, basePos, portalAxis)) { - generatePortal(targetWorld, basePos, portalAxis, portalId); - return basePos.immutable(); - } - else { - Direction direction = Direction.EAST; - BlockPos.MutableBlockPos checkPos = basePos.mutable(); - int radius = (int) ((SEARCH_RADIUS / multiplier) + 1); - for (int step = 1; step < radius; step++) { - for (int i = 0; i < (step >> 1); i++) { - ChunkAccess chunk = targetWorld.getChunk(checkPos); - if (chunk != null) { - int surfaceY = chunk.getHeight( - Heightmap.Types.WORLD_SURFACE, - checkPos.getX() & 15, - checkPos.getZ() & 15 - ); - int motionY = chunk.getHeight( - Heightmap.Types.MOTION_BLOCKING, - checkPos.getX() & 15, - checkPos.getZ() & 15 - ); - int ceil = Math.min(Math.max(surfaceY, motionY) + 1, worldCeil); - if (ceil < 5) continue; - checkPos.setY(ceil); - while (checkPos.getY() >= 5) { - if (checkIsAreaValid(targetWorld, checkPos, portalAxis)) { - generatePortal(targetWorld, checkPos, portalAxis, portalId); - return checkPos.immutable(); - } - checkPos.move(Direction.DOWN); - } - } - checkPos.move(direction); - } - direction = direction.getClockWise(); - } - } - if (targetWorld.dimension() == Level.END) { - net.minecraft.data.worldgen.features.EndFeatures.END_ISLAND.value().place( - targetWorld, - targetWorld.getChunkSource().getGenerator(), - new LegacyRandomSource(basePos.asLong()), - basePos.below() - ); - } - else if (targetWorld.dimension() == Level.OVERWORLD) { - basePos.setY(targetWorld.getChunk(basePos).getHeight(Heightmap.Types.WORLD_SURFACE, basePos.getX(), basePos.getZ()) + 1); - } - EndFeatures.BIOME_ISLAND - .getPlacedFeature() - .value() - .place(targetWorld, - targetWorld.getChunkSource().getGenerator(), - new LegacyRandomSource(basePos.asLong()), - basePos.below() - ); - generatePortal(targetWorld, basePos, portalAxis, portalId); - return basePos.immutable(); - } - - private Level getTargetWorld(int state) { - if (world.dimension() == Level.END) { - return EndPortals.getWorld(world.getServer(), state); - } - return Objects.requireNonNull(world.getServer()).getLevel(Level.END); - } - - private boolean checkIsAreaValid(Level world, BlockPos pos, Direction.Axis axis) { - if (pos.getY() >= world.getHeight() - 1) return false; - if (!isBaseValid(world, pos, axis)) return false; - return EternalRitual.checkArea(world, pos, axis); - } - - private boolean isBaseValid(Level world, BlockPos pos, Direction.Axis axis) { - boolean solid = true; - if (axis.equals(Direction.Axis.X)) { - pos = pos.below().offset(0, 0, -3); - for (int i = 0; i < 7; i++) { - BlockPos checkPos = pos.offset(0, 0, i); - BlockState state = world.getBlockState(checkPos); - solid &= validBlock(world, checkPos, state); - } - } - else { - pos = pos.below().offset(-3, 0, 0); - for (int i = 0; i < 7; i++) { - BlockPos checkPos = pos.offset(i, 0, 0); - BlockState state = world.getBlockState(checkPos); - solid &= validBlock(world, checkPos, state); - } - } - return solid; - } - - private boolean validBlock(Level world, BlockPos pos, BlockState state) { - return state.isRedstoneConductor(world, pos) && state.isCollisionShapeFullBlock(world, pos); - } - - public void configure(BlockPos initial) { - BlockPos checkPos = initial.east(12); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.X; - this.center = initial.east(6); - return; - } - checkPos = initial.west(12); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.X; - this.center = initial.west(6); - return; - } - checkPos = initial.south(12); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.Z; - this.center = initial.south(6); - return; - } - checkPos = initial.north(12); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.Z; - this.center = initial.north(6); - return; - } - checkPos = initial.north(10); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.X; - checkPos = checkPos.east(8); - if (this.hasPedestal(checkPos)) { - this.center = initial.north(5).east(4); - } - else { - this.center = initial.north(5).west(4); - } - return; - } - checkPos = initial.south(10); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.X; - checkPos = checkPos.east(8); - if (this.hasPedestal(checkPos)) { - this.center = initial.south(5).east(4); - } - else { - this.center = initial.south(5).west(4); - } - return; - } - checkPos = initial.east(10); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.Z; - checkPos = checkPos.south(8); - if (this.hasPedestal(checkPos)) { - this.center = initial.east(5).south(4); - } - else { - this.center = initial.east(5).north(4); - } - return; - } - checkPos = initial.west(10); - if (this.hasPedestal(checkPos)) { - this.axis = Direction.Axis.Z; - checkPos = checkPos.south(8); - if (this.hasPedestal(checkPos)) { - this.center = initial.west(5).south(4); - } - else { - this.center = initial.west(5).north(4); - } - } - } - - private boolean hasPedestal(BlockPos pos) { - return world.getBlockState(pos).is(PEDESTAL); - } - - private boolean isActive(BlockPos pos) { - BlockState state = world.getBlockState(pos); - if (state.is(PEDESTAL)) { - EternalPedestalEntity pedestal = (EternalPedestalEntity) world.getBlockEntity(pos); - if (pedestal != null) { - if (!pedestal.hasRitual()) { - pedestal.linkRitual(this); - } - else { - EternalRitual ritual = pedestal.getRitual(); - if (!ritual.equals(this)) { - pedestal.linkRitual(this); - } - } - } - return state.getValue(ACTIVE); - } - return false; - } - - public CompoundTag toTag(CompoundTag tag) { - tag.put("center", NbtUtils.writeBlockPos(center)); - tag.putString("axis", axis.getName()); - tag.putBoolean("active", active); - if (targetWorldId != null) { - tag.putString("key_item", targetWorldId.toString()); - } - if (exit != null) { - tag.put("exit", NbtUtils.writeBlockPos(exit)); - } - return tag; - } - - public void fromTag(CompoundTag tag) { - axis = Direction.Axis.byName(tag.getString("axis")); - center = NbtUtils.readBlockPos(tag.getCompound("center")); - active = tag.getBoolean("active"); - if (tag.contains("exit")) { - exit = NbtUtils.readBlockPos(tag.getCompound("exit")); - } - if (tag.contains("key_item")) { - targetWorldId = new ResourceLocation(tag.getString("key_item")); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - EternalRitual ritual = (EternalRitual) o; - return world.equals(ritual.world) && Objects.equals(center, ritual.center) && Objects.equals(exit, ritual.exit); - } - - public static void generatePortal(Level world, BlockPos center, Direction.Axis axis, int portalId) { - BlockPos framePos = center.below(); - Direction moveDir = Direction.Axis.X == axis ? Direction.EAST : Direction.NORTH; - BlockState frame = FRAME.defaultBlockState().setValue(ACTIVE, true); - FRAME_MAP.forEach(point -> { - BlockPos pos = framePos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - world.setBlockAndUpdate(pos, frame); - pos = framePos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - world.setBlockAndUpdate(pos, frame); - }); - BlockState portal = PORTAL.defaultBlockState() - .setValue(EndPortalBlock.AXIS, axis) - .setValue(EndPortalBlock.PORTAL, portalId); - PORTAL_MAP.forEach(point -> { - BlockPos pos = center.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - world.setBlockAndUpdate(pos, portal); - pos = center.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - world.setBlockAndUpdate(pos, portal); - }); - generateBase(world, framePos, moveDir); - } - - private static void generateBase(Level world, BlockPos center, Direction moveX) { - BlockState base = BASE.defaultBlockState(); - Direction moveY = moveX.getClockWise(); - BASE_MAP.forEach(point -> { - BlockPos pos = center.mutable().move(moveX, point.x).move(moveY, point.y); - world.setBlockAndUpdate(pos, base); - pos = center.mutable().move(moveX, -point.x).move(moveY, point.y); - world.setBlockAndUpdate(pos, base); - pos = center.mutable().move(moveX, point.x).move(moveY, -point.y); - world.setBlockAndUpdate(pos, base); - pos = center.mutable().move(moveX, -point.x).move(moveY, -point.y); - world.setBlockAndUpdate(pos, base); - }); - } - - public static boolean checkArea(Level world, BlockPos center, Direction.Axis axis) { - Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST; - for (BlockPos checkPos : BlockPos.betweenClosed( - center.relative(moveDir.getClockWise()), - center.relative(moveDir.getCounterClockWise()) - )) { - for (Point point : PORTAL_MAP) { - BlockPos pos = checkPos.mutable().move(moveDir, point.x).move(Direction.UP, point.y); - BlockState state = world.getBlockState(pos); - if (isStateInvalid(state)) return false; - pos = checkPos.mutable().move(moveDir, -point.x).move(Direction.UP, point.y); - state = world.getBlockState(pos); - if (isStateInvalid(state)) return false; - } - } - return true; - } - - private static boolean isStateInvalid(BlockState state) { - if (!state.getFluidState().isEmpty()) return true; - Material material = state.getMaterial(); - return !material.isReplaceable() && !material.equals(Material.PLANT); - } - - /** - * @param world World for search - * @param checkPos Start search position - * @param radius Search radius - * @param searchBlock Target block - * @param condition Predicate for test block states in the chunk section - * @return Position of the first found block or null. - */ - @Nullable - public static BlockPos.MutableBlockPos findBlockPos(Level world, BlockPos.MutableBlockPos checkPos, int radius, Block searchBlock, Predicate condition) { - Direction moveDirection = Direction.EAST; - for (int step = 1; step < radius; step++) { - for (int i = 0; i < (step >> 1); i++) { - ChunkAccess chunk = world.getChunk(checkPos); - if (!(chunk instanceof LevelChunk) || ((LevelChunk) chunk).isEmpty()) continue; - for (LevelChunkSection section : chunk.getSections()) { - if (section == null || !section.getStates().maybeHas(condition)) continue; - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - BlockState checkState = section.getBlockState(x, y, z); - if (checkState.is(searchBlock)) { - int worldX = (chunk.getPos().x << 4) + x; - int worldY = section.bottomBlockY() + y; - int worldZ = (chunk.getPos().z << 4) + z; - checkPos.set(worldX, worldY, worldZ); - return checkPos; - } - } - } - } - } - checkPos.move(moveDirection, 16); - } - moveDirection = moveDirection.getClockWise(); - } - return null; - } - - /** - * @param world World for search - * @param checkPos Start search position - * @param radius Search radius - * @param searchBlock Target block - * @param condition Predicate for test block states in the chunk section - * @return List of positions of the all found blocks or empty list. - */ - public static List findAllBlockPos(Level world, BlockPos.MutableBlockPos checkPos, int radius, Block searchBlock, Predicate condition) { - List posFound = Lists.newArrayList(); - Direction moveDirection = Direction.EAST; - for (int step = 1; step < radius; step++) { - for (int i = 0; i < (step >> 1); i++) { - ChunkAccess chunk = world.getChunk(checkPos); - if (!(chunk instanceof LevelChunk) || ((LevelChunk) chunk).isEmpty()) continue; - for (LevelChunkSection section : chunk.getSections()) { - if (section == null || !section.getStates().maybeHas(condition)) continue; - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - BlockState checkState = section.getBlockState(x, y, z); - if (checkState.is(searchBlock)) { - int worldX = (chunk.getPos().x << 4) + x; - int worldY = section.bottomBlockY() + y; - int worldZ = (chunk.getPos().z << 4) + z; - checkPos.set(worldX, worldY, worldZ); - posFound.add(checkPos.mutable()); - } - } - } - } - } - checkPos.move(moveDirection, 16); - } - moveDirection = moveDirection.getClockWise(); - } - return posFound; - } - - public static int calculateSearchSteps(int radius) { - return radius * 4 - 1; - } -} diff --git a/src/main/java/ru/betterend/rituals/InfusionRitual.java b/src/main/java/ru/betterend/rituals/InfusionRitual.java deleted file mode 100644 index f90c1694..00000000 --- a/src/main/java/ru/betterend/rituals/InfusionRitual.java +++ /dev/null @@ -1,260 +0,0 @@ -package ru.betterend.rituals; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import ru.betterend.blocks.entities.InfusionPedestalEntity; -import ru.betterend.blocks.entities.PedestalBlockEntity; -import ru.betterend.particle.InfusionParticleType; -import ru.betterend.recipe.builders.InfusionRecipe; - -import java.awt.Point; -import java.util.Arrays; -import java.util.Objects; - -public class InfusionRitual implements Container { - private static final Point[] PEDESTALS_MAP = new Point[] { - new Point(0, 3), - new Point(2, 2), - new Point(3, 0), - new Point(2, -2), - new Point(0, -3), - new Point(-2, -2), - new Point(-3, 0), - new Point(-2, 2) - }; - - private Level world; - private BlockPos worldPos; - private InfusionRecipe activeRecipe; - private boolean isDirty = false; - private boolean hasRecipe = false; - private int progress = 0; - private int time = 0; - - private final PedestalBlockEntity[] catalysts = new PedestalBlockEntity[8]; - private final InfusionPedestalEntity input; - - public InfusionRitual(InfusionPedestalEntity pedestal, Level world, BlockPos pos) { - this.input = pedestal; - this.world = world; - this.worldPos = pos; - configure(); - } - - public void configure() { - if (world == null || worldPos == null) return; - for (int i = 0; i < catalysts.length; i++) { - Point point = PEDESTALS_MAP[i]; - MutableBlockPos checkPos = worldPos.mutable().move(Direction.EAST, point.x).move(Direction.NORTH, point.y); - BlockEntity catalystEntity = world.getBlockEntity(checkPos); - if (catalystEntity instanceof PedestalBlockEntity) { - catalysts[i] = (PedestalBlockEntity) catalystEntity; - } - else { - catalysts[i] = null; - } - } - } - - public boolean checkRecipe() { - if (!isValid()) return false; - InfusionRecipe recipe = world.getRecipeManager().getRecipeFor(InfusionRecipe.TYPE, this, world).orElse(null); - if (hasRecipe()) { - if (recipe == null) { - reset(); - return false; - } - else if (activeRecipe == null || recipe.getInfusionTime() != time) { - updateRecipe(recipe); - } - return true; - } - if (recipe != null) { - updateRecipe(recipe); - return true; - } - return false; - } - - private void updateRecipe(InfusionRecipe recipe) { - activeRecipe = recipe; - hasRecipe = true; - resetTimer(); - setChanged(); - } - - private void resetTimer() { - time = activeRecipe != null ? activeRecipe.getInfusionTime() : 0; - progress = 0; - } - - public void reset() { - activeRecipe = null; - hasRecipe = false; - resetTimer(); - setChanged(); - } - - public void tick() { - if (isDirty) { - configure(); - isDirty = false; - } - if (!checkRecipe()) return; - progress++; - if (progress == time) { - clearContent(); - input.setItem(0, activeRecipe.assemble(this)); - reset(); - } - else if (world instanceof ServerLevel) { - ServerLevel serverLevel = (ServerLevel) world; - BlockPos target = worldPos.above(); - double tx = target.getX() + 0.5; - double ty = target.getY() + 0.5; - double tz = target.getZ() + 0.5; - for (PedestalBlockEntity catalyst : catalysts) { - ItemStack stack = catalyst.getItem(0); - if (!stack.isEmpty()) { - BlockPos start = catalyst.getBlockPos(); - double sx = start.getX() + 0.5; - double sy = start.getY() + 1.25; - double sz = start.getZ() + 0.5; - serverLevel.sendParticles( - new InfusionParticleType(stack), - sx, - sy, - sz, - 0, - tx - sx, - ty - sy, - tz - sz, - 0.5 - ); - } - } - } - - } - - @Override - public boolean canPlaceItem(int slot, ItemStack stack) { - return isValid(); - } - - public boolean isValid() { - if (world == null || worldPos == null || input == null) return false; - return Arrays.stream(catalysts).noneMatch(Objects::isNull); - } - - public boolean hasRecipe() { - return hasRecipe; - } - - public void setLocation(Level world, BlockPos pos) { - this.world = world; - this.worldPos = pos; - this.isDirty = true; - } - - @Override - public void clearContent() { - if (!isValid()) return; - input.clearContent(); - Arrays.stream(catalysts).forEach(PedestalBlockEntity::clearContent); - } - - @Override - public int getContainerSize() { - return 9; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public ItemStack getItem(int slot) { - if (slot > 8) return ItemStack.EMPTY; - if (slot == 0) { - return input.getItem(0); - } - else { - return catalysts[slot - 1].getItem(0); - } - } - - @Override - public ItemStack removeItem(int slot, int amount) { - return removeItemNoUpdate(slot); - } - - @Override - public ItemStack removeItemNoUpdate(int slot) { - if (slot > 8) return ItemStack.EMPTY; - if (slot == 0) { - return input.removeItemNoUpdate(0); - } - else { - return catalysts[slot - 1].removeItemNoUpdate(0); - } - } - - @Override - public void setItem(int slot, ItemStack stack) { - if (slot > 8) return; - if (slot == 0) { - input.setItem(0, stack); - } - else { - catalysts[slot - 1].setItem(0, stack); - } - } - - @Override - public void setChanged() { - if (isValid()) { - input.setChanged(); - Arrays.stream(catalysts).forEach(PedestalBlockEntity::setChanged); - } - } - - public void setDirty() { - this.isDirty = true; - } - - @Override - public boolean stillValid(Player player) { - return true; - } - - public void fromTag(CompoundTag tag) { - if (tag.contains("recipe")) { - hasRecipe = tag.getBoolean("recipe"); - progress = tag.getInt("progress"); - time = tag.getInt("time"); - } - } - - public CompoundTag toTag(CompoundTag tag) { - if (hasRecipe()) { - tag.putBoolean("recipe", hasRecipe); - tag.putInt("progress", progress); - tag.putInt("time", time); - } - return tag; - } - - public static Point[] getMap() { - return PEDESTALS_MAP; - } -} diff --git a/src/main/java/ru/betterend/tab/CreativeTabs.java b/src/main/java/ru/betterend/tab/CreativeTabs.java deleted file mode 100644 index cc85999b..00000000 --- a/src/main/java/ru/betterend/tab/CreativeTabs.java +++ /dev/null @@ -1,34 +0,0 @@ -package ru.betterend.tab; - -import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -import java.util.stream.Collectors; - -public class CreativeTabs { - public static final CreativeModeTab TAB_BLOCKS; - public static final CreativeModeTab TAB_ITEMS; - - static { - TAB_BLOCKS = FabricItemGroupBuilder - .create(BetterEnd.makeID("end_blocks")) - .icon(() -> new ItemStack(EndBlocks.END_MYCELIUM)) - .appendItems(stacks -> stacks.addAll(EndBlocks.getModBlockItems() - .stream() - .map(ItemStack::new) - .collect(Collectors.toList()))) - .build(); - TAB_ITEMS = FabricItemGroupBuilder - .create(BetterEnd.makeID("end_items")) - .icon(() -> new ItemStack(EndItems.ETERNAL_CRYSTAL)) - .appendItems(stacks -> stacks.addAll(EndItems.getModItems() - .stream() - .map(ItemStack::new) - .collect(Collectors.toList()))) - .build(); - } -} diff --git a/src/main/java/ru/betterend/util/BlockFixer.java b/src/main/java/ru/betterend/util/BlockFixer.java deleted file mode 100644 index 76b6de89..00000000 --- a/src/main/java/ru/betterend/util/BlockFixer.java +++ /dev/null @@ -1,233 +0,0 @@ -package ru.betterend.util; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.FallingBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.dimension.DimensionType; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.blocks.StalactiteBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.BlueVineBlock; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Set; -import java.util.stream.IntStream; - -public class BlockFixer { - private static final BlockState AIR = Blocks.AIR.defaultBlockState(); - private static final BlockState WATER = Blocks.WATER.defaultBlockState(); - - public static void fixBlocks(LevelAccessor level, BlockPos start, BlockPos end) { - final Registry registry = level.registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - final ResourceLocation dimKey = registry.getKey(level.dimensionType()); - if (dimKey != null && "world_blender".equals(dimKey.getNamespace())) { - return; - } - final Set doubleCheck = Sets.newConcurrentHashSet(); - final int dx = end.getX() - start.getX() + 1; - final int dz = end.getZ() - start.getZ() + 1; - final int count = dx * dz; - final int minY = Math.max(start.getY(), level.getMinBuildHeight()); - final int maxY = Math.min(end.getY(), level.getMaxBuildHeight()); - IntStream.range(0, count).parallel().forEach(index -> { - MutableBlockPos POS = new MutableBlockPos(); - POS.setX((index % dx) + start.getX()); - POS.setZ((index / dx) + start.getZ()); - BlockState state; - for (int y = minY; y <= maxY; y++) { - POS.setY(y); - state = level.getBlockState(POS); - - if (state.getBlock() instanceof FurBlock) { - doubleCheck.add(POS.immutable()); - } - // Liquids - else if (!state.getFluidState().isEmpty()) { - if (!state.canSurvive(level, POS)) { - setWithoutUpdate(level, POS, WATER); - POS.setY(POS.getY() - 1); - state = level.getBlockState(POS); - while (!state.canSurvive(level, POS)) { - state = state.getFluidState().isEmpty() ? AIR : WATER; - setWithoutUpdate(level, POS, state); - POS.setY(POS.getY() - 1); - state = level.getBlockState(POS); - } - } - POS.setY(y - 1); - if (level.isEmptyBlock(POS)) { - POS.setY(y); - while (!level.getFluidState(POS).isEmpty()) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() + 1); - } - continue; - } - for (Direction dir : BlocksHelper.HORIZONTAL) { - if (level.isEmptyBlock(POS.relative(dir))) { - try { - level.scheduleTick(POS, state.getFluidState().getType(), 0); - } - catch (Exception e) {} - break; - } - } - } - else if (state.is(EndBlocks.SMARAGDANT_CRYSTAL)) { - POS.setY(POS.getY() - 1); - if (level.isEmptyBlock(POS)) { - POS.setY(POS.getY() + 1); - while (state.is(EndBlocks.SMARAGDANT_CRYSTAL)) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() + 1); - state = level.getBlockState(POS); - } - } - } - else if (state.getBlock() instanceof StalactiteBlock) { - if (!state.canSurvive(level, POS)) { - if (level.getBlockState(POS.above()).getBlock() instanceof StalactiteBlock) { - while (state.getBlock() instanceof StalactiteBlock) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() + 1); - state = level.getBlockState(POS); - } - } - else { - while (state.getBlock() instanceof StalactiteBlock) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() - 1); - state = level.getBlockState(POS); - } - } - } - } - else if (state.is(EndBlocks.CAVE_PUMPKIN)) { - if (!level.getBlockState(POS.above()).is(EndBlocks.CAVE_PUMPKIN_SEED)) { - setWithoutUpdate(level, POS, AIR); - } - } - else if (!state.canSurvive(level, POS)) { - // Chorus - if (state.is(Blocks.CHORUS_PLANT)) { - Set ends = Sets.newHashSet(); - Set add = Sets.newHashSet(); - ends.add(POS.immutable()); - - for (int i = 0; i < 64 && !ends.isEmpty(); i++) { - ends.forEach((pos) -> { - setWithoutUpdate(level, pos, AIR); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos p = pos.relative(dir); - BlockState st = level.getBlockState(p); - if ((st.is(Blocks.CHORUS_PLANT) || st.is(Blocks.CHORUS_FLOWER)) && !st.canSurvive( - level, - p - )) { - add.add(p); - } - } - BlockPos p = pos.above(); - BlockState st = level.getBlockState(p); - if ((st.is(Blocks.CHORUS_PLANT) || st.is(Blocks.CHORUS_FLOWER)) && !st.canSurvive( - level, - p - )) { - add.add(p); - } - }); - ends.clear(); - ends.addAll(add); - add.clear(); - } - } - // Vines - else if (state.getBlock() instanceof BaseVineBlock) { - while (level.getBlockState(POS).getBlock() instanceof BaseVineBlock) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() - 1); - } - } - // Falling blocks - else if (state.getBlock() instanceof FallingBlock) { - BlockState falling = state; - - POS.setY(POS.getY() - 1); - state = level.getBlockState(POS); - - int ray = BlocksHelper.downRayRep(level, POS.immutable(), 64); - if (ray > 32) { - setWithoutUpdate(level, POS, Blocks.END_STONE.defaultBlockState()); - if (level.getRandom().nextBoolean()) { - POS.setY(POS.getY() - 1); - state = level.getBlockState(POS); - setWithoutUpdate(level, POS, Blocks.END_STONE.defaultBlockState()); - } - } - else { - POS.setY(y); - BlockState replacement = AIR; - for (Direction dir : BlocksHelper.HORIZONTAL) { - state = level.getBlockState(POS.relative(dir)); - if (!state.getFluidState().isEmpty()) { - replacement = state; - break; - } - } - setWithoutUpdate(level, POS, replacement); - POS.setY(y - ray); - setWithoutUpdate(level, POS, falling); - } - } - // Blocks without support - else { - // Blue Vine - if (state.getBlock() instanceof BlueVineBlock) { - while (state.is(EndBlocks.BLUE_VINE) || state.is(EndBlocks.BLUE_VINE_LANTERN) || state.is( - EndBlocks.BLUE_VINE_FUR)) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() + 1); - state = level.getBlockState(POS); - } - } - // Double plants - if (state.getBlock() instanceof BaseDoublePlantBlock) { - setWithoutUpdate(level, POS, AIR); - POS.setY(POS.getY() + 1); - setWithoutUpdate(level, POS, AIR); - } - // Other blocks - else { - setWithoutUpdate(level, POS, getAirOrFluid(state)); - } - } - } - } - }); - - doubleCheck.forEach((pos) -> { - if (!level.getBlockState(pos).canSurvive(level, pos)) { - setWithoutUpdate(level, pos, AIR); - } - }); - } - - private static BlockState getAirOrFluid(BlockState state) { - return state.getFluidState().isEmpty() ? AIR : state.getFluidState().createLegacyBlock(); - } - - private static void setWithoutUpdate(LevelAccessor world, BlockPos pos, BlockState state) { - synchronized (world) { - BlocksHelper.setWithoutUpdate(world, pos, state); - } - } -} diff --git a/src/main/java/ru/betterend/util/BonemealPlants.java b/src/main/java/ru/betterend/util/BonemealPlants.java deleted file mode 100644 index b8d0ad24..00000000 --- a/src/main/java/ru/betterend/util/BonemealPlants.java +++ /dev/null @@ -1,121 +0,0 @@ -package ru.betterend.util; - -import com.google.common.collect.Lists; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import ru.bclib.api.BonemealAPI; -import ru.betterend.blocks.basis.EndTerrainBlock; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndBlocks; - -import java.util.List; - -public class BonemealPlants { - public static void init() { - BonemealAPI.addLandGrass(EndBlocks.CREEPING_MOSS, EndBlocks.END_MOSS); - BonemealAPI.addLandGrass(EndBlocks.UMBRELLA_MOSS, EndBlocks.END_MOSS); - BonemealAPI.addLandGrass(EndBlocks.CREEPING_MOSS, EndBlocks.END_MYCELIUM); - BonemealAPI.addLandGrass(EndBlocks.UMBRELLA_MOSS, EndBlocks.END_MYCELIUM); - - BonemealAPI.addLandGrass(EndBlocks.CAVE_GRASS, EndBlocks.CAVE_MOSS); - BonemealAPI.addLandGrass(EndBlocks.CHORUS_GRASS, EndBlocks.CHORUS_NYLIUM); - BonemealAPI.addLandGrass(EndBlocks.CRYSTAL_GRASS, EndBlocks.CRYSTAL_MOSS); - BonemealAPI.addLandGrass(EndBlocks.SHADOW_PLANT, EndBlocks.SHADOW_GRASS); - BonemealAPI.addLandGrass(EndBlocks.BUSHY_GRASS, EndBlocks.PINK_MOSS); - BonemealAPI.addLandGrass(EndBlocks.AMBER_GRASS, EndBlocks.AMBER_MOSS); - - BonemealAPI.addLandGrass(EndBlocks.JUNGLE_GRASS, EndBlocks.JUNGLE_MOSS); - BonemealAPI.addLandGrass(EndBlocks.TWISTED_UMBRELLA_MOSS, EndBlocks.JUNGLE_MOSS); - BonemealAPI.addLandGrass(EndBlocks.SMALL_JELLYSHROOM, EndBlocks.JUNGLE_MOSS, 0.1F); - - BonemealAPI.addLandGrass( - EndBiomes.GLOWING_GRASSLANDS.getID(), - EndBlocks.BLOOMING_COOKSONIA, - EndBlocks.END_MOSS - ); - BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.VAIOLUSH_FERN, EndBlocks.END_MOSS); - BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.FRACTURN, EndBlocks.END_MOSS); - BonemealAPI.addLandGrass(EndBiomes.GLOWING_GRASSLANDS.getID(), EndBlocks.SALTEAGO, EndBlocks.END_MOSS); - - BonemealAPI.addLandGrass( - EndBiomes.GLOWING_GRASSLANDS.getID(), - EndBlocks.CREEPING_MOSS, - EndBlocks.END_MOSS, - 0.1F - ); - BonemealAPI.addLandGrass( - EndBiomes.GLOWING_GRASSLANDS.getID(), - EndBlocks.UMBRELLA_MOSS, - EndBlocks.END_MOSS, - 0.1F - ); - BonemealAPI.addLandGrass( - EndBiomes.GLOWING_GRASSLANDS.getID(), - EndBlocks.TWISTED_UMBRELLA_MOSS, - EndBlocks.END_MOSS, - 0.1F - ); - - BonemealAPI.addLandGrass(EndBlocks.ORANGO, EndBlocks.RUTISCUS); - BonemealAPI.addLandGrass(EndBlocks.AERIDIUM, EndBlocks.RUTISCUS, 0.2F); - BonemealAPI.addLandGrass(EndBlocks.LUTEBUS, EndBlocks.RUTISCUS, 0.2F); - BonemealAPI.addLandGrass(EndBlocks.LAMELLARIUM, EndBlocks.RUTISCUS); - - BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.AERIDIUM, EndBlocks.RUTISCUS, 0.2F); - BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.LAMELLARIUM, EndBlocks.RUTISCUS); - BonemealAPI.addLandGrass(EndBiomes.LANTERN_WOODS.getID(), EndBlocks.BOLUX_MUSHROOM, EndBlocks.RUTISCUS, 0.05F); - - BonemealAPI.addLandGrass( - EndBlocks.GLOBULAGUS, - EndBlocks.SANGNUM, - EndBlocks.MOSSY_OBSIDIAN, - EndBlocks.MOSSY_DRAGON_BONE - ); - BonemealAPI.addLandGrass( - EndBlocks.CLAWFERN, - EndBlocks.SANGNUM, - EndBlocks.MOSSY_OBSIDIAN, - EndBlocks.MOSSY_DRAGON_BONE - ); - BonemealAPI.addLandGrass(EndBlocks.SANGNUM, EndBlocks.SMALL_AMARANITA_MUSHROOM, 0.1F); - BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_OBSIDIAN, 0.1F); - BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_DRAGON_BONE, 0.1F); - - BonemealAPI.addLandGrass(EndBlocks.GLOBULAGUS, EndBlocks.MOSSY_DRAGON_BONE); - BonemealAPI.addLandGrass(EndBlocks.CLAWFERN, EndBlocks.MOSSY_DRAGON_BONE); - BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_DRAGON_BONE, 0.1F); - - BonemealAPI.addLandGrass(EndBlocks.GLOBULAGUS, EndBlocks.MOSSY_OBSIDIAN); - BonemealAPI.addLandGrass(EndBlocks.CLAWFERN, EndBlocks.MOSSY_OBSIDIAN); - BonemealAPI.addLandGrass(EndBlocks.SMALL_AMARANITA_MUSHROOM, EndBlocks.MOSSY_OBSIDIAN, 0.1F); - - Block[] charnias = new Block[] { - EndBlocks.CHARNIA_CYAN, - EndBlocks.CHARNIA_GREEN, - EndBlocks.CHARNIA_ORANGE, - EndBlocks.CHARNIA_LIGHT_BLUE, - EndBlocks.CHARNIA_PURPLE, - EndBlocks.CHARNIA_RED - }; - List terrain = Lists.newArrayList(); - EndBlocks.getModBlocks().forEach(block -> { - if (block instanceof EndTerrainBlock) { - terrain.add(block); - } - }); - terrain.add(Blocks.END_STONE); - terrain.add(EndBlocks.ENDSTONE_DUST); - terrain.add(EndBlocks.CAVE_MOSS); - terrain.add(EndBlocks.SULPHURIC_ROCK.stone); - terrain.add(EndBlocks.VIOLECITE.stone); - terrain.add(EndBlocks.FLAVOLITE.stone); - terrain.add(EndBlocks.AZURE_JADESTONE.stone); - terrain.add(EndBlocks.VIRID_JADESTONE.stone); - terrain.add(EndBlocks.SANDY_JADESTONE.stone); - terrain.add(EndBlocks.BRIMSTONE); - Block[] terrainBlocks = terrain.toArray(new Block[terrain.size()]); - for (Block charnia : charnias) { - BonemealAPI.addWaterGrass(charnia, terrainBlocks); - } - } -} diff --git a/src/main/java/ru/betterend/util/GlobalState.java b/src/main/java/ru/betterend/util/GlobalState.java deleted file mode 100644 index 4f20c85b..00000000 --- a/src/main/java/ru/betterend/util/GlobalState.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.betterend.util; - -import net.minecraft.core.BlockPos.MutableBlockPos; - -public class GlobalState { - private static final ThreadLocal STATE = ThreadLocal.withInitial(()->new GlobalState()); - public static GlobalState stateForThread() { return STATE.get(); } - - public final MutableBlockPos POS = new MutableBlockPos(); -} diff --git a/src/main/java/ru/betterend/util/LangUtil.java b/src/main/java/ru/betterend/util/LangUtil.java deleted file mode 100644 index 615f9690..00000000 --- a/src/main/java/ru/betterend/util/LangUtil.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.betterend.util; - -import net.minecraft.client.resources.language.I18n; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - - -public class LangUtil { - public final static String CONFIG_ELEMENT = "configuration"; - - private String element; - - public LangUtil(String element) { - this.element = element; - } - - public void setElement(String key) { - this.element = key; - } - - public String getString(String key) { - return getString(element, key); - } - - public MutableComponent getText(String key) { - return getText(element, key); - } - - public static String translate(String key) { - return I18n.get(key); - } - - public static String getString(String element, String key) { - return translate(String.format("%s.%s", element, key)); - } - - public static MutableComponent getText(String element, String key) { - return Component.translatable(getString(element, key)); - } -} diff --git a/src/main/java/ru/betterend/util/LootTableUtil.java b/src/main/java/ru/betterend/util/LootTableUtil.java deleted file mode 100644 index 607a80e5..00000000 --- a/src/main/java/ru/betterend/util/LootTableUtil.java +++ /dev/null @@ -1,155 +0,0 @@ -package ru.betterend.util; - -import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder; -import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder; -import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback; -import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.storage.loot.entries.LootItem; -import net.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceCondition; -import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; -import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.complexmaterials.WoodenComplexMaterial; -import ru.bclib.world.biomes.BCLBiome; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndItems; - -public class LootTableUtil { - private static final ResourceLocation END_CITY_TREASURE_ID = new ResourceLocation("chests/end_city_treasure"); - private static final ResourceLocation COMMON = BetterEnd.makeID("chests/common"); - private static final ResourceLocation FOGGY_MUSHROOMLAND = BetterEnd.makeID("chests/foggy_mushroomland"); - private static final ResourceLocation CHORUS_FOREST = BetterEnd.makeID("chests/chorus_forest"); - private static final ResourceLocation SHADOW_FOREST = BetterEnd.makeID("chests/shadow_forest"); - private static final ResourceLocation LANTERN_WOODS = BetterEnd.makeID("chests/lantern_woods"); - private static final ResourceLocation UMBRELLA_JUNGLE = BetterEnd.makeID("chests/umbrella_jungle"); - - public static void init() { - LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, table, setter) -> { - if (END_CITY_TREASURE_ID.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(ConstantValue.exactly(1)); - builder.withCondition(LootItemRandomChanceCondition.randomChance(0.2f).build()); - builder.withEntry(LootItem.lootTableItem(Items.GHAST_TEAR).build()); - table.withPool(builder); - - builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(0, 3)); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_STRANGE_AND_ALIEN).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_GRASPING_AT_STARS).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_ENDSEEKER).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_EO_DRACONA).build()); - table.withPool(builder); - } - else if (id.getNamespace().equals(BetterEnd.MOD_ID)) { - addCommonItems(table); - if (FOGGY_MUSHROOMLAND.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.MOSSY_GLOWSHROOM.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.MOSSY_GLOWSHROOM_SAPLING).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.BLUE_VINE_SEED).build()); - table.withPool(builder); - } - else if (CHORUS_FOREST.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.PYTHADENDRON.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.PYTHADENDRON_SAPLING).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.CHORUS_MUSHROOM).build()); - table.withPool(builder); - } - else if (SHADOW_FOREST.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.DRAGON_TREE.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.DRAGON_TREE_SAPLING).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.SHADOW_BERRY).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.SHADOW_BERRY_RAW).build()); - table.withPool(builder); - } - else if (LANTERN_WOODS.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.LUCERNIA.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.LUCERNIA_SAPLING).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.BOLUX_MUSHROOM).build()); - table.withPool(builder); - } - else if (UMBRELLA_JUNGLE.equals(id)) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.UMBRELLA_TREE.getBlock(WoodenComplexMaterial.BLOCK_PLANKS)).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.UMBRELLA_TREE_SAPLING).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.SMALL_JELLYSHROOM).build()); - table.withPool(builder); - } - } - }); - } - - public static ResourceLocation getTable(Holder biome) { - BCLBiome bclBiome = BiomeAPI.getBiome(biome.value()); - if (bclBiome == EndBiomes.FOGGY_MUSHROOMLAND) { - return FOGGY_MUSHROOMLAND; - } - else if (bclBiome == EndBiomes.CHORUS_FOREST) { - return CHORUS_FOREST; - } - else if (bclBiome == EndBiomes.SHADOW_FOREST) { - return SHADOW_FOREST; - } - else if (bclBiome == EndBiomes.LANTERN_WOODS) { - return LANTERN_WOODS; - } - else if (bclBiome == EndBiomes.UMBRELLA_JUNGLE) { - return UMBRELLA_JUNGLE; - } - return COMMON; - } - - private static void addCommonItems(FabricLootSupplierBuilder table) { - FabricLootPoolBuilder builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(0, 2)); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_STRANGE_AND_ALIEN).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_GRASPING_AT_STARS).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_ENDSEEKER).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.MUSIC_DISC_EO_DRACONA).build()); - table.withPool(builder); - - builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(4, 8)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.ingot).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.rawOre).build()); - builder.withEntry(LootItem.lootTableItem(Items.ENDER_PEARL).build()); - table.withPool(builder); - - builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(2, 4)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.TERMINITE.ingot).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.ENDER_SHARD).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.AURORA_CRYSTAL).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.axe).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.pickaxe).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.hoe).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.sword).build()); - builder.withEntry(LootItem.lootTableItem(EndBlocks.THALLASIUM.shovel).build()); - builder.withEntry(LootItem.lootTableItem(Items.ENDER_EYE).build()); - builder.withEntry(LootItem.lootTableItem(Blocks.OBSIDIAN).build()); - table.withPool(builder); - - builder = FabricLootPoolBuilder.builder(); - builder.setRolls(UniformGenerator.between(0, 4)); - builder.withEntry(LootItem.lootTableItem(EndBlocks.FLAVOLITE_RUNED).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.AETERNIUM_INGOT).build()); - builder.withEntry(LootItem.lootTableItem(EndItems.AMBER_GEM).build()); - builder.withEntry(LootItem.lootTableItem(Items.END_CRYSTAL).build()); - builder.withEntry(LootItem.lootTableItem(Items.GHAST_TEAR).build()); - table.withPool(builder); - } -} diff --git a/src/main/java/ru/betterend/util/StructureErode.java b/src/main/java/ru/betterend/util/StructureErode.java deleted file mode 100644 index 4bc5991a..00000000 --- a/src/main/java/ru/betterend/util/StructureErode.java +++ /dev/null @@ -1,278 +0,0 @@ -package ru.betterend.util; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; - -public class StructureErode { - private static final Direction[] DIR = BlocksHelper.makeHorizontal(); - - public static void erode(WorldGenLevel world, BoundingBox bounds, int iterations, RandomSource random) { - MutableBlockPos mut = new MutableBlockPos(); - boolean canDestruct = true; - for (int i = 0; i < iterations; i++) { - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - for (int y = bounds.maxY(); y >= bounds.minY(); y--) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - boolean ignore = ignore(state, world, mut); - if (canDestruct && BlocksHelper.isInvulnerable( - state, - world, - mut - ) && random.nextInt(8) == 0 && world.isEmptyBlock(mut.below(2))) { - int r = MHelper.randRange(1, 4, random); - int cx = mut.getX(); - int cy = mut.getY(); - int cz = mut.getZ(); - int x1 = cx - r; - int y1 = cy - r; - int z1 = cz - r; - int x2 = cx + r; - int y2 = cy + r; - int z2 = cz + r; - for (int px = x1; px <= x2; px++) { - int dx = px - cx; - dx *= dx; - mut.setX(px); - for (int py = y1; py <= y2; py++) { - int dy = py - cy; - dy *= dy; - mut.setY(py); - for (int pz = z1; pz <= z2; pz++) { - int dz = pz - cz; - dz *= dz; - mut.setZ(pz); - if (dx + dy + dz <= r && BlocksHelper.isInvulnerable( - world.getBlockState(mut), - world, - mut - )) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - } - } - } - } - mut.setX(cx); - mut.setY(cy); - mut.setZ(cz); - canDestruct = false; - continue; - } - else if (ignore) { - continue; - } - if (!state.isAir() && random.nextBoolean()) { - MHelper.shuffle(DIR, random); - for (Direction dir : DIR) { - if (world.isEmptyBlock(mut.relative(dir)) && world.isEmptyBlock(mut.below() - .relative(dir))) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - mut.move(dir).move(Direction.DOWN); - for (int py = mut.getY(); y >= bounds.minY() - 10; y--) { - mut.setY(py - 1); - if (!world.isEmptyBlock(mut)) { - mut.setY(py); - BlocksHelper.setWithoutUpdate(world, mut, state); - break; - } - } - } - } - break; - } - else if (random.nextInt(8) == 0 && !BlocksHelper.isInvulnerable( - world.getBlockState(mut.above()), - world, - mut - )) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - } - } - } - } - } - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - for (int y = bounds.maxY(); y >= bounds.minY(); y--) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (!ignore(state, world, mut) && world.isEmptyBlock(mut.below())) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - for (int py = mut.getY(); py >= bounds.minY() - 10; py--) { - mut.setY(py - 1); - if (!world.isEmptyBlock(mut)) { - mut.setY(py); - BlocksHelper.setWithoutUpdate(world, mut, state); - break; - } - } - } - } - } - } - } - - public static void erodeIntense(WorldGenLevel world, BoundingBox bounds, RandomSource random) { - MutableBlockPos mut = new MutableBlockPos(); - MutableBlockPos mut2 = new MutableBlockPos(); - int minY = bounds.minY() - 10; - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - for (int y = bounds.maxY(); y >= bounds.minY(); y--) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (!ignore(state, world, mut)) { - if (random.nextInt(6) == 0) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - if (random.nextBoolean()) { - int px = MHelper.floor(random.nextGaussian() * 2 + x + 0.5); - int pz = MHelper.floor(random.nextGaussian() * 2 + z + 0.5); - mut2.set(px, y, pz); - while (world.getBlockState(mut2).getMaterial().isReplaceable() && mut2.getY() > minY) { - mut2.setY(mut2.getY() - 1); - } - if (!world.getBlockState(mut2).isAir() && state.canSurvive(world, mut2)) { - mut2.setY(mut2.getY() + 1); - BlocksHelper.setWithoutUpdate(world, mut2, state); - } - } - } - else if (random.nextInt(8) == 0) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - } - } - } - } - } - - drop(world, bounds); - } - - private static void drop(WorldGenLevel world, BoundingBox bounds) { - MutableBlockPos mut = new MutableBlockPos(); - - Set blocks = Sets.newHashSet(); - Set edge = Sets.newHashSet(); - Set add = Sets.newHashSet(); - - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - for (int y = bounds.minY(); y <= bounds.maxY(); y++) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (!ignore(state, world, mut) && isTerrainNear(world, mut)) { - edge.add(mut.immutable()); - } - } - } - } - - if (edge.isEmpty()) { - return; - } - - while (!edge.isEmpty()) { - for (BlockPos center : edge) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - BlockState state = world.getBlockState(center); - if (state.isCollisionShapeFullBlock(world, center)) { - mut.set(center).move(dir); - if (bounds.isInside(mut)) { - state = world.getBlockState(mut); - if (!ignore(state, world, mut) && !blocks.contains(mut)) { - add.add(mut.immutable()); - } - } - } - } - } - - blocks.addAll(edge); - edge.clear(); - edge.addAll(add); - add.clear(); - } - - int minY = bounds.minY() - 10; - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - for (int y = bounds.minY(); y <= bounds.maxY(); y++) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (!ignore(state, world, mut) && !blocks.contains(mut)) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.AIR); - while (world.getBlockState(mut).getMaterial().isReplaceable() && mut.getY() > minY) { - mut.setY(mut.getY() - 1); - } - if (mut.getY() > minY) { - mut.setY(mut.getY() + 1); - BlocksHelper.setWithoutUpdate(world, mut, state); - } - } - } - } - } - } - - private static boolean ignore(BlockState state, WorldGenLevel world, BlockPos pos) { - if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(BlockTags.NYLIUM)) { - return true; - } - return !state.getMaterial().equals(Material.STONE) || BlocksHelper.isInvulnerable(state, world, pos); - } - - private static boolean isTerrainNear(WorldGenLevel world, BlockPos pos) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (world.getBlockState(pos.relative(dir)).is(CommonBlockTags.GEN_END_STONES)) { - return true; - } - } - return false; - } - - public static void cover(WorldGenLevel world, BoundingBox bounds, RandomSource random, BlockState defaultBlock) { - MutableBlockPos mut = new MutableBlockPos(); - for (int x = bounds.minX(); x <= bounds.maxX(); x++) { - mut.setX(x); - for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { - mut.setZ(z); - BlockState top = BiomeAPI.findTopMaterial(world.getBiome(mut)).orElse(defaultBlock); - for (int y = bounds.maxY(); y >= bounds.minY(); y--) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (state.is(CommonBlockTags.END_STONES) && !world.getBlockState(mut.above()).getMaterial().isSolidBlocking()) { - BlocksHelper.setWithoutUpdate(world, mut, top); - } - } - } - } - } -} diff --git a/src/main/java/ru/betterend/world/biome/EndBiome.java b/src/main/java/ru/betterend/world/biome/EndBiome.java deleted file mode 100644 index f1d21547..00000000 --- a/src/main/java/ru/betterend/world/biome/EndBiome.java +++ /dev/null @@ -1,175 +0,0 @@ -package ru.betterend.world.biome; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SurfaceRules; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.surface.SurfaceRuleBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.bclib.world.biomes.BCLBiome; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndTags; - -public class EndBiome extends BCLBiome implements SurfaceMaterialProvider { - public static class DefaultSurfaceMaterialProvider implements SurfaceMaterialProvider{ - public static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); - @Override - public BlockState getTopMaterial() { - return getUnderMaterial(); - } - - @Override - public BlockState getAltTopMaterial() { - return getTopMaterial(); - } - - @Override - public BlockState getUnderMaterial() { - return END_STONE; - } - - @Override - public boolean generateFloorRule(){ - return true; - } - - @Override - public SurfaceRuleBuilder surface() { - SurfaceRuleBuilder builder = SurfaceRuleBuilder.start(); - - if (generateFloorRule() && getTopMaterial()!=getUnderMaterial()){ - if (getTopMaterial()!=getAltTopMaterial()){ - builder.floor(getTopMaterial()); - } else { - builder.chancedFloor(getTopMaterial(), getAltTopMaterial()); - } - } - return builder.filler(getUnderMaterial()); - } - } - - public abstract static class Config { - public static final SurfaceMaterialProvider DEFAULT_MATERIAL = new DefaultSurfaceMaterialProvider(); - - protected static final SurfaceRules.RuleSource END_STONE = SurfaceRules.state(DefaultSurfaceMaterialProvider.END_STONE); - protected static final SurfaceRules.RuleSource END_MOSS = SurfaceRules.state(EndBlocks.END_MOSS.defaultBlockState()); - protected static final SurfaceRules.RuleSource ENDSTONE_DUST = SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()); - protected static final SurfaceRules.RuleSource END_MYCELIUM = SurfaceRules.state(EndBlocks.END_MYCELIUM.defaultBlockState()); - protected static final SurfaceRules.RuleSource FLAVOLITE =SurfaceRules.state(EndBlocks.FLAVOLITE.stone.defaultBlockState()); - protected static final SurfaceRules.RuleSource SULPHURIC_ROCK =SurfaceRules.state(EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState()); - protected static final SurfaceRules.RuleSource BRIMSTONE =SurfaceRules.state(EndBlocks.BRIMSTONE.defaultBlockState()); - protected static final SurfaceRules.RuleSource PALLIDIUM_FULL =SurfaceRules.state(EndBlocks.PALLIDIUM_FULL.defaultBlockState()); - protected static final SurfaceRules.RuleSource PALLIDIUM_HEAVY =SurfaceRules.state(EndBlocks.PALLIDIUM_HEAVY.defaultBlockState()); - protected static final SurfaceRules.RuleSource PALLIDIUM_THIN =SurfaceRules.state(EndBlocks.PALLIDIUM_THIN.defaultBlockState()); - protected static final SurfaceRules.RuleSource PALLIDIUM_TINY =SurfaceRules.state(EndBlocks.PALLIDIUM_TINY.defaultBlockState()); - protected static final SurfaceRules.RuleSource UMBRALITH =SurfaceRules.state(EndBlocks.UMBRALITH.stone.defaultBlockState()); - - public final ResourceLocation ID; - - protected Config(String name) { - this.ID = BetterEnd.makeID(name); - } - - protected abstract void addCustomBuildData(BCLBiomeBuilder builder); - - public BiomeSupplier getSupplier(){ - return EndBiome::new; - } - - protected boolean hasCaves(){ - return true; - } - - protected SurfaceMaterialProvider surfaceMaterial() { - return DEFAULT_MATERIAL; - } - } - - public EndBiome(ResourceLocation biomeID, Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - } - - public static EndBiome create(Config biomeConfig){ - BCLBiomeBuilder builder = BCLBiomeBuilder - .start(biomeConfig.ID) - .music(SoundEvents.MUSIC_END) - .waterColor(4159204) - .waterFogColor(329011) - .fogColor(0xA080A0) - .skyColor(0) - .mood(EndSounds.AMBIENT_DUST_WASTELANDS) - .temperature(0.5f) - .wetness(0.5f) - .precipitation(Biome.Precipitation.NONE) - .surface(biomeConfig.surfaceMaterial().surface().build()); - - biomeConfig.addCustomBuildData(builder); - EndFeatures.addDefaultFeatures(builder, biomeConfig.hasCaves()); - - - EndBiome biome = builder.build(biomeConfig.getSupplier()); - biome.addCustomData("has_caves", biomeConfig.hasCaves()); - biome.setSurfaceMaterial(biomeConfig.surfaceMaterial()); - - EndTags.addBiomeSurfaceToEndGroup(biome); - return biome; - } - - - private SurfaceMaterialProvider surfMatProv = Config.DEFAULT_MATERIAL; - private void setSurfaceMaterial(SurfaceMaterialProvider prov) { - surfMatProv = prov; - } - - @Override - public BlockState getTopMaterial() { - return surfMatProv.getTopMaterial(); - } - - @Override - public BlockState getUnderMaterial() { - return surfMatProv.getUnderMaterial(); - } - - @Override - public BlockState getAltTopMaterial() { - return surfMatProv.getAltTopMaterial(); - } - - @Override - public boolean generateFloorRule() { return surfMatProv.generateFloorRule(); } - - @Override - public SurfaceRuleBuilder surface() { return surfMatProv.surface(); } - - public static BlockState findTopMaterial(BCLBiome biome){ - return BiomeAPI.findTopMaterial(biome).orElse(EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); - } - - public static BlockState findTopMaterial(Biome biome){ - return findTopMaterial(BiomeAPI.getBiome(biome)); - } - - public static BlockState findTopMaterial(WorldGenLevel world, BlockPos pos){ - return findTopMaterial(BiomeAPI.getBiome(world.getBiome(pos))); - } - - public static BlockState findUnderMaterial(BCLBiome biome){ - return BiomeAPI.findUnderMaterial(biome).orElse(EndBiome.Config.DEFAULT_MATERIAL.getUnderMaterial()); - } - - public static BlockState findUnderMaterial(WorldGenLevel world, BlockPos pos){ - return findUnderMaterial(BiomeAPI.getBiome(world.getBiome(pos))); - } -} diff --git a/src/main/java/ru/betterend/world/biome/air/BiomeIceStarfield.java b/src/main/java/ru/betterend/world/biome/air/BiomeIceStarfield.java deleted file mode 100644 index 9e5536a1..00000000 --- a/src/main/java/ru/betterend/world/biome/air/BiomeIceStarfield.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.betterend.world.biome.air; - -import net.minecraft.world.entity.EntityType; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class BiomeIceStarfield extends EndBiome.Config { - public BiomeIceStarfield() { - super("ice_starfield"); - } - - @Override - protected boolean hasCaves() { - return false; - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder.structure(EndStructures.GIANT_ICE_STAR) - .fogColor(224, 245, 254) - .temperature(0F) - .fogDensity(2.2F) - .foliageColor(193, 244, 244) - .genChance(0.25F) - .particles(EndParticles.SNOWFLAKE, 0.002F) - .feature(EndFeatures.ICE_STAR) - .feature(EndFeatures.ICE_STAR_SMALL) - .spawn(EntityType.ENDERMAN, 20, 1, 4); - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/EmptyAuroraCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/EmptyAuroraCaveBiome.java deleted file mode 100644 index 8d6dbdb4..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/EmptyAuroraCaveBiome.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.resources.ResourceLocation; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.world.biome.EndBiome; - -public class EmptyAuroraCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1); - - this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); - } - - @Override - public float getFloorDensity() { - return 0.01F; - } - - @Override - public float getCeilDensity() { - return 0.1F; - } - } - - public EmptyAuroraCaveBiome() { - super("empty_aurora_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogColor(150, 30, 68) - .fogDensity(2.0F) - .plantsColor(108, 25, 46) - .waterAndFogColor(186, 77, 237) - .particles(EndParticles.GLOWING_SPHERE, 0.001F); - } - - @Override - public BiomeSupplier getSupplier() { - return EmptyAuroraCaveBiome.Biome::new; - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/EmptyEndCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/EmptyEndCaveBiome.java deleted file mode 100644 index 5556e898..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/EmptyEndCaveBiome.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.resources.ResourceLocation; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.registry.EndFeatures; -import ru.betterend.world.biome.EndBiome; - -public class EmptyEndCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE, 1); - this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); - } - - @Override - public float getFloorDensity() { - return 0.1F; - } - - @Override - public float getCeilDensity() { - return 0.1F; - } - } - - public EmptyEndCaveBiome() { - super("empty_end_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogDensity(2.0F); - } - - @Override - public BiomeSupplier getSupplier() { - return Biome::new; - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java deleted file mode 100644 index a90d3536..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/EmptySmaragdantCaveBiome.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.resources.ResourceLocation; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.world.biome.EndBiome; - -public class EmptySmaragdantCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1); - this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20); - - this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); - } - - @Override - public float getFloorDensity() { - return 0.1F; - } - - @Override - public float getCeilDensity() { - return 0.1F; - } - } - - public EmptySmaragdantCaveBiome() { - super("empty_smaragdant_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogColor(0, 253, 182) - .fogDensity(2.0F) - .plantsColor(0, 131, 145) - .waterAndFogColor(31, 167, 212) - .particles(EndParticles.SMARAGDANT, 0.001F); - } - - @Override - public BiomeSupplier getSupplier() { - return EmptySmaragdantCaveBiome.Biome::new; - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/EndCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/EndCaveBiome.java deleted file mode 100644 index c00924b3..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/EndCaveBiome.java +++ /dev/null @@ -1,96 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.GenerationStep; -import net.minecraft.world.level.levelgen.feature.Feature; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.features.BCLCommonFeatures; -import ru.bclib.util.WeightedList; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.bclib.world.features.BCLFeature; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.features.terrain.caves.CaveChunkPopulatorFeature; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndCaveBiome extends EndBiome { - public static abstract class Config extends EndBiome.Config { - protected Config(String name) { - super(name); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - BCLFeature feature = BCLCommonFeatures.makeChunkFeature( - BetterEnd.makeID(ID.getPath() + "_cave_populator"), - GenerationStep.Decoration.RAW_GENERATION, - new CaveChunkPopulatorFeature(() -> (EndCaveBiome) BiomeAPI.getBiome(ID)) - ); - - builder.feature(feature) - .music(EndSounds.MUSIC_CAVES) - .loop(EndSounds.AMBIENT_CAVES); - } - - @Override - protected boolean hasCaves() { - return false; - } - - @Override - public BiomeSupplier getSupplier() { - return EndCaveBiome::new; - } - } - - private WeightedList> floorFeatures = new WeightedList>(); - private WeightedList> ceilFeatures = new WeightedList>(); - - public EndCaveBiome(ResourceLocation biomeID, Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - } - - public void addFloorFeature(Feature feature, float weight) { - floorFeatures.add(feature, weight); - } - - public void addCeilFeature(Feature feature, float weight) { - ceilFeatures.add(feature, weight); - } - - public Feature getFloorFeature(RandomSource random) { - return floorFeatures.isEmpty() ? null : floorFeatures.get(random); - } - - public Feature getCeilFeature(RandomSource random) { - return ceilFeatures.isEmpty() ? null : ceilFeatures.get(random); - } - - public float getFloorDensity() { - return 0; - } - - public float getCeilDensity() { - return 0; - } - - public BlockState getCeil(BlockPos pos) { - return null; - } - - public BlockState getWall(BlockPos pos) { - return null; - } - - public static EndCaveBiome create(EndBiome.Config biomeConfig){ - return (EndCaveBiome) EndBiome.create(biomeConfig); - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/JadeCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/JadeCaveBiome.java deleted file mode 100644 index 39e22937..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/JadeCaveBiome.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.world.biome.EndBiome; - -public class JadeCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - private static final OpenSimplexNoise WALL_NOISE = new OpenSimplexNoise("jade_cave".hashCode()); - private static final OpenSimplexNoise DEPTH_NOISE = new OpenSimplexNoise("depth_noise".hashCode()); - private static final BlockState[] JADE = new BlockState[3]; - - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - JADE[0] = EndBlocks.VIRID_JADESTONE.stone.defaultBlockState(); - JADE[1] = EndBlocks.AZURE_JADESTONE.stone.defaultBlockState(); - JADE[2] = EndBlocks.SANDY_JADESTONE.stone.defaultBlockState(); - } - - @Override - public BlockState getWall(BlockPos pos) { - double depth = DEPTH_NOISE.eval(pos.getX() * 0.02, pos.getZ() * 0.02) * 0.2 + 0.5; - int index = Mth.floor((pos.getY() + WALL_NOISE.eval(pos.getX() * 0.2, pos.getZ() * 0.2) * 1.5) * depth + 0.5); - index = Mth.abs(index) % 3; - return JADE[index]; - } - } - - public JadeCaveBiome() { - super("jade_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogColor(118, 150, 112) - .fogDensity(2.0F) - .waterAndFogColor(95, 223, 255); - } - - @Override - public BiomeSupplier getSupplier() { - return JadeCaveBiome.Biome::new; - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/LushAuroraCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/LushAuroraCaveBiome.java deleted file mode 100644 index fd452ad1..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/LushAuroraCaveBiome.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.world.biome.EndBiome; - -public class LushAuroraCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1); - this.addFloorFeature(EndFeatures.CAVE_BUSH, 5); - this.addFloorFeature(EndFeatures.CAVE_GRASS, 40); - this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE_CAVEMOSS, 5); - - this.addCeilFeature(EndFeatures.CAVE_BUSH, 1); - this.addCeilFeature(EndFeatures.CAVE_PUMPKIN, 1); - this.addCeilFeature(EndFeatures.RUBINEA, 3); - this.addCeilFeature(EndFeatures.MAGNULA, 1); - this.addCeilFeature(EndFeatures.END_STONE_STALACTITE_CAVEMOSS, 10); - } - - @Override - public float getFloorDensity() { - return 0.2F; - } - - @Override - public float getCeilDensity() { - return 0.1F; - } - - @Override - public BlockState getCeil(BlockPos pos) { - return EndBlocks.CAVE_MOSS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP); - } - } - - public LushAuroraCaveBiome() { - super("lush_aurora_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogColor(150, 30, 68) - .fogDensity(2.0F) - .plantsColor(108, 25, 46) - .waterAndFogColor(186, 77, 237) - .particles(EndParticles.GLOWING_SPHERE, 0.001F) - ; - } - - @Override - public BiomeSupplier getSupplier() { - return LushAuroraCaveBiome.Biome::new; - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.CAVE_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/cave/LushSmaragdantCaveBiome.java b/src/main/java/ru/betterend/world/biome/cave/LushSmaragdantCaveBiome.java deleted file mode 100644 index 240e7a52..00000000 --- a/src/main/java/ru/betterend/world/biome/cave/LushSmaragdantCaveBiome.java +++ /dev/null @@ -1,64 +0,0 @@ -package ru.betterend.world.biome.cave; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.biomes.BCLBiomeBuilder.BiomeSupplier; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.bclib.world.biomes.BCLBiomeSettings; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.world.biome.EndBiome; - -public class LushSmaragdantCaveBiome extends EndCaveBiome.Config { - public static class Biome extends EndCaveBiome { - public Biome(ResourceLocation biomeID, net.minecraft.world.level.biome.Biome biome, BCLBiomeSettings settings) { - super(biomeID, biome, settings); - - this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1); - this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20); - - this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1); - } - - @Override - public float getFloorDensity() { - return 0.1F; - } - - @Override - public float getCeilDensity() { - return 0.1F; - } - } - - public LushSmaragdantCaveBiome() { - super("lush_smaragdant_cave"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - super.addCustomBuildData(builder); - builder.fogColor(0, 253, 182) - .fogDensity(2.0F) - .plantsColor(0, 131, 145) - .waterAndFogColor(31, 167, 212) - .particles(EndParticles.SMARAGDANT, 0.001F); - } - - @Override - public BiomeSupplier getSupplier() { - return LushSmaragdantCaveBiome.Biome::new; - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.CAVE_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/AmberLandBiome.java b/src/main/java/ru/betterend/world/biome/land/AmberLandBiome.java deleted file mode 100644 index 175e5301..00000000 --- a/src/main/java/ru/betterend/world/biome/land/AmberLandBiome.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class AmberLandBiome extends EndBiome.Config { - public AmberLandBiome() { - super("amber_land"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(255, 184, 71) - .fogDensity(2.0F) - .plantsColor(219, 115, 38) - .waterAndFogColor(145, 108, 72) - .music(EndSounds.MUSIC_FOREST) - .loop(EndSounds.AMBIENT_AMBER_LAND) - .particles(EndParticles.AMBER_SPHERE, 0.001F) - .feature(EndFeatures.AMBER_ORE) - .feature(EndFeatures.END_LAKE_RARE) - .feature(EndFeatures.HELIX_TREE) - .feature(EndFeatures.LANCELEAF) - .feature(EndFeatures.GLOW_PILLAR) - .feature(EndFeatures.AMBER_GRASS) - .feature(EndFeatures.AMBER_ROOT) - .feature(EndFeatures.BULB_MOSS) - .feature(EndFeatures.BULB_MOSS_WOOD) - .feature(EndFeatures.CHARNIA_ORANGE) - .feature(EndFeatures.CHARNIA_RED) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 4) - .spawn(EndEntities.END_SLIME, 30, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.AMBER_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/BlossomingSpiresBiome.java b/src/main/java/ru/betterend/world/biome/land/BlossomingSpiresBiome.java deleted file mode 100644 index 90fdda64..00000000 --- a/src/main/java/ru/betterend/world/biome/land/BlossomingSpiresBiome.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class BlossomingSpiresBiome extends EndBiome.Config { - public BlossomingSpiresBiome() { - super("blossoming_spires"); - } - - @Override - protected boolean hasCaves() { - return false; - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(241, 146, 229) - .fogDensity(1.7F) - .plantsColor(122, 45, 122) - .music(EndSounds.MUSIC_FOREST) - .loop(EndSounds.AMBIENT_BLOSSOMING_SPIRES) - .feature(EndFeatures.SPIRE) - .feature(EndFeatures.FLOATING_SPIRE) - .feature(EndFeatures.TENANEA) - .feature(EndFeatures.TENANEA_BUSH) - .feature(EndFeatures.BULB_VINE) - .feature(EndFeatures.BUSHY_GRASS) - .feature(EndFeatures.BUSHY_GRASS_WG) - .feature(EndFeatures.BLOSSOM_BERRY) - .feature(EndFeatures.TWISTED_MOSS) - .feature(EndFeatures.TWISTED_MOSS_WOOD) - .feature(EndFeatures.SILK_MOTH_NEST) - .spawn(EntityType.ENDERMAN, 50, 1, 4) - .spawn(EndEntities.SILK_MOTH, 5, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.PINK_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/ChorusForestBiome.java b/src/main/java/ru/betterend/world/biome/land/ChorusForestBiome.java deleted file mode 100644 index bed1954b..00000000 --- a/src/main/java/ru/betterend/world/biome/land/ChorusForestBiome.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.data.worldgen.placement.EndPlacements; -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class ChorusForestBiome extends EndBiome.Config { - public ChorusForestBiome() { - super("chorus_forest"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(87, 26, 87) - .fogDensity(1.5F) - .plantsColor(122, 45, 122) - .waterAndFogColor(73, 30, 73) - .particles(ParticleTypes.PORTAL, 0.01F) - .loop(EndSounds.AMBIENT_CHORUS_FOREST) - .music(EndSounds.MUSIC_DARK) - .feature(EndFeatures.VIOLECITE_LAYER) - .feature(EndFeatures.END_LAKE_RARE) - .feature(EndFeatures.PYTHADENDRON_TREE) - .feature(EndFeatures.PYTHADENDRON_BUSH) - .feature(EndFeatures.PURPLE_POLYPORE) - .feature(Decoration.VEGETAL_DECORATION, EndPlacements.CHORUS_PLANT) - .feature(EndFeatures.CHORUS_GRASS) - .feature(EndFeatures.CHORUS_MUSHROOM) - .feature(EndFeatures.TAIL_MOSS) - .feature(EndFeatures.TAIL_MOSS_WOOD) - .feature(EndFeatures.CHARNIA_PURPLE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EndEntities.END_SLIME, 5, 1, 2) - .spawn(EntityType.ENDERMAN, 50, 1, 4); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.CHORUS_NYLIUM.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/CrystalMountainsBiome.java b/src/main/java/ru/betterend/world/biome/land/CrystalMountainsBiome.java deleted file mode 100644 index d8d7227d..00000000 --- a/src/main/java/ru/betterend/world/biome/land/CrystalMountainsBiome.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class CrystalMountainsBiome extends EndBiome.Config { - public CrystalMountainsBiome() { - super("crystal_mountains"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .structure(EndStructures.MOUNTAIN) - .plantsColor(255, 133, 211) - .music(EndSounds.MUSIC_OPENSPACE) - .feature(EndFeatures.CRYSTAL_GRASS) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.CRYSTAL_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/DragonGraveyardsBiome.java b/src/main/java/ru/betterend/world/biome/land/DragonGraveyardsBiome.java deleted file mode 100644 index 07a60085..00000000 --- a/src/main/java/ru/betterend/world/biome/land/DragonGraveyardsBiome.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class DragonGraveyardsBiome extends EndBiome.Config { - public DragonGraveyardsBiome() { - super("dragon_graveyards"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .genChance(0.1f) - .fogColor(244, 46, 79) - .fogDensity(1.3F) - .particles(EndParticles.FIREFLY, 0.0007F) - .music(EndSounds.MUSIC_OPENSPACE) - .loop(EndSounds.AMBIENT_GLOWING_GRASSLANDS) - .waterAndFogColor(203, 59, 167) - .plantsColor(244, 46, 79) - .feature(EndFeatures.OBSIDIAN_PILLAR_BASEMENT) - .feature(EndFeatures.DRAGON_BONE_BLOCK_ORE) - .feature(EndFeatures.FALLEN_PILLAR) - .feature(EndFeatures.OBSIDIAN_BOULDER) - .feature(EndFeatures.GIGANTIC_AMARANITA) - .feature(EndFeatures.LARGE_AMARANITA) - .feature(EndFeatures.SMALL_AMARANITA) - .feature(EndFeatures.GLOBULAGUS) - .feature(EndFeatures.CLAWFERN) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.SANGNUM.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/DryShrublandBiome.java b/src/main/java/ru/betterend/world/biome/land/DryShrublandBiome.java deleted file mode 100644 index 32c29180..00000000 --- a/src/main/java/ru/betterend/world/biome/land/DryShrublandBiome.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class DryShrublandBiome extends EndBiome.Config { - public DryShrublandBiome() { - super("dry_shrubland"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(132, 35, 13) - .fogDensity(1.2F) - .waterAndFogColor(113, 88, 53) - .plantsColor(237, 122, 66) - .music(EndSounds.MUSIC_OPENSPACE) - .feature(EndFeatures.LUCERNIA_BUSH_RARE) - .feature(EndFeatures.ORANGO) - .feature(EndFeatures.AERIDIUM) - .feature(EndFeatures.LUTEBUS) - .feature(EndFeatures.LAMELLARIUM) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.RUTISCUS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/DustWastelandsBiome.java b/src/main/java/ru/betterend/world/biome/land/DustWastelandsBiome.java deleted file mode 100644 index 8b10f8fa..00000000 --- a/src/main/java/ru/betterend/world/biome/land/DustWastelandsBiome.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SurfaceRules; -import net.minecraft.world.level.levelgen.placement.CaveSurface; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.surface.SurfaceRuleBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class DustWastelandsBiome extends EndBiome.Config { - public DustWastelandsBiome() { - super("dust_wastelands"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(226, 239, 168) - .fogDensity(2) - .waterAndFogColor(192, 180, 131) - .terrainHeight(1.5F) - .particles(ParticleTypes.WHITE_ASH, 0.01F) - .loop(EndSounds.AMBIENT_DUST_WASTELANDS) - .music(EndSounds.MUSIC_OPENSPACE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - - @Override - public SurfaceRuleBuilder surface() { - return super - .surface() - .ceil(Blocks.END_STONE.defaultBlockState()) - .rule(4, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), - SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()) - )); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/FoggyMushroomlandBiome.java b/src/main/java/ru/betterend/world/biome/land/FoggyMushroomlandBiome.java deleted file mode 100644 index fdf860c5..00000000 --- a/src/main/java/ru/betterend/world/biome/land/FoggyMushroomlandBiome.java +++ /dev/null @@ -1,70 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class FoggyMushroomlandBiome extends EndBiome.Config { - public FoggyMushroomlandBiome() { - super("foggy_mushroomland"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .structure(EndStructures.GIANT_MOSSY_GLOWSHROOM) - .plantsColor(73, 210, 209) - .fogColor(41, 122, 173) - .fogDensity(3) - .waterAndFogColor(119, 227, 250) - .particles(EndParticles.GLOWING_SPHERE, 0.001F) - .loop(EndSounds.AMBIENT_FOGGY_MUSHROOMLAND) - .music(EndSounds.MUSIC_FOREST) - .feature(EndFeatures.END_LAKE) - .feature(EndFeatures.MOSSY_GLOWSHROOM) - .feature(EndFeatures.BLUE_VINE) - .feature(EndFeatures.UMBRELLA_MOSS) - .feature(EndFeatures.CREEPING_MOSS) - .feature(EndFeatures.DENSE_VINE) - //.feature(EndFeatures.PEARLBERRY) - .feature(EndFeatures.CYAN_MOSS) - .feature(EndFeatures.CYAN_MOSS_WOOD) - .feature(EndFeatures.END_LILY) - .feature(EndFeatures.BUBBLE_CORAL) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_LIGHT_BLUE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EndEntities.DRAGONFLY, 80, 2, 5) - .spawn(EndEntities.END_FISH, 20, 2, 5) - .spawn(EndEntities.CUBOZOA, 10, 3, 8) - .spawn(EndEntities.END_SLIME, 10, 1, 2) - .spawn(EntityType.ENDERMAN, 10, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.END_MOSS.defaultBlockState(); - } - - @Override - public BlockState getAltTopMaterial() { - return EndBlocks.END_MYCELIUM.defaultBlockState(); - } - }; - - - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/GlowingGrasslandsBiome.java b/src/main/java/ru/betterend/world/biome/land/GlowingGrasslandsBiome.java deleted file mode 100644 index 1cc8aa2c..00000000 --- a/src/main/java/ru/betterend/world/biome/land/GlowingGrasslandsBiome.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class GlowingGrasslandsBiome extends EndBiome.Config { - public GlowingGrasslandsBiome() { - super("glowing_grasslands"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(99, 228, 247) - .fogDensity(1.3F) - .particles(EndParticles.FIREFLY, 0.001F) - .music(EndSounds.MUSIC_OPENSPACE) - .loop(EndSounds.AMBIENT_GLOWING_GRASSLANDS) - .waterAndFogColor(92, 250, 230) - .plantsColor(73, 210, 209) - .feature(EndFeatures.END_LAKE_RARE) - .feature(EndFeatures.LUMECORN) - .feature(EndFeatures.BLOOMING_COOKSONIA) - .feature(EndFeatures.SALTEAGO) - .feature(EndFeatures.VAIOLUSH_FERN) - .feature(EndFeatures.FRACTURN) - .feature(EndFeatures.UMBRELLA_MOSS_RARE) - .feature(EndFeatures.CREEPING_MOSS_RARE) - .feature(EndFeatures.TWISTED_UMBRELLA_MOSS_RARE) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_GREEN) - .feature(EndFeatures.CHARNIA_LIGHT_BLUE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.END_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/LanternWoodsBiome.java b/src/main/java/ru/betterend/world/biome/land/LanternWoodsBiome.java deleted file mode 100644 index 9a55a60d..00000000 --- a/src/main/java/ru/betterend/world/biome/land/LanternWoodsBiome.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class LanternWoodsBiome extends EndBiome.Config { - public LanternWoodsBiome() { - super("lantern_woods"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(189, 82, 70) - .fogDensity(1.1F) - .waterAndFogColor(171, 234, 226) - .plantsColor(254, 85, 57) - .music(EndSounds.MUSIC_FOREST) - .particles(EndParticles.GLOWING_SPHERE, 0.001F) - .feature(EndFeatures.END_LAKE_NORMAL) - .feature(EndFeatures.FLAMAEA) - .feature(EndFeatures.LUCERNIA) - .feature(EndFeatures.LUCERNIA_BUSH) - .feature(EndFeatures.FILALUX) - .feature(EndFeatures.AERIDIUM) - .feature(EndFeatures.LAMELLARIUM) - .feature(EndFeatures.BOLUX_MUSHROOM) - .feature(EndFeatures.AURANT_POLYPORE) - .feature(EndFeatures.POND_ANEMONE) - .feature(EndFeatures.CHARNIA_ORANGE) - .feature(EndFeatures.CHARNIA_RED) - .feature(EndFeatures.RUSCUS) - .feature(EndFeatures.RUSCUS_WOOD) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.RUTISCUS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/MegalakeBiome.java b/src/main/java/ru/betterend/world/biome/land/MegalakeBiome.java deleted file mode 100644 index dc8b85fc..00000000 --- a/src/main/java/ru/betterend/world/biome/land/MegalakeBiome.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class MegalakeBiome extends EndBiome.Config { - public MegalakeBiome() { - super("megalake"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .structure(EndStructures.MEGALAKE) - .plantsColor(73, 210, 209) - .fogColor(178, 209, 248) - .waterAndFogColor(96, 163, 255) - .fogDensity(1.75F) - .music(EndSounds.MUSIC_WATER) - .loop(EndSounds.AMBIENT_MEGALAKE) - .terrainHeight(0F) - .feature(EndFeatures.END_LOTUS) - .feature(EndFeatures.END_LOTUS_LEAF) - .feature(EndFeatures.BUBBLE_CORAL_RARE) - .feature(EndFeatures.END_LILY_RARE) - .feature(EndFeatures.UMBRELLA_MOSS) - .feature(EndFeatures.CREEPING_MOSS) - //.feature(EndFeatures.PEARLBERRY) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_LIGHT_BLUE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .feature(EndFeatures.MENGER_SPONGE) - .spawn(EndEntities.DRAGONFLY, 50, 1, 3) - .spawn(EndEntities.END_FISH, 50, 3, 8) - .spawn(EndEntities.CUBOZOA, 50, 3, 8) - .spawn(EndEntities.END_SLIME, 5, 1, 2) - .spawn(EntityType.ENDERMAN, 10, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.END_MOSS.defaultBlockState(); - } - - @Override - public BlockState getAltTopMaterial() { - return EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/MegalakeGroveBiome.java b/src/main/java/ru/betterend/world/biome/land/MegalakeGroveBiome.java deleted file mode 100644 index fbd6b820..00000000 --- a/src/main/java/ru/betterend/world/biome/land/MegalakeGroveBiome.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class MegalakeGroveBiome extends EndBiome.Config { - public MegalakeGroveBiome() { - super("megalake_grove"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .structure(EndStructures.MEGALAKE_SMALL) - .plantsColor(73, 210, 209) - .fogColor(178, 209, 248) - .waterAndFogColor(96, 163, 255) - .fogDensity(2.0F) - .particles(EndParticles.GLOWING_SPHERE, 0.001F) - .music(EndSounds.MUSIC_WATER) - .loop(EndSounds.AMBIENT_MEGALAKE_GROVE) - .terrainHeight(0F) - .feature(EndFeatures.LACUGROVE) - .feature(EndFeatures.END_LOTUS) - .feature(EndFeatures.END_LOTUS_LEAF) - .feature(EndFeatures.BUBBLE_CORAL_RARE) - .feature(EndFeatures.END_LILY_RARE) - .feature(EndFeatures.UMBRELLA_MOSS) - //.feature(EndFeatures.PEARLBERRY) - .feature(EndFeatures.CREEPING_MOSS) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_LIGHT_BLUE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .feature(EndFeatures.MENGER_SPONGE) - .spawn(EndEntities.DRAGONFLY, 20, 1, 3) - .spawn(EndEntities.END_FISH, 20, 3, 8) - .spawn(EndEntities.CUBOZOA, 50, 3, 8) - .spawn(EndEntities.END_SLIME, 5, 1, 2) - .spawn(EntityType.ENDERMAN, 10, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.END_MOSS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/NeonOasisBiome.java b/src/main/java/ru/betterend/world/biome/land/NeonOasisBiome.java deleted file mode 100644 index fa00a357..00000000 --- a/src/main/java/ru/betterend/world/biome/land/NeonOasisBiome.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SurfaceRules; -import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; -import net.minecraft.world.level.levelgen.placement.CaveSurface; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.surface.SurfaceRuleBuilder; -import ru.bclib.api.surface.rules.SwitchRuleSource; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.surface.SplitNoiseCondition; - -import java.util.List; - -public class NeonOasisBiome extends EndBiome.Config { - public NeonOasisBiome() { - super("neon_oasis"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .genChance(0.5F) - .fogColor(226, 239, 168) - .fogDensity(2) - .waterAndFogColor(106, 238, 215) - .particles(ParticleTypes.WHITE_ASH, 0.01F) - .loop(EndSounds.AMBIENT_DUST_WASTELANDS) - .music(EndSounds.MUSIC_OPENSPACE) - .feature(EndFeatures.DESERT_LAKE) - .feature(EndFeatures.NEON_CACTUS) - .feature(EndFeatures.UMBRELLA_MOSS) - .feature(EndFeatures.CREEPING_MOSS) - .feature(EndFeatures.CHARNIA_GREEN) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_RED) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - - @Override - public BlockState getAltTopMaterial() { - return EndBlocks.END_MOSS.defaultBlockState(); - } - - @Override - public SurfaceRuleBuilder surface() { - RuleSource surfaceBlockRule = new SwitchRuleSource( - new SplitNoiseCondition(), - List.of( - SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()), - SurfaceRules.state(EndBlocks.END_MOSS.defaultBlockState()) - ) - ); - return super - .surface() - .ceil(Blocks.END_STONE.defaultBlockState()) - .rule(1, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, surfaceBlockRule)) - .rule(4, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), - SurfaceRules.state(EndBlocks.ENDSTONE_DUST.defaultBlockState()) - )); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/PaintedMountainsBiome.java b/src/main/java/ru/betterend/world/biome/land/PaintedMountainsBiome.java deleted file mode 100644 index c8ae2f8d..00000000 --- a/src/main/java/ru/betterend/world/biome/land/PaintedMountainsBiome.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndSounds; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -public class PaintedMountainsBiome extends EndBiome.Config { - public PaintedMountainsBiome() { - super("painted_mountains"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .structure(EndStructures.PAINTED_MOUNTAIN) - .fogColor(226, 239, 168) - .fogDensity(2) - .waterAndFogColor(192, 180, 131) - .music(EndSounds.MUSIC_OPENSPACE) - .loop(EndSounds.AMBIENT_DUST_WASTELANDS) - .particles(ParticleTypes.WHITE_ASH, 0.01F) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/ShadowForestBiome.java b/src/main/java/ru/betterend/world/biome/land/ShadowForestBiome.java deleted file mode 100644 index f8792f1d..00000000 --- a/src/main/java/ru/betterend/world/biome/land/ShadowForestBiome.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class ShadowForestBiome extends EndBiome.Config { - public ShadowForestBiome() { - super("shadow_forest"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(0, 0, 0) - .fogDensity(2.5F) - .plantsColor(45, 45, 45) - .waterAndFogColor(42, 45, 80) - .particles(ParticleTypes.MYCELIUM, 0.01F) - .loop(EndSounds.AMBIENT_CHORUS_FOREST) - .music(EndSounds.MUSIC_DARK) - .feature(EndFeatures.VIOLECITE_LAYER) - .feature(EndFeatures.END_LAKE_RARE) - .feature(EndFeatures.DRAGON_TREE) - .feature(EndFeatures.DRAGON_TREE_BUSH) - .feature(EndFeatures.SHADOW_PLANT) - .feature(EndFeatures.MURKWEED) - .feature(EndFeatures.NEEDLEGRASS) - .feature(EndFeatures.SHADOW_BERRY) - .feature(EndFeatures.TWISTED_VINE) - .feature(EndFeatures.PURPLE_POLYPORE) - .feature(EndFeatures.TAIL_MOSS) - .feature(EndFeatures.TAIL_MOSS_WOOD) - .feature(EndFeatures.CHARNIA_PURPLE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EndEntities.SHADOW_WALKER, 80, 2, 4) - .spawn(EntityType.ENDERMAN, 40, 1, 4) - .spawn(EntityType.PHANTOM, 1, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.SHADOW_GRASS.defaultBlockState(); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/SulphurSpringsBiome.java b/src/main/java/ru/betterend/world/biome/land/SulphurSpringsBiome.java deleted file mode 100644 index 07b51b8b..00000000 --- a/src/main/java/ru/betterend/world/biome/land/SulphurSpringsBiome.java +++ /dev/null @@ -1,93 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SurfaceRules; -import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; -import net.minecraft.world.level.levelgen.placement.CaveSurface; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.surface.SurfaceRuleBuilder; -import ru.bclib.api.surface.rules.SwitchRuleSource; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndEntities; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.surface.SulphuricSurfaceNoiseCondition; - -import java.util.List; - -public class SulphurSpringsBiome extends EndBiome.Config { - public SulphurSpringsBiome() { - super("sulphur_springs"); - } - - @Override - protected boolean hasCaves() { - return false; - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .music(EndSounds.MUSIC_OPENSPACE) - .loop(EndSounds.AMBIENT_SULPHUR_SPRINGS) - .waterColor(25, 90, 157) - .waterFogColor(30, 65, 61) - .fogColor(207, 194, 62) - .fogDensity(1.5F) - .terrainHeight(0F) - .particles(EndParticles.SULPHUR_PARTICLE, 0.001F) - .feature(EndFeatures.GEYSER) - .feature(EndFeatures.SURFACE_VENT) - .feature(EndFeatures.SULPHURIC_LAKE) - .feature(EndFeatures.SULPHURIC_CAVE) - .feature(EndFeatures.HYDRALUX) - .feature(EndFeatures.CHARNIA_GREEN) - .feature(EndFeatures.CHARNIA_ORANGE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .spawn(EndEntities.END_FISH, 50, 3, 8) - .spawn(EndEntities.CUBOZOA, 50, 3, 8) - .spawn(EntityType.ENDERMAN, 50, 1, 4); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.FLAVOLITE.stone.defaultBlockState(); - } - - @Override - public BlockState getAltTopMaterial() { - return Blocks.END_STONE.defaultBlockState(); - } - - @Override - public boolean generateFloorRule() { - return false; - } - - @Override - public SurfaceRuleBuilder surface() { - RuleSource surfaceBlockRule = new SwitchRuleSource( - new SulphuricSurfaceNoiseCondition(), - List.of( - SurfaceRules.state(surfaceMaterial().getAltTopMaterial()), - SurfaceRules.state(surfaceMaterial().getTopMaterial()), - SULPHURIC_ROCK, - BRIMSTONE - ) - ); - return super - .surface() - .rule(2, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, surfaceBlockRule)) - .rule(2, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(5, false, CaveSurface.FLOOR), surfaceBlockRule)); - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/UmbraValleyBiome.java b/src/main/java/ru/betterend/world/biome/land/UmbraValleyBiome.java deleted file mode 100644 index 5e75208d..00000000 --- a/src/main/java/ru/betterend/world/biome/land/UmbraValleyBiome.java +++ /dev/null @@ -1,92 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SurfaceRules; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.api.surface.SurfaceRuleBuilder; -import ru.bclib.api.surface.rules.SwitchRuleSource; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.surface.UmbraSurfaceNoiseCondition; - -import java.util.List; - -public class UmbraValleyBiome extends EndBiome.Config { - private static final Block[] SURFACE_BLOCKS = new Block[] { - EndBlocks.PALLIDIUM_FULL, - EndBlocks.PALLIDIUM_HEAVY, - EndBlocks.PALLIDIUM_THIN, - EndBlocks.PALLIDIUM_TINY, - EndBlocks.UMBRALITH.stone - }; - - public UmbraValleyBiome() { - super("umbra_valley"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(100, 100, 100) - .plantsColor(172, 189, 190) - .waterAndFogColor(69, 104, 134) - .particles(EndParticles.AMBER_SPHERE, 0.0001F) - .loop(EndSounds.UMBRA_VALLEY) - .music(EndSounds.MUSIC_DARK) - .feature(EndFeatures.UMBRALITH_ARCH) - .feature(EndFeatures.THIN_UMBRALITH_ARCH) - .feature(EndFeatures.INFLEXIA) - .feature(EndFeatures.FLAMMALIX); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.UMBRALITH.stone.defaultBlockState(); - } - - @Override - public BlockState getUnderMaterial() { - return EndBlocks.UMBRALITH.stone.defaultBlockState(); - } - - @Override - public BlockState getAltTopMaterial() { - return EndBlocks.PALLIDIUM_FULL.defaultBlockState(); - } - - @Override - public boolean generateFloorRule() { - return false; - } - - @Override - public SurfaceRuleBuilder surface() { - return super.surface() - .rule(2, SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, - new SwitchRuleSource( - new UmbraSurfaceNoiseCondition(), - List.of( - SurfaceRules.state(surfaceMaterial().getAltTopMaterial()), - PALLIDIUM_HEAVY, - PALLIDIUM_THIN, - PALLIDIUM_TINY, - SurfaceRules.state(surfaceMaterial().getTopMaterial()) - ) - ) - )); - } - }; - } - - public static Block getSurface(int x, int z) { - return SURFACE_BLOCKS[UmbraSurfaceNoiseCondition.getDepth(x, z)]; - } -} diff --git a/src/main/java/ru/betterend/world/biome/land/UmbrellaJungleBiome.java b/src/main/java/ru/betterend/world/biome/land/UmbrellaJungleBiome.java deleted file mode 100644 index 5460ab63..00000000 --- a/src/main/java/ru/betterend/world/biome/land/UmbrellaJungleBiome.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.betterend.world.biome.land; - -import net.minecraft.tags.BiomeTags; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.api.biomes.BCLBiomeBuilder; -import ru.bclib.interfaces.SurfaceMaterialProvider; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.registry.EndParticles; -import ru.betterend.registry.EndSounds; -import ru.betterend.world.biome.EndBiome; - -public class UmbrellaJungleBiome extends EndBiome.Config { - public UmbrellaJungleBiome() { - super("umbrella_jungle"); - } - - @Override - protected void addCustomBuildData(BCLBiomeBuilder builder) { - builder - .fogColor(87, 223, 221) - .waterAndFogColor(119, 198, 253) - .foliageColor(27, 183, 194) - .fogDensity(2.3F) - .particles(EndParticles.JUNGLE_SPORE, 0.001F) - .music(EndSounds.MUSIC_FOREST) - .loop(EndSounds.AMBIENT_UMBRELLA_JUNGLE) - .feature(EndFeatures.END_LAKE) - .feature(EndFeatures.UMBRELLA_TREE) - .feature(EndFeatures.JELLYSHROOM) - .feature(EndFeatures.TWISTED_UMBRELLA_MOSS) - .feature(EndFeatures.SMALL_JELLYSHROOM_FLOOR) - .feature(EndFeatures.JUNGLE_GRASS) - .feature(EndFeatures.CYAN_MOSS) - .feature(EndFeatures.CYAN_MOSS_WOOD) - .feature(EndFeatures.JUNGLE_FERN_WOOD) - .feature(EndFeatures.SMALL_JELLYSHROOM_WALL) - .feature(EndFeatures.SMALL_JELLYSHROOM_WOOD) - .feature(EndFeatures.SMALL_JELLYSHROOM_CEIL) - .feature(EndFeatures.JUNGLE_VINE) - .feature(EndFeatures.CHARNIA_CYAN) - .feature(EndFeatures.CHARNIA_GREEN) - .feature(EndFeatures.CHARNIA_LIGHT_BLUE) - .feature(EndFeatures.CHARNIA_RED_RARE) - .structure(BiomeTags.HAS_END_CITY) - .spawn(EntityType.ENDERMAN, 50, 1, 2); - } - - @Override - protected SurfaceMaterialProvider surfaceMaterial() { - return new EndBiome.DefaultSurfaceMaterialProvider() { - @Override - public BlockState getTopMaterial() { - return EndBlocks.JUNGLE_MOSS.defaultBlockState(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java b/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java deleted file mode 100644 index 66cddb25..00000000 --- a/src/main/java/ru/betterend/world/features/BiomeIslandFeature.java +++ /dev/null @@ -1,73 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.world.biome.EndBiome; - -public class BiomeIslandFeature extends DefaultFeature { - private static final MutableBlockPos CENTER = new MutableBlockPos(); - private static final SDF ISLAND; - - private static OpenSimplexNoise simplexNoise = new OpenSimplexNoise(412L); - private static BlockState topBlock = Blocks.GRASS_BLOCK.defaultBlockState(); - private static BlockState underBlock = Blocks.DIRT.defaultBlockState(); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - //Holder biome = world.getBiome(pos); - int dist = BlocksHelper.downRay(world, pos, 10) + 1; - BlockPos surfacePos = new BlockPos(pos.getX(), pos.getY()-dist, pos.getZ()); - BlockState topMaterial = EndBiome.findTopMaterial(world, surfacePos);; - - if (BlocksHelper.isFluid(topMaterial)) { - topBlock = Blocks.GRAVEL.defaultBlockState(); - underBlock = Blocks.STONE.defaultBlockState(); - } - else { - underBlock = EndBiome.findUnderMaterial(world, surfacePos); - } - - simplexNoise = new OpenSimplexNoise(world.getSeed()); - CENTER.set(pos); - ISLAND.fillRecursive(world, pos.below()); - return true; - } - - private static SDF createSDFIsland() { - SDF sdfCone = new SDFCappedCone().setRadius1(0).setRadius2(6).setHeight(4).setBlock(pos -> { - if (pos.getY() > CENTER.getY()) return AIR; - if (pos.getY() == CENTER.getY()) return topBlock; - return underBlock; - }); - sdfCone = new SDFTranslate().setTranslate(0, -2, 0).setSource(sdfCone); - sdfCone = new SDFDisplacement().setFunction(pos -> { - float deltaX = Math.abs(pos.x()); - float deltaY = Math.abs(pos.y()); - float deltaZ = Math.abs(pos.z()); - if (deltaY < 2.0f && (deltaX < 3.0f || deltaZ < 3.0F)) return 0.0f; - return (float) simplexNoise.eval(CENTER.getX() + pos.x(), CENTER.getY() + pos.y(), CENTER.getZ() + pos.z()); - }) - .setSource(sdfCone) - .setReplaceFunction(state -> BlocksHelper.isFluid(state) || state.getMaterial() - .isReplaceable()); - return sdfCone; - } - - static { - ISLAND = createSDFIsland(); - } -} diff --git a/src/main/java/ru/betterend/world/features/BlueVineFeature.java b/src/main/java/ru/betterend/world/features/BlueVineFeature.java deleted file mode 100644 index 68d6de1c..00000000 --- a/src/main/java/ru/betterend/world/features/BlueVineFeature.java +++ /dev/null @@ -1,45 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BlueVineFeature extends ScatterFeature { - private boolean small; - - public BlueVineFeature() { - super(5); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - float d = MHelper.length( - center.getX() - blockPos.getX(), - center.getZ() - blockPos.getZ() - ) / radius * 0.6F + random.nextFloat() * 0.4F; - small = d > 0.5F; - return EndBlocks.BLUE_VINE_SEED.canSurvive(AIR, world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - if (small) { - BlocksHelper.setWithoutUpdate( - world, - blockPos, - EndBlocks.BLUE_VINE_SEED.defaultBlockState().setValue(EndPlantWithAgeBlock.AGE, random.nextInt(4)) - ); - } - else { - EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.BLUE_VINE_SEED); - seed.growAdult(world, random, blockPos); - } - } -} diff --git a/src/main/java/ru/betterend/world/features/BuildingListFeature.java b/src/main/java/ru/betterend/world/features/BuildingListFeature.java deleted file mode 100644 index 9f2bfb66..00000000 --- a/src/main/java/ru/betterend/world/features/BuildingListFeature.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.ChestBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import org.jetbrains.annotations.Nullable; -import ru.bclib.world.features.ListFeature; -import ru.betterend.util.LootTableUtil; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BuildingListFeature extends ListFeature { - public BuildingListFeature(List list, BlockState defaultBlock) { - super(list, defaultBlock); - } - - @Override - protected void addStructureData(StructurePlaceSettings data) { - super.addStructureData(data); - data.addProcessor(new ChestProcessor()); - } - - class ChestProcessor extends StructureProcessor { - @Nullable - @Override - public StructureTemplate.StructureBlockInfo processBlock(LevelReader levelReader, BlockPos blockPos, BlockPos blockPos2, StructureBlockInfo structureBlockInfo, StructureBlockInfo structureBlockInfo2, StructurePlaceSettings structurePlaceSettings) { - BlockState blockState = structureBlockInfo2.state; - if (blockState.getBlock() instanceof ChestBlock) { - RandomSource random = structurePlaceSettings.getRandom(structureBlockInfo2.pos); - BlockPos chestPos = structureBlockInfo2.pos; - ChestBlock chestBlock = ChestBlock.class.cast(blockState.getBlock()); - BlockEntity entity = chestBlock.newBlockEntity(chestPos, blockState); - levelReader.getChunk(chestPos).setBlockEntity(entity); - RandomizableContainerBlockEntity chestEntity = RandomizableContainerBlockEntity.class.cast(entity); - Holder biome = levelReader.getNoiseBiome( - chestPos.getX() >> 2, - chestPos.getY() >> 2, - chestPos.getZ() >> 2 - ); - chestEntity.setLootTable(LootTableUtil.getTable(biome), random.nextLong()); - chestEntity.setChanged(); - } - return structureBlockInfo2; - } - - @Override - protected StructureProcessorType getType() { - return StructureProcessorType.NOP; - } - } -} diff --git a/src/main/java/ru/betterend/world/features/CavePumpkinFeature.java b/src/main/java/ru/betterend/world/features/CavePumpkinFeature.java deleted file mode 100644 index 40afc49f..00000000 --- a/src/main/java/ru/betterend/world/features/CavePumpkinFeature.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.EndBlockProperties; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class CavePumpkinFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.above()).is(CommonBlockTags.GEN_END_STONES) || !world.isEmptyBlock(pos) || !world.isEmptyBlock( - pos.below())) { - return false; - } - - int age = random.nextInt(4); - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.CAVE_PUMPKIN_SEED.defaultBlockState().setValue(EndBlockProperties.AGE, age) - ); - if (age > 1) { - BlocksHelper.setWithoutUpdate( - world, - pos.below(), - EndBlocks.CAVE_PUMPKIN.defaultBlockState().setValue(EndBlockProperties.SMALL, age < 3) - ); - } - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/CharniaFeature.java b/src/main/java/ru/betterend/world/features/CharniaFeature.java deleted file mode 100644 index c8022a39..00000000 --- a/src/main/java/ru/betterend/world/features/CharniaFeature.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.world.level.block.Block; - -public class CharniaFeature extends UnderwaterPlantFeature { - public CharniaFeature(Block plant) { - super(plant, 6); - } - - @Override - protected int getChance() { - return 3; - } -} diff --git a/src/main/java/ru/betterend/world/features/CrashedShipFeature.java b/src/main/java/ru/betterend/world/features/CrashedShipFeature.java deleted file mode 100644 index 8900e619..00000000 --- a/src/main/java/ru/betterend/world/features/CrashedShipFeature.java +++ /dev/null @@ -1,149 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -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.StructureProcessor; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.MHelper; -import ru.bclib.util.StructureHelper; -import ru.bclib.world.features.NBTFeature; -import ru.betterend.util.BlockFixer; -import ru.betterend.util.StructureErode; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class CrashedShipFeature extends NBTFeature { - private static final StructureProcessor REPLACER; - private static final String STRUCTURE_PATH = "/data/minecraft/structures/end_city/ship.nbt"; - private StructureTemplate structure; - - public CrashedShipFeature() { - super(EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); - } - - @Override - protected StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, RandomSource random) { - if (structure == null) { - structure = world.getLevel().getStructureManager().getOrCreate(new ResourceLocation("end_city/ship")); - if (structure == null) { - structure = StructureHelper.readStructure(STRUCTURE_PATH); - } - } - return structure; - } - - @Override - protected boolean canSpawn(WorldGenLevel world, BlockPos pos, RandomSource random) { - long x = pos.getX() >> 4; - long z = pos.getX() >> 4; - if (x * x + z * z < 3600) { - return false; - } - return pos.getY() > 5 && world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES); - } - - @Override - protected Rotation getRotation(WorldGenLevel world, BlockPos pos, RandomSource random) { - return Rotation.getRandom(random); - } - - @Override - protected Mirror getMirror(WorldGenLevel world, BlockPos pos, RandomSource random) { - return Mirror.values()[random.nextInt(3)]; - } - - @Override - protected int getYOffset(StructureTemplate structure, WorldGenLevel world, BlockPos pos, RandomSource random) { - int min = structure.getSize().getY() >> 3; - int max = structure.getSize().getY() >> 2; - return -MHelper.randRange(min, max, random); - } - - @Override - protected TerrainMerge getTerrainMerge(WorldGenLevel world, BlockPos pos, RandomSource random) { - return TerrainMerge.NONE; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - center = new BlockPos(((center.getX() >> 4) << 4) | 8, 128, ((center.getZ() >> 4) << 4) | 8); - center = getGround(world, center); - BoundingBox bounds = makeBox(center); - - if (!canSpawn(world, center, random)) { - return false; - } - - StructureTemplate structure = getStructure(world, center, random); - Rotation rotation = getRotation(world, center, random); - Mirror mirror = getMirror(world, center, random); - BlockPos offset = StructureTemplate.transform( - new BlockPos(structure.getSize()), - mirror, - rotation, - BlockPos.ZERO - ); - center = center.offset(0, getYOffset(structure, world, center, random) + 0.5, 0); - StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror); - center = center.offset(-offset.getX() * 0.5, 0, -offset.getZ() * 0.5); - - BoundingBox structB = structure.getBoundingBox(placementData, center); - bounds = StructureHelper.intersectBoxes(bounds, structB); - - addStructureData(placementData); - structure.placeInWorld(world, center, center, placementData.setBoundingBox(bounds), random, 2); - - StructureErode.erodeIntense(world, bounds, random); - BlockFixer.fixBlocks( - world, - new BlockPos(bounds.minX(), bounds.minY(), bounds.minZ()), - new BlockPos(bounds.maxX(), bounds.maxY(), bounds.maxZ()) - ); - - return true; - } - - @Override - protected void addStructureData(StructurePlaceSettings data) { - data.addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(REPLACER).setIgnoreEntities(true); - } - - static { - REPLACER = new StructureProcessor() { - @Override - public StructureBlockInfo processBlock(LevelReader worldView, BlockPos pos, BlockPos blockPos, StructureBlockInfo structureBlockInfo, StructureBlockInfo structureBlockInfo2, StructurePlaceSettings structurePlacementData) { - BlockState state = structureBlockInfo2.state; - if (state.is(Blocks.SPAWNER) || state.getMaterial().equals(Material.WOOL)) { - return new StructureBlockInfo(structureBlockInfo2.pos, AIR, null); - } - return structureBlockInfo2; - } - - @Override - protected StructureProcessorType getType() { - return StructureProcessorType.NOP; - } - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/DoublePlantFeature.java b/src/main/java/ru/betterend/world/features/DoublePlantFeature.java deleted file mode 100644 index 92d784bf..00000000 --- a/src/main/java/ru/betterend/world/features/DoublePlantFeature.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class DoublePlantFeature extends ScatterFeature { - private final Block smallPlant; - private final Block largePlant; - private Block plant; - - public DoublePlantFeature(Block smallPlant, Block largePlant, int radius) { - super(radius); - this.smallPlant = smallPlant; - this.largePlant = largePlant; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - float d = MHelper.length( - center.getX() - blockPos.getX(), - center.getZ() - blockPos.getZ() - ) / radius * 0.6F + random.nextFloat() * 0.4F; - plant = d < 0.5F ? largePlant : smallPlant; - return plant.canSurvive(plant.defaultBlockState(), world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - if (plant instanceof BaseDoublePlantBlock) { - int rot = random.nextInt(4); - BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); - BlocksHelper.setWithoutUpdate(world, blockPos, state); - BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); - } - else { - BlocksHelper.setWithoutUpdate(world, blockPos, plant); - } - } -} diff --git a/src/main/java/ru/betterend/world/features/EndLilyFeature.java b/src/main/java/ru/betterend/world/features/EndLilyFeature.java deleted file mode 100644 index 9ca11d6a..00000000 --- a/src/main/java/ru/betterend/world/features/EndLilyFeature.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.betterend.blocks.EndLilySeedBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLilyFeature extends UnderwaterPlantScatter { - public EndLilyFeature(int radius) { - super(radius); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - EndLilySeedBlock seed = (EndLilySeedBlock) EndBlocks.END_LILY_SEED; - seed.grow(world, random, blockPos); - } - - @Override - protected int getChance() { - return 15; - } -} diff --git a/src/main/java/ru/betterend/world/features/EndLotusFeature.java b/src/main/java/ru/betterend/world/features/EndLotusFeature.java deleted file mode 100644 index 89cf23fe..00000000 --- a/src/main/java/ru/betterend/world/features/EndLotusFeature.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.betterend.blocks.EndLotusSeedBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLotusFeature extends UnderwaterPlantScatter { - public EndLotusFeature(int radius) { - super(radius); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - EndLotusSeedBlock seed = (EndLotusSeedBlock) EndBlocks.END_LOTUS_SEED; - seed.grow(world, random, blockPos); - } - - @Override - protected int getChance() { - return 15; - } -} diff --git a/src/main/java/ru/betterend/world/features/EndLotusLeafFeature.java b/src/main/java/ru/betterend/world/features/EndLotusLeafFeature.java deleted file mode 100644 index 75c18daa..00000000 --- a/src/main/java/ru/betterend/world/features/EndLotusLeafFeature.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.EndLotusLeafBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLotusLeafFeature extends ScatterFeature { - public EndLotusLeafFeature(int radius) { - super(radius); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - if (canGenerate(world, blockPos)) { - generateLeaf(world, blockPos); - } - } - - @Override - protected int getChance() { - return 15; - } - - @Override - protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { - return getPosOnSurface(world, pos); - } - - private void generateLeaf(WorldGenLevel world, BlockPos pos) { - MutableBlockPos p = new MutableBlockPos(); - BlockState leaf = EndBlocks.END_LOTUS_LEAF.defaultBlockState(); - BlocksHelper.setWithoutUpdate(world, pos, leaf.setValue(EndLotusLeafBlock.SHAPE, TripleShape.BOTTOM)); - for (Direction move : BlocksHelper.HORIZONTAL) { - BlocksHelper.setWithoutUpdate( - world, - p.set(pos).move(move), - leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, move) - .setValue(EndLotusLeafBlock.SHAPE, TripleShape.MIDDLE) - ); - } - for (int i = 0; i < 4; i++) { - Direction d1 = BlocksHelper.HORIZONTAL[i]; - Direction d2 = BlocksHelper.HORIZONTAL[(i + 1) & 3]; - BlocksHelper.setWithoutUpdate( - world, - p.set(pos).move(d1).move(d2), - leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, d1) - .setValue(EndLotusLeafBlock.SHAPE, TripleShape.TOP) - ); - } - } - - private boolean canGenerate(WorldGenLevel world, BlockPos pos) { - MutableBlockPos p = new MutableBlockPos(); - p.setY(pos.getY()); - int count = 0; - for (int x = -1; x < 2; x++) { - p.setX(pos.getX() + x); - for (int z = -1; z < 2; z++) { - p.setZ(pos.getZ() + z); - if (world.isEmptyBlock(p) && world.getBlockState(p.below()).is(Blocks.WATER)) count++; - } - } - return count == 9; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return world.isEmptyBlock(blockPos) && world.getBlockState(blockPos.below()).is(Blocks.WATER); - } -} diff --git a/src/main/java/ru/betterend/world/features/FilaluxFeature.java b/src/main/java/ru/betterend/world/features/FilaluxFeature.java deleted file mode 100644 index 23891764..00000000 --- a/src/main/java/ru/betterend/world/features/FilaluxFeature.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class FilaluxFeature extends SkyScatterFeature { - public FilaluxFeature() { - super(10); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - BlockState vine = EndBlocks.FILALUX.defaultBlockState(); - BlockState wings = EndBlocks.FILALUX_WINGS.defaultBlockState(); - BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.FILALUX_LANTERN); - BlocksHelper.setWithoutUpdate( - world, - blockPos.above(), - wings.setValue(BlockStateProperties.FACING, Direction.UP) - ); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlocksHelper.setWithoutUpdate( - world, - blockPos.relative(dir), - wings.setValue(BlockStateProperties.FACING, dir) - ); - } - int length = MHelper.randRange(1, 3, random); - for (int i = 1; i <= length; i++) { - TripleShape shape = length > 1 ? TripleShape.TOP : TripleShape.BOTTOM; - if (i > 1) { - shape = i == length ? TripleShape.BOTTOM : TripleShape.MIDDLE; - } - BlocksHelper.setWithoutUpdate(world, blockPos.below(i), vine.setValue(BlockProperties.TRIPLE_SHAPE, shape)); - } - } -} diff --git a/src/main/java/ru/betterend/world/features/FullHeightScatterFeature.java b/src/main/java/ru/betterend/world/features/FullHeightScatterFeature.java deleted file mode 100644 index cca7f4cc..00000000 --- a/src/main/java/ru/betterend/world/features/FullHeightScatterFeature.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class FullHeightScatterFeature extends DefaultFeature { - private final int radius; - - public FullHeightScatterFeature(int radius) { - this.radius = radius; - } - - public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius); - - public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - final RandomSource random = featureConfig.random(); - final BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, center.getX(), center.getZ()); - int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); - for (int y = maxY; y > minY; y--) { - POS.set(center.getX(), y, center.getZ()); - if (world.getBlockState(POS).isAir() && !world.getBlockState(POS.below()).isAir()) { - float r = MHelper.randRange(radius * 0.5F, radius, random); - int count = MHelper.floor(r * r * MHelper.randRange(1.5F, 3F, random)); - for (int i = 0; i < count; i++) { - float pr = r * (float) Math.sqrt(random.nextFloat()); - float theta = random.nextFloat() * MHelper.PI2; - float x = pr * (float) Math.cos(theta); - float z = pr * (float) Math.sin(theta); - - POS.set(center.getX() + x, y + 5, center.getZ() + z); - int down = BlocksHelper.downRay(world, POS, 16); - if (down > 10) continue; - POS.setY(POS.getY() - down); - - if (canGenerate(world, random, center, POS, r)) { - generate(world, random, POS); - } - } - } - } - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/GlowPillarFeature.java b/src/main/java/ru/betterend/world/features/GlowPillarFeature.java deleted file mode 100644 index 7570c0fa..00000000 --- a/src/main/java/ru/betterend/world/features/GlowPillarFeature.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class GlowPillarFeature extends ScatterFeature { - public GlowPillarFeature() { - super(9); - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return EndBlocks.GLOWING_PILLAR_SEED.canSurvive(AIR, world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.GLOWING_PILLAR_SEED); - seed.growAdult(world, random, blockPos); - } - - @Override - protected int getChance() { - return 10; - } -} diff --git a/src/main/java/ru/betterend/world/features/HydraluxFeature.java b/src/main/java/ru/betterend/world/features/HydraluxFeature.java deleted file mode 100644 index c9b47619..00000000 --- a/src/main/java/ru/betterend/world/features/HydraluxFeature.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.betterend.blocks.HydraluxSaplingBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class HydraluxFeature extends UnderwaterPlantScatter { - public HydraluxFeature(int radius) { - super(radius); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - HydraluxSaplingBlock seed = (HydraluxSaplingBlock) EndBlocks.HYDRALUX_SAPLING; - seed.grow(world, random, blockPos); - } - - @Override - protected int getChance() { - return 15; - } -} diff --git a/src/main/java/ru/betterend/world/features/InvertedScatterFeature.java b/src/main/java/ru/betterend/world/features/InvertedScatterFeature.java deleted file mode 100644 index 07e65599..00000000 --- a/src/main/java/ru/betterend/world/features/InvertedScatterFeature.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class InvertedScatterFeature extends DefaultFeature { - private final int radius; - - public InvertedScatterFeature(int radius) { - this.radius = radius; - } - - public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius); - - public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - final RandomSource random = featureConfig.random(); - final BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); - int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); - for (int y = maxY; y > minY; y--) { - POS.set(center.getX(), y, center.getZ()); - if (world.getBlockState(POS).isAir() && !world.getBlockState(POS.above()).isAir()) { - float r = MHelper.randRange(radius * 0.5F, radius, random); - int count = MHelper.floor(r * r * MHelper.randRange(0.5F, 1.5F, random)); - for (int i = 0; i < count; i++) { - float pr = r * (float) Math.sqrt(random.nextFloat()); - float theta = random.nextFloat() * MHelper.PI2; - float x = pr * (float) Math.cos(theta); - float z = pr * (float) Math.sin(theta); - - POS.set(center.getX() + x, center.getY() - 7, center.getZ() + z); - int up = BlocksHelper.upRay(world, POS, 16); - if (up > 14) continue; - POS.setY(POS.getY() + up); - - if (canGenerate(world, random, center, POS, r)) { - generate(world, random, POS); - } - } - } - } - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/LanceleafFeature.java b/src/main/java/ru/betterend/world/features/LanceleafFeature.java deleted file mode 100644 index d5afefc5..00000000 --- a/src/main/java/ru/betterend/world/features/LanceleafFeature.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LanceleafFeature extends ScatterFeature { - public LanceleafFeature() { - super(7); - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return EndBlocks.LANCELEAF_SEED.canSurvive(AIR, world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.LANCELEAF_SEED); - seed.growAdult(world, random, blockPos); - } - - @Override - protected int getChance() { - return 5; - } -} diff --git a/src/main/java/ru/betterend/world/features/MengerSpongeFeature.java b/src/main/java/ru/betterend/world/features/MengerSpongeFeature.java deleted file mode 100644 index c29b8bfc..00000000 --- a/src/main/java/ru/betterend/world/features/MengerSpongeFeature.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.util.BlocksHelper; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class MengerSpongeFeature extends UnderwaterPlantScatter { - private static final Function REPLACE; - - public MengerSpongeFeature(int radius) { - super(radius); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.MENGER_SPONGE_WET); - if (random.nextBoolean()) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - BlockPos pos = blockPos.relative(dir); - if (REPLACE.apply(world.getBlockState(pos))) { - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.MENGER_SPONGE_WET); - } - } - } - } - - static { - REPLACE = (state) -> { - if (state.is(EndBlocks.END_LOTUS_STEM)) { - return false; - } - return !state.getFluidState().isEmpty() || state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/NeonCactusFeature.java b/src/main/java/ru/betterend/world/features/NeonCactusFeature.java deleted file mode 100644 index f3f629d0..00000000 --- a/src/main/java/ru/betterend/world/features/NeonCactusFeature.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.NeonCactusPlantBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class NeonCactusFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - BlockState ground = world.getBlockState(pos.below()); - if (!ground.is(EndBlocks.ENDSTONE_DUST) && !ground.is(EndBlocks.END_MOSS)) { - return false; - } - - NeonCactusPlantBlock cactus = ((NeonCactusPlantBlock) EndBlocks.NEON_CACTUS); - cactus.growPlant(world, pos, random); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/ScatterFeature.java b/src/main/java/ru/betterend/world/features/ScatterFeature.java deleted file mode 100644 index a273d3a5..00000000 --- a/src/main/java/ru/betterend/world/features/ScatterFeature.java +++ /dev/null @@ -1,93 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class ScatterFeature extends DefaultFeature { - private final int radius; - - public ScatterFeature(int radius) { - this.radius = radius; - } - - public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius); - - public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos); - - protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { - return getPosOnSurfaceWG(world, pos); - } - - protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { - if (pos.getY() < 5) { - return false; - } - else if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - return false; - } - return true; - } - - protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { - int down = BlocksHelper.downRay(world, pos, 16); - if (down > Math.abs(getYOffset() * 2)) { - return false; - } - pos.setY(pos.getY() - down); - return true; - } - - protected int getYOffset() { - return 5; - } - - protected int getChance() { - return 1; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - final RandomSource random = featureConfig.random(); - BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - center = getCenterGround(world, center); - - if (!canSpawn(world, center)) { - return false; - } - - float r = MHelper.randRange(radius * 0.5F, radius, random); - int count = MHelper.floor(r * r * MHelper.randRange(1.5F, 3F, random)); - for (int i = 0; i < count; i++) { - float pr = r * (float) Math.sqrt(random.nextFloat()); - float theta = random.nextFloat() * MHelper.PI2; - float x = pr * (float) Math.cos(theta); - float z = pr * (float) Math.sin(theta); - - POS.set(center.getX() + x, center.getY() + getYOffset(), center.getZ() + z); - if (getGroundPlant(world, POS) && canGenerate( - world, - random, - center, - POS, - r - ) && (getChance() < 2 || random.nextInt(getChance()) == 0)) { - generate(world, random, POS); - } - } - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/SilkMothNestFeature.java b/src/main/java/ru/betterend/world/features/SilkMothNestFeature.java deleted file mode 100644 index 36b044f6..00000000 --- a/src/main/java/ru/betterend/world/features/SilkMothNestFeature.java +++ /dev/null @@ -1,67 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SilkMothNestFeature extends DefaultFeature { - private boolean canGenerate(WorldGenLevel world, BlockPos pos) { - BlockState state = world.getBlockState(pos.above()); - if (state.is(BlockTags.LEAVES) || state.is(BlockTags.LOGS)) { - state = world.getBlockState(pos); - if ((state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) && world.isEmptyBlock(pos.below())) { - for (Direction dir : BlocksHelper.HORIZONTAL) { - return !world.getBlockState(pos.below().relative(dir)).getMaterial().blocksMotion(); - } - } - } - return false; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - final RandomSource random = featureConfig.random(); - final BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); - int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); - POS.set(center); - for (int y = maxY; y > minY; y--) { - POS.setY(y); - if (canGenerate(world, POS)) { - Direction dir = BlocksHelper.randomHorizontal(random); - BlocksHelper.setWithoutUpdate( - world, - POS, - EndBlocks.SILK_MOTH_NEST.defaultBlockState() - .setValue(BlockStateProperties.HORIZONTAL_FACING, dir) - .setValue(BlockProperties.ACTIVE, false) - ); - POS.setY(y - 1); - BlocksHelper.setWithoutUpdate( - world, - POS, - EndBlocks.SILK_MOTH_NEST.defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_FACING, dir) - ); - return true; - } - } - return false; - } -} diff --git a/src/main/java/ru/betterend/world/features/SingleInvertedScatterFeature.java b/src/main/java/ru/betterend/world/features/SingleInvertedScatterFeature.java deleted file mode 100644 index daa144cd..00000000 --- a/src/main/java/ru/betterend/world/features/SingleInvertedScatterFeature.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -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 ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.util.BlocksHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SingleInvertedScatterFeature extends InvertedScatterFeature { - private final Block block; - - public SingleInvertedScatterFeature(Block block, int radius) { - super(radius); - this.block = block; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - if (!world.isEmptyBlock(blockPos)) { - return false; - } - BlockState state = block.defaultBlockState(); - if (block instanceof BaseAttachedBlock) { - state = state.setValue(BlockStateProperties.FACING, Direction.DOWN); - } - return state.canSurvive(world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - BlockState state = block.defaultBlockState(); - if (block instanceof BaseAttachedBlock) { - state = state.setValue(BlockStateProperties.FACING, Direction.DOWN); - } - BlocksHelper.setWithoutUpdate(world, blockPos, state); - } -} diff --git a/src/main/java/ru/betterend/world/features/SinglePlantFeature.java b/src/main/java/ru/betterend/world/features/SinglePlantFeature.java deleted file mode 100644 index 5824ed05..00000000 --- a/src/main/java/ru/betterend/world/features/SinglePlantFeature.java +++ /dev/null @@ -1,74 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseCropBlock; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.util.BlocksHelper; -import ru.betterend.blocks.basis.EndPlantWithAgeBlock; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SinglePlantFeature extends ScatterFeature { - private final Block plant; - private final boolean rawHeightmap; - private final int chance; - - public SinglePlantFeature(Block plant, int radius) { - this(plant, radius, true, 1); - } - - public SinglePlantFeature(Block plant, int radius, int chance) { - this(plant, radius, true, chance); - } - - public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap) { - this(plant, radius, rawHeightmap, 1); - } - - public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap, int chance) { - super(radius); - this.plant = plant; - this.rawHeightmap = rawHeightmap; - this.chance = chance; - } - - protected int getChance() { - return chance; - } - - @Override - protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { - return rawHeightmap ? getPosOnSurfaceWG(world, pos) : getPosOnSurface(world, pos); - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return plant.canSurvive(plant.defaultBlockState(), world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - if (plant instanceof BaseDoublePlantBlock) { - int rot = random.nextInt(4); - BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); - BlocksHelper.setWithoutUpdate(world, blockPos, state); - BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); - } - else if (plant instanceof BaseCropBlock) { - BlockState state = plant.defaultBlockState().setValue(BaseCropBlock.AGE, 3); - BlocksHelper.setWithoutUpdate(world, blockPos, state); - } - else if (plant instanceof EndPlantWithAgeBlock) { - int age = random.nextInt(4); - BlockState state = plant.defaultBlockState().setValue(EndPlantWithAgeBlock.AGE, age); - BlocksHelper.setWithoutUpdate(world, blockPos, state); - } - else { - BlocksHelper.setWithoutUpdate(world, blockPos, plant); - } - } -} diff --git a/src/main/java/ru/betterend/world/features/SkyScatterFeature.java b/src/main/java/ru/betterend/world/features/SkyScatterFeature.java deleted file mode 100644 index 3c243f6e..00000000 --- a/src/main/java/ru/betterend/world/features/SkyScatterFeature.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class SkyScatterFeature extends ScatterFeature { - public SkyScatterFeature(int radius) { - super(radius); - } - - @Override - protected int getChance() { - return 10; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - if (!world.isEmptyBlock(blockPos)) { - return false; - } - - for (Direction dir : BlocksHelper.HORIZONTAL) { - if (!world.isEmptyBlock(blockPos.relative(dir))) { - return false; - } - } - - int maxD = getYOffset() + 2; - int maxV = getYOffset() - 2; - - return BlocksHelper.upRay(world, blockPos, maxD) > maxV && BlocksHelper.downRay(world, blockPos, maxD) > maxV; - } - - @Override - protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { - return true; - } - - @Override - protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { - return new BlockPos(pos.getX(), MHelper.randRange(32, 192, world.getRandom()), pos.getZ()); - } - - protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { - pos.setY(pos.getY() + MHelper.randRange(-getYOffset(), getYOffset(), world.getRandom())); - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/UnderwaterPlantFeature.java b/src/main/java/ru/betterend/world/features/UnderwaterPlantFeature.java deleted file mode 100644 index fc002201..00000000 --- a/src/main/java/ru/betterend/world/features/UnderwaterPlantFeature.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseDoublePlantBlock; -import ru.bclib.util.BlocksHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class UnderwaterPlantFeature extends UnderwaterPlantScatter { - private final Block plant; - - public UnderwaterPlantFeature(Block plant, int radius) { - super(radius); - this.plant = plant; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return super.canSpawn(world, blockPos) && plant.canSurvive(plant.defaultBlockState(), world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - if (plant instanceof BaseDoublePlantBlock) { - int rot = random.nextInt(4); - BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot); - BlocksHelper.setWithoutUpdate(world, blockPos, state); - BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true)); - } - else { - BlocksHelper.setWithoutUpdate(world, blockPos, plant); - } - } -} diff --git a/src/main/java/ru/betterend/world/features/UnderwaterPlantScatter.java b/src/main/java/ru/betterend/world/features/UnderwaterPlantScatter.java deleted file mode 100644 index 432bce87..00000000 --- a/src/main/java/ru/betterend/world/features/UnderwaterPlantScatter.java +++ /dev/null @@ -1,57 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class UnderwaterPlantScatter extends ScatterFeature { - public UnderwaterPlantScatter(int radius) { - super(radius); - } - - @Override - protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - POS.setX(pos.getX()); - POS.setZ(pos.getZ()); - POS.setY(0); - return getGround(world, POS).immutable(); - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - return world.getBlockState(blockPos).is(Blocks.WATER); - } - - @Override - protected boolean canSpawn(WorldGenLevel world, BlockPos pos) { - return world.getBlockState(pos).is(Blocks.WATER); - } - - @Override - protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) { - return getGround(world, pos).getY() < 128; - } - - @Override - protected int getYOffset() { - return -5; - } - - @Override - protected int getChance() { - return 5; - } - - private BlockPos getGround(WorldGenLevel world, MutableBlockPos pos) { - while (pos.getY() < 128 && world.getFluidState(pos).isEmpty()) { - pos.setY(pos.getY() + 1); - } - return pos; - } -} diff --git a/src/main/java/ru/betterend/world/features/VineFeature.java b/src/main/java/ru/betterend/world/features/VineFeature.java deleted file mode 100644 index 94646ef3..00000000 --- a/src/main/java/ru/betterend/world/features/VineFeature.java +++ /dev/null @@ -1,71 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import ru.bclib.blocks.BaseVineBlock; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class VineFeature extends InvertedScatterFeature { - private final Block vineBlock; - private final int maxLength; - private final boolean vine; - - public VineFeature(Block vineBlock, int maxLength) { - super(6); - this.vineBlock = vineBlock; - this.maxLength = maxLength; - this.vine = vineBlock instanceof BaseVineBlock; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos center, BlockPos blockPos, float radius) { - BlockState state = world.getBlockState(blockPos); - return state.getMaterial().isReplaceable() && canPlaceBlock(state, world, blockPos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) { - int h = BlocksHelper.downRay(world, blockPos, random.nextInt(maxLength)) - 1; - if (h > 2) { - BlockState top = getTopState(); - BlockState middle = getMiggleState(); - BlockState bottom = getBottomState(); - BlocksHelper.setWithoutUpdate(world, blockPos, top); - for (int i = 1; i < h; i++) { - BlocksHelper.setWithoutUpdate(world, blockPos.below(i), middle); - } - BlocksHelper.setWithoutUpdate(world, blockPos.below(h), bottom); - } - } - - private boolean canPlaceBlock(BlockState state, WorldGenLevel world, BlockPos blockPos) { - if (vine) { - return ((BaseVineBlock) vineBlock).canGenerate(state, world, blockPos); - } - else { - return vineBlock.canSurvive(state, world, blockPos); - } - } - - private BlockState getTopState() { - BlockState state = vineBlock.defaultBlockState(); - return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) : state; - } - - private BlockState getMiggleState() { - BlockState state = vineBlock.defaultBlockState(); - return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) : state; - } - - private BlockState getBottomState() { - BlockState state = vineBlock.defaultBlockState(); - return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM) : state; - } -} diff --git a/src/main/java/ru/betterend/world/features/WallPlantFeature.java b/src/main/java/ru/betterend/world/features/WallPlantFeature.java deleted file mode 100644 index 880c7c91..00000000 --- a/src/main/java/ru/betterend/world/features/WallPlantFeature.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -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 ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.blocks.BaseWallPlantBlock; -import ru.bclib.util.BlocksHelper; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class WallPlantFeature extends WallScatterFeature { - private final Block block; - - public WallPlantFeature(Block block, int radius) { - super(radius); - this.block = block; - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { - if (block instanceof BaseWallPlantBlock) { - BlockState state = block.defaultBlockState().setValue(BaseWallPlantBlock.FACING, dir); - return block.canSurvive(state, world, pos); - } - else if (block instanceof BaseAttachedBlock) { - BlockState state = block.defaultBlockState().setValue(BlockStateProperties.FACING, dir); - return block.canSurvive(state, world, pos); - } - return block.canSurvive(block.defaultBlockState(), world, pos); - } - - @Override - public void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { - BlockState state = block.defaultBlockState(); - if (block instanceof BaseWallPlantBlock) { - state = state.setValue(BaseWallPlantBlock.FACING, dir); - } - else if (block instanceof BaseAttachedBlock) { - state = state.setValue(BlockStateProperties.FACING, dir); - } - BlocksHelper.setWithoutUpdate(world, pos, state); - } -} diff --git a/src/main/java/ru/betterend/world/features/WallPlantOnLogFeature.java b/src/main/java/ru/betterend/world/features/WallPlantOnLogFeature.java deleted file mode 100644 index 19fb3bea..00000000 --- a/src/main/java/ru/betterend/world/features/WallPlantOnLogFeature.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class WallPlantOnLogFeature extends WallPlantFeature { - public WallPlantOnLogFeature(Block block, int radius) { - super(block, radius); - } - - @Override - public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) { - BlockPos blockPos = pos.relative(dir.getOpposite()); - BlockState blockState = world.getBlockState(blockPos); - return blockState.is(BlockTags.LOGS); - } -} diff --git a/src/main/java/ru/betterend/world/features/WallScatterFeature.java b/src/main/java/ru/betterend/world/features/WallScatterFeature.java deleted file mode 100644 index 97f6f73a..00000000 --- a/src/main/java/ru/betterend/world/features/WallScatterFeature.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.betterend.world.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class WallScatterFeature extends DefaultFeature { - private static final Direction[] DIR = BlocksHelper.makeHorizontal(); - private final int radius; - - public WallScatterFeature(int radius) { - this.radius = radius; - } - - public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir); - - public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos center = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ()); - int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY); - if (maxY < 10 || maxY < minY) { - return false; - } - int py = MHelper.randRange(minY, maxY, random); - - MutableBlockPos mut = new MutableBlockPos(); - for (int x = -radius; x <= radius; x++) { - mut.setX(center.getX() + x); - for (int y = -radius; y <= radius; y++) { - mut.setY(py + y); - for (int z = -radius; z <= radius; z++) { - mut.setZ(center.getZ() + z); - if (random.nextInt(4) == 0 && world.isEmptyBlock(mut)) { - shuffle(random); - for (Direction dir : DIR) { - if (canGenerate(world, random, mut, dir)) { - generate(world, random, mut, dir); - break; - } - } - } - } - } - } - - return true; - } - - private void shuffle(RandomSource random) { - for (int i = 0; i < 4; i++) { - int j = random.nextInt(4); - Direction d = DIR[i]; - DIR[i] = DIR[j]; - DIR[j] = d; - } - } -} diff --git a/src/main/java/ru/betterend/world/features/bushes/BushFeature.java b/src/main/java/ru/betterend/world/features/bushes/BushFeature.java deleted file mode 100644 index c39b4ad8..00000000 --- a/src/main/java/ru/betterend/world/features/bushes/BushFeature.java +++ /dev/null @@ -1,101 +0,0 @@ -package ru.betterend.world.features.bushes; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class BushFeature extends DefaultFeature { - private static final Function REPLACE; - private final Block leaves; - private final Block stem; - - public BushFeature(Block leaves, Block stem) { - this.leaves = leaves; - this.stem = stem; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES) && !world.getBlockState(pos.above()) - .is(CommonBlockTags.END_STONES)) - return false; - - float radius = MHelper.randRange(1.8F, 3.5F, random); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); - SDF sphere = new SDFSphere().setRadius(radius).setBlock(this.leaves); - sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; - }).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return MHelper.randRange(-2F, 2F, random); - }).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere) - .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); - sphere.setReplaceFunction(REPLACE); - sphere.addPostProcess((info) -> { - if (info.getState().getBlock() instanceof LeavesBlock) { - int distance = info.getPos().distManhattan(pos); - if (distance < 7) { - return info.getState().setValue(LeavesBlock.DISTANCE, distance); - } - else { - return AIR; - } - } - return info.getState(); - }); - sphere.fillRecursive(world, pos); - BlocksHelper.setWithoutUpdate(world, pos, stem); - for (Direction d : Direction.values()) { - BlockPos p = pos.relative(d); - if (world.isEmptyBlock(p)) { - if (leaves instanceof LeavesBlock) { - BlocksHelper.setWithoutUpdate( - world, - p, - leaves.defaultBlockState().setValue(LeavesBlock.DISTANCE, 1) - ); - } - else { - BlocksHelper.setWithoutUpdate(world, p, leaves.defaultBlockState()); - } - } - } - - return true; - } - - static { - REPLACE = (state) -> { - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/bushes/BushWithOuterFeature.java b/src/main/java/ru/betterend/world/features/bushes/BushWithOuterFeature.java deleted file mode 100644 index 8630fa4b..00000000 --- a/src/main/java/ru/betterend/world/features/bushes/BushWithOuterFeature.java +++ /dev/null @@ -1,118 +0,0 @@ -package ru.betterend.world.features.bushes; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class BushWithOuterFeature extends DefaultFeature { - private static final Direction[] DIRECTIONS = Direction.values(); - private static final Function REPLACE; - private final Block outer_leaves; - private final Block leaves; - private final Block stem; - - public BushWithOuterFeature(Block leaves, Block outer_leaves, Block stem) { - this.outer_leaves = outer_leaves; - this.leaves = leaves; - this.stem = stem; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES) && !world.getBlockState(pos.above()) - .is(CommonBlockTags.END_STONES)) - return false; - - float radius = MHelper.randRange(1.8F, 3.5F, random); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); - SDF sphere = new SDFSphere().setRadius(radius).setBlock(this.leaves); - sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; - }).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return MHelper.randRange(-2F, 2F, random); - }).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere) - .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); - sphere.setReplaceFunction(REPLACE); - sphere.addPostProcess((info) -> { - if (info.getState().getBlock() instanceof LeavesBlock) { - int distance = info.getPos().distManhattan(pos); - if (distance < 7) { - return info.getState().setValue(LeavesBlock.DISTANCE, distance); - } - else { - return AIR; - } - } - return info.getState(); - }).addPostProcess((info) -> { - if (info.getState().getBlock() instanceof LeavesBlock) { - MHelper.shuffle(DIRECTIONS, random); - for (Direction dir : DIRECTIONS) { - if (info.getState(dir).isAir()) { - info.setBlockPos( - info.getPos().relative(dir), - outer_leaves.defaultBlockState().setValue(BlockStateProperties.FACING, dir) - ); - } - } - } - return info.getState(); - }); - sphere.fillRecursive(world, pos); - BlocksHelper.setWithoutUpdate(world, pos, stem); - for (Direction d : Direction.values()) { - BlockPos p = pos.relative(d); - if (world.isEmptyBlock(p)) { - if (leaves instanceof LeavesBlock) { - BlocksHelper.setWithoutUpdate( - world, - p, - leaves.defaultBlockState().setValue(LeavesBlock.DISTANCE, 1) - ); - } - else { - BlocksHelper.setWithoutUpdate(world, p, leaves.defaultBlockState()); - } - } - } - - return true; - } - - static { - REPLACE = (state) -> { - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/bushes/LargeAmaranitaFeature.java b/src/main/java/ru/betterend/world/features/bushes/LargeAmaranitaFeature.java deleted file mode 100644 index ff59b7fd..00000000 --- a/src/main/java/ru/betterend/world/features/bushes/LargeAmaranitaFeature.java +++ /dev/null @@ -1,56 +0,0 @@ -package ru.betterend.world.features.bushes; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LargeAmaranitaFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - - MutableBlockPos mut = new MutableBlockPos().set(pos); - int height = MHelper.randRange(2, 3, random); - for (int i = 1; i < height; i++) { - mut.setY(mut.getY() + 1); - if (!world.isEmptyBlock(mut)) { - return false; - } - } - mut.set(pos); - - BlockState state = EndBlocks.LARGE_AMARANITA_MUSHROOM.defaultBlockState(); - BlocksHelper.setWithUpdate(world, mut, state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM)); - if (height > 2) { - BlocksHelper.setWithUpdate( - world, - mut.move(Direction.UP), - state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) - ); - } - BlocksHelper.setWithUpdate( - world, - mut.move(Direction.UP), - state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) - ); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/bushes/Lumecorn.java b/src/main/java/ru/betterend/world/features/bushes/Lumecorn.java deleted file mode 100644 index bc01148e..00000000 --- a/src/main/java/ru/betterend/world/features/bushes/Lumecorn.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.betterend.world.features.bushes; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.EndBlockProperties.LumecornShape; -import ru.betterend.blocks.LumecornBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class Lumecorn extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - - int height = MHelper.randRange(4, 7, random); - MutableBlockPos mut = new MutableBlockPos().set(pos); - for (int i = 1; i < height; i++) { - mut.move(Direction.UP); - if (!world.isEmptyBlock(mut)) { - return false; - } - } - mut.set(pos); - BlockState topMiddle = EndBlocks.LUMECORN.defaultBlockState() - .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_TOP_MIDDLE); - BlockState middle = EndBlocks.LUMECORN.defaultBlockState() - .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_MIDDLE); - BlockState bottom = EndBlocks.LUMECORN.defaultBlockState() - .setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_BOTTOM); - BlockState top = EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.LIGHT_TOP); - if (height == 4) { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_SMALL) - ); - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), bottom); - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), topMiddle); - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), top); - return true; - } - if (random.nextBoolean()) { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_SMALL) - ); - } - else { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.BOTTOM_BIG) - ); - BlocksHelper.setWithoutUpdate( - world, - mut.move(Direction.UP), - EndBlocks.LUMECORN.defaultBlockState().setValue(LumecornBlock.SHAPE, LumecornShape.MIDDLE) - ); - height--; - } - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), bottom); - for (int i = 4; i < height; i++) { - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), middle); - } - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), topMiddle); - BlocksHelper.setWithoutUpdate(world, mut.move(Direction.UP), top); - return false; - } -} diff --git a/src/main/java/ru/betterend/world/features/bushes/TenaneaBushFeature.java b/src/main/java/ru/betterend/world/features/bushes/TenaneaBushFeature.java deleted file mode 100644 index ccbcc19e..00000000 --- a/src/main/java/ru/betterend/world/features/bushes/TenaneaBushFeature.java +++ /dev/null @@ -1,139 +0,0 @@ -package ru.betterend.world.features.bushes; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class TenaneaBushFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Direction[] DIRECTIONS = Direction.values(); - - public TenaneaBushFeature() { - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) return false; - - float radius = MHelper.randRange(1.8F, 3.5F, random); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); - BlockState leaves = EndBlocks.TENANEA_LEAVES.defaultBlockState(); - SDF sphere = new SDFSphere().setRadius(radius).setBlock(leaves); - sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( - vec.x() * 0.2, - vec.y() * 0.2, - vec.z() * 0.2 - ) * 3).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-2F, 2F, random)).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere) - .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); - sphere.setReplaceFunction(REPLACE); - List support = Lists.newArrayList(); - sphere.addPostProcess((info) -> { - if (info.getState().getBlock() instanceof LeavesBlock) { - int distance = info.getPos().distManhattan(pos); - if (distance < 7) { - if (random.nextInt(4) == 0 && info.getStateDown().isAir()) { - BlockPos d = info.getPos().below(); - support.add(d); - } - - MHelper.shuffle(DIRECTIONS, random); - for (Direction d : DIRECTIONS) { - if (info.getState(d).isAir()) { - info.setBlockPos( - info.getPos().relative(d), - EndBlocks.TENANEA_OUTER_LEAVES.defaultBlockState().setValue(FurBlock.FACING, d) - ); - } - } - - return info.getState().setValue(LeavesBlock.DISTANCE, distance); - } - else { - return AIR; - } - } - return info.getState(); - }); - sphere.fillRecursive(world, pos); - BlockState stem = EndBlocks.TENANEA.getBark().defaultBlockState(); - BlocksHelper.setWithoutUpdate(world, pos, stem); - for (Direction d : Direction.values()) { - BlockPos p = pos.relative(d); - if (world.isEmptyBlock(p)) { - BlocksHelper.setWithoutUpdate(world, p, leaves.setValue(LeavesBlock.DISTANCE, 1)); - } - } - - MutableBlockPos mut = new MutableBlockPos(); - BlockState top = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); - BlockState middle = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); - BlockState bottom = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); - support.forEach((bpos) -> { - BlockState state = world.getBlockState(bpos); - if (state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) { - int count = MHelper.randRange(3, 8, random); - mut.set(bpos); - if (world.getBlockState(mut.above()).is(EndBlocks.TENANEA_LEAVES)) { - BlocksHelper.setWithoutUpdate(world, mut, top); - for (int i = 1; i < count; i++) { - mut.setY(mut.getY() - 1); - if (world.isEmptyBlock(mut.below())) { - BlocksHelper.setWithoutUpdate(world, mut, middle); - } - else { - break; - } - } - BlocksHelper.setWithoutUpdate(world, mut, bottom); - } - } - }); - - return true; - } - - static { - REPLACE = (state) -> { - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/ArchFeature.java b/src/main/java/ru/betterend/world/features/terrain/ArchFeature.java deleted file mode 100644 index 47930fe9..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/ArchFeature.java +++ /dev/null @@ -1,86 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.primitive.SDFTorus; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class ArchFeature extends DefaultFeature { - private Function surfaceFunction; - private Block block; - - public ArchFeature(Block block, Function surfaceFunction) { - this.surfaceFunction = surfaceFunction; - this.block = block; - } - - @Override - public boolean place(FeaturePlaceContext featurePlaceContext) { - final WorldGenLevel world = featurePlaceContext.level(); - BlockPos origin = featurePlaceContext.origin(); - RandomSource random = featurePlaceContext.random(); - - BlockPos pos = getPosOnSurfaceWG( - world, - new BlockPos((origin.getX() & 0xFFFFFFF0) | 7, 0, (origin.getZ() & 0xFFFFFFF0) | 7) - ); - if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - float bigRadius = MHelper.randRange(10F, 20F, random); - float smallRadius = MHelper.randRange(3F, 7F, random); - if (smallRadius + bigRadius > 23) { - smallRadius = 23 - bigRadius; - } - SDF arch = new SDFTorus().setBigRadius(bigRadius).setSmallRadius(smallRadius).setBlock(block); - arch = new SDFRotation().setRotation(MHelper.randomHorizontal(random), (float) Math.PI * 0.5F).setSource(arch); - - final float smallRadiusF = smallRadius; - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - arch = new SDFDisplacement().setFunction((vec) -> { - return (float) (Math.abs(noise.eval(vec.x() * 0.1, - vec.y() * 0.1, - vec.z() * 0.1 - )) * 3F + Math.abs(noise.eval( - vec.x() * 0.3, - vec.y() * 0.3 + 100, - vec.z() * 0.3 - )) * 1.3F) - smallRadiusF * Math.abs(1 - vec.y() / bigRadius); - }).setSource(arch); - - List surface = Lists.newArrayList(); - arch.addPostProcess((info) -> { - if (info.getStateUp().isAir()) { - return surfaceFunction.apply(info.getPos()); - } - return info.getState(); - }); - - float side = (bigRadius + smallRadius + 3F) * 2; - if (side > 47) { - side = 47; - } - arch.fillArea(world, pos, AABB.ofSize(Vec3.atCenterOf(pos), side, side, side)); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/BigAuroraCrystalFeature.java b/src/main/java/ru/betterend/world/features/terrain/BigAuroraCrystalFeature.java deleted file mode 100644 index a5fcf4b8..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/BigAuroraCrystalFeature.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.primitive.SDFHexPrism; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class BigAuroraCrystalFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int maxY = pos.getY() + BlocksHelper.upRay(world, pos, 16); - int minY = pos.getY() - BlocksHelper.downRay(world, pos, 16); - - if (maxY - minY < 10) { - return false; - } - - int y = MHelper.randRange(minY, maxY, random); - pos = new BlockPos(pos.getX(), y, pos.getZ()); - - int height = MHelper.randRange(5, 25, random); - SDF prism = new SDFHexPrism().setHeight(height) - .setRadius(MHelper.randRange(1.7F, 3F, random)) - .setBlock(EndBlocks.AURORA_CRYSTAL); - Vector3f vec = MHelper.randomHorizontal(random); - prism = new SDFRotation().setRotation(vec, random.nextFloat()).setSource(prism); - prism.setReplaceFunction((bState) -> { - return bState.getMaterial().isReplaceable() || bState.is(CommonBlockTags.GEN_END_STONES) || bState.getMaterial() - .equals(Material.PLANT) || bState - .getMaterial() - .equals(Material.LEAVES); - }); - prism.fillRecursive(world, pos); - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.AURORA_CRYSTAL); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/DesertLakeFeature.java b/src/main/java/ru/betterend/world/features/terrain/DesertLakeFeature.java deleted file mode 100644 index 94205525..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/DesertLakeFeature.java +++ /dev/null @@ -1,242 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.util.BlockFixer; -import ru.betterend.util.GlobalState; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class DesertLakeFeature extends DefaultFeature { - private static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - - final RandomSource random = featureConfig.random(); - BlockPos blockPos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - double radius = MHelper.randRange(8.0, 15.0, random); - double depth = radius * 0.5 * MHelper.randRange(0.8, 1.2, random); - int dist = MHelper.floor(radius); - int dist2 = MHelper.floor(radius * 1.5); - int bott = MHelper.floor(depth); - blockPos = getPosOnSurfaceWG(world, blockPos); - - if (blockPos.getY() < 10) return false; - - int waterLevel = blockPos.getY(); - - BlockPos pos = getPosOnSurfaceRaycast(world, blockPos.north(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.south(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.east(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.west(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - BlockState state; - - int minX = blockPos.getX() - dist2; - int maxX = blockPos.getX() + dist2; - int minZ = blockPos.getZ() - dist2; - int maxZ = blockPos.getZ() + dist2; - int maskMinX = minX - 1; - int maskMinZ = minZ - 1; - - boolean[][] mask = new boolean[maxX - minX + 3][maxZ - minZ + 3]; - for (int x = minX; x <= maxX; x++) { - POS.setX(x); - int mx = x - maskMinX; - for (int z = minZ; z <= maxZ; z++) { - POS.setZ(z); - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - for (int y = waterLevel + 1; y <= waterLevel + 20; y++) { - POS.setY(y); - FluidState fluid = world.getFluidState(POS); - if (!fluid.isEmpty()) { - for (int i = -1; i < 2; i++) { - int px = mx + i; - for (int j = -1; j < 2; j++) { - int pz = mz + j; - mask[px][pz] = true; - } - } - break; - } - } - } - } - } - - for (int x = minX; x <= maxX; x++) { - POS.setX(x); - int x2 = x - blockPos.getX(); - x2 *= x2; - int mx = x - maskMinX; - for (int z = minZ; z <= maxZ; z++) { - POS.setZ(z); - int z2 = z - blockPos.getZ(); - z2 *= z2; - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - double size = 1; - for (int y = blockPos.getY(); y <= blockPos.getY() + 20; y++) { - POS.setY(y); - double add = y - blockPos.getY(); - if (add > 5) { - size *= 0.8; - add = 5; - } - double r = (add * 1.8 + radius * (NOISE.eval( - x * 0.2, - y * 0.2, - z * 0.2 - ) * 0.25 + 0.75)) - 1.0 / size; - if (r > 0) { - r *= r; - if (x2 + z2 <= r) { - state = world.getBlockState(POS); - if (state.is(CommonBlockTags.GEN_END_STONES)) { - BlocksHelper.setWithoutUpdate(world, POS, AIR); - } - pos = POS.below(); - if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { - state = EndBiome.findTopMaterial(world, pos); //world.getBiome(pos).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - if (y > waterLevel + 1) BlocksHelper.setWithoutUpdate(world, pos, state); - else if (y > waterLevel) - BlocksHelper.setWithoutUpdate( - world, - pos, - random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - else - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - } - } - } - else { - break; - } - } - } - } - } - - double aspect = ((double) radius / (double) depth); - - for (int x = blockPos.getX() - dist; x <= blockPos.getX() + dist; x++) { - POS.setX(x); - int x2 = x - blockPos.getX(); - x2 *= x2; - int mx = x - maskMinX; - for (int z = blockPos.getZ() - dist; z <= blockPos.getZ() + dist; z++) { - POS.setZ(z); - int z2 = z - blockPos.getZ(); - z2 *= z2; - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - for (int y = blockPos.getY() - bott; y < blockPos.getY(); y++) { - POS.setY(y); - double y2 = (double) (y - blockPos.getY()) * aspect; - y2 *= y2; - double r = radius * (NOISE.eval(x * 0.2, y * 0.2, z * 0.2) * 0.25 + 0.75); - double rb = r * 1.2; - r *= r; - rb *= rb; - if (y2 + x2 + z2 <= r) { - state = world.getBlockState(POS); - if (canReplace(state)) { - state = world.getBlockState(POS.above()); - state = canReplace(state) ? (y < waterLevel ? WATER : AIR) : state; - BlocksHelper.setWithoutUpdate(world, POS, state); - } - pos = POS.below(); - if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.ENDSTONE_DUST.defaultBlockState()); - } - pos = POS.above(); - while (canReplace(state = world.getBlockState(pos)) && !state.isAir() && state.getFluidState() - .isEmpty()) { - BlocksHelper.setWithoutUpdate(world, pos, pos.getY() < waterLevel ? WATER : AIR); - pos = pos.above(); - } - } - // Make border - else if (y2 + x2 + z2 <= rb) { - state = world.getBlockState(POS); - if (state.is(CommonBlockTags.GEN_END_STONES) && world.isEmptyBlock(POS.above())) { - BlocksHelper.setWithoutUpdate(world, POS, EndBlocks.END_MOSS); - } - else if (y < waterLevel) { - if (world.isEmptyBlock(POS.above())) { - state = EndBiome.findTopMaterial(world, pos); //world.getBiome(POS).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - BlocksHelper.setWithoutUpdate( - world, - POS, - random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); - } - else { - BlocksHelper.setWithoutUpdate( - world, - POS, - EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); - } - } - } - } - } - } - } - - BlockFixer.fixBlocks( - world, - new BlockPos(minX - 2, waterLevel - 2, minZ - 2), - new BlockPos(maxX + 2, blockPos.getY() + 20, maxZ + 2) - ); - - return true; - } - - private boolean canReplace(BlockState state) { - return state.getMaterial() - .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.ENDSTONE_DUST) || state.getMaterial() - .equals( - Material.PLANT) || state - .getMaterial() - .equals(Material.WATER_PLANT); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/EndLakeFeature.java b/src/main/java/ru/betterend/world/features/terrain/EndLakeFeature.java deleted file mode 100644 index 60a3cdc4..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/EndLakeFeature.java +++ /dev/null @@ -1,238 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.util.BlockFixer; -import ru.betterend.util.GlobalState; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class EndLakeFeature extends DefaultFeature { - private static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); - public EndLakeFeature(){ - - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final MutableBlockPos POS = GlobalState.stateForThread().POS; - final RandomSource random = featureConfig.random(); - BlockPos blockPos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - double radius = MHelper.randRange(10.0, 20.0, random); - double depth = radius * 0.5 * MHelper.randRange(0.8, 1.2, random); - int dist = MHelper.floor(radius); - int dist2 = MHelper.floor(radius * 1.5); - int bott = MHelper.floor(depth); - blockPos = getPosOnSurfaceWG(world, blockPos); - - if (blockPos.getY() < 10) return false; - - int waterLevel = blockPos.getY(); - - BlockPos pos = getPosOnSurfaceRaycast(world, blockPos.north(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.south(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.east(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - - pos = getPosOnSurfaceRaycast(world, blockPos.west(dist).above(10), 20); - if (Math.abs(blockPos.getY() - pos.getY()) > 5) return false; - waterLevel = MHelper.min(pos.getY(), waterLevel); - BlockState state; - - int minX = blockPos.getX() - dist2; - int maxX = blockPos.getX() + dist2; - int minZ = blockPos.getZ() - dist2; - int maxZ = blockPos.getZ() + dist2; - int maskMinX = minX - 1; - int maskMinZ = minZ - 1; - - boolean[][] mask = new boolean[maxX - minX + 3][maxZ - minZ + 3]; - for (int x = minX; x <= maxX; x++) { - POS.setX(x); - int mx = x - maskMinX; - for (int z = minZ; z <= maxZ; z++) { - POS.setZ(z); - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - for (int y = waterLevel + 1; y <= waterLevel + 20; y++) { - POS.setY(y); - FluidState fluid = world.getFluidState(POS); - if (!fluid.isEmpty()) { - for (int i = -1; i < 2; i++) { - int px = mx + i; - for (int j = -1; j < 2; j++) { - int pz = mz + j; - mask[px][pz] = true; - } - } - break; - } - } - } - } - } - - for (int x = minX; x <= maxX; x++) { - POS.setX(x); - int x2 = x - blockPos.getX(); - x2 *= x2; - int mx = x - maskMinX; - for (int z = minZ; z <= maxZ; z++) { - POS.setZ(z); - int z2 = z - blockPos.getZ(); - z2 *= z2; - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - double size = 1; - for (int y = blockPos.getY(); y <= blockPos.getY() + 20; y++) { - POS.setY(y); - double add = y - blockPos.getY(); - if (add > 5) { - size *= 0.8; - add = 5; - } - double r = (add * 1.8 + radius * (NOISE.eval( - x * 0.2, - y * 0.2, - z * 0.2 - ) * 0.25 + 0.75)) - 1.0 / size; - if (r > 0) { - r *= r; - if (x2 + z2 <= r) { - state = world.getBlockState(POS); - if (state.is(CommonBlockTags.GEN_END_STONES)) { - BlocksHelper.setWithoutUpdate(world, POS, AIR); - } - pos = POS.below(); - if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { - state = EndBiome.findTopMaterial(world, pos); - if (y > waterLevel + 1) BlocksHelper.setWithoutUpdate(world, pos, state); - else if (y > waterLevel) - BlocksHelper.setWithoutUpdate( - world, - pos, - random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - else - BlocksHelper.setWithoutUpdate( - world, - pos, - EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - } - } - } - else { - break; - } - } - } - } - } - - double aspect = ((double) radius / (double) depth); - - for (int x = blockPos.getX() - dist; x <= blockPos.getX() + dist; x++) { - POS.setX(x); - int x2 = x - blockPos.getX(); - x2 *= x2; - int mx = x - maskMinX; - for (int z = blockPos.getZ() - dist; z <= blockPos.getZ() + dist; z++) { - POS.setZ(z); - int z2 = z - blockPos.getZ(); - z2 *= z2; - int mz = z - maskMinZ; - if (!mask[mx][mz]) { - for (int y = blockPos.getY() - bott; y < blockPos.getY(); y++) { - POS.setY(y); - double y2 = (double) (y - blockPos.getY()) * aspect; - y2 *= y2; - double r = radius * (NOISE.eval(x * 0.2, y * 0.2, z * 0.2) * 0.25 + 0.75); - double rb = r * 1.2; - r *= r; - rb *= rb; - if (y2 + x2 + z2 <= r) { - state = world.getBlockState(POS); - if (canReplace(state)) { - state = world.getBlockState(POS.above()); - state = canReplace(state) ? (y < waterLevel ? WATER : AIR) : state; - BlocksHelper.setWithoutUpdate(world, POS, state); - } - pos = POS.below(); - if (world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES)) { - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.ENDSTONE_DUST.defaultBlockState()); - } - pos = POS.above(); - while (canReplace(state = world.getBlockState(pos)) && !state.isAir() && state.getFluidState() - .isEmpty()) { - BlocksHelper.setWithoutUpdate(world, pos, pos.getY() < waterLevel ? WATER : AIR); - pos = pos.above(); - } - } - // Make border - else if (y < waterLevel && y2 + x2 + z2 <= rb) { - if (world.isEmptyBlock(POS.above())) { - state = EndBiome.findTopMaterial(world, pos); -// state = world.getBiome(POS) -// .getGenerationSettings() -// .getSurfaceBuilderConfig() -// .getTopMaterial(); - BlocksHelper.setWithoutUpdate( - world, - POS, - random.nextBoolean() ? state : EndBlocks.ENDSTONE_DUST.defaultBlockState() - ); - BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); - } - else { - BlocksHelper.setWithoutUpdate(world, POS, EndBlocks.ENDSTONE_DUST.defaultBlockState()); - BlocksHelper.setWithoutUpdate(world, POS.below(), END_STONE); - } - } - } - } - } - } - - BlockFixer.fixBlocks( - world, - new BlockPos(minX - 2, waterLevel - 2, minZ - 2), - new BlockPos(maxX + 2, blockPos.getY() + 20, maxZ + 2) - ); - - return true; - } - - private boolean canReplace(BlockState state) { - return state.getMaterial() - .isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.ENDSTONE_DUST) || state.getMaterial() - .equals( - Material.PLANT) || state - .getMaterial() - .equals(Material.WATER_PLANT); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/FallenPillarFeature.java b/src/main/java/ru/betterend/world/features/terrain/FallenPillarFeature.java deleted file mode 100644 index 7845af76..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/FallenPillarFeature.java +++ /dev/null @@ -1,67 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class FallenPillarFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - pos = getPosOnSurface( - world, - new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) - ); - if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - float height = MHelper.randRange(20F, 40F, random); - float radius = MHelper.randRange(2F, 4F, random); - SDF pillar = new SDFCappedCone().setRadius1(radius) - .setRadius2(radius) - .setHeight(height * 0.5F) - .setBlock(Blocks.OBSIDIAN); - pillar = new SDFTranslate().setTranslate(0, radius * 0.5F - 2, 0).setSource(pillar); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - pillar = new SDFDisplacement().setFunction((vec) -> { - return (float) (noise.eval(vec.x() * 0.3, vec.y() * 0.3, vec.z() * 0.3) * 0.5F); - }).setSource(pillar); - Vector3f vec = MHelper.randomHorizontal(random); - float angle = (float) random.nextGaussian() * 0.05F + (float) Math.PI; - pillar = new SDFRotation().setRotation(vec, angle).setSource(pillar); - - BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); - pillar.addPostProcess((info) -> { - if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { - return mossy; - } - return info.getState(); - }).setReplaceFunction((state) -> { - return state.getMaterial().isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() - .equals(Material.PLANT); - }).fillRecursive(world, pos); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/FloatingSpireFeature.java b/src/main/java/ru/betterend/world/features/terrain/FloatingSpireFeature.java deleted file mode 100644 index b6fbe382..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/FloatingSpireFeature.java +++ /dev/null @@ -1,90 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndFeatures; -import ru.betterend.world.biome.EndBiome; - -import java.util.List; -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class FloatingSpireFeature extends SpireFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); - int minY = getYOnSurface(world, pos.getX(), pos.getZ()); - int y = minY > 57 ? MHelper.floor(MHelper.randRange(minY, minY * 2, random) * 0.5F + 32) : MHelper.randRange( - 64, - 192, - random - ); - pos = new BlockPos(pos.getX(), y, pos.getZ()); - - SDF sdf = new SDFSphere().setRadius(MHelper.randRange(2, 3, random)).setBlock(Blocks.END_STONE); - int count = MHelper.randRange(3, 5, random); - - for (int i = 0; i < count; i++) { - float rMin = (i * 1.3F) + 2.5F; - sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); - } - for (int i = count - 1; i > 0; i--) { - float rMin = (i * 1.3F) + 2.5F; - sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); - } - - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - sdf = new SDFDisplacement().setFunction((vec) -> { - return (float) (Math.abs(noise.eval( - vec.x() * 0.1, - vec.y() * 0.1, - vec.z() * 0.1 - )) * 3F + Math.abs(noise.eval(vec.x() * 0.3, vec.y() * 0.3 + 100, vec.z() * 0.3)) * 1.3F); - }).setSource(sdf); - final BlockPos center = pos; - List support = Lists.newArrayList(); - sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { - if (info.getStateUp().isAir()) { - if (random.nextInt(16) == 0) { - support.add(info.getPos().above()); - } - return EndBiome.findTopMaterial(world, info.getPos());//world.getBiome(info.getPos()).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - } - else if (info.getState(Direction.UP, 3).isAir()) { - return EndBiome.findUnderMaterial(world, info.getPos()); -// return world.getBiome(info.getPos()) -// .getGenerationSettings() -// .getSurfaceBuilderConfig() -// .getUnderMaterial(); - } - return info.getState(); - }); - sdf.fillRecursive(world, center); - - support.forEach((bpos) -> { - if (BiomeAPI.getFromBiome(world.getBiome(bpos)) == EndBiomes.BLOSSOMING_SPIRES) { - EndFeatures.TENANEA_BUSH.getFeature() - .place(new FeaturePlaceContext<>(Optional.empty(), world, chunkGenerator, random, bpos, null)); - } - }); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java b/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java deleted file mode 100644 index 5eda1a8c..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java +++ /dev/null @@ -1,294 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFCoordModify; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFInvert; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.sdf.primitive.SDFFlatland; -import ru.bclib.sdf.primitive.SDFPrimitive; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.HydrothermalVentBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndFeatures; -import ru.betterend.util.BlockFixer; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class GeyserFeature extends DefaultFeature { - protected static final Function REPLACE1; - protected static final Function REPLACE2; - private static final Function IGNORE; - private static final Direction[] HORIZONTAL = BlocksHelper.makeHorizontal(); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final WorldGenLevel world = featureConfig.level(); - final BlockPos pos = getPosOnSurfaceWG(world, featureConfig.origin()); - final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); - - if (pos.getY() < 10) { - return false; - } - - MutableBlockPos bpos = new MutableBlockPos().set(pos); - bpos.setY(bpos.getY() - 1); - BlockState state = world.getBlockState(bpos); - while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - - if (pos.getY() - bpos.getY() < 25) { - return false; - } - - int halfHeight = MHelper.randRange(10, 20, random); - float radius1 = halfHeight * 0.5F; - float radius2 = halfHeight * 0.1F + 0.5F; - SDF sdf = new SDFCappedCone().setHeight(halfHeight) - .setRadius1(radius1) - .setRadius2(radius2) - .setBlock(EndBlocks.SULPHURIC_ROCK.stone); - sdf = new SDFTranslate().setTranslate(0, halfHeight - 3, 0).setSource(sdf); - - int count = halfHeight; - for (int i = 0; i < count; i++) { - int py = i << 1; - float delta = (float) i / (float) (count - 1); - float radius = Mth.lerp(delta, radius1, radius2) * 1.3F; - - SDF bowl = new SDFCappedCone().setHeight(radius) - .setRadius1(0) - .setRadius2(radius) - .setBlock(EndBlocks.SULPHURIC_ROCK.stone); - - SDF brimstone = new SDFCappedCone().setHeight(radius) - .setRadius1(0) - .setRadius2(radius) - .setBlock(EndBlocks.BRIMSTONE); - brimstone = new SDFTranslate().setTranslate(0, 2F, 0).setSource(brimstone); - bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(brimstone); - bowl = new SDFUnion().setSourceA(brimstone).setSourceB(bowl); - - SDF water = new SDFCappedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(Blocks.WATER); - water = new SDFTranslate().setTranslate(0, 4, 0).setSource(water); - bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(water); - bowl = new SDFUnion().setSourceA(water).setSourceB(bowl); - - final OpenSimplexNoise noise1 = new OpenSimplexNoise(random.nextLong()); - final OpenSimplexNoise noise2 = new OpenSimplexNoise(random.nextLong()); - - bowl = new SDFCoordModify().setFunction((vec) -> { - float dx = (float) noise1.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); - float dz = (float) noise2.eval(vec.x() * 0.1, vec.y() * 0.1, vec.z() * 0.1); - vec.set(vec.x() + dx, vec.y(), vec.z() + dz); - }).setSource(bowl); - - SDF cut = new SDFFlatland().setBlock(Blocks.AIR); - cut = new SDFInvert().setSource(cut); - cut = new SDFTranslate().setTranslate(0, radius - 2, 0).setSource(cut); - bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(cut); - - bowl = new SDFTranslate().setTranslate(radius, py - radius, 0).setSource(bowl); - bowl = new SDFRotation().setRotation(Vector3f.YP, i * 4F).setSource(bowl); - sdf = new SDFUnion().setSourceA(sdf).setSourceB(bowl); - } - sdf.setReplaceFunction(REPLACE2).fillRecursive(world, pos); - - radius2 = radius2 * 0.5F; - if (radius2 < 0.7F) { - radius2 = 0.7F; - } - final OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - - SDFPrimitive obj1; - SDFPrimitive obj2; - - obj1 = new SDFCappedCone().setHeight(halfHeight + 5).setRadius1(radius1 * 0.5F).setRadius2(radius2); - sdf = new SDFTranslate().setTranslate(0, halfHeight - 13, 0).setSource(obj1); - sdf = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.3F, vec.y() * 0.3F, vec.z() * 0.3F) * 0.5F; - }).setSource(sdf); - - obj2 = new SDFSphere().setRadius(radius1); - SDF cave = new SDFScale3D().setScale(1.5F, 1, 1.5F).setSource(obj2); - cave = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.1F, vec.y() * 0.1F, vec.z() * 0.1F) * 2F; - }).setSource(cave); - cave = new SDFTranslate().setTranslate(0, -halfHeight - 10, 0).setSource(cave); - - sdf = new SDFSmoothUnion().setRadius(5).setSourceA(cave).setSourceB(sdf); - - obj1.setBlock(WATER); - obj2.setBlock(WATER); - sdf.setReplaceFunction(REPLACE2); - sdf.fillRecursive(world, pos); - - obj1.setBlock(EndBlocks.BRIMSTONE); - obj2.setBlock(EndBlocks.BRIMSTONE); - new SDFDisplacement().setFunction((vec) -> { - return -2F; - }).setSource(sdf).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); - - obj1.setBlock(EndBlocks.SULPHURIC_ROCK.stone); - obj2.setBlock(EndBlocks.SULPHURIC_ROCK.stone); - new SDFDisplacement().setFunction((vec) -> { - return -4F; - }).setSource(cave).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); - - obj1.setBlock(Blocks.END_STONE); - obj2.setBlock(Blocks.END_STONE); - new SDFDisplacement().setFunction((vec) -> { - return -6F; - }).setSource(cave).setReplaceFunction(REPLACE1).fillRecursiveIgnore(world, pos, IGNORE); - - BlocksHelper.setWithoutUpdate(world, pos, WATER); - MutableBlockPos mut = new MutableBlockPos().set(pos); - count = getYOnSurface(world, pos.getX(), pos.getZ()) - pos.getY(); - for (int i = 0; i < count; i++) { - BlocksHelper.setWithoutUpdate(world, mut, WATER); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlocksHelper.setWithoutUpdate(world, mut.relative(dir), WATER); - } - mut.setY(mut.getY() + 1); - } - - for (int i = 0; i < 150; i++) { - mut.set(pos) - .move(MHelper.floor(random.nextGaussian() * 4 + 0.5), - -halfHeight - 10, - MHelper.floor(random.nextGaussian() * 4 + 0.5) - ); - float distRaw = MHelper.length(mut.getX() - pos.getX(), mut.getZ() - pos.getZ()); - int dist = MHelper.floor(6 - distRaw) + random.nextInt(2); - if (dist >= 0) { - state = world.getBlockState(mut); - while (!state.getFluidState().isEmpty() || state.getMaterial().equals(Material.WATER_PLANT)) { - mut.setY(mut.getY() - 1); - state = world.getBlockState(mut); - } - if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()).is(EndBlocks.HYDROTHERMAL_VENT)) { - for (int j = 0; j <= dist; j++) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); - MHelper.shuffle(HORIZONTAL, random); - for (Direction dir : HORIZONTAL) { - BlockPos p = mut.relative(dir); - if (random.nextBoolean() && world.getBlockState(p).is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate( - world, - p, - EndBlocks.TUBE_WORM.defaultBlockState() - .setValue(HorizontalDirectionalBlock.FACING, dir) - ); - } - } - mut.setY(mut.getY() + 1); - } - state = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() - .setValue(HydrothermalVentBlock.ACTIVATED, distRaw < 2); - BlocksHelper.setWithoutUpdate(world, mut, state); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - while (state.is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - } - } - } - } - - for (int i = 0; i < 10; i++) { - mut.set(pos) - .move(MHelper.floor(random.nextGaussian() * 0.7 + 0.5), - -halfHeight - 10, - MHelper.floor(random.nextGaussian() * 0.7 + 0.5) - ); - float distRaw = MHelper.length(mut.getX() - pos.getX(), mut.getZ() - pos.getZ()); - int dist = MHelper.floor(6 - distRaw) + random.nextInt(2); - if (dist >= 0) { - state = world.getBlockState(mut); - while (state.is(Blocks.WATER)) { - mut.setY(mut.getY() - 1); - state = world.getBlockState(mut); - } - if (state.is(CommonBlockTags.GEN_END_STONES)) { - for (int j = 0; j <= dist; j++) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); - mut.setY(mut.getY() + 1); - } - state = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() - .setValue(HydrothermalVentBlock.ACTIVATED, distRaw < 2); - BlocksHelper.setWithoutUpdate(world, mut, state); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - while (state.is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - } - } - } - } - - EndFeatures.SULPHURIC_LAKE.getFeature() - .place(new FeaturePlaceContext<>(Optional.empty(), world, chunkGenerator, random, pos, null)); - - double distance = radius1 * 1.7; - BlockPos start = pos.offset(-distance, -halfHeight - 15 - distance, -distance); - BlockPos end = pos.offset(distance, -halfHeight - 5 + distance, distance); - BlockFixer.fixBlocks(world, start, end); - - return true; - } - - static { - REPLACE1 = (state) -> { - return state.isAir() || (state.is(CommonBlockTags.GEN_END_STONES)); - }; - - REPLACE2 = (state) -> { - if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.HYDROTHERMAL_VENT) || state.is(EndBlocks.SULPHUR_CRYSTAL)) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = (state) -> { - return state.is(Blocks.WATER) || state.is(Blocks.CAVE_AIR) || state.is(EndBlocks.SULPHURIC_ROCK.stone) || state - .is(EndBlocks.BRIMSTONE); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/IceStarFeature.java b/src/main/java/ru/betterend/world/features/terrain/IceStarFeature.java deleted file mode 100644 index 018e7c6a..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/IceStarFeature.java +++ /dev/null @@ -1,117 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class IceStarFeature extends DefaultFeature { - private final float minSize; - private final float maxSize; - private final int minCount; - private final int maxCount; - - public IceStarFeature(float minSize, float maxSize, int minCount, int maxCount) { - this.minSize = minSize; - this.maxSize = maxSize; - this.minCount = minCount; - this.maxCount = maxCount; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - float size = MHelper.randRange(minSize, maxSize, random); - int count = MHelper.randRange(minCount, maxCount, random); - List points = getFibonacciPoints(count); - SDF sdf = null; - SDF spike = new SDFCappedCone().setRadius1(3 + (size - 5) * 0.2F) - .setRadius2(0) - .setHeight(size) - .setBlock(EndBlocks.DENSE_SNOW); - spike = new SDFTranslate().setTranslate(0, size - 0.5F, 0).setSource(spike); - for (Vector3f point : points) { - SDF rotated = spike; - point = MHelper.normalize(point); - float angle = MHelper.angle(Vector3f.YP, point); - if (angle > 0.01F && angle < 3.14F) { - Vector3f axis = MHelper.normalize(MHelper.cross(Vector3f.YP, point)); - rotated = new SDFRotation().setRotation(axis, angle).setSource(spike); - } - else if (angle > 1) { - rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(spike); - } - sdf = (sdf == null) ? rotated : new SDFUnion().setSourceA(sdf).setSourceB(rotated); - } - - int x1 = (pos.getX() >> 4) << 4; - int z1 = (pos.getZ() >> 4) << 4; - pos = new BlockPos(x1 + random.nextInt(16), MHelper.randRange(32, 128, random), z1 + random.nextInt(16)); - - final float ancientRadius = size * 0.7F; - final float denseRadius = size * 0.9F; - final float iceRadius = size < 7 ? size * 5 : size * 1.3F; - final float randScale = size * 0.3F; - - final BlockPos center = pos; - final BlockState ice = EndBlocks.EMERALD_ICE.defaultBlockState(); - final BlockState dense = EndBlocks.DENSE_EMERALD_ICE.defaultBlockState(); - final BlockState ancient = EndBlocks.ANCIENT_EMERALD_ICE.defaultBlockState(); - final SDF sdfCopy = sdf; - - sdf.addPostProcess((info) -> { - BlockPos bpos = info.getPos(); - float px = bpos.getX() - center.getX(); - float py = bpos.getY() - center.getY(); - float pz = bpos.getZ() - center.getZ(); - float distance = MHelper.length(px, py, pz) + sdfCopy.getDistance( - px, - py, - pz - ) * 0.4F + random.nextFloat() * randScale; - if (distance < ancientRadius) { - return ancient; - } - else if (distance < denseRadius) { - return dense; - } - else if (distance < iceRadius) { - return ice; - } - return info.getState(); - }).fillRecursive(world, pos); - - return true; - } - - private List getFibonacciPoints(int count) { - float max = count - 1; - List result = new ArrayList(count); - for (int i = 0; i < count; i++) { - float y = 1F - (i / max) * 2F; - float radius = (float) Math.sqrt(1F - y * y); - float theta = MHelper.PHI * i; - float x = (float) Math.cos(theta) * radius; - float z = (float) Math.sin(theta) * radius; - result.add(new Vector3f(x, y, z)); - } - return result; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/ObsidianBoulderFeature.java b/src/main/java/ru/betterend/world/features/terrain/ObsidianBoulderFeature.java deleted file mode 100644 index 1be9cd43..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/ObsidianBoulderFeature.java +++ /dev/null @@ -1,76 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class ObsidianBoulderFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - pos = getPosOnSurface( - world, - new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) - ); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - return false; - } - - int count = MHelper.randRange(1, 5, random); - for (int i = 0; i < count; i++) { - BlockPos p = getPosOnSurface( - world, - new BlockPos(pos.getX() + random.nextInt(16) - 8, pos.getY(), pos.getZ() + random.nextInt(16) - 8) - ); - makeBoulder(world, p, random); - } - - return true; - } - - private void makeBoulder(WorldGenLevel world, BlockPos pos, RandomSource random) { - if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) { - return; - } - - float radius = MHelper.randRange(1F, 5F, random); - SDF sphere = new SDFSphere().setRadius(radius).setBlock(Blocks.OBSIDIAN); - float sx = MHelper.randRange(0.7F, 1.3F, random); - float sy = MHelper.randRange(0.7F, 1.3F, random); - float sz = MHelper.randRange(0.7F, 1.3F, random); - sphere = new SDFScale3D().setScale(sx, sy, sz).setSource(sphere); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) (noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 1.5F); - }).setSource(sphere); - - BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); - sphere.addPostProcess((info) -> { - if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { - return mossy; - } - return info.getState(); - }).setReplaceFunction((state) -> { - return state.getMaterial().isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() - .equals(Material.PLANT); - }).fillRecursive(world, pos); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/ObsidianPillarBasementFeature.java b/src/main/java/ru/betterend/world/features/terrain/ObsidianPillarBasementFeature.java deleted file mode 100644 index 51bf8aca..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/ObsidianPillarBasementFeature.java +++ /dev/null @@ -1,74 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.sdf.primitive.SDFFlatland; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class ObsidianPillarBasementFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - pos = getPosOnSurface( - world, - new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) - ); - if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - float height = MHelper.randRange(10F, 35F, random); - float radius = MHelper.randRange(2F, 5F, random); - SDF pillar = new SDFCappedCone().setRadius1(radius) - .setRadius2(radius) - .setHeight(height * 0.5F) - .setBlock(Blocks.OBSIDIAN); - pillar = new SDFTranslate().setTranslate(0, height * 0.5F - 3, 0).setSource(pillar); - SDF cut = new SDFFlatland().setBlock(Blocks.OBSIDIAN); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - cut = new SDFDisplacement().setFunction((vec) -> { - return (float) (noise.eval(vec.x() * 0.2, vec.z() * 0.2) * 3); - }).setSource(cut); - Vector3f vec = MHelper.randomHorizontal(random); - float angle = random.nextFloat() * 0.5F + (float) Math.PI; - cut = new SDFRotation().setRotation(vec, angle).setSource(cut); - cut = new SDFTranslate().setTranslate(0, height * 0.7F - 3, 0).setSource(cut); - pillar = new SDFSubtraction().setSourceA(pillar).setSourceB(cut); - vec = MHelper.randomHorizontal(random); - angle = random.nextFloat() * 0.2F; - pillar = new SDFRotation().setRotation(vec, angle).setSource(pillar); - BlockState mossy = EndBlocks.MOSSY_OBSIDIAN.defaultBlockState(); - pillar.addPostProcess((info) -> { - if (info.getStateUp().isAir() && random.nextFloat() > 0.1F) { - return mossy; - } - return info.getState(); - }).setReplaceFunction((state) -> { - return state.getMaterial().isReplaceable() || state.is(CommonBlockTags.GEN_END_STONES) || state.getMaterial() - .equals(Material.PLANT); - }).fillRecursive(world, pos); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/OreLayerFeature.java b/src/main/java/ru/betterend/world/features/terrain/OreLayerFeature.java deleted file mode 100644 index 73f060a6..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/OreLayerFeature.java +++ /dev/null @@ -1,77 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFCoordModify; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class OreLayerFeature extends DefaultFeature { - private static final SDFSphere SPHERE; - private static final SDFCoordModify NOISE; - private static final SDF FUNCTION; - - private final BlockState state; - private final float radius; - private final int minY; - private final int maxY; - private OpenSimplexNoise noise; - - public OreLayerFeature(BlockState state, float radius, int minY, int maxY) { - this.state = state; - this.radius = radius; - this.minY = minY; - this.maxY = maxY; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - float radius = this.radius * 0.5F; - int r = MHelper.floor(radius + 1); - int posX = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getX(); - int posZ = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getZ(); - int posY = MHelper.randRange(minY, maxY, random); - - if (noise == null) { - noise = new OpenSimplexNoise(world.getSeed()); - } - - SPHERE.setRadius(radius).setBlock(state); - NOISE.setFunction((vec) -> { - double x = (vec.x() + pos.getX()) * 0.1; - double z = (vec.z() + pos.getZ()) * 0.1; - double offset = noise.eval(x, z); - vec.set(vec.x(), vec.y() + (float) offset * 8, vec.z()); - }); - FUNCTION.fillRecursive(world, new BlockPos(posX, posY, posZ)); - return true; - } - - static { - SPHERE = new SDFSphere(); - NOISE = new SDFCoordModify(); - - SDF body = SPHERE; - body = new SDFScale3D().setScale(1, 0.2F, 1).setSource(body); - body = NOISE.setSource(body); - body.setReplaceFunction((state) -> { - return state.is(Blocks.END_STONE); - }); - - FUNCTION = body; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SingleBlockFeature.java b/src/main/java/ru/betterend/world/features/terrain/SingleBlockFeature.java deleted file mode 100644 index d78fd62f..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SingleBlockFeature.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.WorldGenLevel; -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.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SingleBlockFeature extends DefaultFeature { - private final Block block; - - public SingleBlockFeature(Block block) { - this.block = block; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - BlockState state = block.defaultBlockState(); - if (block.getStateDefinition().getProperty("waterlogged") != null) { - boolean waterlogged = !world.getFluidState(pos).isEmpty(); - state = state.setValue(BlockStateProperties.WATERLOGGED, waterlogged); - } - BlocksHelper.setWithoutUpdate(world, pos, state); - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SmaragdantCrystalFeature.java b/src/main/java/ru/betterend/world/features/terrain/SmaragdantCrystalFeature.java deleted file mode 100644 index 54d6de82..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SmaragdantCrystalFeature.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SmaragdantCrystalFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - MutableBlockPos mut = new MutableBlockPos(); - int count = MHelper.randRange(15, 30, random); - BlockState crystal = EndBlocks.SMARAGDANT_CRYSTAL.defaultBlockState(); - BlockState shard = EndBlocks.SMARAGDANT_CRYSTAL_SHARD.defaultBlockState(); - for (int i = 0; i < count; i++) { - mut.set(pos) - .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), 5, MHelper.floor(random.nextGaussian() * 2 + 0.5)); - int dist = MHelper.floor(1.5F - MHelper.length( - mut.getX() - pos.getX(), - mut.getZ() - pos.getZ() - )) + random.nextInt(3); - if (dist > 0) { - BlockState state = world.getBlockState(mut); - for (int n = 0; n < 10 && state.isAir(); n++) { - mut.setY(mut.getY() - 1); - state = world.getBlockState(mut); - } - if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()).is(crystal.getBlock())) { - for (int j = 0; j <= dist; j++) { - BlocksHelper.setWithoutUpdate(world, mut, crystal); - mut.setY(mut.getY() + 1); - } - boolean waterlogged = !world.getFluidState(mut).isEmpty(); - BlocksHelper.setWithoutUpdate( - world, - mut, - shard.setValue(BlockStateProperties.WATERLOGGED, waterlogged) - ); - } - } - } - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java b/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java deleted file mode 100644 index 87594eed..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java +++ /dev/null @@ -1,115 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBiomes; -import ru.betterend.registry.EndFeatures; -import ru.betterend.world.biome.EndBiome; - -import java.util.List; -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class SpireFeature extends DefaultFeature { - protected static final Function REPLACE; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - final ChunkGenerator chunkGenerator = featureConfig.chunkGenerator(); - pos = getPosOnSurfaceWG(world, pos); - if (pos.getY() < 10 || !world.getBlockState(pos.below(3)) - .is(CommonBlockTags.GEN_END_STONES) || !world.getBlockState(pos.below(6)) - .is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - SDF sdf = new SDFSphere().setRadius(MHelper.randRange(2, 3, random)).setBlock(Blocks.END_STONE); - int count = MHelper.randRange(3, 7, random); - for (int i = 0; i < count; i++) { - float rMin = (i * 1.3F) + 2.5F; - sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); - } - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - sdf = new SDFDisplacement().setFunction((vec) -> { - return (float) (Math.abs(noise.eval( - vec.x() * 0.1, - vec.y() * 0.1, - vec.z() * 0.1 - )) * 3F + Math.abs(noise.eval(vec.x() * 0.3, vec.y() * 0.3 + 100, vec.z() * 0.3)) * 1.3F); - }).setSource(sdf); - final BlockPos center = pos; - List support = Lists.newArrayList(); - sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { - if (info.getStateUp().isAir()) { - if (random.nextInt(16) == 0) { - support.add(info.getPos().above()); - } - return EndBiome.findTopMaterial(world, info.getPos()); - //return world.getBiome(info.getPos()).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - } - else if (info.getState(Direction.UP, 3).isAir()) { - return EndBiome.findUnderMaterial(world, info.getPos()); -// return world.getBiome(info.getPos()) -// .getGenerationSettings() -// .getSurfaceBuilderConfig() -// .getUnderMaterial(); - } - return info.getState(); - }).fillRecursive(world, center); - - support.forEach((bpos) -> { - if (BiomeAPI.getFromBiome(world.getBiome(bpos)) == EndBiomes.BLOSSOMING_SPIRES) { - EndFeatures.TENANEA_BUSH.getFeature() - .place(new FeaturePlaceContext<>(Optional.empty(), world, chunkGenerator, random, bpos, null)); - } - }); - - return true; - } - - protected SDF addSegment(SDF sdf, float radius, RandomSource random) { - SDF sphere = new SDFSphere().setRadius(radius).setBlock(Blocks.END_STONE); - SDF offseted = new SDFTranslate().setTranslate(0, radius + random.nextFloat() * 0.25F * radius, 0) - .setSource(sdf); - return new SDFSmoothUnion().setRadius(radius * 0.5F).setSourceA(sphere).setSourceB(offseted); - } - - static { - REPLACE = (state) -> { - if (state.is(CommonBlockTags.END_STONES)) { - return true; - } - if (state.getBlock() instanceof LeavesBlock) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/StalactiteFeature.java b/src/main/java/ru/betterend/world/features/terrain/StalactiteFeature.java deleted file mode 100644 index c7e9367e..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/StalactiteFeature.java +++ /dev/null @@ -1,85 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -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.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.StalactiteBlock; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class StalactiteFeature extends DefaultFeature { - private final boolean ceiling; - private final Block[] ground; - private final Block block; - - public StalactiteFeature(boolean ceiling, Block block, Block... ground) { - this.ceiling = ceiling; - this.ground = ground; - this.block = block; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!isGround(world.getBlockState(ceiling ? pos.above() : pos.below()).getBlock())) { - return false; - } - - MutableBlockPos mut = new MutableBlockPos().set(pos); - int height = random.nextInt(16); - int dir = ceiling ? -1 : 1; - boolean stalagnate = false; - - for (int i = 1; i <= height; i++) { - mut.setY(pos.getY() + i * dir); - BlockState state = world.getBlockState(mut); - if (!state.getMaterial().isReplaceable()) { - stalagnate = state.is(CommonBlockTags.GEN_END_STONES); - height = i; - break; - } - } - - if (!stalagnate && height > 7) { - height = random.nextInt(8); - } - - float center = height * 0.5F; - for (int i = 0; i < height; i++) { - mut.setY(pos.getY() + i * dir); - int size = stalagnate ? Mth.clamp((int) (Mth.abs(i - center) + 1), 1, 7) : height - i - 1; - boolean waterlogged = !world.getFluidState(mut).isEmpty(); - BlockState base = block.defaultBlockState() - .setValue(StalactiteBlock.SIZE, size) - .setValue(BlockStateProperties.WATERLOGGED, waterlogged); - BlockState state = stalagnate ? base.setValue( - StalactiteBlock.IS_FLOOR, - dir > 0 ? i < center : i > center - ) : base.setValue(StalactiteBlock.IS_FLOOR, dir > 0); - BlocksHelper.setWithoutUpdate(world, mut, state); - } - - return true; - } - - private boolean isGround(Block block) { - for (Block b : ground) { - if (b == block) { - return true; - } - } - return false; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SulphurHillFeature.java b/src/main/java/ru/betterend/world/features/terrain/SulphurHillFeature.java deleted file mode 100644 index aff59889..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SulphurHillFeature.java +++ /dev/null @@ -1,98 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SulphurHillFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - pos = getPosOnSurfaceWG(world, pos); - if (pos.getY() < 57 || pos.getY() > 70) { - return false; - } - - int count = MHelper.randRange(5, 13, random); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - for (int i = 0; i < count; i++) { - int dist = count - i; - int px = pos.getX() + MHelper.floor(random.nextGaussian() * dist * 0.6 + 0.5); - int pz = pos.getZ() + MHelper.floor(random.nextGaussian() * dist * 0.6 + 0.5); - int py = getYOnSurface(world, px, pz); - if (py > 56 && py - pos.getY() <= count) { - makeCircle(world, new BlockPos(px, py, pz), noise, random); - } - } - return true; - } - - private void makeCircle(WorldGenLevel world, BlockPos pos, OpenSimplexNoise noise, RandomSource random) { - int radius = MHelper.randRange(5, 9, random); - int min = -radius - 3; - int max = radius + 4; - MutableBlockPos mut = new MutableBlockPos(); - BlockState rock = EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState(); - BlockState brimstone = EndBlocks.BRIMSTONE.defaultBlockState().setValue(BlockProperties.ACTIVE, true); - for (int x = min; x < max; x++) { - int x2 = x * x; - int px = pos.getX() + x; - mut.setX(px); - for (int z = min; z < max; z++) { - int z2 = z * z; - int pz = pos.getZ() + z; - mut.setZ(pz); - double r1 = radius * (noise.eval(px * 0.1, pz * 0.1) * 0.2 + 0.8); - double r2 = r1 - 1.5; - double r3 = r1 - 3; - int d = x2 + z2; - mut.setY(pos.getY()); - BlockState state = world.getBlockState(mut); - if (state.getMaterial().isReplaceable() || state.is(EndBlocks.HYDROTHERMAL_VENT)) { - if (d < r2 * r2) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.WATER); - mut.move(Direction.DOWN); - if (d < r3 * r3) { - BlocksHelper.setWithoutUpdate(world, mut, Blocks.WATER); - mut.move(Direction.DOWN); - } - BlocksHelper.setWithoutUpdate(world, mut, brimstone); - mut.move(Direction.DOWN); - state = world.getBlockState(mut); - int maxIt = MHelper.floor(10 - Math.sqrt(d)) + random.nextInt(1); - for (int i = 0; i < maxIt && state.getMaterial().isReplaceable(); i++) { - BlocksHelper.setWithoutUpdate(world, mut, rock); - mut.move(Direction.DOWN); - } - } - else if (d < r1 * r1) { - BlocksHelper.setWithoutUpdate(world, mut, brimstone); - mut.move(Direction.DOWN); - state = world.getBlockState(mut); - int maxIt = MHelper.floor(10 - Math.sqrt(d)) + random.nextInt(1); - for (int i = 0; i < maxIt && state.getMaterial().isReplaceable(); i++) { - BlocksHelper.setWithoutUpdate(world, mut, rock); - mut.move(Direction.DOWN); - } - } - } - } - } - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java deleted file mode 100644 index 08abdc46..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SulphuricCaveFeature.java +++ /dev/null @@ -1,222 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.EndBlockProperties; -import ru.betterend.blocks.SulphurCrystalBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.util.BlockFixer; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; - -public class SulphuricCaveFeature extends DefaultFeature { - private static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); - private static final BlockState WATER = Blocks.WATER.defaultBlockState(); - private static final Direction[] HORIZONTAL = BlocksHelper.makeHorizontal(); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - int radius = MHelper.randRange(10, 30, random); - - int top = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - MutableBlockPos bpos = new MutableBlockPos(); - bpos.setX(pos.getX()); - bpos.setZ(pos.getZ()); - bpos.setY(top - 1); - - BlockState state = world.getBlockState(bpos); - while (!state.is(CommonBlockTags.GEN_END_STONES) && bpos.getY() > 5) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - if (bpos.getY() < 10) { - return false; - } - top = (int) (bpos.getY() - (radius * 1.3F + 5)); - - while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - int bottom = (int) (bpos.getY() + radius * 1.3F + 5); - - if (top <= bottom) { - return false; - } - - MutableBlockPos mut = new MutableBlockPos(); - pos = new BlockPos(pos.getX(), MHelper.randRange(bottom, top, random), pos.getZ()); - - OpenSimplexNoise noise = new OpenSimplexNoise(MHelper.getSeed(534, pos.getX(), pos.getZ())); - - int x1 = pos.getX() - radius - 5; - int z1 = pos.getZ() - radius - 5; - int x2 = pos.getX() + radius + 5; - int z2 = pos.getZ() + radius + 5; - int y1 = MHelper.floor(pos.getY() - (radius + 5) / 1.6); - int y2 = MHelper.floor(pos.getY() + (radius + 5) / 1.6); - - double hr = radius * 0.75; - double nr = radius * 0.25; - - Set brimstone = Sets.newHashSet(); - BlockState rock = EndBlocks.SULPHURIC_ROCK.stone.defaultBlockState(); - int waterLevel = pos.getY() + MHelper.randRange(MHelper.floor(radius * 0.8), radius, random); - for (int x = x1; x <= x2; x++) { - int xsq = x - pos.getX(); - xsq *= xsq; - mut.setX(x); - for (int z = z1; z <= z2; z++) { - int zsq = z - pos.getZ(); - zsq *= zsq; - mut.setZ(z); - for (int y = y1; y <= y2; y++) { - int ysq = y - pos.getY(); - ysq *= 1.6; - ysq *= ysq; - mut.setY(y); - double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; - double r2 = r + 5; - double dist = xsq + ysq + zsq; - if (dist < r * r) { - state = world.getBlockState(mut); - if (isReplaceable(state)) { - BlocksHelper.setWithoutUpdate(world, mut, y < waterLevel ? WATER : CAVE_AIR); - } - } - else if (dist < r2 * r2) { - state = world.getBlockState(mut); - if (state.is(CommonBlockTags.GEN_END_STONES) || state.is(Blocks.AIR)) { - double v = noise.eval(x * 0.1, y * 0.1, z * 0.1) + noise.eval( - x * 0.03, - y * 0.03, - z * 0.03 - ) * 0.5; - if (v > 0.4) { - brimstone.add(mut.immutable()); - } - else { - BlocksHelper.setWithoutUpdate(world, mut, rock); - } - } - } - } - } - } - brimstone.forEach((blockPos) -> { - placeBrimstone(world, blockPos, random); - }); - - if (random.nextInt(4) == 0) { - int count = MHelper.randRange(5, 20, random); - for (int i = 0; i < count; i++) { - mut.set(pos) - .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), - 0, - MHelper.floor(random.nextGaussian() * 2 + 0.5) - ); - int dist = MHelper.floor(3 - MHelper.length( - mut.getX() - pos.getX(), - mut.getZ() - pos.getZ() - )) + random.nextInt(2); - if (dist > 0) { - state = world.getBlockState(mut); - while (!state.getFluidState().isEmpty() || state.getMaterial().equals(Material.WATER_PLANT)) { - mut.setY(mut.getY() - 1); - state = world.getBlockState(mut); - } - if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()) - .is(EndBlocks.HYDROTHERMAL_VENT)) { - for (int j = 0; j <= dist; j++) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); - MHelper.shuffle(HORIZONTAL, random); - for (Direction dir : HORIZONTAL) { - BlockPos p = mut.relative(dir); - if (random.nextBoolean() && world.getBlockState(p).is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate( - world, - p, - EndBlocks.TUBE_WORM.defaultBlockState() - .setValue(HorizontalDirectionalBlock.FACING, dir) - ); - } - } - mut.setY(mut.getY() + 1); - } - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.HYDROTHERMAL_VENT); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - while (state.is(Blocks.WATER)) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.VENT_BUBBLE_COLUMN.defaultBlockState()); - world.scheduleTick(mut.immutable(), EndBlocks.VENT_BUBBLE_COLUMN, MHelper.randRange(8, 32, random)); - mut.setY(mut.getY() + 1); - state = world.getBlockState(mut); - } - } - } - } - } - - BlockFixer.fixBlocks(world, new BlockPos(x1, y1, z1), new BlockPos(x2, y2, z2)); - - return true; - } - - private boolean isReplaceable(BlockState state) { - return state.is(CommonBlockTags.GEN_END_STONES) || state.is(EndBlocks.HYDROTHERMAL_VENT) || state.is(EndBlocks.VENT_BUBBLE_COLUMN) || state - .is(EndBlocks.SULPHUR_CRYSTAL) || state.getMaterial().isReplaceable() || state.getMaterial() - .equals(Material.PLANT) || state - .getMaterial() - .equals(Material.WATER_PLANT) || state.getMaterial().equals(Material.LEAVES); - } - - private void placeBrimstone(WorldGenLevel world, BlockPos pos, RandomSource random) { - BlockState state = getBrimstone(world, pos); - BlocksHelper.setWithoutUpdate(world, pos, state); - if (state.getValue(EndBlockProperties.ACTIVE)) { - makeShards(world, pos, random); - } - } - - private BlockState getBrimstone(WorldGenLevel world, BlockPos pos) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (world.getBlockState(pos.relative(dir)).is(Blocks.WATER)) { - return EndBlocks.BRIMSTONE.defaultBlockState().setValue(EndBlockProperties.ACTIVE, true); - } - } - return EndBlocks.BRIMSTONE.defaultBlockState(); - } - - private void makeShards(WorldGenLevel world, BlockPos pos, RandomSource random) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - BlockPos side; - if (random.nextInt(16) == 0 && world.getBlockState((side = pos.relative(dir))).is(Blocks.WATER)) { - BlockState state = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() - .setValue(SulphurCrystalBlock.WATERLOGGED, true) - .setValue(SulphurCrystalBlock.FACING, dir) - .setValue(SulphurCrystalBlock.AGE, random.nextInt(3)); - BlocksHelper.setWithoutUpdate(world, side, state); - } - } - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SulphuricLakeFeature.java b/src/main/java/ru/betterend/world/features/terrain/SulphuricLakeFeature.java deleted file mode 100644 index cfd79072..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SulphuricLakeFeature.java +++ /dev/null @@ -1,212 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Fluids; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.EndBlockProperties; -import ru.betterend.blocks.SulphurCrystalBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; - -public class SulphuricLakeFeature extends DefaultFeature { - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(15152); - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - BlockPos blockPos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - blockPos = getPosOnSurfaceWG(world, blockPos); - - if (blockPos.getY() < 57) { - return false; - } - - final RandomSource random = featureConfig.random(); - final MutableBlockPos POS = GlobalState.stateForThread().POS; - double radius = MHelper.randRange(10.0, 20.0, random); - int dist2 = MHelper.floor(radius * 1.5); - - int minX = blockPos.getX() - dist2; - int maxX = blockPos.getX() + dist2; - int minZ = blockPos.getZ() - dist2; - int maxZ = blockPos.getZ() + dist2; - - Set brimstone = Sets.newHashSet(); - for (int x = minX; x <= maxX; x++) { - POS.setX(x); - int x2 = x - blockPos.getX(); - x2 *= x2; - for (int z = minZ; z <= maxZ; z++) { - POS.setZ(z); - int z2 = z - blockPos.getZ(); - z2 *= z2; - double r = radius * (NOISE.eval(x * 0.2, z * 0.2) * 0.25 + 0.75); - double r2 = r * 1.5; - r *= r; - r2 *= r2; - int dist = x2 + z2; - if (dist <= r) { - POS.setY(getYOnSurface(world, x, z) - 1); - if (world.getBlockState(POS).is(CommonBlockTags.GEN_END_STONES)) { - if (isBorder(world, POS)) { - if (random.nextInt(8) > 0) { - brimstone.add(POS.immutable()); - if (random.nextBoolean()) { - brimstone.add(POS.below()); - if (random.nextBoolean()) { - brimstone.add(POS.below(2)); - } - } - } - else { - if (!isAbsoluteBorder(world, POS)) { - BlocksHelper.setWithoutUpdate(world, POS, Blocks.WATER); - //world.setBlock(blockPos, Blocks.WATER.defaultBlockState(), 2); - world.scheduleTick(POS, Fluids.WATER, 0); - brimstone.add(POS.below()); - if (random.nextBoolean()) { - brimstone.add(POS.below(2)); - if (random.nextBoolean()) { - brimstone.add(POS.below(3)); - } - } - } - else { - brimstone.add(POS.immutable()); - if (random.nextBoolean()) { - brimstone.add(POS.below()); - } - } - } - } - else { - BlocksHelper.setWithoutUpdate(world, POS, Blocks.WATER); - brimstone.remove(POS); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos offseted = POS.relative(dir); - if (world.getBlockState(offseted).is(CommonBlockTags.GEN_END_STONES)) { - brimstone.add(offseted); - } - } - if (isDeepWater(world, POS)) { - BlocksHelper.setWithoutUpdate(world, POS.move(Direction.DOWN), Blocks.WATER); - brimstone.remove(POS); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos offseted = POS.relative(dir); - if (world.getBlockState(offseted).is(CommonBlockTags.GEN_END_STONES)) { - brimstone.add(offseted); - } - } - } - brimstone.add(POS.below()); - if (random.nextBoolean()) { - brimstone.add(POS.below(2)); - if (random.nextBoolean()) { - brimstone.add(POS.below(3)); - } - } - } - } - } - else if (dist < r2) { - POS.setY(getYOnSurface(world, x, z) - 1); - if (world.getBlockState(POS).is(CommonBlockTags.GEN_END_STONES)) { - brimstone.add(POS.immutable()); - if (random.nextBoolean()) { - brimstone.add(POS.below()); - if (random.nextBoolean()) { - brimstone.add(POS.below(2)); - } - } - } - } - } - } - - brimstone.forEach((bpos) -> { - placeBrimstone(world, bpos, random); - }); - - return true; - } - - private boolean isBorder(WorldGenLevel world, BlockPos pos) { - int y = pos.getY() + 1; - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (getYOnSurface(world, pos.getX() + dir.getStepX(), pos.getZ() + dir.getStepZ()) < y) { - return true; - } - } - return false; - } - - private boolean isAbsoluteBorder(WorldGenLevel world, BlockPos pos) { - int y = pos.getY() - 2; - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (getYOnSurface(world, pos.getX() + dir.getStepX() * 3, pos.getZ() + dir.getStepZ() * 3) < y) { - return true; - } - } - return false; - } - - private boolean isDeepWater(WorldGenLevel world, BlockPos pos) { - int y = pos.getY() + 1; - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (getYOnSurface(world, pos.getX() + dir.getStepX(), pos.getZ() + dir.getStepZ()) < y || getYOnSurface( - world, - pos.getX() + dir.getStepX() * 2, - pos.getZ() + dir.getStepZ() * 2 - ) < y || getYOnSurface(world, pos.getX() + dir.getStepX() * 3, pos.getZ() + dir.getStepZ() * 3) < y) { - return false; - } - } - return true; - } - - private void placeBrimstone(WorldGenLevel world, BlockPos pos, RandomSource random) { - BlockState state = getBrimstone(world, pos); - BlocksHelper.setWithoutUpdate(world, pos, state); - if (state.getValue(EndBlockProperties.ACTIVE)) { - makeShards(world, pos, random); - } - } - - private BlockState getBrimstone(WorldGenLevel world, BlockPos pos) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (world.getBlockState(pos.relative(dir)).is(Blocks.WATER)) { - return EndBlocks.BRIMSTONE.defaultBlockState().setValue(EndBlockProperties.ACTIVE, true); - } - } - return EndBlocks.BRIMSTONE.defaultBlockState(); - } - - private void makeShards(WorldGenLevel world, BlockPos pos, RandomSource random) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - BlockPos side; - if (random.nextInt(16) == 0 && world.getBlockState((side = pos.relative(dir))).is(Blocks.WATER)) { - BlockState state = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState() - .setValue(SulphurCrystalBlock.WATERLOGGED, true) - .setValue(SulphurCrystalBlock.FACING, dir) - .setValue(SulphurCrystalBlock.AGE, random.nextInt(3)); - BlocksHelper.setWithoutUpdate(world, side, state); - } - } - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/SurfaceVentFeature.java b/src/main/java/ru/betterend/world/features/terrain/SurfaceVentFeature.java deleted file mode 100644 index 9e9e72fe..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/SurfaceVentFeature.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.betterend.world.features.terrain; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.HydrothermalVentBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class SurfaceVentFeature extends DefaultFeature { - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - pos = getPosOnSurface( - world, - new BlockPos(pos.getX() + random.nextInt(16), pos.getY(), pos.getZ() + random.nextInt(16)) - ); - if (!world.getBlockState(pos.below(3)).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - MutableBlockPos mut = new MutableBlockPos(); - int count = MHelper.randRange(15, 30, random); - BlockState vent = EndBlocks.HYDROTHERMAL_VENT.defaultBlockState() - .setValue(HydrothermalVentBlock.WATERLOGGED, false); - for (int i = 0; i < count; i++) { - mut.set(pos) - .move(MHelper.floor(random.nextGaussian() * 2 + 0.5), 5, MHelper.floor(random.nextGaussian() * 2 + 0.5)); - int dist = MHelper.floor(2 - MHelper.length( - mut.getX() - pos.getX(), - mut.getZ() - pos.getZ() - )) + random.nextInt(2); - if (dist > 0) { - BlockState state = world.getBlockState(mut); - for (int n = 0; n < 10 && state.isAir(); n++) { - mut.setY(mut.getY() - 1); - state = world.getBlockState(mut); - } - if (state.is(CommonBlockTags.GEN_END_STONES) && !world.getBlockState(mut.above()).is(EndBlocks.HYDROTHERMAL_VENT)) { - for (int j = 0; j <= dist; j++) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.SULPHURIC_ROCK.stone); - mut.setY(mut.getY() + 1); - } - BlocksHelper.setWithoutUpdate(world, mut, vent); - } - } - } - - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/ThinArchFeature.java b/src/main/java/ru/betterend/world/features/terrain/ThinArchFeature.java deleted file mode 100644 index 72fc60b9..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/ThinArchFeature.java +++ /dev/null @@ -1,78 +0,0 @@ -package ru.betterend.world.features.terrain; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFCoordModify; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFTorus; -import ru.bclib.util.MHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class ThinArchFeature extends DefaultFeature { - private Block block; - - public ThinArchFeature(Block block) { - this.block = block; - } - - @Override - public boolean place(FeaturePlaceContext featurePlaceContext) { - final WorldGenLevel world = featurePlaceContext.level(); - BlockPos origin = featurePlaceContext.origin(); - RandomSource random = featurePlaceContext.random(); - - BlockPos pos = getPosOnSurfaceWG(world, new BlockPos((origin.getX() & 0xFFFFFFF0) | 7, 0, (origin.getZ() & 0xFFFFFFF0) | 7)); - if (!world.getBlockState(pos.below(5)).is(CommonBlockTags.GEN_END_STONES)) { - return false; - } - - SDF sdf = null; - float bigRadius = MHelper.randRange(15F, 20F, random); - float variation = bigRadius * 0.3F; - int count = MHelper.randRange(2, 4, random); - - for (int i = 0; i < count; i++) { - float smallRadius = MHelper.randRange(0.6F, 1.3F, random); - SDF arch = new SDFTorus().setBigRadius(bigRadius - random.nextFloat() * variation).setSmallRadius(smallRadius).setBlock(block); - float angle = (i - count * 0.5F) * 0.3F + random.nextFloat() * 0.05F + (float) Math.PI * 0.5F; - arch = new SDFRotation().setRotation(Vector3f.XP, angle).setSource(arch); - sdf = sdf == null ? arch : new SDFUnion().setSourceA(sdf).setSourceB(arch); - } - - sdf = new SDFRotation().setRotation(MHelper.randomHorizontal(random), random.nextFloat() * MHelper.PI2).setSource(sdf); - - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - sdf = new SDFCoordModify().setFunction(vec -> { - float dx = (float) noise.eval(vec.y() * 0.02, vec.z() * 0.02); - float dy = (float) noise.eval(vec.x() * 0.02, vec.z() * 0.02); - float dz = (float) noise.eval(vec.x() * 0.02, vec.y() * 0.02); - vec.add(dx * 10, dy * 10, dz * 10); - }).setSource(sdf); - sdf = new SDFDisplacement().setFunction(vec -> { - float offset = vec.y() / bigRadius - 0.5F; - return Mth.clamp(offset * 3, -10F, 0F); - }).setSource(sdf); - - float side = (bigRadius + 2.5F) * 2; - if (side > 47) { - side = 47; - } - sdf.fillArea(world, pos, AABB.ofSize(Vec3.atCenterOf(pos), side, side, side)); - return true; - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java deleted file mode 100644 index 9ff9719e..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/caves/CaveChunkPopulatorFeature.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.betterend.world.features.terrain.caves; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.util.BlockFixer; -import ru.betterend.world.biome.cave.EndCaveBiome; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; -import java.util.function.Supplier; - -public class CaveChunkPopulatorFeature extends DefaultFeature { - private Supplier supplier; - - public CaveChunkPopulatorFeature(Supplier biome) { - this.supplier = biome; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - Set floorPositions = Sets.newHashSet(); - Set ceilPositions = Sets.newHashSet(); - int sx = (pos.getX() >> 4) << 4; - int sz = (pos.getZ() >> 4) << 4; - MutableBlockPos min = new MutableBlockPos().set(pos); - MutableBlockPos max = new MutableBlockPos().set(pos); - fillSets(sx, sz, world.getChunk(pos), floorPositions, ceilPositions, min, max); - EndCaveBiome biome = supplier.get(); - BlockState surfaceBlock = Blocks.END_STONE.defaultBlockState(); //biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - placeFloor(world, biome, floorPositions, random, surfaceBlock); - placeCeil(world, biome, ceilPositions, random); - BlockFixer.fixBlocks(world, min, max); - return true; - } - - protected void fillSets(int sx, int sz, ChunkAccess chunk, Set floorPositions, Set ceilPositions, MutableBlockPos min, MutableBlockPos max) { - MutableBlockPos mut = new MutableBlockPos(); - MutableBlockPos mut2 = new MutableBlockPos(); - MutableBlockPos mut3 = new MutableBlockPos(); - for (int x = 0; x < 16; x++) { - mut.setX(x); - mut2.setX(x); - for (int z = 0; z < 16; z++) { - mut.setZ(z); - mut2.setZ(z); - mut2.setY(0); - for (int y = 1; y < chunk.getMaxBuildHeight(); y++) { - mut.setY(y); - BlockState top = chunk.getBlockState(mut); - BlockState bottom = chunk.getBlockState(mut2); - if (top.isAir() && (bottom.is(CommonBlockTags.GEN_END_STONES) || bottom.is(Blocks.STONE))) { - mut3.set(mut2).move(sx, 0, sz); - floorPositions.add(mut3.immutable()); - updateMin(mut3, min); - updateMax(mut3, max); - } - else if (bottom.isAir() && (top.is(CommonBlockTags.GEN_END_STONES) || top.is(Blocks.STONE))) { - mut3.set(mut).move(sx, 0, sz); - ceilPositions.add(mut3.immutable()); - updateMin(mut3, min); - updateMax(mut3, max); - } - mut2.setY(y); - } - } - } - } - - private void updateMin(BlockPos pos, MutableBlockPos min) { - if (pos.getX() < min.getX()) { - min.setX(pos.getX()); - } - if (pos.getY() < min.getY()) { - min.setY(pos.getY()); - } - if (pos.getZ() < min.getZ()) { - min.setZ(pos.getZ()); - } - } - - private void updateMax(BlockPos pos, MutableBlockPos max) { - if (pos.getX() > max.getX()) { - max.setX(pos.getX()); - } - if (pos.getY() > max.getY()) { - max.setY(pos.getY()); - } - if (pos.getZ() > max.getZ()) { - max.setZ(pos.getZ()); - } - } - - protected void placeFloor(WorldGenLevel world, EndCaveBiome biome, Set floorPositions, RandomSource random, BlockState surfaceBlock) { - float density = biome.getFloorDensity(); - floorPositions.forEach((pos) -> { - BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getFloorFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); - } - } - }); - } - - protected void placeCeil(WorldGenLevel world, EndCaveBiome biome, Set ceilPositions, RandomSource random) { - float density = biome.getCeilDensity(); - ceilPositions.forEach((pos) -> { - BlockState ceilBlock = biome.getCeil(pos); - if (ceilBlock != null) { - BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); - } - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getCeilFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); - } - } - }); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java deleted file mode 100644 index d3aa2121..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java +++ /dev/null @@ -1,262 +0,0 @@ -package ru.betterend.world.features.terrain.caves; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.core.Vec3i; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.world.biomes.BCLBiome; -import ru.bclib.world.features.DefaultFeature; -import ru.bclib.world.generator.BiomePicker; -import ru.betterend.registry.EndBiomes; -import ru.betterend.util.BlockFixer; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.biome.cave.EndCaveBiome; - -import java.util.List; -import java.util.Optional; - -import net.minecraft.util.RandomSource; -import java.util.Set; - -public abstract class EndCaveFeature extends DefaultFeature { - protected static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); - protected static final BlockState END_STONE = Blocks.END_STONE.defaultBlockState(); - protected static final BlockState WATER = Blocks.WATER.defaultBlockState(); - private static final Vec3i[] SPHERE; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 2500) { - return false; - } - - if (biomeMissingCaves(world, pos)) { - return false; - } - - int radius = MHelper.randRange(10, 30, random); - BlockPos center = findPos(world, pos, radius, random); - - if (center == null) { - return false; - } - - BiomePicker.ActualBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ()); - Set caveBlocks = generate(world, center, radius, random); - if (!caveBlocks.isEmpty()) { - if (biome != null) { - setBiomes(world, biome, caveBlocks); - Set floorPositions = Sets.newConcurrentHashSet(); - Set ceilPositions = Sets.newConcurrentHashSet(); - caveBlocks.parallelStream().forEach((bpos) -> { - if (world.getBlockState(bpos).getMaterial().isReplaceable()) { - BlockPos side = bpos.below(); - if (world.getBlockState(side).is(CommonBlockTags.GEN_END_STONES)) { - floorPositions.add(side); - } - side = bpos.above(); - if (world.getBlockState(side).is(CommonBlockTags.GEN_END_STONES)) { - ceilPositions.add(side); - } - } - }); - - BlockState surfaceBlock = EndBiome.findTopMaterial(biome.bclBiome); - placeFloor(world, (EndCaveBiome) biome.bclBiome, floorPositions, random, surfaceBlock); - placeCeil(world, (EndCaveBiome) biome.bclBiome, ceilPositions, random); - placeWalls(world, (EndCaveBiome) biome.bclBiome, caveBlocks, random); - } - fixBlocks(world, caveBlocks); - } - - return true; - } - - protected abstract Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random); - - protected void placeFloor(WorldGenLevel world, EndCaveBiome biome, Set floorPositions, RandomSource random, BlockState surfaceBlock) { - float density = biome.getFloorDensity(); - floorPositions.forEach((pos) -> { - if (!surfaceBlock.is(Blocks.END_STONE)) { - BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); - } - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getFloorFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); - } - } - }); - } - - protected void placeCeil(WorldGenLevel world, EndCaveBiome biome, Set ceilPositions, RandomSource random) { - float density = biome.getCeilDensity(); - ceilPositions.forEach((pos) -> { - BlockState ceilBlock = biome.getCeil(pos); - if (ceilBlock != null) { - BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); - } - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getCeilFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); - } - } - }); - } - - protected void placeWalls(WorldGenLevel world, EndCaveBiome biome, Set positions, RandomSource random) { - Set placed = Sets.newHashSet(); - positions.forEach(pos -> { - if (random.nextInt(4) == 0 && hasOpenSide(pos, positions)) { - BlockState wallBlock = biome.getWall(pos); - if (wallBlock != null) { - for (Vec3i offset : SPHERE) { - BlockPos wallPos = pos.offset(offset); - if (!positions.contains(wallPos) && !placed.contains(wallPos) && world.getBlockState(wallPos).is(CommonBlockTags.GEN_END_STONES)) { - wallBlock = biome.getWall(wallPos); - BlocksHelper.setWithoutUpdate(world, wallPos, wallBlock); - placed.add(wallPos); - } - } - } - } - }); - } - - private boolean hasOpenSide(BlockPos pos, Set positions) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (!positions.contains(pos.relative(dir))) { - return true; - } - } - return false; - } - - protected void setBiomes(WorldGenLevel world, BiomePicker.ActualBiome biome, Set blocks) { - blocks.forEach((pos) -> setBiome(world, pos, biome)); - } - - protected void setBiome(WorldGenLevel world, BlockPos pos, BiomePicker.ActualBiome biome) { - BiomeAPI.setBiome(world, pos, biome.biome); - } - - private BlockPos findPos(WorldGenLevel world, BlockPos pos, int radius, RandomSource random) { - int top = world.getHeight(Heightmap.Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - MutableBlockPos bpos = new MutableBlockPos(); - bpos.setX(pos.getX()); - bpos.setZ(pos.getZ()); - bpos.setY(top - 1); - - BlockState state = world.getBlockState(bpos); - while (!state.is(CommonBlockTags.GEN_END_STONES) && bpos.getY() > 5) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - if (bpos.getY() < 10) { - return null; - } - top = (int) (bpos.getY() - (radius * 1.3F + 5)); - - while (state.is(CommonBlockTags.GEN_END_STONES) || !state.getFluidState().isEmpty() && bpos.getY() > 5) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - int bottom = (int) (bpos.getY() + radius * 1.3F + 5); - - if (top <= bottom) { - return null; - } - - return new BlockPos(pos.getX(), MHelper.randRange(bottom, top, random), pos.getZ()); - } - - protected void fixBlocks(WorldGenLevel world, Set caveBlocks) { - BlockPos pos = caveBlocks.iterator().next(); - MutableBlockPos start = new MutableBlockPos().set(pos); - MutableBlockPos end = new MutableBlockPos().set(pos); - caveBlocks.forEach((bpos) -> { - if (bpos.getX() < start.getX()) { - start.setX(bpos.getX()); - } - if (bpos.getX() > end.getX()) { - end.setX(bpos.getX()); - } - - if (bpos.getY() < start.getY()) { - start.setY(bpos.getY()); - } - if (bpos.getY() > end.getY()) { - end.setY(bpos.getY()); - } - - if (bpos.getZ() < start.getZ()) { - start.setZ(bpos.getZ()); - } - if (bpos.getZ() > end.getZ()) { - end.setZ(bpos.getZ()); - } - }); - BlockFixer.fixBlocks(world, start.offset(-2, -2, -2), end.offset(2, 2, 2)); - } - - protected boolean isWaterNear(WorldGenLevel world, BlockPos pos) { - for (Direction dir : BlocksHelper.DIRECTIONS) { - if (!world.getFluidState(pos.relative(dir, 5)).isEmpty()) { - return true; - } - } - return false; - } - - protected boolean biomeMissingCaves(WorldGenLevel world, BlockPos pos) { - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - Holder biome = world.getBiome(pos.offset(x << 4, 0, z << 4)); - BCLBiome endBiome = BiomeAPI.getFromBiome(biome); - boolean hasCaves = endBiome.getCustomData("has_caves", true); - if (!hasCaves && BiomeAPI.wasRegisteredAsEndLandBiome(endBiome.getID())) { - return true; - } - } - } - return false; - } - - static { - List prePos = Lists.newArrayList(); - int radius = 5; - int r2 = radius * radius; - for (int x = -radius; x <= radius; x++) { - int x2 = x * x; - for (int y = -radius; y <= radius; y++) { - int y2 = y * y; - for (int z = -radius; z <= radius; z++) { - int z2 = z * z; - if (x2 + y2 + z2 < r2) { - prePos.add(new Vec3i(x, y, z)); - } - } - } - } - SPHERE = prePos.toArray(new Vec3i[] {}); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/RoundCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/RoundCaveFeature.java deleted file mode 100644 index d193cf80..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/caves/RoundCaveFeature.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.betterend.world.features.terrain.caves; - -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.Set; -import java.util.stream.IntStream; - -public class RoundCaveFeature extends EndCaveFeature { - @Override - protected Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random) { - OpenSimplexNoise noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); - - int x1 = center.getX() - radius - 5; - int z1 = center.getZ() - radius - 5; - int x2 = center.getX() + radius + 5; - int z2 = center.getZ() + radius + 5; - int y1 = MHelper.floor(center.getY() - (radius + 5) / 1.6); - int y2 = MHelper.floor(center.getY() + (radius + 5) / 1.6); - - double hr = radius * 0.75; - double nr = radius * 0.25; - - int dx = x2 - x1 + 1; - int dz = z2 - z1 + 1; - int count = dx * dz; - Set blocks = Sets.newConcurrentHashSet(); - IntStream.range(0, count).parallel().forEach(index -> { - MutableBlockPos bpos = new MutableBlockPos(); - int x = (index % dx) + x1; - int z = (index / dx) + z1; - bpos.setX(x); - bpos.setZ(z); - int xsq = MHelper.sqr(x - center.getX()); - int zsq = MHelper.sqr(z - center.getZ()); - int dxz = xsq + zsq; - BlockState state; - for (int y = y1; y <= y2; y++) { - int ysq = (int) MHelper.sqr((y - center.getY()) * 1.6); - double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; - double dist = dxz + ysq; - if (dist < r * r) { - bpos.setY(y); - state = world.getBlockState(bpos); - if (isReplaceable(state) && !isWaterNear(world, bpos)) { - blocks.add(bpos.immutable()); - - while (state.getMaterial().equals(Material.LEAVES)) { - bpos.setY(bpos.getY() + 1); - state = world.getBlockState(bpos); - } - - bpos.setY(y - 1); - while (state.getMaterial().equals(Material.LEAVES)) { - bpos.setY(bpos.getY() - 1); - state = world.getBlockState(bpos); - } - } - } - } - }); - blocks.forEach(bpos -> BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR)); - - return blocks; - } - - private boolean isReplaceable(BlockState state) { - return state.is(CommonBlockTags.GEN_END_STONES) || - state.getMaterial().isReplaceable() || - state.getMaterial().equals(Material.PLANT) || - state.getMaterial().equals(Material.LEAVES); - } -} diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java deleted file mode 100644 index 2a85e0a3..00000000 --- a/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java +++ /dev/null @@ -1,238 +0,0 @@ -package ru.betterend.world.features.terrain.caves; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.LegacyRandomSource; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.world.biomes.BCLBiome; -import ru.bclib.world.generator.BiomePicker; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBiomes; -import ru.betterend.world.biome.EndBiome; -import ru.betterend.world.biome.cave.EndCaveBiome; - -import java.util.Map; -import java.util.Optional; - -import net.minecraft.util.RandomSource; -import java.util.Set; -import java.util.stream.IntStream; - -public class TunelCaveFeature extends EndCaveFeature { - private Set generate(WorldGenLevel world, BlockPos center, RandomSource random) { - int cx = center.getX() >> 4; - int cz = center.getZ() >> 4; - if ((long) cx * (long) cx + (long) cz + (long) cz < 256) { - return Sets.newHashSet(); - } - - int x1 = cx << 4; - int z1 = cz << 4; - int x2 = x1 + 16; - int z2 = z1 + 16; - - RandomSource rand = new LegacyRandomSource(world.getSeed()); - OpenSimplexNoise noiseH = new OpenSimplexNoise(rand.nextInt()); - OpenSimplexNoise noiseV = new OpenSimplexNoise(rand.nextInt()); - OpenSimplexNoise noiseD = new OpenSimplexNoise(rand.nextInt()); - - Set positions = Sets.newConcurrentHashSet(); - - float a = hasCaves(world, new BlockPos(x1, 0, z1)) ? 1F : 0F; - float b = hasCaves(world, new BlockPos(x2, 0, z1)) ? 1F : 0F; - float c = hasCaves(world, new BlockPos(x1, 0, z2)) ? 1F : 0F; - float d = hasCaves(world, new BlockPos(x2, 0, z2)) ? 1F : 0F; - - ChunkAccess chunk = world.getChunk(cx, cz); - IntStream.range(0, 256).parallel().forEach(index -> { - MutableBlockPos pos = new MutableBlockPos(); - int x = index & 15; - int z = index >> 4; - int wheight = chunk.getHeight(Types.WORLD_SURFACE_WG, x, z); - float dx = x / 16F; - float dz = z / 16F; - pos.setX(x + x1); - pos.setZ(z + z1); - float da = Mth.lerp(dx, a, b); - float db = Mth.lerp(dx, c, d); - float density = 1 - Mth.lerp(dz, da, db); - if (density < 0.5) { - for (int y = 0; y < wheight; y++) { - pos.setY(y); - float gradient = 1 - Mth.clamp((wheight - y) * 0.1F, 0F, 1F); - if (gradient > 0.5) { - break; - } - float val = Mth.abs((float) noiseH.eval(pos.getX() * 0.02, y * 0.01, pos.getZ() * 0.02)); - float vert = Mth.sin((y + (float) noiseV.eval( - pos.getX() * 0.01, - pos.getZ() * 0.01 - ) * 20) * 0.1F) * 0.9F; - float dist = (float) noiseD.eval(pos.getX() * 0.1, y * 0.1, pos.getZ() * 0.1) * 0.12F; - val = (val + vert * vert + dist) + density + gradient; - if (val < 0.15 && world.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES) && noWaterNear(world, pos)) { - positions.add(pos.immutable()); - } - } - } - }); - positions.forEach(bpos -> BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR)); - - return positions; - } - - private boolean noWaterNear(WorldGenLevel world, BlockPos pos) { - BlockPos above1 = pos.above(); - BlockPos above2 = pos.above(2); - if (!world.getFluidState(above1).isEmpty() || !world.getFluidState(above2).isEmpty()) { - return false; - } - for (Direction dir : BlocksHelper.HORIZONTAL) { - if (!world.getFluidState(above1.relative(dir)).isEmpty()) { - return false; - } - if (!world.getFluidState(above2.relative(dir)).isEmpty()) { - return false; - } - } - return true; - } - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 2500) { - return false; - } - - if (biomeMissingCaves(world, pos)) { - return false; - } - - Set caveBlocks = generate(world, pos, random); - if (caveBlocks.isEmpty()) { - return false; - } - - Map> floorSets = Maps.newHashMap(); - Map> ceilSets = Maps.newHashMap(); - MutableBlockPos mut = new MutableBlockPos(); - Set remove = Sets.newHashSet(); - caveBlocks.forEach((bpos) -> { - mut.set(bpos); - BiomePicker.ActualBiome bio = EndBiomes.getCaveBiome(bpos.getX(), bpos.getZ()); - int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ()); - if (mut.getY() >= height) { - remove.add(bpos); - } - else if (world.getBlockState(mut).getMaterial().isReplaceable()) { - mut.setY(bpos.getY() - 1); - if (world.getBlockState(mut).is(CommonBlockTags.GEN_END_STONES)) { - Set floorPositions = floorSets.get(bio); - if (floorPositions == null) { - floorPositions = Sets.newHashSet(); - floorSets.put(bio, floorPositions); - } - floorPositions.add(mut.immutable()); - } - mut.setY(bpos.getY() + 1); - if (world.getBlockState(mut).is(CommonBlockTags.GEN_END_STONES)) { - Set ceilPositions = ceilSets.get(bio); - if (ceilPositions == null) { - ceilPositions = Sets.newHashSet(); - ceilSets.put(bio, ceilPositions); - } - ceilPositions.add(mut.immutable()); - } - setBiome(world, bpos, bio); - } - }); - caveBlocks.removeAll(remove); - - if (caveBlocks.isEmpty()) { - return true; - } - - floorSets.forEach((biome, floorPositions) -> { - BlockState surfaceBlock = EndBiome.findTopMaterial(biome.bclBiome); - placeFloor(world, (EndCaveBiome) biome.bclBiome, floorPositions, random, surfaceBlock); - }); - ceilSets.forEach((biome, ceilPositions) -> { - placeCeil(world, (EndCaveBiome) biome.bclBiome, ceilPositions, random); - }); - BiomePicker.ActualBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ()); - placeWalls(world, (EndCaveBiome) biome.bclBiome, caveBlocks, random); - fixBlocks(world, caveBlocks); - - return true; - } - - @Override - protected Set generate(WorldGenLevel world, BlockPos center, int radius, RandomSource random) { - return null; - } - - @Override - protected void placeFloor(WorldGenLevel world, EndCaveBiome biome, Set floorPositions, RandomSource random, BlockState surfaceBlock) { - float density = biome.getFloorDensity() * 0.2F; - floorPositions.forEach((pos) -> { - if (!surfaceBlock.is(Blocks.END_STONE)) { - BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock); - } - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getFloorFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.above(), null)); - } - } - }); - } - - @Override - protected void placeCeil(WorldGenLevel world, EndCaveBiome biome, Set ceilPositions, RandomSource random) { - float density = biome.getCeilDensity() * 0.2F; - ceilPositions.forEach((pos) -> { - BlockState ceilBlock = biome.getCeil(pos); - if (ceilBlock != null) { - BlocksHelper.setWithoutUpdate(world, pos, ceilBlock); - } - if (density > 0 && random.nextFloat() <= density) { - Feature feature = biome.getCeilFeature(random); - if (feature != null) { - feature.place(new FeaturePlaceContext<>(Optional.empty(), world, null, random, pos.below(), null)); - } - } - }); - } - - protected boolean hasCaves(WorldGenLevel world, BlockPos pos) { - return hasCavesInBiome(world, pos.offset(-8, 0, -8)) && hasCavesInBiome( - world, - pos.offset(8, 0, -8) - ) && hasCavesInBiome(world, pos.offset(-8, 0, 8)) && hasCavesInBiome(world, pos.offset(8, 0, 8)); - } - - protected boolean hasCavesInBiome(WorldGenLevel world, BlockPos pos) { - Holder biome = world.getBiome(pos); - BCLBiome endBiome = BiomeAPI.getFromBiome(biome); - return endBiome.getCustomData("has_caves", true); - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/DragonTreeFeature.java b/src/main/java/ru/betterend/world/features/trees/DragonTreeFeature.java deleted file mode 100644 index 405c2a1d..00000000 --- a/src/main/java/ru/betterend/world/features/trees/DragonTreeFeature.java +++ /dev/null @@ -1,252 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class DragonTreeFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Function IGNORE; - private static final Function POST; - private static final List BRANCH; - private static final List SIDE1; - private static final List SIDE2; - private static final List ROOT; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - float size = MHelper.randRange(10, 25, random); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 6); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - - if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { - return false; - } - BlocksHelper.setWithoutUpdate(world, pos, AIR); - - Vector3f last = SplineHelper.getPos(spline, 3.5F); - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - float radius = size * MHelper.randRange(0.5F, 0.7F, random); - makeCap(world, pos.offset(last.x(), last.y(), last.z()), radius, random, noise); - - last = spline.get(0); - makeRoots(world, pos.offset(last.x(), last.y(), last.z()), radius, random); - - radius = MHelper.randRange(1.2F, 2.3F, random); - SDF function = SplineHelper.buildSDF(spline, radius, 1.2F, (bpos) -> { - return EndBlocks.DRAGON_TREE.getBark().defaultBlockState(); - }); - - function.setReplaceFunction(REPLACE); - function.addPostProcess(POST); - function.fillRecursiveIgnore(world, pos, IGNORE); - - return true; - } - - private void makeCap(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise) { - int count = (int) radius; - int offset = (int) (BRANCH.get(BRANCH.size() - 1).y() * radius); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(BRANCH); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); - - branch = SplineHelper.copySpline(SIDE1); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); - - branch = SplineHelper.copySpline(SIDE2); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); - } - leavesBall(world, pos.above(offset), radius * 1.15F + 2, random, noise); - } - - private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random) { - int count = (int) (radius * 1.5F); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(ROOT); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - Vector3f last = branch.get(branch.size() - 1); - if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { - SplineHelper.fillSpline(branch, world, EndBlocks.DRAGON_TREE.getBark().defaultBlockState(), pos, REPLACE); - } - } - } - - private void leavesBall(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise) { - SDF sphere = new SDFSphere().setRadius(radius) - .setBlock(EndBlocks.DRAGON_TREE_LEAVES.defaultBlockState() - .setValue(LeavesBlock.DISTANCE, 6)); - SDF sub = new SDFScale().setScale(5).setSource(sphere); - sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); - sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 1.5F; - }).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return random.nextFloat() * 3F - 1.5F; - }).setSource(sphere); - MutableBlockPos mut = new MutableBlockPos(); - sphere.addPostProcess((info) -> { - if (random.nextInt(5) == 0) { - for (Direction dir : Direction.values()) { - BlockState state = info.getState(dir, 2); - if (state.isAir()) { - return info.getState(); - } - } - info.setState(EndBlocks.DRAGON_TREE.getBark().defaultBlockState()); - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }); - sphere.fillRecursiveIgnore(world, pos, IGNORE); - - if (radius > 5) { - int count = (int) (radius * 2.5F); - for (int i = 0; i < count; i++) { - BlockPos p = pos.offset( - random.nextGaussian() * 1, - random.nextGaussian() * 1, - random.nextGaussian() * 1 - ); - boolean place = true; - for (Direction d : Direction.values()) { - BlockState state = world.getBlockState(p.relative(d)); - if (!EndBlocks.DRAGON_TREE.isTreeLog(state) && !state.is(EndBlocks.DRAGON_TREE_LEAVES)) { - place = false; - break; - } - } - if (place) { - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.DRAGON_TREE.getBark()); - } - } - } - - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.DRAGON_TREE.getBark()); - } - - static { - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (state.getBlock() == EndBlocks.DRAGON_TREE_LEAVES) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = (state) -> { - return EndBlocks.DRAGON_TREE.isTreeLog(state); - }; - - POST = (info) -> { - if (EndBlocks.DRAGON_TREE.isTreeLog(info.getStateUp()) && EndBlocks.DRAGON_TREE.isTreeLog(info.getStateDown())) { - return EndBlocks.DRAGON_TREE.getLog().defaultBlockState(); - } - return info.getState(); - }; - - BRANCH = Lists.newArrayList( - new Vector3f(0, 0, 0), - new Vector3f(0.1F, 0.3F, 0), - new Vector3f(0.4F, 0.6F, 0), - new Vector3f(0.8F, 0.8F, 0), - new Vector3f(1, 1, 0) - ); - SIDE1 = Lists.newArrayList(new Vector3f(0.4F, 0.6F, 0), new Vector3f(0.8F, 0.8F, 0), new Vector3f(1, 1, 0)); - SIDE2 = SplineHelper.copySpline(SIDE1); - - Vector3f offset1 = new Vector3f(-0.4F, -0.6F, 0); - Vector3f offset2 = new Vector3f(0.4F, 0.6F, 0); - - SplineHelper.offset(SIDE1, offset1); - SplineHelper.offset(SIDE2, offset1); - SplineHelper.rotateSpline(SIDE1, 0.5F); - SplineHelper.rotateSpline(SIDE2, -0.5F); - SplineHelper.offset(SIDE1, offset2); - SplineHelper.offset(SIDE2, offset2); - - ROOT = Lists.newArrayList( - new Vector3f(0F, 1F, 0), - new Vector3f(0.1F, 0.7F, 0), - new Vector3f(0.3F, 0.3F, 0), - new Vector3f(0.7F, 0.05F, 0), - new Vector3f(0.8F, -0.2F, 0) - ); - SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java b/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java deleted file mode 100644 index 3bf4e43f..00000000 --- a/src/main/java/ru/betterend/world/features/trees/GiganticAmaranitaFeature.java +++ /dev/null @@ -1,380 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BaseAttachedBlock; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class GiganticAmaranitaFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Function IGNORE; - private static final Function POST; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - float size = MHelper.randRange(5, 10, random); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 5); - SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); - - if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { - return false; - } - BlocksHelper.setWithoutUpdate(world, pos, AIR); - - float radius = size * 0.17F;// MHelper.randRange(0.8F, 1.2F, random); - SDF function = SplineHelper.buildSDF( - spline, - radius, - 0.2F, - (bpos) -> EndBlocks.AMARANITA_STEM.defaultBlockState() - ); - - Vector3f capPos = spline.get(spline.size() - 1); - makeHead(world, pos.offset(capPos.x() + 0.5F, capPos.y() + 1.5F, capPos.z() + 0.5F), Mth.floor(size / 1.6F)); - - function.setReplaceFunction(REPLACE); - function.addPostProcess(POST); - function.fillRecursiveIgnore(world, pos, IGNORE); - - for (int i = 0; i < 3; i++) { - List copy = SplineHelper.copySpline(spline); - SplineHelper.offsetParts(copy, random, 0.2F, 0, 0.2F); - SplineHelper.fillSplineForce(copy, world, EndBlocks.AMARANITA_HYPHAE.defaultBlockState(), pos, REPLACE); - } - - return true; - } - - private void makeHead(WorldGenLevel world, BlockPos pos, int radius) { - MutableBlockPos mut = new MutableBlockPos(); - if (radius < 2) { - for (int i = -1; i < 2; i++) { - mut.set(pos).move(Direction.NORTH, 2).move(Direction.EAST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.SOUTH, 2).move(Direction.EAST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.EAST, 2).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - } - for (int x = -1; x < 2; x++) { - for (int z = -1; z < 2; z++) { - mut.set(pos).move(x, 0, z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - mut.move(Direction.DOWN); - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - mut.move(Direction.DOWN); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.AMARANITA_FUR.defaultBlockState() - .setValue(BaseAttachedBlock.FACING, Direction.DOWN) - ); - } - } - } - } - - int h = radius + 1; - for (int y = 0; y < h; y++) { - mut.setY(pos.getY() + y + 1); - for (int x = -1; x < 2; x++) { - mut.setX(pos.getX() + x); - for (int z = -1; z < 2; z++) { - mut.setZ(pos.getZ() + z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - - mut.setY(pos.getY() + h + 1); - for (int x = -1; x < 2; x++) { - mut.setX(pos.getX() + x); - for (int z = -1; z < 2; z++) { - mut.setZ(pos.getZ() + z); - if ((x == 0 || z == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - else if (radius < 4) { - pos = pos.offset(-1, 0, -1); - for (int i = -2; i < 2; i++) { - mut.set(pos).move(Direction.NORTH, 2).move(Direction.WEST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.SOUTH, 3).move(Direction.WEST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.set(pos).move(Direction.WEST, 2).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - } - for (int x = -1; x < 3; x++) { - for (int z = -1; z < 3; z++) { - mut.set(pos).move(x, 0, z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - mut.move(Direction.DOWN); - if ((x >> 1) == 0 || (z >> 1) == 0) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; - int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; - BlockPos offseted = mut.relative(axis, distance); - if (world.getBlockState(offseted).getMaterial().isReplaceable()) { - Direction dir = Direction.fromAxisAndDirection( - axis, - distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE - ); - BlocksHelper.setWithoutUpdate( - world, - offseted, - EndBlocks.AMARANITA_FUR.defaultBlockState().setValue(BaseAttachedBlock.FACING, dir) - ); - } - mut.move(Direction.DOWN); - } - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.AMARANITA_FUR.defaultBlockState() - .setValue(BaseAttachedBlock.FACING, Direction.DOWN) - ); - } - } - } - } - - int h = radius - 1; - for (int y = 0; y < h; y++) { - mut.setY(pos.getY() + y + 1); - for (int x = -1; x < 3; x++) { - mut.setX(pos.getX() + x); - for (int z = -1; z < 3; z++) { - mut.setZ(pos.getZ() + z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - - mut.setY(pos.getY() + h + 1); - for (int x = -1; x < 3; x++) { - mut.setX(pos.getX() + x); - for (int z = -1; z < 3; z++) { - mut.setZ(pos.getZ() + z); - if (((x >> 1) == 0 || (z >> 1) == 0) && world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - else { - for (int i = -2; i < 3; i++) { - mut.set(pos).move(Direction.NORTH, 3).move(Direction.EAST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.UP); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.NORTH); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - - mut.set(pos).move(Direction.SOUTH, 3).move(Direction.EAST, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.UP); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.SOUTH); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - - mut.set(pos).move(Direction.EAST, 3).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.UP); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.EAST); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - - mut.set(pos).move(Direction.WEST, 3).move(Direction.NORTH, i); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.UP); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - mut.move(Direction.WEST); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - } - - for (int i = 0; i < 4; i++) { - mut.set(pos) - .move(Direction.UP) - .move(BlocksHelper.HORIZONTAL[i], 3) - .move(BlocksHelper.HORIZONTAL[(i + 1) & 3], 3); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_HYMENOPHORE); - } - } - - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - mut.set(pos).move(x, 0, z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - mut.move(Direction.DOWN); - if ((x / 2) == 0 || (z / 2) == 0) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_LANTERN); - Axis axis = x < 0 || x > 1 ? Axis.X : Axis.Z; - int distance = axis == Axis.X ? x < 0 ? -1 : 1 : z < 0 ? -1 : 1; - BlockPos offseted = mut.relative(axis, distance); - if (world.getBlockState(offseted).getMaterial().isReplaceable()) { - Direction dir = Direction.fromAxisAndDirection( - axis, - distance < 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE - ); - BlocksHelper.setWithoutUpdate( - world, - offseted, - EndBlocks.AMARANITA_FUR.defaultBlockState().setValue(BaseAttachedBlock.FACING, dir) - ); - } - mut.move(Direction.DOWN); - } - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate( - world, - mut, - EndBlocks.AMARANITA_FUR.defaultBlockState() - .setValue(BaseAttachedBlock.FACING, Direction.DOWN) - ); - } - } - } - } - - for (int y = 0; y < 3; y++) { - mut.setY(pos.getY() + y + 1); - for (int x = -2; x < 3; x++) { - mut.setX(pos.getX() + x); - for (int z = -2; z < 3; z++) { - mut.setZ(pos.getZ() + z); - if (world.getBlockState(mut).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - - int h = radius + 1; - for (int y = 4; y < h; y++) { - mut.setY(pos.getY() + y); - for (int x = -2; x < 3; x++) { - mut.setX(pos.getX() + x); - for (int z = -2; z < 3; z++) { - mut.setZ(pos.getZ() + z); - if (y < 6) { - if (((x / 2) == 0 || (z / 2) == 0) && world.getBlockState(mut) - .getMaterial() - .isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - else { - if ((x == 0 || z == 0) && (Math.abs(x) < 2 && Math.abs(z) < 2) && world.getBlockState(mut) - .getMaterial() - .isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, mut, EndBlocks.AMARANITA_CAP); - } - } - } - } - } - } - } - - static { - REPLACE = (state) -> { - if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = EndBlocks.DRAGON_TREE::isTreeLog; - - POST = (info) -> { - if (!info.getStateUp().is(EndBlocks.AMARANITA_STEM) || !info.getStateDown().is(EndBlocks.AMARANITA_STEM)) { - return EndBlocks.AMARANITA_HYPHAE.defaultBlockState(); - } - return info.getState(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/HelixTreeFeature.java b/src/main/java/ru/betterend/world/features/trees/HelixTreeFeature.java deleted file mode 100644 index 9640d0e9..00000000 --- a/src/main/java/ru/betterend/world/features/trees/HelixTreeFeature.java +++ /dev/null @@ -1,198 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.phys.AABB; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.HelixTreeLeavesBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class HelixTreeFeature extends DefaultFeature { - private static final Function POST; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - BlocksHelper.setWithoutUpdate(world, pos, AIR); - - float angle = random.nextFloat() * MHelper.PI2; - float radiusRange = MHelper.randRange(4.5F, 6F, random); - float scale = MHelper.randRange(0.5F, 1F, random); - - float dx; - float dz; - List spline = new ArrayList(10); - for (int i = 0; i < 10; i++) { - float radius = (0.9F - i * 0.1F) * radiusRange; - dx = (float) Math.sin(i + angle) * radius; - dz = (float) Math.cos(i + angle) * radius; - spline.add(new Vector3f(dx, i * 2, dz)); - } - SDF sdf = SplineHelper.buildSDF(spline, 1.7F, 0.5F, (p) -> { - return EndBlocks.HELIX_TREE.getBark().defaultBlockState(); - }); - SDF rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(sdf); - sdf = new SDFUnion().setSourceA(rotated).setSourceB(sdf); - - Vector3f lastPoint = spline.get(spline.size() - 1); - List spline2 = SplineHelper.makeSpline(0, 0, 0, 0, 20, 0, 5); - SDF stem = SplineHelper.buildSDF(spline2, 1.0F, 0.5F, (p) -> { - return EndBlocks.HELIX_TREE.getBark().defaultBlockState(); - }); - stem = new SDFTranslate().setTranslate(lastPoint.x(), lastPoint.y(), lastPoint.z()).setSource(stem); - sdf = new SDFSmoothUnion().setRadius(3).setSourceA(sdf).setSourceB(stem); - - sdf = new SDFScale().setScale(scale).setSource(sdf); - dx = 30 * scale; - float dy1 = -20 * scale; - float dy2 = 100 * scale; - sdf.addPostProcess(POST).fillArea(world, pos, new AABB(pos.offset(-dx, dy1, -dx), pos.offset(dx, dy2, dx))); - SplineHelper.scale(spline, scale); - SplineHelper.fillSplineForce(spline, world, EndBlocks.HELIX_TREE.getBark().defaultBlockState(), pos, (state) -> { - return state.getMaterial().isReplaceable(); - }); - SplineHelper.rotateSpline(spline, (float) Math.PI); - SplineHelper.fillSplineForce(spline, world, EndBlocks.HELIX_TREE.getBark().defaultBlockState(), pos, (state) -> { - return state.getMaterial().isReplaceable(); - }); - SplineHelper.scale(spline2, scale); - BlockPos leafStart = pos.offset(lastPoint.x() + 0.5, lastPoint.y() + 0.5, lastPoint.z() + 0.5); - SplineHelper.fillSplineForce( - spline2, - world, - EndBlocks.HELIX_TREE.getLog().defaultBlockState(), - leafStart, - (state) -> { - return state.getMaterial().isReplaceable(); - } - ); - - spline.clear(); - float rad = MHelper.randRange(8F, 11F, random); - int count = MHelper.randRange(20, 30, random); - float scaleM = 20F / (float) count * scale * 1.75F; - float hscale = 20F / (float) count * 0.05F; - for (int i = 0; i <= count; i++) { - float radius = 1 - i * hscale; - radius = radius * radius * 2 - 1; - radius *= radius; - radius = (1 - radius) * rad * scale; - dx = (float) Math.sin(i * 0.45F + angle) * radius; - dz = (float) Math.cos(i * 0.45F + angle) * radius; - spline.add(new Vector3f(dx, i * scaleM, dz)); - } - - Vector3f start = new Vector3f(); - Vector3f end = new Vector3f(); - lastPoint = spline.get(0); - BlockState leaf = EndBlocks.HELIX_TREE_LEAVES.defaultBlockState(); - for (int i = 1; i < spline.size(); i++) { - Vector3f point = spline.get(i); - int minY = MHelper.floor(lastPoint.y()); - int maxY = MHelper.floor(point.y()); - float div = point.y() - lastPoint.y(); - for (float py = minY; py <= maxY; py += 0.2F) { - start.set(0, py, 0); - float delta = (float) (py - minY) / div; - float px = Mth.lerp(delta, lastPoint.x(), point.x()); - float pz = Mth.lerp(delta, lastPoint.z(), point.z()); - end.set(px, py, pz); - fillLine(start, end, world, leaf, leafStart, i / 2 - 1); - float ax = Math.abs(px); - float az = Math.abs(pz); - if (ax > az) { - start.set(start.x(), start.y(), start.z() + az > 0 ? 1 : -1); - end.set(end.x(), end.y(), end.z() + az > 0 ? 1 : -1); - } - else { - start.set(start.x() + ax > 0 ? 1 : -1, start.y(), start.z()); - end.set(end.x() + ax > 0 ? 1 : -1, end.y(), end.z()); - } - fillLine(start, end, world, leaf, leafStart, i / 2 - 1); - } - lastPoint = point; - } - - leaf = leaf.setValue(HelixTreeLeavesBlock.COLOR, 7); - leafStart = leafStart.offset(0, lastPoint.y(), 0); - if (world.getBlockState(leafStart).isAir()) { - BlocksHelper.setWithoutUpdate(world, leafStart, leaf); - leafStart = leafStart.above(); - if (world.getBlockState(leafStart).isAir()) { - BlocksHelper.setWithoutUpdate(world, leafStart, leaf); - leafStart = leafStart.above(); - if (world.getBlockState(leafStart).isAir()) { - BlocksHelper.setWithoutUpdate(world, leafStart, leaf); - } - } - } - - return true; - } - - private void fillLine(Vector3f start, Vector3f end, WorldGenLevel world, BlockState state, BlockPos pos, int offset) { - float dx = end.x() - start.x(); - float dy = end.y() - start.y(); - float dz = end.z() - start.z(); - float max = MHelper.max(Math.abs(dx), Math.abs(dy), Math.abs(dz)); - int count = MHelper.floor(max + 1); - dx /= max; - dy /= max; - dz /= max; - float x = start.x(); - float y = start.y(); - float z = start.z(); - - MutableBlockPos bPos = new MutableBlockPos(); - for (int i = 0; i < count; i++) { - bPos.set(x + pos.getX(), y + pos.getY(), z + pos.getZ()); - int color = MHelper.floor((float) i / (float) count * 7F + 0.5F) + offset; - color = Mth.clamp(color, 0, 7); - if (world.getBlockState(bPos).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, bPos, state.setValue(HelixTreeLeavesBlock.COLOR, color)); - } - x += dx; - y += dy; - z += dz; - } - bPos.set(end.x() + pos.getX(), end.y() + pos.getY(), end.z() + pos.getZ()); - if (world.getBlockState(bPos).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, bPos, state.setValue(HelixTreeLeavesBlock.COLOR, 7)); - } - } - - static { - POST = (info) -> { - if (EndBlocks.HELIX_TREE.isTreeLog(info.getStateUp()) && EndBlocks.HELIX_TREE.isTreeLog(info.getStateDown())) { - return EndBlocks.HELIX_TREE.getLog().defaultBlockState(); - } - return info.getState(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/JellyshroomFeature.java b/src/main/java/ru/betterend/world/features/trees/JellyshroomFeature.java deleted file mode 100644 index df5ef0f7..00000000 --- a/src/main/java/ru/betterend/world/features/trees/JellyshroomFeature.java +++ /dev/null @@ -1,133 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFFlatWave; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.JellyshroomCapBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class JellyshroomFeature extends DefaultFeature { - private static final Function REPLACE; - private static final List ROOT; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - BlockState bark = EndBlocks.JELLYSHROOM.getBark().defaultBlockState(); - BlockState membrane = EndBlocks.JELLYSHROOM_CAP_PURPLE.defaultBlockState(); - - int height = MHelper.randRange(5, 8, random); - float radius = height * MHelper.randRange(0.15F, 0.25F, random); - List spline = SplineHelper.makeSpline(0, -1, 0, 0, height, 0, 3); - SplineHelper.offsetParts(spline, random, 0.5F, 0, 0.5F); - SDF sdf = SplineHelper.buildSDF(spline, radius, 0.8F, (bpos) -> { - return bark; - }); - - radius = height * MHelper.randRange(0.7F, 0.9F, random); - if (radius < 1.5F) { - radius = 1.5F; - } - final float membraneRadius = radius; - SDF cap = makeCap(membraneRadius, random, membrane); - final Vector3f last = spline.get(spline.size() - 1); - cap = new SDFTranslate().setTranslate(last.x(), last.y(), last.z()).setSource(cap); - sdf = new SDFSmoothUnion().setRadius(3F).setSourceA(sdf).setSourceB(cap); - sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { - if (EndBlocks.JELLYSHROOM.isTreeLog(info.getState())) { - if (EndBlocks.JELLYSHROOM.isTreeLog(info.getStateUp()) && EndBlocks.JELLYSHROOM.isTreeLog(info.getStateDown())) { - return EndBlocks.JELLYSHROOM.getLog().defaultBlockState(); - } - } - else if (info.getState().is(EndBlocks.JELLYSHROOM_CAP_PURPLE)) { - float dx = info.getPos().getX() - pos.getX() - last.x(); - float dz = info.getPos().getZ() - pos.getZ() - last.z(); - float distance = MHelper.length(dx, dz) / membraneRadius * 7F; - int color = Mth.clamp(MHelper.floor(distance), 0, 7); - return info.getState().setValue(JellyshroomCapBlock.COLOR, color); - } - return info.getState(); - }).fillRecursive(world, pos); - radius = height * 0.5F; - makeRoots(world, pos.offset(0, 2, 0), radius, random, bark); - - return true; - } - - private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, BlockState wood) { - int count = (int) (radius * 3.5F); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(ROOT); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - Vector3f last = branch.get(branch.size() - 1); - if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { - SplineHelper.fillSpline(branch, world, wood, pos, REPLACE); - } - } - } - - private SDF makeCap(float radius, RandomSource random, BlockState cap) { - SDF sphere = new SDFSphere().setRadius(radius).setBlock(cap); - SDF sub = new SDFTranslate().setTranslate(0, -4, 0).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); - sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); - sphere = new SDFTranslate().setTranslate(0, 1 - radius * 0.5F, 0).setSource(sphere); - - float angle = random.nextFloat() * MHelper.PI2; - int count = (int) MHelper.randRange(radius * 0.5F, radius, random); - if (count < 3) { - count = 3; - } - sphere = new SDFFlatWave().setAngle(angle).setRaysCount(count).setIntensity(0.2F).setSource(sphere); - - return sphere; - } - - static { - ROOT = Lists.newArrayList( - new Vector3f(0.1F, 0.70F, 0), - new Vector3f(0.3F, 0.30F, 0), - new Vector3f(0.7F, 0.05F, 0), - new Vector3f(0.8F, -0.20F, 0) - ); - SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); - - REPLACE = (state) -> { - if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/LacugroveFeature.java b/src/main/java/ru/betterend/world/features/trees/LacugroveFeature.java deleted file mode 100644 index 475804ad..00000000 --- a/src/main/java/ru/betterend/world/features/trees/LacugroveFeature.java +++ /dev/null @@ -1,219 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class LacugroveFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Function IGNORE; - private static final Function POST; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - float size = MHelper.randRange(15, 25, random); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 6); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - - if (!SplineHelper.canGenerate(spline, pos, world, REPLACE)) { - return false; - } - - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - - float radius = MHelper.randRange(6F, 8F, random); - radius *= (size - 15F) / 20F + 1F; - Vector3f center = spline.get(4); - leavesBall(world, pos.offset(center.x(), center.y(), center.z()), radius, random, noise); - - radius = MHelper.randRange(1.2F, 1.8F, random); - SDF function = SplineHelper.buildSDF(spline, radius, 0.7F, (bpos) -> { - return EndBlocks.LACUGROVE.getBark().defaultBlockState(); - }); - - function.setReplaceFunction(REPLACE); - function.addPostProcess(POST); - function.fillRecursive(world, pos); - - spline = spline.subList(4, 6); - SplineHelper.fillSpline(spline, world, EndBlocks.LACUGROVE.getBark().defaultBlockState(), pos, REPLACE); - - MutableBlockPos mut = new MutableBlockPos(); - int offset = random.nextInt(2); - for (int i = 0; i < 100; i++) { - double px = pos.getX() + MHelper.randRange(-5, 5, random); - double pz = pos.getZ() + MHelper.randRange(-5, 5, random); - mut.setX(MHelper.floor(px + 0.5)); - mut.setZ(MHelper.floor(pz + 0.5)); - if (((mut.getX() + mut.getZ() + offset) & 1) == 0) { - double distance = 3.5 - MHelper.length(px - pos.getX(), pz - pos.getZ()) * 0.5; - if (distance > 0) { - int minY = MHelper.floor(pos.getY() - distance * 0.5); - int maxY = MHelper.floor(pos.getY() + distance + random.nextDouble()); - boolean generate = false; - for (int y = minY; y < maxY; y++) { - mut.setY(y); - if (world.getBlockState(mut).is(CommonBlockTags.END_STONES)) { - generate = true; - break; - } - } - if (generate) { - int top = maxY - 1; - for (int y = top; y >= minY; y--) { - mut.setY(y); - BlockState state = world.getBlockState(mut); - if (state.getMaterial().isReplaceable() || state.getMaterial() - .equals(Material.PLANT) || state.is(CommonBlockTags.END_STONES)) { - BlocksHelper.setWithoutUpdate( - world, - mut, - y == top ? EndBlocks.LACUGROVE.getBark() : EndBlocks.LACUGROVE.getLog() - ); - } - else { - break; - } - } - } - } - } - } - - return true; - } - - private void leavesBall(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise) { - SDF sphere = new SDFSphere().setRadius(radius) - .setBlock(EndBlocks.LACUGROVE_LEAVES.defaultBlockState() - .setValue(LeavesBlock.DISTANCE, 6)); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; - }).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return random.nextFloat() * 3F - 1.5F; - }).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere) - .setSourceB(new SDFTranslate().setTranslate(0, -radius - 2, 0).setSource(sphere)); - MutableBlockPos mut = new MutableBlockPos(); - sphere.addPostProcess((info) -> { - if (random.nextInt(5) == 0) { - for (Direction dir : Direction.values()) { - BlockState state = info.getState(dir, 2); - if (state.isAir()) { - return info.getState(); - } - } - info.setState(EndBlocks.LACUGROVE.getBark().defaultBlockState()); - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }); - sphere.fillRecursiveIgnore(world, pos, IGNORE); - - if (radius > 5) { - int count = (int) (radius * 2.5F); - for (int i = 0; i < count; i++) { - BlockPos p = pos.offset( - random.nextGaussian() * 1, - random.nextGaussian() * 1, - random.nextGaussian() * 1 - ); - boolean place = true; - for (Direction d : Direction.values()) { - BlockState state = world.getBlockState(p.relative(d)); - if (!EndBlocks.LACUGROVE.isTreeLog(state) && !state.is(EndBlocks.LACUGROVE_LEAVES)) { - place = false; - break; - } - } - if (place) { - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LACUGROVE.getBark()); - } - } - } - - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.LACUGROVE.getBark()); - } - - static { - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (EndBlocks.LACUGROVE.isTreeLog(state)) { - return true; - } - if (state.getBlock() == EndBlocks.LACUGROVE_LEAVES) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = (state) -> { - return EndBlocks.LACUGROVE.isTreeLog(state); - }; - - POST = (info) -> { - if (EndBlocks.LACUGROVE.isTreeLog(info.getStateUp()) && EndBlocks.LACUGROVE.isTreeLog(info.getStateDown())) { - return EndBlocks.LACUGROVE.getLog().defaultBlockState(); - } - return info.getState(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/LucerniaFeature.java b/src/main/java/ru/betterend/world/features/trees/LucerniaFeature.java deleted file mode 100644 index a83d9f39..00000000 --- a/src/main/java/ru/betterend/world/features/trees/LucerniaFeature.java +++ /dev/null @@ -1,230 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class LucerniaFeature extends DefaultFeature { - private static final Direction[] DIRECTIONS = Direction.values(); - private static final Function REPLACE; - private static final Function IGNORE; - private static final List SPLINE; - private static final List ROOT; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - final NoneFeatureConfiguration config = featureConfig.config(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - float size = MHelper.randRange(12, 20, random); - int count = (int) (size * 0.3F); - float var = MHelper.PI2 / (float) (count * 3); - float start = MHelper.randRange(0, MHelper.PI2, random); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; - List spline = SplineHelper.copySpline(SPLINE); - SplineHelper.rotateSpline(spline, angle); - SplineHelper.scale(spline, size * MHelper.randRange(0.5F, 1F, random)); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - SplineHelper.fillSpline(spline, world, EndBlocks.LUCERNIA.getBark().defaultBlockState(), pos, REPLACE); - Vector3f last = spline.get(spline.size() - 1); - float leavesRadius = (size * 0.13F + MHelper.randRange(0.8F, 1.5F, random)) * 1.4F; - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - leavesBall(world, pos.offset(last.x(), last.y(), last.z()), leavesRadius, random, noise, config != null); - } - - makeRoots(world, pos.offset(0, MHelper.randRange(3, 5, random), 0), size * 0.35F, random); - - return true; - } - - private void leavesBall(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise, boolean natural) { - SDF sphere = new SDFSphere().setRadius(radius) - .setBlock(EndBlocks.LUCERNIA_LEAVES.defaultBlockState() - .setValue(LeavesBlock.DISTANCE, 6)); - SDF sub = new SDFScale().setScale(5).setSource(sphere); - sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); - sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( - vec.x() * 0.2, - vec.y() * 0.2, - vec.z() * 0.2 - ) * 2F).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-1.5F, 1.5F, random)).setSource(sphere); - - MutableBlockPos mut = new MutableBlockPos(); - for (Direction d1 : BlocksHelper.HORIZONTAL) { - BlockPos p = mut.set(pos).move(Direction.UP).move(d1).immutable(); - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LUCERNIA.getBark().defaultBlockState()); - for (Direction d2 : BlocksHelper.HORIZONTAL) { - mut.set(p).move(Direction.UP).move(d2); - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.LUCERNIA.getBark().defaultBlockState()); - } - } - - BlockState top = EndBlocks.FILALUX.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); - BlockState middle = EndBlocks.FILALUX.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); - BlockState bottom = EndBlocks.FILALUX.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); - BlockState outer = EndBlocks.LUCERNIA_OUTER_LEAVES.defaultBlockState(); - - List support = Lists.newArrayList(); - sphere.addPostProcess((info) -> { - if (natural && random.nextInt(6) == 0 && info.getStateDown().isAir()) { - BlockPos d = info.getPos().below(); - support.add(d); - } - if (random.nextInt(15) == 0) { - for (Direction dir : Direction.values()) { - BlockState state = info.getState(dir, 2); - if (state.isAir()) { - return info.getState(); - } - } - info.setState(EndBlocks.LUCERNIA.getBark().defaultBlockState()); - } - - MHelper.shuffle(DIRECTIONS, random); - for (Direction d : DIRECTIONS) { - if (info.getState(d).isAir()) { - info.setBlockPos(info.getPos().relative(d), outer.setValue(FurBlock.FACING, d)); - } - } - - if (EndBlocks.LUCERNIA.isTreeLog(info.getState())) { - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }); - sphere.fillRecursiveIgnore(world, pos, IGNORE); - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.LUCERNIA.getBark()); - - support.forEach((bpos) -> { - BlockState state = world.getBlockState(bpos); - if (state.isAir() || state.is(EndBlocks.LUCERNIA_OUTER_LEAVES)) { - int count = MHelper.randRange(3, 8, random); - mut.set(bpos); - if (world.getBlockState(mut.above()).is(EndBlocks.LUCERNIA_LEAVES)) { - BlocksHelper.setWithoutUpdate(world, mut, top); - for (int i = 1; i < count; i++) { - mut.setY(mut.getY() - 1); - if (world.isEmptyBlock(mut.below())) { - BlocksHelper.setWithoutUpdate(world, mut, middle); - } - else { - break; - } - } - BlocksHelper.setWithoutUpdate(world, mut, bottom); - } - } - }); - } - - private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random) { - int count = (int) (radius * 1.5F); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(ROOT); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - Vector3f last = branch.get(branch.size() - 1); - if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { - SplineHelper.fillSplineForce(branch, world, EndBlocks.LUCERNIA.getBark().defaultBlockState(), pos, REPLACE); - } - } - } - - static { - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (state.getBlock() == EndBlocks.LUCERNIA_LEAVES) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = EndBlocks.LUCERNIA::isTreeLog; - - SPLINE = Lists.newArrayList( - new Vector3f(0.00F, 0.00F, 0.00F), - new Vector3f(0.10F, 0.35F, 0.00F), - new Vector3f(0.20F, 0.50F, 0.00F), - new Vector3f(0.30F, 0.55F, 0.00F), - new Vector3f(0.42F, 0.70F, 0.00F), - new Vector3f(0.50F, 1.00F, 0.00F) - ); - - ROOT = Lists.newArrayList( - new Vector3f(0.1F, 0.70F, 0), - new Vector3f(0.3F, 0.30F, 0), - new Vector3f(0.7F, 0.05F, 0), - new Vector3f(0.8F, -0.20F, 0) - ); - SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/MossyGlowshroomFeature.java b/src/main/java/ru/betterend/world/features/trees/MossyGlowshroomFeature.java deleted file mode 100644 index 24630ce9..00000000 --- a/src/main/java/ru/betterend/world/features/trees/MossyGlowshroomFeature.java +++ /dev/null @@ -1,184 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFBinary; -import ru.bclib.sdf.operator.SDFCoordModify; -import ru.bclib.sdf.operator.SDFFlatWave; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.sdf.primitive.SDFPrimitive; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.MossyGlowshroomCapBlock; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class MossyGlowshroomFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Vector3f CENTER = new Vector3f(); - private static final SDFBinary FUNCTION; - private static final SDFTranslate HEAD_POS; - private static final SDFFlatWave ROOTS_ROT; - - private static final SDFPrimitive CONE1; - private static final SDFPrimitive CONE2; - private static final SDFPrimitive CONE_GLOW; - private static final SDFPrimitive ROOTS; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos blockPos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - BlockState down = world.getBlockState(blockPos.below()); - if (!down.is(EndBlocks.END_MYCELIUM) && !down.is(EndBlocks.END_MOSS)) return false; - - CONE1.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); - CONE2.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); - CONE_GLOW.setBlock(EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE); - ROOTS.setBlock(EndBlocks.MOSSY_GLOWSHROOM.getBark()); - - float height = MHelper.randRange(10F, 25F, random); - int count = MHelper.floor(height / 4); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { - return EndBlocks.MOSSY_GLOWSHROOM.getLog().defaultBlockState(); - }); - Vector3f pos = spline.get(spline.size() - 1); - float scale = MHelper.randRange(0.75F, 1.1F, random); - - if (!SplineHelper.canGenerate(spline, scale, blockPos, world, REPLACE)) { - return false; - } - BlocksHelper.setWithoutUpdate(world, blockPos, AIR); - - CENTER.set(blockPos.getX(), 0, blockPos.getZ()); - HEAD_POS.setTranslate(pos.x(), pos.y(), pos.z()); - ROOTS_ROT.setAngle(random.nextFloat() * MHelper.PI2); - FUNCTION.setSourceA(sdf); - - new SDFScale().setScale(scale).setSource(FUNCTION).setReplaceFunction(REPLACE).addPostProcess((info) -> { - if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) { - if (random.nextBoolean() && info.getStateUp().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() - .setValue(MossyGlowshroomCapBlock.TRANSITION, true)); - return info.getState(); - } - else if (!EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !EndBlocks.MOSSY_GLOWSHROOM.isTreeLog( - info.getStateDown())) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM.getBark().defaultBlockState()); - return info.getState(); - } - } - else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { - if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() - .setValue(MossyGlowshroomCapBlock.TRANSITION, true)); - return info.getState(); - } - - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState()); - return info.getState(); - } - else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { - for (Direction dir : BlocksHelper.HORIZONTAL) { - if (info.getState(dir) == AIR) { - info.setBlockPos( - info.getPos().relative(dir), - EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState().setValue(FurBlock.FACING, dir) - ); - } - } - - if (info.getStateDown().getBlock() != EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { - info.setBlockPos( - info.getPos().below(), - EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState().setValue(FurBlock.FACING, Direction.DOWN) - ); - } - } - return info.getState(); - }).fillRecursive(world, blockPos); - - return true; - } - - static { - SDFCappedCone cone1 = new SDFCappedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); - SDFCappedCone cone2 = new SDFCappedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); - SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); - SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0) - .setSource(new SDFScale().setScale(2).setSource(cone2)); - SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); - SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); - SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); - - CONE1 = cone1; - CONE2 = cone2; - - SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone); - innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone); - cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone); - - SDF glowCone = new SDFCappedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F); - CONE_GLOW = (SDFPrimitive) glowCone; - glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone); - glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3); - - cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone); - - OpenSimplexNoise noise = new OpenSimplexNoise(1234); - cones = new SDFCoordModify().setFunction((pos) -> { - float dist = MHelper.length(pos.x(), pos.z()); - float y = pos.y() + (float) noise.eval( - pos.x() * 0.1 + CENTER.x(), - pos.z() * 0.1 + CENTER.z() - ) * dist * 0.3F - dist * 0.15F; - pos.set(pos.x(), y, pos.z()); - }).setSource(cones); - - HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0) - .setSource(cones)); - - SDF roots = new SDFSphere().setRadius(4F); - ROOTS = (SDFPrimitive) roots; - roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots); - ROOTS_ROT = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots); - - FUNCTION = new SDFSmoothUnion().setRadius(4) - .setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(ROOTS_ROT)); - - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/PythadendronTreeFeature.java b/src/main/java/ru/betterend/world/features/trees/PythadendronTreeFeature.java deleted file mode 100644 index 1e4ced9a..00000000 --- a/src/main/java/ru/betterend/world/features/trees/PythadendronTreeFeature.java +++ /dev/null @@ -1,214 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.sdf.PosInfo; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class PythadendronTreeFeature extends DefaultFeature { - private static final Function REPLACE; - private static final Function IGNORE; - private static final Function POST; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (world.getBlockState(pos.below()).getBlock() != EndBlocks.CHORUS_NYLIUM) { - return false; - } - BlocksHelper.setWithoutUpdate(world, pos, AIR); - - float size = MHelper.randRange(10, 20, random); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 4); - SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); - Vector3f last = spline.get(spline.size() - 1); - - int depth = MHelper.floor((size - 10F) * 3F / 10F + 1F); - float bsize = (10F - (size - 10F)) / 10F + 1.5F; - branch( - last.x(), - last.y(), - last.z(), - size * bsize, - MHelper.randRange(0, MHelper.PI2, random), - random, - depth, - world, - pos - ); - - SDF function = SplineHelper.buildSDF(spline, 1.7F, 1.1F, (bpos) -> { - return EndBlocks.PYTHADENDRON.getBark().defaultBlockState(); - }); - function.setReplaceFunction(REPLACE); - function.addPostProcess(POST); - function.fillRecursive(world, pos); - - return true; - } - - private void branch(float x, float y, float z, float size, float angle, RandomSource random, int depth, WorldGenLevel world, BlockPos pos) { - if (depth == 0) return; - - float dx = (float) Math.cos(angle) * size * 0.15F; - float dz = (float) Math.sin(angle) * size * 0.15F; - - float x1 = x + dx; - float z1 = z + dz; - float x2 = x - dx; - float z2 = z - dz; - - List spline = SplineHelper.makeSpline(x, y, z, x1, y, z1, 5); - SplineHelper.powerOffset(spline, size * MHelper.randRange(1.0F, 2.0F, random), 4); - SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); - Vector3f pos1 = spline.get(spline.size() - 1); - - boolean s1 = SplineHelper.fillSpline( - spline, - world, - EndBlocks.PYTHADENDRON.getBark().defaultBlockState(), - pos, - REPLACE - ); - - spline = SplineHelper.makeSpline(x, y, z, x2, y, z2, 5); - SplineHelper.powerOffset(spline, size * MHelper.randRange(1.0F, 2.0F, random), 4); - SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); - Vector3f pos2 = spline.get(spline.size() - 1); - - boolean s2 = SplineHelper.fillSpline( - spline, - world, - EndBlocks.PYTHADENDRON.getBark().defaultBlockState(), - pos, - REPLACE - ); - - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); - if (depth < 3) { - if (s1) { - leavesBall(world, pos.offset(pos1.x(), pos1.y(), pos1.z()), random, noise); - } - if (s2) { - leavesBall(world, pos.offset(pos2.x(), pos2.y(), pos2.z()), random, noise); - } - } - - float size1 = size * MHelper.randRange(0.75F, 0.95F, random); - float size2 = size * MHelper.randRange(0.75F, 0.95F, random); - float angle1 = angle + (float) Math.PI * 0.5F + MHelper.randRange(-0.1F, 0.1F, random); - float angle2 = angle + (float) Math.PI * 0.5F + MHelper.randRange(-0.1F, 0.1F, random); - - if (s1) { - branch(pos1.x(), pos1.y(), pos1.z(), size1, angle1, random, depth - 1, world, pos); - } - if (s2) { - branch(pos2.x(), pos2.y(), pos2.z(), size2, angle2, random, depth - 1, world, pos); - } - } - - private void leavesBall(WorldGenLevel world, BlockPos pos, RandomSource random, OpenSimplexNoise noise) { - float radius = MHelper.randRange(4.5F, 6.5F, random); - - SDF sphere = new SDFSphere().setRadius(radius) - .setBlock(EndBlocks.PYTHADENDRON_LEAVES.defaultBlockState() - .setValue(LeavesBlock.DISTANCE, 6)); - sphere = new SDFScale3D().setScale(1, 0.6F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return (float) noise.eval(vec.x() * 0.2, vec.y() * 0.2, vec.z() * 0.2) * 3; - }).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { - return random.nextFloat() * 3F - 1.5F; - }).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere) - .setSourceB(new SDFTranslate().setTranslate(0, -radius, 0).setSource(sphere)); - MutableBlockPos mut = new MutableBlockPos(); - sphere.addPostProcess((info) -> { - if (random.nextInt(5) == 0) { - for (Direction dir : Direction.values()) { - BlockState state = info.getState(dir, 2); - if (state.isAir()) { - return info.getState(); - } - } - info.setState(EndBlocks.PYTHADENDRON.getBark().defaultBlockState()); - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }); - sphere.fillRecursiveIgnore(world, pos, IGNORE); - } - - static { - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (state.getBlock() == EndBlocks.PYTHADENDRON_LEAVES) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = (state) -> { - return EndBlocks.PYTHADENDRON.isTreeLog(state); - }; - - POST = (info) -> { - if (EndBlocks.PYTHADENDRON.isTreeLog(info.getStateUp()) && EndBlocks.PYTHADENDRON.isTreeLog(info.getStateDown())) { - return EndBlocks.PYTHADENDRON.getLog().defaultBlockState(); - } - return info.getState(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java b/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java deleted file mode 100644 index d862f7b5..00000000 --- a/src/main/java/ru/betterend/world/features/trees/TenaneaFeature.java +++ /dev/null @@ -1,202 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.LeavesBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.blocks.BlockProperties; -import ru.bclib.blocks.BlockProperties.TripleShape; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFDisplacement; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class TenaneaFeature extends DefaultFeature { - private static final Direction[] DIRECTIONS = Direction.values(); - private static final Function REPLACE; - private static final Function IGNORE; - private static final List SPLINE; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - float size = MHelper.randRange(7, 10, random); - int count = (int) (size * 0.45F); - float var = MHelper.PI2 / (float) (count * 3); - float start = MHelper.randRange(0, MHelper.PI2, random); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; - List spline = SplineHelper.copySpline(SPLINE); - SplineHelper.rotateSpline(spline, angle); - SplineHelper.scale(spline, size + MHelper.randRange(0, size * 0.5F, random)); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - SplineHelper.fillSpline(spline, world, EndBlocks.TENANEA.getBark().defaultBlockState(), pos, REPLACE); - Vector3f last = spline.get(spline.size() - 1); - float leavesRadius = (size * 0.3F + MHelper.randRange(0.8F, 1.5F, random)) * 1.4F; - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); - leavesBall(world, pos.offset(last.x(), last.y(), last.z()), leavesRadius, random, noise); - } - - return true; - } - - private void leavesBall(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, OpenSimplexNoise noise) { - SDF sphere = new SDFSphere().setRadius(radius) - .setBlock(EndBlocks.TENANEA_LEAVES.defaultBlockState() - .setValue(LeavesBlock.DISTANCE, 6)); - SDF sub = new SDFScale().setScale(5).setSource(sphere); - sub = new SDFTranslate().setTranslate(0, -radius * 5, 0).setSource(sub); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); - sphere = new SDFScale3D().setScale(1, 0.75F, 1).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> (float) noise.eval( - vec.x() * 0.2, - vec.y() * 0.2, - vec.z() * 0.2 - ) * 2F).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> MHelper.randRange(-1.5F, 1.5F, random)).setSource(sphere); - - MutableBlockPos mut = new MutableBlockPos(); - for (Direction d1 : BlocksHelper.HORIZONTAL) { - BlockPos p = mut.set(pos).move(Direction.UP).move(d1).immutable(); - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.TENANEA.getBark().defaultBlockState()); - for (Direction d2 : BlocksHelper.HORIZONTAL) { - mut.set(p).move(Direction.UP).move(d2); - BlocksHelper.setWithoutUpdate(world, p, EndBlocks.TENANEA.getBark().defaultBlockState()); - } - } - - BlockState top = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP); - BlockState middle = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE); - BlockState bottom = EndBlocks.TENANEA_FLOWERS.defaultBlockState() - .setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM); - BlockState outer = EndBlocks.TENANEA_OUTER_LEAVES.defaultBlockState(); - - List support = Lists.newArrayList(); - sphere.addPostProcess((info) -> { - if (random.nextInt(6) == 0 && info.getStateDown().isAir()) { - BlockPos d = info.getPos().below(); - support.add(d); - } - if (random.nextInt(5) == 0) { - for (Direction dir : Direction.values()) { - BlockState state = info.getState(dir, 2); - if (state.isAir()) { - return info.getState(); - } - } - info.setState(EndBlocks.TENANEA.getBark().defaultBlockState()); - } - - MHelper.shuffle(DIRECTIONS, random); - for (Direction d : DIRECTIONS) { - if (info.getState(d).isAir()) { - info.setBlockPos(info.getPos().relative(d), outer.setValue(FurBlock.FACING, d)); - } - } - - if (EndBlocks.TENANEA.isTreeLog(info.getState())) { - for (int x = -6; x < 7; x++) { - int ax = Math.abs(x); - mut.setX(x + info.getPos().getX()); - for (int z = -6; z < 7; z++) { - int az = Math.abs(z); - mut.setZ(z + info.getPos().getZ()); - for (int y = -6; y < 7; y++) { - int ay = Math.abs(y); - int d = ax + ay + az; - if (d < 7) { - mut.setY(y + info.getPos().getY()); - BlockState state = info.getState(mut); - if (state.getBlock() instanceof LeavesBlock) { - int distance = state.getValue(LeavesBlock.DISTANCE); - if (d < distance) { - info.setState(mut, state.setValue(LeavesBlock.DISTANCE, d)); - } - } - } - } - } - } - } - return info.getState(); - }); - sphere.fillRecursiveIgnore(world, pos, IGNORE); - BlocksHelper.setWithoutUpdate(world, pos, EndBlocks.TENANEA.getBark()); - - support.forEach((bpos) -> { - BlockState state = world.getBlockState(bpos); - if (state.isAir() || state.is(EndBlocks.TENANEA_OUTER_LEAVES)) { - int count = MHelper.randRange(3, 8, random); - mut.set(bpos); - if (world.getBlockState(mut.above()).is(EndBlocks.TENANEA_LEAVES)) { - BlocksHelper.setWithoutUpdate(world, mut, top); - for (int i = 1; i < count; i++) { - mut.setY(mut.getY() - 1); - if (world.isEmptyBlock(mut.below())) { - BlocksHelper.setWithoutUpdate(world, mut, middle); - } - else { - break; - } - } - BlocksHelper.setWithoutUpdate(world, mut, bottom); - } - } - }); - } - - static { - REPLACE = (state) -> { - /*if (state.is(CommonBlockTags.END_STONES)) { - return true; - }*/ - if (state.getBlock() == EndBlocks.TENANEA_LEAVES) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - - IGNORE = EndBlocks.TENANEA::isTreeLog; - - SPLINE = Lists.newArrayList( - new Vector3f(0.00F, 0.00F, 0.00F), - new Vector3f(0.10F, 0.35F, 0.00F), - new Vector3f(0.20F, 0.50F, 0.00F), - new Vector3f(0.30F, 0.55F, 0.00F), - new Vector3f(0.42F, 0.70F, 0.00F), - new Vector3f(0.50F, 1.00F, 0.00F) - ); - } -} diff --git a/src/main/java/ru/betterend/world/features/trees/UmbrellaTreeFeature.java b/src/main/java/ru/betterend/world/features/trees/UmbrellaTreeFeature.java deleted file mode 100644 index 3dc87359..00000000 --- a/src/main/java/ru/betterend/world/features/trees/UmbrellaTreeFeature.java +++ /dev/null @@ -1,246 +0,0 @@ -package ru.betterend.world.features.trees; - -import com.google.common.collect.Lists; -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.material.Material; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFFlatWave; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.bclib.world.features.DefaultFeature; -import ru.betterend.blocks.UmbrellaTreeClusterBlock; -import ru.betterend.blocks.UmbrellaTreeMembraneBlock; -import ru.betterend.registry.EndBlocks; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Function; - -public class UmbrellaTreeFeature extends DefaultFeature { - private static final Function REPLACE; - private static final List SPLINE; - private static final List ROOT; - - @Override - public boolean place(FeaturePlaceContext featureConfig) { - final RandomSource random = featureConfig.random(); - final BlockPos pos = featureConfig.origin(); - final WorldGenLevel world = featureConfig.level(); - final NoneFeatureConfiguration config = featureConfig.config(); - if (!world.getBlockState(pos.below()).is(BlockTags.NYLIUM)) return false; - - BlockState wood = EndBlocks.UMBRELLA_TREE.getBark().defaultBlockState(); - BlockState membrane = EndBlocks.UMBRELLA_TREE_MEMBRANE.defaultBlockState().setValue(UmbrellaTreeMembraneBlock.COLOR, 1); - BlockState center = EndBlocks.UMBRELLA_TREE_MEMBRANE.defaultBlockState().setValue(UmbrellaTreeMembraneBlock.COLOR, 0); - BlockState fruit = EndBlocks.UMBRELLA_TREE_CLUSTER.defaultBlockState().setValue(UmbrellaTreeClusterBlock.NATURAL, true); - - float size = MHelper.randRange(10, 20, random); - int count = (int) (size * 0.15F); - float var = MHelper.PI2 / (float) (count * 3); - float start = MHelper.randRange(0, MHelper.PI2, random); - SDF sdf = null; - List
centers = Lists.newArrayList(); - - float scale = 1; - if (config != null) { - scale = MHelper.randRange(1F, 1.7F, random); - } - - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2 + MHelper.randRange(0, var, random) + start; - List spline = SplineHelper.copySpline(SPLINE); - float sizeXZ = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.7F; - SplineHelper.scale(spline, sizeXZ, sizeXZ * MHelper.randRange(1F, 2F, random), sizeXZ); - // SplineHelper.offset(spline, new Vector3f((20 - size) * 0.2F, 0, 0)); - SplineHelper.rotateSpline(spline, angle); - SplineHelper.offsetParts(spline, random, 0.5F, 0, 0.5F); - - if (SplineHelper.canGenerate(spline, pos, world, REPLACE)) { - float rScale = (scale - 1) * 0.4F + 1; - SDF branch = SplineHelper.buildSDF(spline, 1.2F * rScale, 0.8F * rScale, (bpos) -> { - return wood; - }); - - Vector3f vec = spline.get(spline.size() - 1); - float radius = (size + MHelper.randRange(0, size * 0.5F, random)) * 0.4F; - - sdf = (sdf == null) ? branch : new SDFUnion().setSourceA(sdf).setSourceB(branch); - SDF mem = makeMembrane(world, radius, random, membrane, center); - - float px = MHelper.floor(vec.x()) + 0.5F; - float py = MHelper.floor(vec.y()) + 0.5F; - float pz = MHelper.floor(vec.z()) + 0.5F; - mem = new SDFTranslate().setTranslate(px, py, pz).setSource(mem); - sdf = new SDFSmoothUnion().setRadius(2).setSourceA(sdf).setSourceB(mem); - centers.add(new Center( - pos.getX() + (double) (px * scale), - pos.getY() + (double) (py * scale), - pos.getZ() + (double) (pz * scale), - radius * scale - )); - - vec = spline.get(0); - } - } - - if (sdf == null) { - return false; - } - - if (scale > 1) { - sdf = new SDFScale().setScale(scale).setSource(sdf); - } - - sdf.setReplaceFunction(REPLACE).addPostProcess((info) -> { - if (EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateUp()) && EndBlocks.UMBRELLA_TREE.isTreeLog(info.getStateDown())) { - return EndBlocks.UMBRELLA_TREE.getLog().defaultBlockState(); - } - else if (info.getState().equals(membrane)) { - Center min = centers.get(0); - double d = Double.MAX_VALUE; - BlockPos bpos = info.getPos(); - for (Center c : centers) { - double d2 = c.distance(bpos.getX(), bpos.getZ()); - if (d2 < d) { - d = d2; - min = c; - } - } - int color = MHelper.floor(d / min.radius * 7); - color = Mth.clamp(color, 1, 7); - return info.getState().setValue(UmbrellaTreeMembraneBlock.COLOR, color); - } - return info.getState(); - }).fillRecursive(world, pos); - makeRoots(world, pos, (size * 0.5F + 3) * scale, random, wood); - - for (Center c : centers) { - if (!world.getBlockState(new BlockPos(c.px, c.py, c.pz)).isAir()) { - count = MHelper.floor(MHelper.randRange(5F, 10F, random) * scale); - float startAngle = random.nextFloat() * MHelper.PI2; - for (int i = 0; i < count; i++) { - float angle = (float) i / count * MHelper.PI2 + startAngle; - float dist = MHelper.randRange(1.5F, 2.5F, random) * scale; - double px = c.px + Math.sin(angle) * dist; - double pz = c.pz + Math.cos(angle) * dist; - makeFruits(world, px, c.py - 1, pz, fruit, scale); - } - } - } - - return true; - } - - private void makeRoots(WorldGenLevel world, BlockPos pos, float radius, RandomSource random, BlockState wood) { - int count = (int) (radius * 1.5F); - for (int i = 0; i < count; i++) { - float angle = (float) i / (float) count * MHelper.PI2; - float scale = radius * MHelper.randRange(0.85F, 1.15F, random); - - List branch = SplineHelper.copySpline(ROOT); - SplineHelper.rotateSpline(branch, angle); - SplineHelper.scale(branch, scale); - Vector3f last = branch.get(branch.size() - 1); - if (world.getBlockState(pos.offset(last.x(), last.y(), last.z())).is(CommonBlockTags.GEN_END_STONES)) { - SplineHelper.fillSplineForce(branch, world, wood, pos, REPLACE); - } - } - } - - private SDF makeMembrane(WorldGenLevel world, float radius, RandomSource random, BlockState membrane, BlockState center) { - SDF sphere = new SDFSphere().setRadius(radius).setBlock(membrane); - SDF sub = new SDFTranslate().setTranslate(0, -4, 0).setSource(sphere); - sphere = new SDFSubtraction().setSourceA(sphere).setSourceB(sub); - sphere = new SDFScale3D().setScale(1, 0.5F, 1).setSource(sphere); - sphere = new SDFTranslate().setTranslate(0, 1 - radius * 0.5F, 0).setSource(sphere); - - float angle = random.nextFloat() * MHelper.PI2; - int count = (int) MHelper.randRange(radius, radius * 2, random); - if (count < 5) { - count = 5; - } - sphere = new SDFFlatWave().setAngle(angle).setRaysCount(count).setIntensity(0.6F).setSource(sphere); - - SDF cent = new SDFSphere().setRadius(2.5F).setBlock(center); - sphere = new SDFUnion().setSourceA(sphere).setSourceB(cent); - - return sphere; - } - - private void makeFruits(WorldGenLevel world, double px, double py, double pz, BlockState fruit, float scale) { - MutableBlockPos mut = new MutableBlockPos().set(px, py, pz); - for (int i = 0; i < 8; i++) { - mut.move(Direction.DOWN); - if (world.isEmptyBlock(mut)) { - BlockState state = world.getBlockState(mut.above()); - if (state.is(EndBlocks.UMBRELLA_TREE_MEMBRANE) && state.getValue(UmbrellaTreeMembraneBlock.COLOR) < 2) { - BlocksHelper.setWithoutUpdate(world, mut, fruit); - } - break; - } - } - } - - static { - SPLINE = Lists.newArrayList( - new Vector3f(0.00F, 0.00F, 0.00F), - new Vector3f(0.10F, 0.35F, 0.00F), - new Vector3f(0.20F, 0.50F, 0.00F), - new Vector3f(0.30F, 0.55F, 0.00F), - new Vector3f(0.42F, 0.70F, 0.00F), - new Vector3f(0.50F, 1.00F, 0.00F) - ); - - ROOT = Lists.newArrayList( - new Vector3f(0.1F, 0.70F, 0), - new Vector3f(0.3F, 0.30F, 0), - new Vector3f(0.7F, 0.05F, 0), - new Vector3f(0.8F, -0.20F, 0) - ); - SplineHelper.offset(ROOT, new Vector3f(0, -0.45F, 0)); - - REPLACE = (state) -> { - if (/*state.is(CommonBlockTags.END_STONES) || */state.getMaterial().equals(Material.PLANT) || state.is(EndBlocks.UMBRELLA_TREE_MEMBRANE)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } - - private class Center { - final double px; - final double py; - final double pz; - final float radius; - - Center(double x, double y, double z, float radius) { - this.px = x; - this.py = y; - this.pz = z; - this.radius = radius; - } - - double distance(float x, float z) { - return MHelper.length(px - x, pz - z); - } - } -} diff --git a/src/main/java/ru/betterend/world/generator/BiomeType.java b/src/main/java/ru/betterend/world/generator/BiomeType.java deleted file mode 100644 index d0dc037a..00000000 --- a/src/main/java/ru/betterend/world/generator/BiomeType.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.betterend.world.generator; - -public enum BiomeType { - LAND, VOID; -} diff --git a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java deleted file mode 100644 index 35f2a85f..00000000 --- a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java +++ /dev/null @@ -1,152 +0,0 @@ -package ru.betterend.world.generator; - -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import ru.betterend.config.Configs; - -public class GeneratorOptions { - private static int biomeSizeCaves; - private static boolean hasPortal; - private static boolean hasPillars; - private static boolean hasDragonFights; - private static boolean changeChorusPlant; - private static boolean newGenerator; - private static boolean generateCentralIsland; - private static boolean generateObsidianPlatform; - private static int endCityFailChance; - public static LayerOptions bigOptions; - public static LayerOptions mediumOptions; - public static LayerOptions smallOptions; - private static boolean changeSpawn; - private static BlockPos spawn; - private static boolean replacePortal; - private static boolean replacePillars; - private static int islandDistChunk; - private static boolean directSpikeHeight; - private static int circleRadius = 1000; - private static int circleRadiusSqr; - - public static void init() { - biomeSizeCaves = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeCaves", 32); - hasPortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "hasPortal", true); - hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true); - hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true); - changeChorusPlant = Configs.GENERATOR_CONFIG.getBoolean("chorusPlant", "changeChorusPlant", true); - newGenerator = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "useNewGenerator", true); - generateCentralIsland = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "generateCentralIsland", true); - endCityFailChance = Configs.GENERATOR_CONFIG.getInt("customGenerator", "endCityFailChance", 5); - generateObsidianPlatform = Configs.GENERATOR_CONFIG.getBooleanRoot("generateObsidianPlatform", true); - bigOptions = new LayerOptions( - "customGenerator.layers.bigIslands", - Configs.GENERATOR_CONFIG, - 300, - 200, - 70, - 10, - false - ); - mediumOptions = new LayerOptions( - "customGenerator.layers.mediumIslands", - Configs.GENERATOR_CONFIG, - 150, - 100, - 70, - 20, - true - ); - smallOptions = new LayerOptions( - "customGenerator.layers.smallIslands", - Configs.GENERATOR_CONFIG, - 60, - 50, - 70, - 30, - false - ); - changeSpawn = Configs.GENERATOR_CONFIG.getBoolean("spawn", "changeSpawn", false); - spawn = new BlockPos( - Configs.GENERATOR_CONFIG.getInt("spawn.point", "x", 20), - Configs.GENERATOR_CONFIG.getInt("spawn.point", "y", 65), - Configs.GENERATOR_CONFIG.getInt("spawn.point", "z", 0) - ); - replacePortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "customEndPortal", true); - replacePillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "customObsidianSpikes", true); - circleRadius = Configs.GENERATOR_CONFIG.getInt("customGenerator", "voidRingSize", 1000); - circleRadiusSqr = circleRadius * circleRadius; - islandDistChunk = (circleRadius >> 3); // Twice bigger than normal - } - - public static int getBiomeSizeCaves() { - return Mth.clamp(biomeSizeCaves, 1, 8192); - } - - public static boolean hasPortal() { - return hasPortal; - } - - public static boolean hasPillars() { - return hasPillars; - } - - public static boolean hasDragonFights() { - return hasDragonFights; - } - - public static boolean changeChorusPlant() { - return changeChorusPlant; - } - - public static boolean useNewGenerator() { - return newGenerator; - } - - public static boolean hasCentralIsland() { - return generateCentralIsland; - } - - public static boolean generateObsidianPlatform() { - return generateObsidianPlatform; - } - - public static int getEndCityFailChance() { - return endCityFailChance; - } - - public static boolean changeSpawn() { - return changeSpawn; - } - - public static BlockPos getSpawn() { - return spawn; - } - - public static boolean replacePortal() { - return replacePortal; - } - - public static boolean replacePillars() { - return replacePillars; - } - - public static int getIslandDistBlock() { - return circleRadius; - } - - public static int getIslandDistBlockSqr() { - return circleRadiusSqr; - } - - public static int getIslandDistChunk() { - return islandDistChunk; - } - - public static void setDirectSpikeHeight() { - directSpikeHeight = true; - } - - public static boolean isDirectSpikeHeight() { - boolean height = directSpikeHeight; - directSpikeHeight = false; - return height; - } -} diff --git a/src/main/java/ru/betterend/world/generator/IslandLayer.java b/src/main/java/ru/betterend/world/generator/IslandLayer.java deleted file mode 100644 index 8917b275..00000000 --- a/src/main/java/ru/betterend/world/generator/IslandLayer.java +++ /dev/null @@ -1,192 +0,0 @@ -package ru.betterend.world.generator; - -import com.google.common.collect.Maps; -import net.minecraft.core.BlockPos; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.LegacyRandomSource; - -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFRadialNoiseMap; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class IslandLayer { - private static final RandomSource RANDOM = new LegacyRandomSource(MHelper.RANDOM.nextLong()); - private final SDFRadialNoiseMap noise; - private final SDF island; - - private final List positions = new ArrayList(9); - private final Map islands = Maps.newHashMap(); - private final OpenSimplexNoise density; - private final int seed; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - private final LayerOptions options; - - public IslandLayer(int seed, LayerOptions options) { - this.density = new OpenSimplexNoise(seed); - this.options = options; - this.seed = seed; - - SDF cone1 = makeCone(0, 0.4F, 0.2F, -0.3F); - SDF cone2 = makeCone(0.4F, 0.5F, 0.1F, -0.1F); - SDF cone3 = makeCone(0.5F, 0.45F, 0.03F, 0.0F); - SDF cone4 = makeCone(0.45F, 0, 0.02F, 0.03F); - - SDF coneBottom = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone1).setSourceB(cone2); - SDF coneTop = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone3).setSourceB(cone4); - noise = (SDFRadialNoiseMap) new SDFRadialNoiseMap().setSeed(seed).setRadius(0.5F).setIntensity(0.2F).setSource(coneTop); - island = new SDFSmoothUnion().setRadius(0.01F).setSourceA(noise).setSourceB(coneBottom); - } - - private int getSeed(int x, int z) { - int h = seed + x * 374761393 + z * 668265263; - h = (h ^ (h >> 13)) * 1274126177; - return h ^ (h >> 16); - } - - public void updatePositions(double x, double z) { - int ix = MHelper.floor(x / options.distance); - int iz = MHelper.floor(z / options.distance); - - if (lastX != ix || lastZ != iz) { - lastX = ix; - lastZ = iz; - positions.clear(); - for (int pox = -1; pox < 2; pox++) { - int px = pox + ix; - long px2 = px; - for (int poz = -1; poz < 2; poz++) { - int pz = poz + iz; - long pz2 = pz; - if (px2 * px2 + pz2 * pz2 > options.centerDist) { - RANDOM.setSeed(getSeed(px, pz)); - double posX = (px + RANDOM.nextFloat()) * options.distance; - double posY = MHelper.randRange(options.minY, options.maxY, RANDOM); - double posZ = (pz + RANDOM.nextFloat()) * options.distance; - if (density.eval(posX * 0.01, posZ * 0.01) > options.coverage) { - positions.add(new BlockPos(posX, posY, posZ)); - } - } - } - } - } - - if (GeneratorOptions.hasCentralIsland() && Math.abs(ix) < GeneratorOptions.getIslandDistChunk() && Math.abs(iz) < GeneratorOptions - .getIslandDistChunk()) { - int count = positions.size(); - for (int n = 0; n < count; n++) { - BlockPos pos = positions.get(n); - long d = (long) pos.getX() * (long) pos.getX() + (long) pos.getZ() * (long) pos.getZ(); - if (d < GeneratorOptions.getIslandDistBlockSqr()) { - positions.remove(n); - count--; - n--; - } - } - if (options.hasCentralIsland) { - positions.add(new BlockPos(0, 64, 0)); - } - } - } - - private SDF getIsland(BlockPos pos) { - SDF island = islands.get(pos); - if (island == null) { - if (pos.getX() == 0 && pos.getZ() == 0) { - island = new SDFScale().setScale(1.3F).setSource(this.island); - } - else { - RANDOM.setSeed(getSeed(pos.getX(), pos.getZ())); - island = new SDFScale().setScale(RANDOM.nextFloat() + 0.5F).setSource(this.island); - } - islands.put(pos, island); - } - noise.setOffset(pos.getX(), pos.getZ()); - return island; - } - - private float getRelativeDistance(SDF sdf, BlockPos center, double px, double py, double pz) { - float x = (float) (px - center.getX()) / options.scale; - float y = (float) (py - center.getY()) / options.scale; - float z = (float) (pz - center.getZ()) / options.scale; - return sdf.getDistance(x, y, z); - } - - private float calculateSDF(double x, double y, double z) { - float distance = 10; - for (BlockPos pos : positions) { - SDF island = getIsland(pos); - float dist = getRelativeDistance(island, pos, x, y, z); - distance = MHelper.min(distance, dist); - } - return distance; - } - - public float getDensity(double x, double y, double z) { - return -calculateSDF(x, y, z); - } - - public float getDensity(double x, double y, double z, float height) { - noise.setIntensity(height); - noise.setRadius(0.5F / (1 + height)); - return -calculateSDF(x, y, z); - } - - public void clearCache() { - if (islands.size() > 128) { - islands.clear(); - } - } - - private static SDF makeCone(float radiusBottom, float radiusTop, float height, float minY) { - float hh = height * 0.5F; - SDF sdf = new SDFCappedCone().setHeight(hh).setRadius1(radiusBottom).setRadius2(radiusTop); - return new SDFTranslate().setTranslate(0, minY + hh, 0).setSource(sdf); - } - - /*private static NativeImage loadMap(String path) { - InputStream stream = IslandLayer.class.getResourceAsStream(path); - if (stream != null) { - try { - NativeImage map = NativeImage.read(stream); - stream.close(); - return map; - } - catch (IOException e) { - BetterEnd.LOGGER.warning(e.getMessage()); - } - } - return null; - }*/ - - /*static { - NativeImage map = loadMap("/assets/" + BetterEnd.MOD_ID + "/textures/heightmaps/mountain_1.png"); - - SDF cone1 = makeCone(0, 0.4F, 0.2F, -0.3F); - SDF cone2 = makeCone(0.4F, 0.5F, 0.1F, -0.1F); - SDF cone3 = makeCone(0.5F, 0.45F, 0.03F, 0.0F); - SDF cone4 = makeCone(0.45F, 0, 0.02F, 0.03F); - - SDF coneBottom = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone1).setSourceB(cone2); - SDF coneTop = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone3).setSourceB(cone4); - - SDF map1 = new SDFHeightmap().setMap(map).setIntensity(0.3F).setSource(coneTop); - NOISE = (SDFRadialNoiseMap) new SDFRadialNoiseMap().setSource(coneTop); - - ISLAND = new SDF[] { - new SDFSmoothUnion().setRadius(0.01F).setSourceA(coneTop).setSourceB(coneBottom), - new SDFSmoothUnion().setRadius(0.01F).setSourceA(map1).setSourceB(coneBottom) - }; - }*/ -} diff --git a/src/main/java/ru/betterend/world/generator/LayerOptions.java b/src/main/java/ru/betterend/world/generator/LayerOptions.java deleted file mode 100644 index 03c6ecab..00000000 --- a/src/main/java/ru/betterend/world/generator/LayerOptions.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.betterend.world.generator; - -import net.minecraft.util.Mth; -import ru.bclib.config.PathConfig; - -public class LayerOptions { - public final float distance; - public final float scale; - public final float coverage; - public final int center; - public final int heightVariation; - public final int minY; - public final int maxY; - public final long centerDist; - public final boolean hasCentralIsland; - - public LayerOptions(String name, PathConfig config, float distance, float scale, int center, int heightVariation, boolean hasCentral) { - this.distance = clampDistance(config.getFloat(name, "distance[1-8192]", distance)); - this.scale = clampScale(config.getFloat(name, "scale[0.1-1024]", scale)); - this.center = clampCenter(config.getInt(name, "averageHeight[0-255]", center)); - this.heightVariation = clampVariation(config.getInt(name, "heightVariation[0-255]", heightVariation)); - this.coverage = clampCoverage(config.getFloat(name, "coverage[0-1]", 0.5F)); - this.minY = this.center - this.heightVariation; - this.maxY = this.center + this.heightVariation; - this.centerDist = Mth.floor(1000 / this.distance); - this.hasCentralIsland = config.getBoolean(name, "hasCentralIsland", hasCentral); - } - - private float clampDistance(float value) { - return Mth.clamp(value, 1, 8192); - } - - private float clampScale(float value) { - return Mth.clamp(value, 0.1F, 1024); - } - - private float clampCoverage(float value) { - return 0.9999F - Mth.clamp(value, 0, 1) * 2; - } - - private int clampCenter(int value) { - return Mth.clamp(value, 0, 255); - } - - private int clampVariation(int value) { - return Mth.clamp(value, 0, 255); - } -} diff --git a/src/main/java/ru/betterend/world/generator/TerrainBoolCache.java b/src/main/java/ru/betterend/world/generator/TerrainBoolCache.java deleted file mode 100644 index 1d3f9362..00000000 --- a/src/main/java/ru/betterend/world/generator/TerrainBoolCache.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.betterend.world.generator; - -public class TerrainBoolCache { - private byte[] data = new byte[16384]; - - public static int scaleCoordinate(int value) { - return value >> 7; - } - - private int getIndex(int x, int z) { - return x << 7 | z; - } - - public void setData(int x, int z, byte value) { - data[getIndex(x & 127, z & 127)] = value; - } - - public byte getData(int x, int z) { - return data[getIndex(x & 127, z & 127)]; - } -} diff --git a/src/main/java/ru/betterend/world/generator/TerrainGenerator.java b/src/main/java/ru/betterend/world/generator/TerrainGenerator.java deleted file mode 100644 index cc14469c..00000000 --- a/src/main/java/ru/betterend/world/generator/TerrainGenerator.java +++ /dev/null @@ -1,200 +0,0 @@ -package ru.betterend.world.generator; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.minecraft.util.Mth; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.Climate.Sampler; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.util.MHelper; -import ru.bclib.world.biomes.BCLBiome; -import ru.betterend.noise.OpenSimplexNoise; - -import java.awt.Point; -import java.util.List; -import java.util.Map; -import java.util.Random; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.LegacyRandomSource; - -import net.fabricmc.fabric.impl.biome.TheEndBiomeData; - -import java.util.concurrent.locks.ReentrantLock; - -public class TerrainGenerator { - private static final Map TERRAIN_BOOL_CACHE_MAP = Maps.newHashMap(); - private static final ReentrantLock LOCKER = new ReentrantLock(); - private static final Point POS = new Point(); - private static final double SCALE_XZ = 8.0; - private static final double SCALE_Y = 4.0; - private static final float[] COEF; - private static final Point[] OFFS; - - private static IslandLayer largeIslands; - private static IslandLayer mediumIslands; - private static IslandLayer smallIslands; - private static OpenSimplexNoise noise1; - private static OpenSimplexNoise noise2; - private static BiomeSource biomeSource; - private static Sampler sampler; - - public static void initNoise(long seed, BiomeSource biomeSource, Sampler sampler) { - RandomSource random = new LegacyRandomSource(seed); - largeIslands = new IslandLayer(random.nextInt(), GeneratorOptions.bigOptions); - mediumIslands = new IslandLayer(random.nextInt(), GeneratorOptions.mediumOptions); - smallIslands = new IslandLayer(random.nextInt(), GeneratorOptions.smallOptions); - noise1 = new OpenSimplexNoise(random.nextInt()); - noise2 = new OpenSimplexNoise(random.nextInt()); - TERRAIN_BOOL_CACHE_MAP.clear(); - TerrainGenerator.biomeSource = biomeSource; - TerrainGenerator.sampler = sampler; - } - - public static void fillTerrainDensity(double[] buffer, int posX, int posZ, int scaleXZ, int scaleY) { - LOCKER.lock(); - - largeIslands.clearCache(); - mediumIslands.clearCache(); - smallIslands.clearCache(); - - int x = Mth.floor(posX / scaleXZ); - int z = Mth.floor(posZ / scaleXZ); - double distortion1 = noise1.eval(x * 0.1, z * 0.1) * 20 + noise2.eval( - x * 0.2, - z * 0.2 - ) * 10 + noise1.eval(x * 0.4, z * 0.4) * 5; - double distortion2 = noise2.eval(x * 0.1, z * 0.1) * 20 + noise1.eval( - x * 0.2, - z * 0.2 - ) * 10 + noise2.eval(x * 0.4, z * 0.4) * 5; - double px = (double) x * scaleXZ + distortion1; - double pz = (double) z * scaleXZ + distortion2; - - largeIslands.updatePositions(px, pz); - mediumIslands.updatePositions(px, pz); - smallIslands.updatePositions(px, pz); - - float height = getAverageDepth(x << 1, z << 1) * 0.5F; - - for (int y = 0; y < buffer.length; y++) { - double py = (double) y * scaleY; - float dist = largeIslands.getDensity(px, py, pz, height); - dist = dist > 1 ? dist : MHelper.max(dist, mediumIslands.getDensity(px, py, pz, height)); - dist = dist > 1 ? dist : MHelper.max(dist, smallIslands.getDensity(px, py, pz, height)); - if (dist > -0.5F) { - dist += noise1.eval(px * 0.01, py * 0.01, pz * 0.01) * 0.02 + 0.02; - dist += noise2.eval(px * 0.05, py * 0.05, pz * 0.05) * 0.01 + 0.01; - dist += noise1.eval(px * 0.1, py * 0.1, pz * 0.1) * 0.005 + 0.005; - } - if (py > 100) { - dist = (float) Mth.lerp((py - 100) / 27F, dist, -1); - } - buffer[y] = dist; - } - - LOCKER.unlock(); - } - - private static float getAverageDepth(int x, int z) { - if (biomeSource == null) { - return 0; - } - if (getBiome(biomeSource, x, z).getTerrainHeight() < 0.1F) { - return 0F; - } - float depth = 0F; - for (int i = 0; i < OFFS.length; i++) { - int px = x + OFFS[i].x; - int pz = z + OFFS[i].y; - depth += getBiome(biomeSource, px, pz).getTerrainHeight() * COEF[i]; - } - return depth; - } - - private static BCLBiome getBiome(BiomeSource biomeSource, int x, int z) { - return BiomeAPI.getBiome(biomeSource.getNoiseBiome(x, 0, z, sampler)); - } - - static { - float sum = 0; - List coef = Lists.newArrayList(); - List pos = Lists.newArrayList(); - for (int x = -3; x <= 3; x++) { - for (int z = -3; z <= 3; z++) { - float dist = MHelper.length(x, z) / 3F; - if (dist <= 1) { - sum += dist; - coef.add(dist); - pos.add(new Point(x, z)); - } - } - } - OFFS = pos.toArray(new Point[] {}); - COEF = new float[coef.size()]; - for (int i = 0; i < COEF.length; i++) { - COEF[i] = coef.get(i) / sum; - } - } - - public static Boolean isLand(int x, int z) { - int sectionX = TerrainBoolCache.scaleCoordinate(x); - int sectionZ = TerrainBoolCache.scaleCoordinate(z); - - LOCKER.lock(); - POS.setLocation(sectionX, sectionZ); - - TerrainBoolCache section = TERRAIN_BOOL_CACHE_MAP.get(POS); - if (section == null) { - if (TERRAIN_BOOL_CACHE_MAP.size() > 64) { - TERRAIN_BOOL_CACHE_MAP.clear(); - } - section = new TerrainBoolCache(); - TERRAIN_BOOL_CACHE_MAP.put(new Point(POS.x, POS.y), section); - } - byte value = section.getData(x, z); - if (value > 0) { - LOCKER.unlock(); - return value > 1; - } - - double px = (x >> 1) + 0.5; - double pz = (z >> 1) + 0.5; - - double distortion1 = noise1.eval(px * 0.1, pz * 0.1) * 20 + noise2.eval(px * 0.2, pz * 0.2) * 10 + noise1.eval( - px * 0.4, - pz * 0.4 - ) * 5; - double distortion2 = noise2.eval(px * 0.1, pz * 0.1) * 20 + noise1.eval(px * 0.2, pz * 0.2) * 10 + noise2.eval( - px * 0.4, - pz * 0.4 - ) * 5; - px = px * SCALE_XZ + distortion1; - pz = pz * SCALE_XZ + distortion2; - - largeIslands.updatePositions(px, pz); - mediumIslands.updatePositions(px, pz); - smallIslands.updatePositions(px, pz); - - boolean result = false; - for (int y = 0; y < 32; y++) { - double py = (double) y * SCALE_Y; - float dist = largeIslands.getDensity(px, py, pz); - dist = dist > 1 ? dist : MHelper.max(dist, mediumIslands.getDensity(px, py, pz)); - dist = dist > 1 ? dist : MHelper.max(dist, smallIslands.getDensity(px, py, pz)); - if (dist > -0.5F) { - dist += noise1.eval(px * 0.01, py * 0.01, pz * 0.01) * 0.02 + 0.02; - dist += noise2.eval(px * 0.05, py * 0.05, pz * 0.05) * 0.01 + 0.01; - dist += noise1.eval(px * 0.1, py * 0.1, pz * 0.1) * 0.005 + 0.005; - } - if (dist > -0.01) { - result = true; - break; - } - } - - section.setData(x, z, (byte) (result ? 2 : 1)); - LOCKER.unlock(); - - return result; - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/EternalPortalStructure.java b/src/main/java/ru/betterend/world/structures/features/EternalPortalStructure.java deleted file mode 100644 index 1154aeec..00000000 --- a/src/main/java/ru/betterend/world/structures/features/EternalPortalStructure.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.chunk.ChunkGenerator; -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.structure.Structure; -import net.minecraft.world.level.levelgen.structure.StructureType; -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.StructureTemplate; -import ru.bclib.util.StructureHelper; -import ru.bclib.world.structures.BCLStructure; -import ru.betterend.BetterEnd; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.NBTPiece; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; - -import javax.swing.text.html.Option; - -public class EternalPortalStructure extends FeatureBaseStructure { - private static final ResourceLocation STRUCTURE_ID = BetterEnd.makeID("portal/eternal_portal"); - private static final StructureTemplate STRUCTURE = StructureHelper.readStructure(STRUCTURE_ID); - - public EternalPortalStructure(StructureSettings s) { - super(s); - } - - @Override - public Optional findGenerationPoint(GenerationContext context) { - if (!BCLStructure.isValidBiome(context)) return Optional.empty(); - - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - - long x = (long) chunkPos.x * (long) chunkPos.x; - long z = (long) chunkPos.z * (long) chunkPos.z; - if (x + z < 1024L) { - return Optional.empty(); - } - if (chunkGenerator.getBaseHeight( - chunkPos.getBlockX(8), - chunkPos.getBlockZ(8), - Heightmap.Types.WORLD_SURFACE_WG, - levelHeightAccessor, - context.randomState() - ) < 5) { - return Optional.empty(); - } - return super.findGenerationPoint(context); - } - - @Override - public StructureType type() { - return EndStructures.ETERNAL_PORTAL.structureType; - } - - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - int x = chunkPos.getBlockX(8); - int z = chunkPos.getBlockZ(8); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, context.randomState()); - structurePiecesBuilder.addPiece(new NBTPiece( - STRUCTURE_ID, - STRUCTURE, - new BlockPos(x, y - 4, z), - random.nextInt(5), - true, - random - )); - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/FeatureBaseStructure.java b/src/main/java/ru/betterend/world/structures/features/FeatureBaseStructure.java deleted file mode 100644 index c8871d8b..00000000 --- a/src/main/java/ru/betterend/world/structures/features/FeatureBaseStructure.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.LegacyRandomSource; -import net.minecraft.world.level.levelgen.RandomState; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.Structure; -import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier; -import ru.bclib.world.structures.BCLStructure; - -import java.util.Optional; -import java.util.Random; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; - -public abstract class FeatureBaseStructure extends Structure { - protected static final BlockState AIR = Blocks.AIR.defaultBlockState(); - - public FeatureBaseStructure(Structure.StructureSettings structureSettings) { - super(structureSettings); - } - - @Override - public Optional findGenerationPoint(GenerationContext context) { - BlockPos pos = getGenerationHeight(context.chunkPos(), context.chunkGenerator(), context.heightAccessor(), context.randomState()); - if (pos.getZ() >= 20 && BCLStructure.isValidBiome(context)){ - return Optional.of(new Structure.GenerationStub(pos, (structurePiecesBuilder) -> { - generatePieces(structurePiecesBuilder, context); - })); - } - return Optional.empty(); - } - - protected Holder getNoiseBiome(ChunkGenerator cg, RandomState rState, int i, int j, int k) { - return cg.getBiomeSource().getNoiseBiome(i, j, k, rState.sampler()); - } - - protected abstract void generatePieces(StructurePiecesBuilder structurePiecesBuilder, Structure.GenerationContext context); - - private static BlockPos getGenerationHeight(ChunkPos chunkPos, ChunkGenerator chunkGenerator, LevelHeightAccessor levelHeightAccessor, RandomState rState) { - LegacyRandomSource random = new LegacyRandomSource(chunkPos.x + chunkPos.z * 10387313); - Rotation blockRotation = Rotation.getRandom(random); - - int i = 5; - int j = 5; - if (blockRotation == Rotation.CLOCKWISE_90) { - i = -5; - } - else if (blockRotation == Rotation.CLOCKWISE_180) { - i = -5; - j = -5; - } - else if (blockRotation == Rotation.COUNTERCLOCKWISE_90) { - j = -5; - } - - int k = chunkPos.getBlockX(7); - int l = chunkPos.getBlockZ(7); - int m = chunkGenerator.getFirstOccupiedHeight(k, l, Heightmap.Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - int n = chunkGenerator.getFirstOccupiedHeight(k, l + j, Heightmap.Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - int o = chunkGenerator.getFirstOccupiedHeight(k + i, l, Heightmap.Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - int p = chunkGenerator.getFirstOccupiedHeight( - k + i, - l + j, - Heightmap.Types.WORLD_SURFACE_WG, - levelHeightAccessor, rState - ); - return new BlockPos(k, l, Math.min(Math.min(m, n), Math.min(o, p))); - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/GiantIceStarStructure.java b/src/main/java/ru/betterend/world/structures/features/GiantIceStarStructure.java deleted file mode 100644 index b77d1313..00000000 --- a/src/main/java/ru/betterend/world/structures/features/GiantIceStarStructure.java +++ /dev/null @@ -1,131 +0,0 @@ -package ru.betterend.world.structures.features; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.StructureType; -import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFRotation; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.VoxelPiece; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class GiantIceStarStructure extends SDFStructureFeature { - private static final float minSize = 20; - private static final float maxSize = 35; - private static final int minCount = 25; - private static final int maxCount = 40; - - public GiantIceStarStructure(StructureSettings s) { - super(s); - } - - @Override - public StructureType type() { - return EndStructures.GIANT_ICE_STAR.structureType; - } - - protected static SDF getSDF(BlockPos pos, RandomSource random) { - float size = MHelper.randRange(minSize, maxSize, random); - int count = MHelper.randRange(minCount, maxCount, random); - List points = getFibonacciPoints(count); - SDF sdf = null; - SDF spike = new SDFCappedCone().setRadius1(3 + (size - 5) * 0.2F) - .setRadius2(0) - .setHeight(size) - .setBlock(EndBlocks.DENSE_SNOW); - spike = new SDFTranslate().setTranslate(0, size - 0.5F, 0).setSource(spike); - for (Vector3f point : points) { - SDF rotated = spike; - point = MHelper.normalize(point); - float angle = MHelper.angle(Vector3f.YP, point); - if (angle > 0.01F && angle < 3.14F) { - Vector3f axis = MHelper.normalize(MHelper.cross(Vector3f.YP, point)); - rotated = new SDFRotation().setRotation(axis, angle).setSource(spike); - } - else if (angle > 1) { - rotated = new SDFRotation().setRotation(Vector3f.YP, (float) Math.PI).setSource(spike); - } - sdf = (sdf == null) ? rotated : new SDFUnion().setSourceA(sdf).setSourceB(rotated); - } - - final float ancientRadius = size * 0.7F; - final float denseRadius = size * 0.9F; - final float iceRadius = size < 7 ? size * 5 : size * 1.3F; - final float randScale = size * 0.3F; - - final BlockPos center = pos; - final BlockState ice = EndBlocks.EMERALD_ICE.defaultBlockState(); - final BlockState dense = EndBlocks.DENSE_EMERALD_ICE.defaultBlockState(); - final BlockState ancient = EndBlocks.ANCIENT_EMERALD_ICE.defaultBlockState(); - final SDF sdfCopy = sdf; - - return sdf.addPostProcess((info) -> { - BlockPos bpos = info.getPos(); - float px = bpos.getX() - center.getX(); - float py = bpos.getY() - center.getY(); - float pz = bpos.getZ() - center.getZ(); - float distance = MHelper.length(px, py, pz) + sdfCopy.getDistance( - px, - py, - pz - ) * 0.4F + random.nextFloat() * randScale; - if (distance < ancientRadius) { - return ancient; - } - else if (distance < denseRadius) { - return dense; - } - else if (distance < iceRadius) { - return ice; - } - return info.getState(); - }); - } - - private static List getFibonacciPoints(int count) { - float max = count - 1; - List result = new ArrayList(count); - for (int i = 0; i < count; i++) { - float y = 1F - (i / max) * 2F; - float radius = (float) Math.sqrt(1F - y * y); - float theta = MHelper.PHI * i; - float x = (float) Math.cos(theta) * radius; - float z = (float) Math.sin(theta) * radius; - result.add(new Vector3f(x, y, z)); - } - return result; - } - - public void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - BlockPos start = new BlockPos(x, MHelper.randRange(32, 128, random), z); - VoxelPiece piece = new VoxelPiece((world) -> { - getSDF(start, random).fillRecursive(world, start); - }, random.nextInt()); - structurePiecesBuilder.addPiece(piece); - - //this.calculateBoundingBox(); - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/GiantMossyGlowshroomStructure.java b/src/main/java/ru/betterend/world/structures/features/GiantMossyGlowshroomStructure.java deleted file mode 100644 index d21010ac..00000000 --- a/src/main/java/ru/betterend/world/structures/features/GiantMossyGlowshroomStructure.java +++ /dev/null @@ -1,169 +0,0 @@ -package ru.betterend.world.structures.features; - -import com.mojang.math.Vector3f; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.StructureType; -import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder; -import ru.bclib.sdf.SDF; -import ru.bclib.sdf.operator.SDFBinary; -import ru.bclib.sdf.operator.SDFCoordModify; -import ru.bclib.sdf.operator.SDFFlatWave; -import ru.bclib.sdf.operator.SDFRound; -import ru.bclib.sdf.operator.SDFScale; -import ru.bclib.sdf.operator.SDFScale3D; -import ru.bclib.sdf.operator.SDFSmoothUnion; -import ru.bclib.sdf.operator.SDFSubtraction; -import ru.bclib.sdf.operator.SDFTranslate; -import ru.bclib.sdf.operator.SDFUnion; -import ru.bclib.sdf.primitive.SDFCappedCone; -import ru.bclib.sdf.primitive.SDFPrimitive; -import ru.bclib.sdf.primitive.SDFSphere; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.bclib.util.SplineHelper; -import ru.betterend.blocks.MossyGlowshroomCapBlock; -import ru.betterend.blocks.basis.FurBlock; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndStructures; - -import java.util.List; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class GiantMossyGlowshroomStructure extends SDFStructureFeature { - public GiantMossyGlowshroomStructure(StructureSettings s) { - super(s); - } - - - @Override - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - SDFStructureFeature.generatePieces(structurePiecesBuilder, context, GiantMossyGlowshroomStructure::getSDF); - } - - protected static SDF getSDF(BlockPos center, RandomSource random) { - SDFCappedCone cone1 = new SDFCappedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); - SDFCappedCone cone2 = new SDFCappedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); - SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); - SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0) - .setSource(new SDFScale().setScale(2).setSource(cone2)); - SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); - SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); - SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); - - SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone); - innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone); - cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone); - - SDF glowCone = new SDFCappedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F); - SDFPrimitive priGlowCone = (SDFPrimitive) glowCone; - glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone); - glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3); - - cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone); - - OpenSimplexNoise noise = new OpenSimplexNoise(1234); - cones = new SDFCoordModify().setFunction((pos) -> { - float dist = MHelper.length(pos.x(), pos.z()); - float y = pos.y() + (float) noise.eval( - pos.x() * 0.1 + center.getX(), - pos.z() * 0.1 + center.getZ() - ) * dist * 0.3F - dist * 0.15F; - pos.set(pos.x(), y, pos.z()); - }).setSource(cones); - - SDFTranslate HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0) - .setSource(cones)); - - SDF roots = new SDFSphere().setRadius(4F); - SDFPrimitive primRoots = (SDFPrimitive) roots; - roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots); - SDFFlatWave rotRoots = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots); - - SDFBinary function = new SDFSmoothUnion().setRadius(4) - .setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(rotRoots)); - - cone1.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); - cone2.setBlock(EndBlocks.MOSSY_GLOWSHROOM_CAP); - priGlowCone.setBlock(EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE); - primRoots.setBlock(EndBlocks.MOSSY_GLOWSHROOM.getBark()); - - float height = MHelper.randRange(10F, 25F, random); - int count = MHelper.floor(height / 4); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count); - SplineHelper.offsetParts(spline, random, 1F, 0, 1F); - SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { - return EndBlocks.MOSSY_GLOWSHROOM.getLog().defaultBlockState(); - }); - Vector3f pos = spline.get(spline.size() - 1); - float scale = MHelper.randRange(2F, 3.5F, random); - - HEAD_POS.setTranslate(pos.x(), pos.y(), pos.z()); - rotRoots.setAngle(random.nextFloat() * MHelper.PI2); - function.setSourceA(sdf); - - return new SDFRound().setRadius(1.5F) - .setSource(new SDFScale().setScale(scale).setSource(function)) - .addPostProcess((info) -> { - if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) { - if (random.nextBoolean() && info.getStateUp() - .getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() - .setValue( - MossyGlowshroomCapBlock.TRANSITION, - true - )); - return info.getState(); - } - else if (!EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !EndBlocks.MOSSY_GLOWSHROOM - .isTreeLog(info.getStateDown())) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM.getBark().defaultBlockState()); - return info.getState(); - } - } - else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_CAP) { - if (EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) { - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState() - .setValue( - MossyGlowshroomCapBlock.TRANSITION, - true - )); - return info.getState(); - } - - info.setState(EndBlocks.MOSSY_GLOWSHROOM_CAP.defaultBlockState()); - return info.getState(); - } - else if (info.getState().getBlock() == EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { - for (Direction dir : BlocksHelper.HORIZONTAL) { - if (info.getState(dir) == AIR) { - info.setBlockPos( - info.getPos().relative(dir), - EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState() - .setValue(FurBlock.FACING, dir) - ); - } - } - - if (info.getStateDown().getBlock() != EndBlocks.MOSSY_GLOWSHROOM_HYMENOPHORE) { - info.setBlockPos( - info.getPos().below(), - EndBlocks.MOSSY_GLOWSHROOM_FUR.defaultBlockState() - .setValue(FurBlock.FACING, Direction.DOWN) - ); - } - } - return info.getState(); - }); - } - - - @Override - public StructureType type() { - return EndStructures.GIANT_MOSSY_GLOWSHROOM.structureType; - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/MegaLakeSmallStructure.java b/src/main/java/ru/betterend/world/structures/features/MegaLakeSmallStructure.java deleted file mode 100644 index 849ee1e2..00000000 --- a/src/main/java/ru/betterend/world/structures/features/MegaLakeSmallStructure.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.RandomState; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.StructureType; -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 ru.bclib.util.MHelper; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.LakePiece; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class MegaLakeSmallStructure extends FeatureBaseStructure { - public MegaLakeSmallStructure(StructureSettings s) { - super(s); - } - - @Override - public StructureType type() { - return EndStructures.MEGALAKE_SMALL.structureType; - } - - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - final RandomState rState = context.randomState(); - - - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - - Holder biome = getNoiseBiome(chunkGenerator, rState,x >> 2, y >> 2, z >> 2); - if (y > 5) { - float radius = MHelper.randRange(20, 40, random); - float depth = MHelper.randRange(5, 10, random); - LakePiece piece = new LakePiece(new BlockPos(x, y, z), radius, depth, random, biome); - structurePiecesBuilder.addPiece(piece); - } - - //this.calculateBoundingBox(); - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/MegaLakeStructure.java b/src/main/java/ru/betterend/world/structures/features/MegaLakeStructure.java deleted file mode 100644 index dfb35fb5..00000000 --- a/src/main/java/ru/betterend/world/structures/features/MegaLakeStructure.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.RandomState; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.Structure; -import net.minecraft.world.level.levelgen.structure.StructureType; -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 ru.bclib.util.MHelper; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.LakePiece; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class MegaLakeStructure extends FeatureBaseStructure { - - - public MegaLakeStructure(Structure.StructureSettings structureSettings){ - super(structureSettings); - } - - @Override - public StructureType type() { - return EndStructures.MEGALAKE.structureType; - } - - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, Structure.GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final RandomState rState = context.randomState(); - - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - - if (y > 5) { - Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); - - float radius = MHelper.randRange(32, 64, random); - float depth = MHelper.randRange(7, 15, random); - LakePiece piece = new LakePiece(new BlockPos(x, y, z), radius, depth, random, biome); - structurePiecesBuilder.addPiece(piece); - } - } - -} diff --git a/src/main/java/ru/betterend/world/structures/features/MountainStructure.java b/src/main/java/ru/betterend/world/structures/features/MountainStructure.java deleted file mode 100644 index 757898c2..00000000 --- a/src/main/java/ru/betterend/world/structures/features/MountainStructure.java +++ /dev/null @@ -1,61 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.RandomState; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.StructureType; -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 ru.bclib.util.MHelper; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.CrystalMountainPiece; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class MountainStructure extends FeatureBaseStructure { - - public MountainStructure(StructureSettings s) { - super(s); - } - - @Override - public StructureType type() { - return EndStructures.MOUNTAIN.structureType; - } - - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - final RandomState rState = context.randomState(); - - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, rState); - if (y > 5) { - Holder biome = getNoiseBiome(chunkGenerator, rState,x >> 2, y >> 2, z >> 2); - float radius = MHelper.randRange(50, 100, random); - float height = radius * MHelper.randRange(0.8F, 1.2F, random); - CrystalMountainPiece piece = new CrystalMountainPiece( - new BlockPos(x, y, z), - radius, - height, - random, - biome - ); - structurePiecesBuilder.addPiece(piece); - } - - //this.calculateBoundingBox(); - } -} - diff --git a/src/main/java/ru/betterend/world/structures/features/PaintedMountainStructure.java b/src/main/java/ru/betterend/world/structures/features/PaintedMountainStructure.java deleted file mode 100644 index 6017c691..00000000 --- a/src/main/java/ru/betterend/world/structures/features/PaintedMountainStructure.java +++ /dev/null @@ -1,71 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.RandomState; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -import net.minecraft.world.level.levelgen.structure.StructureType; -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 ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.structures.piece.PaintedMountainPiece; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class PaintedMountainStructure extends FeatureBaseStructure { - private static final BlockState[] VARIANTS; - - public PaintedMountainStructure(StructureSettings s) { - super(s); - } - - @Override - public StructureType type() { - return EndStructures.PAINTED_MOUNTAIN.structureType; - } - - protected void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - final RandomState rState = context.randomState(); - - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor,rState); - if (y > 50) { - Holder biome = getNoiseBiome(chunkGenerator, rState, x >> 2, y >> 2, z >> 2); - float radius = MHelper.randRange(50, 100, random); - float height = radius * MHelper.randRange(0.4F, 0.6F, random); - int count = MHelper.floor(height * MHelper.randRange(0.1F, 0.35F, random) + 1); - BlockState[] slises = new BlockState[count]; - for (int i = 0; i < count; i++) { - slises[i] = VARIANTS[random.nextInt(VARIANTS.length)]; - } - structurePiecesBuilder.addPiece(new PaintedMountainPiece(new BlockPos(x, y, z), radius, height, random, biome, slises)); - } - - //this.calculateBoundingBox(); - } - - - static { - VARIANTS = new BlockState[] { - Blocks.END_STONE.defaultBlockState(), - EndBlocks.FLAVOLITE.stone.defaultBlockState(), - EndBlocks.VIOLECITE.stone.defaultBlockState(), - }; - } -} diff --git a/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java b/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java deleted file mode 100644 index 35f474e0..00000000 --- a/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.betterend.world.structures.features; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; -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 ru.bclib.sdf.SDF; -import ru.bclib.util.MHelper; -import ru.betterend.world.structures.piece.VoxelPiece; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.BiFunction; - -public abstract class SDFStructureFeature extends FeatureBaseStructure { - public SDFStructureFeature(StructureSettings s) { - super(s); - } - - public static void generatePieces(StructurePiecesBuilder structurePiecesBuilder, GenerationContext context, BiFunction sdf) { - final RandomSource random = context.random(); - final ChunkPos chunkPos = context.chunkPos(); - final ChunkGenerator chunkGenerator = context.chunkGenerator(); - final LevelHeightAccessor levelHeightAccessor = context.heightAccessor(); - int x = chunkPos.getBlockX(MHelper.randRange(4, 12, random)); - int z = chunkPos.getBlockZ(MHelper.randRange(4, 12, random)); - int y = chunkGenerator.getBaseHeight(x, z, Types.WORLD_SURFACE_WG, levelHeightAccessor, context.randomState()); - if (y > 5) { - BlockPos start = new BlockPos(x, y, z); - VoxelPiece piece = new VoxelPiece((world) -> { - sdf.apply(start, random).fillRecursive(world, start); - }, random.nextInt()); - - structurePiecesBuilder.addPiece(piece); - } - - //this.calculateBoundingBox(); - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/BasePiece.java b/src/main/java/ru/betterend/world/structures/piece/BasePiece.java deleted file mode 100644 index 88777eea..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/BasePiece.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.StructurePiece; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; - -public abstract class BasePiece extends StructurePiece { - protected BasePiece(StructurePieceType type, int i, BoundingBox boundingBox) { - super(type, i, boundingBox); - } - - protected BasePiece(StructurePieceType type, CompoundTag tag) { - super(type, tag); - fromNbt(tag); - } - - protected abstract void fromNbt(CompoundTag tag); - - protected void addAdditionalSaveData(CompoundTag tag) {} - - @Override - protected void addAdditionalSaveData(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag) { - addAdditionalSaveData(compoundTag); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/world/structures/piece/CavePiece.java b/src/main/java/ru/betterend/world/structures/piece/CavePiece.java deleted file mode 100644 index fb5483dd..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/CavePiece.java +++ /dev/null @@ -1,110 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndStructures; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class CavePiece extends BasePiece { - private OpenSimplexNoise noise; - private BlockPos center; - private float radius; - - public CavePiece(BlockPos center, float radius, int id) { - super(EndStructures.CAVE_PIECE, id, null); - this.center = center; - this.radius = radius; - this.noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); - makeBoundingBox(); - } - - public CavePiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.CAVE_PIECE, tag); - makeBoundingBox(); - } - - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - int x1 = MHelper.max(this.boundingBox.minX(), blockBox.minX()); - int z1 = MHelper.max(this.boundingBox.minZ(), blockBox.minZ()); - int x2 = MHelper.min(this.boundingBox.maxX(), blockBox.maxX()); - int z2 = MHelper.min(this.boundingBox.maxZ(), blockBox.maxZ()); - int y1 = this.boundingBox.minY(); - int y2 = this.boundingBox.maxY(); - - double hr = radius * 0.75; - double nr = radius * 0.25; - final MutableBlockPos pos = GlobalState.stateForThread().POS; - for (int x = x1; x <= x2; x++) { - int xsq = x - center.getX(); - xsq *= xsq; - pos.setX(x); - for (int z = z1; z <= z2; z++) { - int zsq = z - center.getZ(); - zsq *= zsq; - pos.setZ(z); - for (int y = y1; y <= y2; y++) { - int ysq = y - center.getY(); - ysq *= 1.6; - ysq *= ysq; - pos.setY(y); - double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr; - double r2 = r - 4.5; - double dist = xsq + ysq + zsq; - if (dist < r2 * r2) { - if (world.getBlockState(pos).is(CommonBlockTags.END_STONES)) { - BlocksHelper.setWithoutUpdate(world, pos, CAVE_AIR); - } - } - else if (dist < r * r) { - if (world.getBlockState(pos).getMaterial().isReplaceable()) { - BlocksHelper.setWithoutUpdate(world, pos, Blocks.END_STONE); - } - } - } - } - } - - return; - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - tag.put("center", NbtUtils.writeBlockPos(center)); - tag.putFloat("radius", radius); - } - - @Override - protected void fromNbt(CompoundTag tag) { - center = NbtUtils.readBlockPos(tag.getCompound("center")); - radius = tag.getFloat("radius"); - noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ())); - } - - private void makeBoundingBox() { - int minX = MHelper.floor(center.getX() - radius); - int minY = MHelper.floor(center.getY() - radius); - int minZ = MHelper.floor(center.getZ() - radius); - int maxX = MHelper.floor(center.getX() + radius + 1); - int maxY = MHelper.floor(center.getY() + radius + 1); - int maxZ = MHelper.floor(center.getZ() + radius + 1); - this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/CrystalMountainPiece.java b/src/main/java/ru/betterend/world/structures/piece/CrystalMountainPiece.java deleted file mode 100644 index c0886772..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/CrystalMountainPiece.java +++ /dev/null @@ -1,178 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndStructures; -import ru.betterend.util.GlobalState; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class CrystalMountainPiece extends MountainPiece { - private BlockState top; - - public CrystalMountainPiece(BlockPos center, float radius, float height, RandomSource random, Holder biome) { - super(EndStructures.MOUNTAIN_PIECE, center, radius, height, random, biome); - top = EndBiome.findTopMaterial(biome.value()); //biome.getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - } - - public CrystalMountainPiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.MOUNTAIN_PIECE, tag); - } - - @Override - protected void fromNbt(CompoundTag tag) { - super.fromNbt(tag); - top = EndBiome.findTopMaterial(BiomeAPI.getBiome(biomeID)); //BiomeAPI.getBiome(biomeID).getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - } - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - int sx = chunkPos.getMinBlockX(); - int sz = chunkPos.getMinBlockZ(); - final MutableBlockPos pos = GlobalState.stateForThread().POS; - ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); - Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); - Heightmap map2 = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE_WG); - for (int x = 0; x < 16; x++) { - int px = x + sx; - int px2 = px - center.getX(); - px2 *= px2; - pos.setX(x); - for (int z = 0; z < 16; z++) { - int pz = z + sz; - int pz2 = pz - center.getZ(); - pz2 *= pz2; - float dist = px2 + pz2; - if (dist < r2) { - pos.setZ(z); - dist = 1 - (float) Math.pow(dist / r2, 0.3); - int minY = map.getFirstAvailable(x, z); - if (minY < 10) { - continue; - } - pos.setY(minY); - while (!chunk.getBlockState(pos).is(CommonBlockTags.GEN_END_STONES) && pos.getY() > 56 && !chunk.getBlockState( - pos.below()).is(Blocks.CAVE_AIR)) { - pos.setY(pos.getY() - 1); - } - minY = pos.getY(); - minY = Math.max(minY, map2.getFirstAvailable(x, z)); - if (minY > center.getY() - 8) { - float maxY = dist * height * getHeightClamp(world, 12, px, pz); - if (maxY > 0) { - maxY *= (float) noise1.eval(px * 0.05, pz * 0.05) * 0.3F + 0.7F; - maxY *= (float) noise1.eval(px * 0.1, pz * 0.1) * 0.1F + 0.8F; - maxY += center.getY(); - int maxYI = (int) (maxY); - int cover = maxYI - 1; - boolean needCover = (noise1.eval(px * 0.1, pz * 0.1) + MHelper.randRange( - -0.4, - 0.4, - random - ) - (center.getY() + 14) * 0.1) > 0; - for (int y = minY - 1; y < maxYI; y++) { - pos.setY(y); - chunk.setBlockState( - pos, - needCover && y == cover ? top : Blocks.END_STONE.defaultBlockState(), - false - ); - } - } - } - } - } - } - - map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); - - // Big crystals - int count = (map.getFirstAvailable(8, 8) - (center.getY() + 24)) / 7; - count = Mth.clamp(count, 0, 8); - for (int i = 0; i < count; i++) { - int radius = MHelper.randRange(2, 3, random); - float fill = MHelper.randRange(0F, 1F, random); - int x = MHelper.randRange(radius, 15 - radius, random); - int z = MHelper.randRange(radius, 15 - radius, random); - int y = map.getFirstAvailable(x, z); - if (y > 80) { - pos.set(x, y, z); - if (chunk.getBlockState(pos.below()).is(Blocks.END_STONE)) { - int height = MHelper.floor(radius * MHelper.randRange(1.5F, 3F, random) + (y - 80) * 0.3F); - crystal(chunk, pos, radius, height, fill, random); - } - } - } - - // Small crystals - count = (map.getFirstAvailable(8, 8) - (center.getY() + 24)) / 2; - count = Mth.clamp(count, 4, 8); - for (int i = 0; i < count; i++) { - int radius = MHelper.randRange(1, 2, random); - float fill = random.nextBoolean() ? 0 : 1; - int x = MHelper.randRange(radius, 15 - radius, random); - int z = MHelper.randRange(radius, 15 - radius, random); - int y = map.getFirstAvailable(x, z); - if (y > 80) { - pos.set(x, y, z); - if (chunk.getBlockState(pos.below()).getBlock() == Blocks.END_STONE) { - int height = MHelper.floor(radius * MHelper.randRange(1.5F, 3F, random) + (y - 80) * 0.3F); - crystal(chunk, pos, radius, height, fill, random); - } - } - } - } - - private void crystal(ChunkAccess chunk, BlockPos pos, int radius, int height, float fill, RandomSource random) { - MutableBlockPos mut = new MutableBlockPos(); - int max = MHelper.floor(fill * radius + radius + 0.5F); - height += pos.getY(); - Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); - int coefX = MHelper.randRange(-1, 1, random); - int coefZ = MHelper.randRange(-1, 1, random); - for (int x = -radius; x <= radius; x++) { - mut.setX(x + pos.getX()); - if (mut.getX() >= 0 && mut.getX() < 16) { - int ax = Math.abs(x); - for (int z = -radius; z <= radius; z++) { - mut.setZ(z + pos.getZ()); - if (mut.getZ() >= 0 && mut.getZ() < 16) { - int az = Math.abs(z); - if (ax + az < max) { - int minY = map.getFirstAvailable(mut.getX(), mut.getZ()) - MHelper.randRange(3, 7, random); - if (pos.getY() - minY > 8) { - minY = pos.getY() - 8; - } - int h = coefX * x + coefZ * z + height; - for (int y = minY; y < h; y++) { - mut.setY(y); - chunk.setBlockState(mut, EndBlocks.AURORA_CRYSTAL.defaultBlockState(), false); - } - } - } - } - } - } - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/LakePiece.java b/src/main/java/ru/betterend/world/structures/piece/LakePiece.java deleted file mode 100644 index 109211ac..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/LakePiece.java +++ /dev/null @@ -1,269 +0,0 @@ -package ru.betterend.world.structures.piece; - -import com.google.common.collect.Maps; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.core.SectionPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import net.minecraft.world.level.material.FluidState; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.api.tag.CommonBlockTags; -import ru.bclib.util.BlocksHelper; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; -import ru.betterend.registry.EndBlocks; -import ru.betterend.registry.EndStructures; -import ru.betterend.world.biome.EndBiome; - -import java.util.Map; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class LakePiece extends BasePiece { - private static final BlockState ENDSTONE = Blocks.END_STONE.defaultBlockState(); - private static final BlockState WATER = Blocks.WATER.defaultBlockState(); - private Map heightmap = Maps.newHashMap(); - private OpenSimplexNoise noise; - private BlockPos center; - private float radius; - private float aspect; - private float depth; - private int seed; - - private ResourceLocation biomeID; - - public LakePiece(BlockPos center, float radius, float depth, RandomSource random, Holder biome) { - super(EndStructures.LAKE_PIECE, random.nextInt(), null); - this.center = center; - this.radius = radius; - this.depth = depth; - this.seed = random.nextInt(); - this.noise = new OpenSimplexNoise(this.seed); - this.aspect = radius / depth; - this.biomeID = BiomeAPI.getBiomeID(biome.value()); - makeBoundingBox(); - } - - public LakePiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.LAKE_PIECE, tag); - makeBoundingBox(); - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - tag.put("center", NbtUtils.writeBlockPos(center)); - tag.putFloat("radius", radius); - tag.putFloat("depth", depth); - tag.putInt("seed", seed); - tag.putString("biome", biomeID.toString()); - } - - @Override - protected void fromNbt(CompoundTag tag) { - center = NbtUtils.readBlockPos(tag.getCompound("center")); - radius = tag.getFloat("radius"); - depth = tag.getFloat("depth"); - seed = tag.getInt("seed"); - noise = new OpenSimplexNoise(seed); - aspect = radius / depth; - biomeID = new ResourceLocation(tag.getString("biome")); - } - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - int minY = this.boundingBox.minY(); - int maxY = this.boundingBox.maxY(); - int sx = SectionPos.sectionToBlockCoord(chunkPos.x); - int sz = SectionPos.sectionToBlockCoord(chunkPos.z); - MutableBlockPos mut = new MutableBlockPos(); - ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); - for (int x = 0; x < 16; x++) { - mut.setX(x); - int wx = x | sx; - double nx = wx * 0.1; - int x2 = wx - center.getX(); - for (int z = 0; z < 16; z++) { - mut.setZ(z); - int wz = z | sz; - double nz = wz * 0.1; - int z2 = wz - center.getZ(); - float clamp = getHeightClamp(world, 8, wx, wz); - if (clamp < 0.01) continue; - - double n = noise.eval(nx, nz) * 1.5 + 1.5; - double x3 = MHelper.sqr(x2 + noise.eval(nx, nz, 100) * 10); - double z3 = MHelper.sqr(z2 + noise.eval(nx, nz, -100) * 10); - - for (int y = maxY; y >= minY; y--) { - mut.setY((int) (y + n)); - double y2 = MHelper.sqr((y - center.getY()) * aspect); - double r2 = radius * clamp; - double r3 = r2 + 8; - r2 *= r2; - r3 = r3 * r3 + 100; - double dist = x3 + y2 + z3; - if (dist < r2) { - BlockState state = chunk.getBlockState(mut); - if (state.is(CommonBlockTags.GEN_END_STONES) || state.isAir()) { - state = mut.getY() < center.getY() ? WATER : CAVE_AIR; - chunk.setBlockState(mut, state, false); - } - } - else if (dist <= r3 && mut.getY() < center.getY()) { - BlockState state = chunk.getBlockState(mut); - BlockPos worldPos = mut.offset(sx, 0, sz); - if (!state.isCollisionShapeFullBlock(world, worldPos) && !state.isRedstoneConductor( - world, - worldPos - )) { - state = chunk.getBlockState(mut.above()); - if (state.isAir()) { - state = random.nextBoolean() ? ENDSTONE : EndBiome.findTopMaterial(world, worldPos); - } - else { - state = state.getFluidState().isEmpty() ? ENDSTONE : EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - chunk.setBlockState(mut, state, false); - } - } - } - } - } - fixWater(world, chunk, mut, random, sx, sz); - } - - private void fixWater(WorldGenLevel world, ChunkAccess chunk, MutableBlockPos mut, RandomSource random, int sx, int sz) { - int minY = this.boundingBox.minY(); - int maxY = this.boundingBox.maxY(); - for (int x = 0; x < 16; x++) { - mut.setX(x); - for (int z = 0; z < 16; z++) { - mut.setZ(z); - for (int y = minY; y <= maxY; y++) { - mut.setY(y); - FluidState state = chunk.getFluidState(mut); - if (!state.isEmpty()) { - mut.setY(y - 1); - if (chunk.getBlockState(mut).isAir()) { - mut.setY(y + 1); - - BlockState bState = chunk.getBlockState(mut); - if (bState.isAir()) { - bState = random.nextBoolean() ? ENDSTONE : EndBiome.findTopMaterial(world, mut.offset(sx, 0, sz)); - } - else { - bState = bState.getFluidState().isEmpty() ? ENDSTONE : EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - - mut.setY(y); - - makeEndstonePillar(chunk, mut, bState); - } - else if (x > 1 && x < 15 && z > 1 && z < 15) { - mut.setY(y); - for (Direction dir : BlocksHelper.HORIZONTAL) { - BlockPos wPos = mut.offset(dir.getStepX(), 0, dir.getStepZ()); - if (chunk.getBlockState(wPos).isAir()) { - mut.setY(y + 1); - BlockState bState = chunk.getBlockState(mut); - if (bState.isAir()) { - bState = random.nextBoolean() ? ENDSTONE : EndBiome.findTopMaterial(world, mut.offset(sx, 0, sz)); - } - else { - bState = bState.getFluidState().isEmpty() ? ENDSTONE : EndBlocks.ENDSTONE_DUST.defaultBlockState(); - } - mut.setY(y); - makeEndstonePillar(chunk, mut, bState); - break; - } - } - } - else if (chunk.getBlockState(mut.move(Direction.UP)).isAir()) { - chunk.markPosForPostprocessing(mut.move(Direction.DOWN).immutable()); - } - } - else if (chunk.getBlockState(mut).isRandomlyTicking()) { - chunk.markPosForPostprocessing(mut.immutable()); - } - } - } - } - } - - private void makeEndstonePillar(ChunkAccess chunk, MutableBlockPos mut, BlockState terrain) { - chunk.setBlockState(mut, terrain, false); - mut.setY(mut.getY() - 1); - while (!chunk.getFluidState(mut).isEmpty()) { - chunk.setBlockState(mut, ENDSTONE, false); - mut.setY(mut.getY() - 1); - } - } - - private int getHeight(WorldGenLevel world, BlockPos pos) { - int p = ((pos.getX() & 2047) << 11) | (pos.getZ() & 2047); - int h = heightmap.getOrDefault(p, Byte.MIN_VALUE); - if (h > Byte.MIN_VALUE) { - return h; - } - - if (!BiomeAPI.getBiomeID(world.getBiome(pos)).equals(biomeID)) { - heightmap.put(p, (byte) 0); - return 0; - } - - h = world.getHeight(Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - h = Mth.abs(h - center.getY()); - h = h < 8 ? 1 : 0; - - heightmap.put(p, (byte) h); - return h; - } - - private float getHeightClamp(WorldGenLevel world, int radius, int posX, int posZ) { - MutableBlockPos mut = new MutableBlockPos(); - int r2 = radius * radius; - float height = 0; - float max = 0; - for (int x = -radius; x <= radius; x++) { - mut.setX(posX + x); - int x2 = x * x; - for (int z = -radius; z <= radius; z++) { - mut.setZ(posZ + z); - int z2 = z * z; - if (x2 + z2 < r2) { - float mult = 1 - (float) Math.sqrt(x2 + z2) / radius; - max += mult; - height += getHeight(world, mut) * mult; - } - } - } - height /= max; - return Mth.clamp(height, 0, 1); - } - - private void makeBoundingBox() { - int minX = MHelper.floor(center.getX() - radius - 8); - int minY = MHelper.floor(center.getY() - depth - 8); - int minZ = MHelper.floor(center.getZ() - radius - 8); - int maxX = MHelper.floor(center.getX() + radius + 8); - int maxY = MHelper.floor(center.getY() + depth); - int maxZ = MHelper.floor(center.getZ() + radius + 8); - this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); - } -} \ No newline at end of file diff --git a/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java b/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java deleted file mode 100644 index 725353a7..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java +++ /dev/null @@ -1,142 +0,0 @@ -package ru.betterend.world.structures.piece; - -import com.google.common.collect.Maps; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; -import ru.bclib.api.biomes.BiomeAPI; -import ru.bclib.util.MHelper; -import ru.betterend.noise.OpenSimplexNoise; - -import java.util.Map; -import java.util.Random; -import net.minecraft.util.RandomSource; - -public abstract class MountainPiece extends BasePiece { - protected Map heightmap = Maps.newHashMap(); - protected OpenSimplexNoise noise1; - protected OpenSimplexNoise noise2; - protected BlockPos center; - protected float radius; - protected float height; - protected float r2; - protected ResourceLocation biomeID; - protected int seed1; - protected int seed2; - - public MountainPiece(StructurePieceType type, BlockPos center, float radius, float height, RandomSource random, Holder biome) { - super(type, random.nextInt(), null); - this.center = center; - this.radius = radius; - this.height = height; - this.r2 = radius * radius; - this.seed1 = random.nextInt(); - this.seed2 = random.nextInt(); - this.noise1 = new OpenSimplexNoise(this.seed1); - this.noise2 = new OpenSimplexNoise(this.seed2); - this.biomeID = BiomeAPI.getBiomeID(biome); - makeBoundingBox(); - } - - public MountainPiece(StructurePieceType type, CompoundTag tag) { - super(type, tag); - makeBoundingBox(); - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - tag.put("center", NbtUtils.writeBlockPos(center)); - tag.putFloat("radius", radius); - tag.putFloat("height", height); - tag.putString("biome", biomeID.toString()); - tag.putInt("seed1", seed1); - tag.putInt("seed2", seed2); - } - - @Override - protected void fromNbt(CompoundTag tag) { - center = NbtUtils.readBlockPos(tag.getCompound("center")); - radius = tag.getFloat("radius"); - height = tag.getFloat("height"); - biomeID = new ResourceLocation(tag.getString("biome")); - r2 = radius * radius; - seed1 = tag.getInt("seed1"); - seed2 = tag.getInt("seed2"); - noise1 = new OpenSimplexNoise(seed1); - noise2 = new OpenSimplexNoise(seed2); - } - - private int getHeight(WorldGenLevel world, BlockPos pos) { - int p = ((pos.getX() & 2047) << 11) | (pos.getZ() & 2047); - int h = heightmap.getOrDefault(p, Integer.MIN_VALUE); - if (h > Integer.MIN_VALUE) { - return h; - } - - if (!BiomeAPI.getBiomeID(world.getBiome(pos)).equals(biomeID)) { - heightmap.put(p, -10); - return -10; - } - h = world.getHeight(Types.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - h = Mth.abs(h - center.getY()); - if (h > 4) { - h = 4 - h; - heightmap.put(p, h); - return h; - } - - h = MHelper.floor(noise2.eval(pos.getX() * 0.01, pos.getZ() * 0.01) * noise2.eval( - pos.getX() * 0.002, - pos.getZ() * 0.002 - ) * 8 + 8); - - if (h < 0) { - heightmap.put(p, 0); - return 0; - } - - heightmap.put(p, h); - - return h; - } - - protected float getHeightClamp(WorldGenLevel world, int radius, int posX, int posZ) { - MutableBlockPos mut = new MutableBlockPos(); - float height = 0; - float max = 0; - for (int x = -radius; x <= radius; x++) { - mut.setX(posX + x); - int x2 = x * x; - for (int z = -radius; z <= radius; z++) { - mut.setZ(posZ + z); - int z2 = z * z; - float mult = 1 - (float) Math.sqrt(x2 + z2) / radius; - if (mult > 0) { - max += mult; - height += getHeight(world, mut) * mult; - } - } - } - height /= max; - return Mth.clamp(height / radius, 0, 1); - } - - private void makeBoundingBox() { - int minX = MHelper.floor(center.getX() - radius); - int minY = MHelper.floor(center.getY() - radius); - int minZ = MHelper.floor(center.getZ() - radius); - int maxX = MHelper.floor(center.getX() + radius + 1); - int maxY = MHelper.floor(center.getY() + radius + 1); - int maxZ = MHelper.floor(center.getZ() + radius + 1); - this.boundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java b/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java deleted file mode 100644 index eb82ef96..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/NBTPiece.java +++ /dev/null @@ -1,100 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import ru.bclib.util.MHelper; -import ru.bclib.util.StructureHelper; -import ru.betterend.registry.EndStructures; -import ru.betterend.util.StructureErode; -import ru.betterend.world.biome.EndBiome; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class NBTPiece extends BasePiece { - private ResourceLocation structureID; - private Rotation rotation; - private Mirror mirror; - private StructureTemplate structure; - private BlockPos pos; - private int erosion; - private boolean cover; - - public NBTPiece(ResourceLocation structureID, StructureTemplate structure, BlockPos pos, int erosion, boolean cover, RandomSource random) { - super(EndStructures.NBT_PIECE, random.nextInt(), null); - this.structureID = structureID; - this.structure = structure; - this.rotation = Rotation.getRandom(random); - this.mirror = Mirror.values()[random.nextInt(3)]; - this.pos = StructureHelper.offsetPos(pos, structure, rotation, mirror); - this.erosion = erosion; - this.cover = cover; - makeBoundingBox(); - } - - public NBTPiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.NBT_PIECE, tag); - makeBoundingBox(); - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - tag.putString("structureID", structureID.toString()); - tag.putInt("rotation", rotation.ordinal()); - tag.putInt("mirror", mirror.ordinal()); - tag.putInt("erosion", erosion); - tag.put("pos", NbtUtils.writeBlockPos(pos)); - tag.putBoolean("cover", cover); - } - - @Override - protected void fromNbt(CompoundTag tag) { - structureID = new ResourceLocation(tag.getString("structureID")); - rotation = Rotation.values()[tag.getInt("rotation")]; - mirror = Mirror.values()[tag.getInt("mirror")]; - erosion = tag.getInt("erosion"); - pos = NbtUtils.readBlockPos(tag.getCompound("pos")); - cover = tag.getBoolean("cover"); - structure = StructureHelper.readStructure(structureID); - } - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - BoundingBox bounds = BoundingBox.fromCorners(new Vec3i( - blockBox.minX(), - this.boundingBox.minY(), - blockBox.minZ() - ), new Vec3i(blockBox.maxX(), this.boundingBox.maxX(), blockBox.maxZ())); - StructurePlaceSettings placementData = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror).setBoundingBox(bounds); - structure.placeInWorld(world, pos, pos, placementData, random, 2); - if (erosion > 0) { - int x1 = MHelper.min(bounds.maxX(), boundingBox.maxX()); - int x0 = MHelper.max(bounds.minX(), boundingBox.minX()); - int z1 = MHelper.min(bounds.maxZ(), boundingBox.maxZ()); - int z0 = MHelper.max(bounds.minZ(), boundingBox.minZ()); - bounds = BoundingBox.fromCorners(new Vec3i(x0, bounds.minY(), z0), new Vec3i(x1, bounds.maxY(), z1)); - StructureErode.erode(world, bounds, erosion, random); - } - if (cover) { - StructureErode.cover(world, bounds, random, EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial()); - } - } - - private void makeBoundingBox() { - this.boundingBox = StructureHelper.getStructureBounds(pos, structure, rotation, mirror); - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/PaintedMountainPiece.java b/src/main/java/ru/betterend/world/structures/piece/PaintedMountainPiece.java deleted file mode 100644 index e922175c..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/PaintedMountainPiece.java +++ /dev/null @@ -1,108 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import ru.bclib.util.MHelper; -import ru.betterend.registry.EndStructures; -import ru.betterend.util.GlobalState; - -import java.util.Random; -import net.minecraft.util.RandomSource; - -public class PaintedMountainPiece extends MountainPiece { - private BlockState[] slises; - - public PaintedMountainPiece(BlockPos center, float radius, float height, RandomSource random, Holder biome, BlockState[] slises) { - super(EndStructures.PAINTED_MOUNTAIN_PIECE, center, radius, height, random, biome); - this.slises = slises; - } - - public PaintedMountainPiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.PAINTED_MOUNTAIN_PIECE, tag); - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - super.addAdditionalSaveData(tag); - ListTag slise = new ListTag(); - for (BlockState state : slises) { - slise.add(NbtUtils.writeBlockState(state)); - } - tag.put("slises", slise); - } - - @Override - protected void fromNbt(CompoundTag tag) { - super.fromNbt(tag); - ListTag slise = tag.getList("slises", 10); - slises = new BlockState[slise.size()]; - for (int i = 0; i < slises.length; i++) { - slises[i] = NbtUtils.readBlockState(slise.getCompound(i)); - } - } - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - int sx = chunkPos.getMinBlockX(); - int sz = chunkPos.getMinBlockZ(); - final MutableBlockPos pos = GlobalState.stateForThread().POS; - ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z); - Heightmap map = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE); - Heightmap map2 = chunk.getOrCreateHeightmapUnprimed(Types.WORLD_SURFACE_WG); - for (int x = 0; x < 16; x++) { - int px = x + sx; - int px2 = px - center.getX(); - px2 *= px2; - pos.setX(x); - for (int z = 0; z < 16; z++) { - int pz = z + sz; - int pz2 = pz - center.getZ(); - pz2 *= pz2; - float dist = px2 + pz2; - if (dist < r2) { - pos.setZ(z); - dist = 1 - dist / r2; - int minY = map.getFirstAvailable(x, z); - pos.setY(minY - 1); - while (chunk.getBlockState(pos).isAir() && pos.getY() > 50) { - pos.setY(minY--); - } - minY = pos.getY(); - minY = Math.max(minY, map2.getFirstAvailable(x, z)); - if (minY > center.getY() - 8) { - float maxY = dist * height * getHeightClamp(world, 10, px, pz); - if (maxY > 0) { - maxY *= (float) noise1.eval(px * 0.05, pz * 0.05) * 0.3F + 0.7F; - maxY *= (float) noise1.eval(px * 0.1, pz * 0.1) * 0.1F + 0.9F; - maxY += center.getY(); - float offset = (float) (noise1.eval(px * 0.07, pz * 0.07) * 5 + noise1.eval( - px * 0.2, - pz * 0.2 - ) * 2 + 7); - for (int y = minY - 1; y < maxY; y++) { - pos.setY(y); - int index = MHelper.floor((y + offset) * 0.65F) % slises.length; - chunk.setBlockState(pos, slises[index], false); - } - } - } - } - } - } - } -} diff --git a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java deleted file mode 100644 index 2eb3169a..00000000 --- a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.betterend.world.structures.piece; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.StructureManager; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; -import ru.bclib.world.structures.StructureWorld; -import ru.betterend.registry.EndStructures; - -import java.util.Random; -import net.minecraft.util.RandomSource; -import java.util.function.Consumer; - -public class VoxelPiece extends BasePiece { - private StructureWorld world; - - public VoxelPiece(Consumer function, int id) { - super(EndStructures.VOXEL_PIECE, id, null); - world = new StructureWorld(); - function.accept(world); - this.boundingBox = world.getBounds(); - } - - public VoxelPiece(StructurePieceSerializationContext type, CompoundTag tag) { - super(EndStructures.VOXEL_PIECE, tag); - this.boundingBox = world.getBounds(); - } - - @Override - protected void addAdditionalSaveData(CompoundTag tag) { - tag.put("world", world.toBNT()); - } - - @Override - protected void fromNbt(CompoundTag tag) { - world = new StructureWorld(tag.getCompound("world")); - } - - @Override - public void postProcess(WorldGenLevel world, StructureManager arg, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { - this.world.placeChunk(world, chunkPos); - } -} diff --git a/src/main/java/ru/betterend/world/surface/SplitNoiseCondition.java b/src/main/java/ru/betterend/world/surface/SplitNoiseCondition.java deleted file mode 100644 index c03d266b..00000000 --- a/src/main/java/ru/betterend/world/surface/SplitNoiseCondition.java +++ /dev/null @@ -1,36 +0,0 @@ -package ru.betterend.world.surface; - -import com.mojang.serialization.Codec; -import net.minecraft.core.Registry; -import ru.bclib.interfaces.NumericProvider; -import ru.bclib.mixin.common.SurfaceRulesContextAccessor; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; -import ru.betterend.noise.OpenSimplexNoise; - -/** - * Noise source that returns a value in [0, 1] - */ -public class SplitNoiseCondition implements NumericProvider { - public static final SplitNoiseCondition DEFAULT = new SplitNoiseCondition(); - public static final Codec CODEC = Codec.BYTE.fieldOf("split_noise").xmap((obj)->DEFAULT, obj -> (byte)0).codec(); - - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(4141); - - @Override - public int getNumber(SurfaceRulesContextAccessor context) { - final int x = context.getBlockX(); - final int z = context.getBlockZ(); - float noise = (float) NOISE.eval(x * 0.1, z * 0.1) + MHelper.randRange(-0.4F, 0.4F, MHelper.RANDOM_SOURCE); - return noise > 0 ? 1 : 0; - } - - @Override - public Codec pcodec() { - return CODEC; - } - - static { - Registry.register(NumericProvider.NUMERIC_PROVIDER , BetterEnd.makeID("split_noise"), SplitNoiseCondition.CODEC); - } -} diff --git a/src/main/java/ru/betterend/world/surface/SulphuricSurfaceNoiseCondition.java b/src/main/java/ru/betterend/world/surface/SulphuricSurfaceNoiseCondition.java deleted file mode 100644 index c42d30ae..00000000 --- a/src/main/java/ru/betterend/world/surface/SulphuricSurfaceNoiseCondition.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.betterend.world.surface; - -import com.mojang.serialization.Codec; -import net.minecraft.core.Registry; -import ru.bclib.interfaces.NumericProvider; -import ru.bclib.mixin.common.SurfaceRulesContextAccessor; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; -import ru.betterend.noise.OpenSimplexNoise; - -/** - * Noise source that returns a value in [0, 3] - */ -public class SulphuricSurfaceNoiseCondition implements NumericProvider { - public static final SulphuricSurfaceNoiseCondition DEFAULT = new SulphuricSurfaceNoiseCondition(); - public static final Codec CODEC = Codec.BYTE.fieldOf("sulphuric_surf").xmap((obj)->DEFAULT, obj -> (byte)0).codec(); - - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(5123); - - @Override - public int getNumber(SurfaceRulesContextAccessor context) { - final int x = context.getBlockX(); - final int z = context.getBlockZ(); - final double value = NOISE.eval(x * 0.03, z * 0.03) + NOISE.eval(x * 0.1, z * 0.1) * 0.3 + MHelper.randRange(-0.1, 0.1, MHelper.RANDOM_SOURCE); - if (value < -0.6) return 0; - if (value < -0.3) return 1; - if (value < 0.5) return 2; - return 3; - } - - @Override - public Codec pcodec() { - return CODEC; - } - - static { - Registry.register(NumericProvider.NUMERIC_PROVIDER , BetterEnd.makeID("sulphuric_surf"), SulphuricSurfaceNoiseCondition.CODEC); - } -} diff --git a/src/main/java/ru/betterend/world/surface/UmbraSurfaceNoiseCondition.java b/src/main/java/ru/betterend/world/surface/UmbraSurfaceNoiseCondition.java deleted file mode 100644 index 18e55cfb..00000000 --- a/src/main/java/ru/betterend/world/surface/UmbraSurfaceNoiseCondition.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.betterend.world.surface; - -import com.mojang.serialization.Codec; -import net.minecraft.core.Registry; -import ru.bclib.interfaces.NumericProvider; -import ru.bclib.mixin.common.SurfaceRulesContextAccessor; -import ru.bclib.util.MHelper; -import ru.betterend.BetterEnd; -import ru.betterend.noise.OpenSimplexNoise; - -/** - * Noise source that returns a value in [0, 4] - */ -public class UmbraSurfaceNoiseCondition implements NumericProvider { - public static final UmbraSurfaceNoiseCondition DEFAULT = new UmbraSurfaceNoiseCondition(); - public static final Codec CODEC = Codec.BYTE.fieldOf("umbra_srf").xmap((obj)->DEFAULT, obj -> (byte)0).codec(); - - private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(1512); - - @Override - public int getNumber(SurfaceRulesContextAccessor context) { - final int x = context.getBlockX(); - final int z = context.getBlockZ(); - return getDepth(x, z); - } - - public static int getDepth(int x, int z) { - final double value = NOISE.eval(x * 0.03, z * 0.03) + NOISE.eval(x * 0.1, z * 0.1) * 0.3 + MHelper.randRange(-0.1, 0.1, MHelper.RANDOM_SOURCE); - if (value > 0.4) return 0; - if (value > 0.15) return 1; - if (value > -0.15) return 2; - if (value > -0.4) return 3; - return 4; - } - - @Override - public Codec pcodec() { - return CODEC; - } - - static { - Registry.register(NumericProvider.NUMERIC_PROVIDER , BetterEnd.makeID("umbra_srf"), UmbraSurfaceNoiseCondition.CODEC); - } -} diff --git a/src/main/resources/betterend.mixins.client.json b/src/main/resources/betterend.mixins.client.json index 1ce18df4..4cd420be 100644 --- a/src/main/resources/betterend.mixins.client.json +++ b/src/main/resources/betterend.mixins.client.json @@ -1,7 +1,7 @@ { "required": true, "minVersion": "0.8", - "package": "ru.betterend.mixin.client", + "package": "org.betterx.betterend.mixin.client", "compatibilityLevel": "JAVA_16", "client": [ "AbstractSoundInstanceAccessor", diff --git a/src/main/resources/betterend.mixins.common.json b/src/main/resources/betterend.mixins.common.json index 3b87bbba..33ede3c7 100644 --- a/src/main/resources/betterend.mixins.common.json +++ b/src/main/resources/betterend.mixins.common.json @@ -1,7 +1,7 @@ { "required": true, "minVersion": "0.8", - "package": "ru.betterend.mixin.common", + "package": "org.betterx.betterend.mixin.common", "compatibilityLevel": "JAVA_16", "mixins": [ "LevelMixin", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b0727f00..a731071c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,13 +26,13 @@ "environment": "*", "entrypoints": { "main": [ - "ru.betterend.BetterEnd" + "org.betterx.betterend.BetterEnd" ], "client": [ - "ru.betterend.client.BetterEndClient" + "org.betterx.betterend.client.BetterEndClient" ], "rei_plugins": [ - "ru.betterend.integration.rei.REIPlugin" + "org.betterx.betterend.integration.rei.REIPlugin" ] }, "accessWidener" : "betterend.accesswidener",