From 2a94691ef06b832ca295e5ddb8432e096a7ba495 Mon Sep 17 00:00:00 2001 From: yurisuika Date: Wed, 11 Dec 2024 10:45:16 -0800 Subject: [PATCH] Changes far too numerous to enumerate. --- .../java/dev/yurisuika/blossom/Blossom.java | 154 +++------ ...rticle.java => FallingPetalsParticle.java} | 12 +- .../dev/yurisuika/blossom/config/Options.java | 6 +- .../core/particles/BlossomParticleTypes.java | 20 ++ .../mixin/world/entity/EntityMixin.java | 20 ++ .../world/entity/animal/BeeAccessor.java | 14 - .../mixin/world/entity/animal/BeeInvoker.java | 10 + .../mixin/world/entity/animal/BeeMixin.java | 184 ++++++++-- .../block/state/BlockBehaviourMixin.java | 32 +- .../server/commands/BlossomCommand.java | 69 ++-- .../blossom/tags/BlossomBlockTags.java | 12 + .../blossom/tags/BlossomItemTags.java | 12 + .../dev/yurisuika/blossom/util/Validate.java | 4 +- .../yurisuika/blossom/util/config/Option.java | 34 +- .../util/config/options/value/Blossoming.java | 12 +- .../util/config/options/value/Fruiting.java | 12 +- .../util/config/options/value/Harvesting.java | 20 +- .../world/entity/ai/goal/BlossomGoal.java | 315 ------------------ .../entity/ai/goal/BlossomLeavesGoal.java | 263 +++++++++++++++ .../world/entity/ai/goal/FruitGoal.java | 94 ------ .../world/entity/ai/goal/FruitLeavesGoal.java | 46 +++ .../entity/ai/goal/GoToKnownLeavesGoal.java | 58 ++++ .../world/entity/animal/BeeInterface.java | 29 ++ .../world/level/block/BlossomBlocks.java | 49 +++ .../level/block/FloweringLeavesBlock.java | 41 +-- .../level/block/FruitingLeavesBlock.java | 73 ++-- .../world/level/item/BlossomItems.java | 22 ++ .../resources/assets/blossom/lang/en_us.json | 37 +- .../assets/blossom/particles/blossom.json | 16 - .../particles/flowering_oak_leaves.json | 16 + .../{blossom_0.png => flowering_oak_0.png} | Bin .../{blossom_1.png => flowering_oak_1.png} | Bin .../{blossom_10.png => flowering_oak_10.png} | Bin .../{blossom_11.png => flowering_oak_11.png} | Bin .../{blossom_2.png => flowering_oak_2.png} | Bin .../{blossom_3.png => flowering_oak_3.png} | Bin .../{blossom_4.png => flowering_oak_4.png} | Bin .../{blossom_5.png => flowering_oak_5.png} | Bin .../{blossom_6.png => flowering_oak_6.png} | Bin .../{blossom_7.png => flowering_oak_7.png} | Bin .../{blossom_8.png => flowering_oak_8.png} | Bin .../{blossom_9.png => flowering_oak_9.png} | Bin src/main/resources/blossom.mixins.json | 6 +- .../blocks/flowering_oak_leaves.json | 57 +--- .../blocks/fruiting_oak_leaves.json | 57 +--- .../blossom/tags/blocks/leaved_flowers.json | 6 + .../blossom/tags/items/leaved_flowers.json | 6 + .../data/minecraft/tags/blocks/flowers.json | 2 +- .../data/minecraft/tags/items/flowers.json | 2 +- 49 files changed, 977 insertions(+), 845 deletions(-) rename src/main/java/dev/yurisuika/blossom/client/particle/{BlossomParticle.java => FallingPetalsParticle.java} (77%) create mode 100644 src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/world/entity/EntityMixin.java delete mode 100644 src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeAccessor.java create mode 100644 src/main/java/dev/yurisuika/blossom/tags/BlossomBlockTags.java create mode 100644 src/main/java/dev/yurisuika/blossom/tags/BlossomItemTags.java delete mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java delete mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitLeavesGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/GoToKnownLeavesGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/entity/animal/BeeInterface.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java create mode 100644 src/main/java/dev/yurisuika/blossom/world/level/item/BlossomItems.java delete mode 100644 src/main/resources/assets/blossom/particles/blossom.json create mode 100644 src/main/resources/assets/blossom/particles/flowering_oak_leaves.json rename src/main/resources/assets/blossom/textures/particle/{blossom_0.png => flowering_oak_0.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_1.png => flowering_oak_1.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_10.png => flowering_oak_10.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_11.png => flowering_oak_11.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_2.png => flowering_oak_2.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_3.png => flowering_oak_3.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_4.png => flowering_oak_4.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_5.png => flowering_oak_5.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_6.png => flowering_oak_6.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_7.png => flowering_oak_7.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_8.png => flowering_oak_8.png} (100%) rename src/main/resources/assets/blossom/textures/particle/{blossom_9.png => flowering_oak_9.png} (100%) create mode 100644 src/main/resources/data/blossom/tags/blocks/leaved_flowers.json create mode 100644 src/main/resources/data/blossom/tags/items/leaved_flowers.json diff --git a/src/main/java/dev/yurisuika/blossom/Blossom.java b/src/main/java/dev/yurisuika/blossom/Blossom.java index c4fa3218..1669b4ee 100644 --- a/src/main/java/dev/yurisuika/blossom/Blossom.java +++ b/src/main/java/dev/yurisuika/blossom/Blossom.java @@ -1,35 +1,31 @@ package dev.yurisuika.blossom; -import dev.yurisuika.blossom.client.particle.BlossomParticle; -import dev.yurisuika.blossom.mixin.world.level.block.BlocksInvoker; +import dev.yurisuika.blossom.client.particle.FallingPetalsParticle; +import dev.yurisuika.blossom.core.particles.BlossomParticleTypes; import dev.yurisuika.blossom.mixin.world.level.block.ComposterBlockInvoker; import dev.yurisuika.blossom.mixin.world.level.block.FireBlockInvoker; import dev.yurisuika.blossom.server.commands.BlossomCommand; import dev.yurisuika.blossom.util.Validate; import dev.yurisuika.blossom.util.config.Config; -import dev.yurisuika.blossom.world.entity.ai.goal.BlossomGoal; -import dev.yurisuika.blossom.world.entity.ai.goal.FruitGoal; +import dev.yurisuika.blossom.world.entity.animal.BeeInterface; +import dev.yurisuika.blossom.world.level.block.BlossomBlocks; import dev.yurisuika.blossom.world.level.block.FloweringLeavesBlock; import dev.yurisuika.blossom.world.level.block.FruitingLeavesBlock; +import dev.yurisuika.blossom.world.level.item.BlossomItems; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BiomeColors; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.item.ItemProperties; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.animal.Bee; -import net.minecraft.world.item.*; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.Items; import net.minecraft.world.level.FoliageColor; -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.MapColor; -import net.minecraft.world.level.material.PushReaction; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RegisterColorHandlersEvent; import net.minecraftforge.client.event.RegisterParticleProvidersEvent; @@ -42,67 +38,24 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegistryObject; import java.util.Objects; -import java.util.function.Supplier; @Mod("blossom") public class Blossom { - public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "blossom"); - public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, "blossom"); - public static final DeferredRegister> PARTICLES = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, "blossom"); - - public static final RegistryObject FRUITING_OAK_LEAVES = register("fruiting_oak_leaves", () -> new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, BlockBehaviour.Properties.of() - .mapColor(MapColor.PLANT) - .strength(0.2F) - .randomTicks() - .sound(SoundType.GRASS) - .noOcclusion() - .isValidSpawn(BlocksInvoker::invokeOcelotOrParrot) - .isSuffocating(BlocksInvoker::invokeNever) - .isViewBlocking(BlocksInvoker::invokeNever) - .ignitedByLava() - .pushReaction(PushReaction.DESTROY) - .isRedstoneConductor(BlocksInvoker::invokeNever)), new Item.Properties()); - public static final RegistryObject FLOWERING_OAK_LEAVES = register("flowering_oak_leaves", () -> new FloweringLeavesBlock(Blocks.OAK_LEAVES, Blossom.FRUITING_OAK_LEAVES.get(), BlockBehaviour.Properties.of() - .mapColor(MapColor.PLANT) - .strength(0.2F) - .randomTicks() - .sound(SoundType.GRASS) - .noOcclusion() - .isValidSpawn(BlocksInvoker::invokeOcelotOrParrot) - .isSuffocating(BlocksInvoker::invokeNever) - .isViewBlocking(BlocksInvoker::invokeNever) - .ignitedByLava() - .pushReaction(PushReaction.DESTROY) - .isRedstoneConductor(BlocksInvoker::invokeNever)), new Item.Properties()); - - public static final RegistryObject BLOSSOM = PARTICLES.register("blossom", () -> new SimpleParticleType(false)); - - public static RegistryObject register(String name, Supplier supplier, Item.Properties properties) { - RegistryObject block = BLOCKS.register(name, supplier); - ITEMS.register(name, () -> new BlockItem(block.get(), properties)); - return block; - } - @Mod.EventBusSubscriber(modid = "blossom") public static class CommonForgeEvents { @SubscribeEvent - public static void registerCommandsEvents(RegisterCommandsEvent event) { + public static void registerCommands(RegisterCommandsEvent event) { BlossomCommand.register(event.getDispatcher(), event.getBuildContext(), event.getCommandSelection()); } @SubscribeEvent - public static void entityJoinLevelEvents(EntityJoinLevelEvent event) { - Entity entity = event.getEntity(); - if (entity instanceof Bee) { - ((Bee) entity).getGoalSelector().addGoal(4, new BlossomGoal((Bee) entity)); - ((Bee) entity).getGoalSelector().addGoal(4, new FruitGoal((Bee) entity)); + public static void registerGoals(EntityJoinLevelEvent event) { + if (event.getEntity() instanceof Bee entity) { + ((BeeInterface) entity).registerGoals(entity); } } @@ -112,17 +65,15 @@ public static void entityJoinLevelEvents(EntityJoinLevelEvent event) { public static class CommonModBusEvents { @SubscribeEvent - public static void commonSetup(FMLCommonSetupEvent event) { - ComposterBlockInvoker.invokeAdd(0.3F, Blossom.FLOWERING_OAK_LEAVES.get()); - ComposterBlockInvoker.invokeAdd(0.3F, Blossom.FRUITING_OAK_LEAVES.get()); - - ((FireBlockInvoker) Blocks.FIRE).invokeSetFlammable(Blossom.FLOWERING_OAK_LEAVES.get(), 30, 60); - ((FireBlockInvoker) Blocks.FIRE).invokeSetFlammable(Blossom.FRUITING_OAK_LEAVES.get(), 30, 60); + public static void registerCompostables(FMLCommonSetupEvent event) { + ComposterBlockInvoker.invokeAdd(0.3F, BlossomBlocks.FRUITING_OAK_LEAVES.get()); + ComposterBlockInvoker.invokeAdd(0.3F, BlossomBlocks.FLOWERING_OAK_LEAVES.get()); } @SubscribeEvent - public static void registerParticleProvidersEvents(RegisterParticleProvidersEvent event) { - Minecraft.getInstance().particleEngine.register(BLOSSOM.get(), BlossomParticle.Factory::new); + public static void registerFlammables(FMLCommonSetupEvent event) { + ((FireBlockInvoker) Blocks.FIRE).invokeSetFlammable(BlossomBlocks.FRUITING_OAK_LEAVES.get(), 30, 60); + ((FireBlockInvoker) Blocks.FIRE).invokeSetFlammable(BlossomBlocks.FLOWERING_OAK_LEAVES.get(), 30, 60); } } @@ -130,65 +81,62 @@ public static void registerParticleProvidersEvents(RegisterParticleProvidersEven @Mod.EventBusSubscriber(modid = "blossom", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public static class ClientModBusEvents { - @SuppressWarnings("removal") @SubscribeEvent - public static void clientSetup(FMLClientSetupEvent event) { - ItemBlockRenderTypes.setRenderLayer(Blossom.FLOWERING_OAK_LEAVES.get(), RenderType.cutout()); - ItemBlockRenderTypes.setRenderLayer(Blossom.FRUITING_OAK_LEAVES.get(), RenderType.cutout()); + public static void registerParticles(RegisterParticleProvidersEvent event) { + Minecraft.getInstance().particleEngine.register(BlossomParticleTypes.FLOWERING_OAK_LEAVES.get(), FallingPetalsParticle.FloweringOakProvider::new); + } + + @SubscribeEvent + public static void registerRenderLayers(FMLClientSetupEvent event) { + ItemBlockRenderTypes.setRenderLayer(BlossomBlocks.FRUITING_OAK_LEAVES.get(), RenderType.cutout()); + ItemBlockRenderTypes.setRenderLayer(BlossomBlocks.FLOWERING_OAK_LEAVES.get(), RenderType.cutout()); + } - ItemProperties.register(FLOWERING_OAK_LEAVES.get().asItem(), new ResourceLocation("age"), (stack, world, entity, seed) -> { + @SubscribeEvent + public static void registerItemProperties(FMLClientSetupEvent event) { + ItemProperties.register(BlossomItems.FRUITING_OAK_LEAVES.get(), ResourceLocation.tryParse("age"), (stack, world, entity, seed) -> { CompoundTag tag = stack.getTagElement("BlockStateTag"); - try { - if (Objects.nonNull(tag) && Objects.nonNull(tag.get(FloweringLeavesBlock.AGE.getName()))) { - return Integer.parseInt(tag.get(FloweringLeavesBlock.AGE.getName()).getAsString()) / 4.0F; - } - } catch (NumberFormatException ignored) {} - return 0.0F; + return Objects.nonNull(tag) ? Integer.parseInt(tag.get(FruitingLeavesBlock.AGE.getName()).getAsString()) / 8.0F : 0.0F; }); - ItemProperties.register(FRUITING_OAK_LEAVES.get().asItem(), new ResourceLocation("age"), (stack, world, entity, seed) -> { + ItemProperties.register(BlossomItems.FLOWERING_OAK_LEAVES.get(), ResourceLocation.tryParse("age"), (stack, world, entity, seed) -> { CompoundTag tag = stack.getTagElement("BlockStateTag"); - try { - if (Objects.nonNull(tag) && Objects.nonNull(tag.get(FloweringLeavesBlock.AGE.getName()))) { - return Integer.parseInt(tag.get(FloweringLeavesBlock.AGE.getName()).getAsString()) / 8.0F; - } - } catch (NumberFormatException ignored) {} - return 0.0F; + return Objects.nonNull(tag) ? Integer.parseInt(tag.get(FloweringLeavesBlock.AGE.getName()).getAsString()) / 4.0F : 0.0F; }); } @SubscribeEvent - public static void registerBlockColorHandlerEvents(RegisterColorHandlersEvent.Block events) { - events.getBlockColors().register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), Blossom.FLOWERING_OAK_LEAVES.get()); - events.getBlockColors().register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), Blossom.FRUITING_OAK_LEAVES.get()); + public static void registerBlockColors(RegisterColorHandlersEvent.Block event) { + event.getBlockColors().register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), BlossomBlocks.FRUITING_OAK_LEAVES.get()); + event.getBlockColors().register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), BlossomBlocks.FLOWERING_OAK_LEAVES.get()); } @SubscribeEvent - public static void registerItemColorHandlerEvents(RegisterColorHandlersEvent.Item events) { - events.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), FLOWERING_OAK_LEAVES.get()); - events.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), FRUITING_OAK_LEAVES.get()); + public static void registerItemColors(RegisterColorHandlersEvent.Item event) { + event.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), BlossomBlocks.FRUITING_OAK_LEAVES.get()); + event.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), BlossomBlocks.FLOWERING_OAK_LEAVES.get()); } @SubscribeEvent - public static void buildCreativeModeTabContentsEvents(BuildCreativeModeTabContentsEvent event) { - if(event.getTabKey() == CreativeModeTabs.NATURAL_BLOCKS) { - event.accept(FLOWERING_OAK_LEAVES); - event.getEntries().putAfter(Items.FLOWERING_AZALEA_LEAVES.getDefaultInstance(), FLOWERING_OAK_LEAVES.get().asItem().getDefaultInstance(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); - event.accept(FRUITING_OAK_LEAVES); - event.getEntries().putAfter(FLOWERING_OAK_LEAVES.get().asItem().getDefaultInstance(), FRUITING_OAK_LEAVES.get().asItem().getDefaultInstance(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); + public static void registerCreativeModeTabs(BuildCreativeModeTabContentsEvent event) { + if (event.getTabKey() == CreativeModeTabs.NATURAL_BLOCKS) { + event.accept(BlossomBlocks.FRUITING_OAK_LEAVES.get()); + event.getEntries().putAfter(Items.FLOWERING_AZALEA_LEAVES.getDefaultInstance(), BlossomItems.FRUITING_OAK_LEAVES.get().getDefaultInstance(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); + event.accept(BlossomBlocks.FLOWERING_OAK_LEAVES.get()); + event.getEntries().putAfter(Items.FLOWERING_AZALEA_LEAVES.getDefaultInstance(), BlossomItems.FLOWERING_OAK_LEAVES.get().getDefaultInstance(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS); } } } - public Blossom() { + public Blossom(FMLJavaModLoadingContext context) { Config.loadConfig(); Validate.checkBounds(); - MinecraftForge.EVENT_BUS.register(this); + BlossomBlocks.register(context.getModEventBus()); + BlossomItems.register(context.getModEventBus()); + BlossomParticleTypes.register(context.getModEventBus()); - BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus()); - ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); - PARTICLES.register(FMLJavaModLoadingContext.get().getModEventBus()); + MinecraftForge.EVENT_BUS.register(this); } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java b/src/main/java/dev/yurisuika/blossom/client/particle/FallingPetalsParticle.java similarity index 77% rename from src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java rename to src/main/java/dev/yurisuika/blossom/client/particle/FallingPetalsParticle.java index 1ec13d9b..5fa33545 100644 --- a/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java +++ b/src/main/java/dev/yurisuika/blossom/client/particle/FallingPetalsParticle.java @@ -4,18 +4,18 @@ import net.minecraft.client.particle.*; import net.minecraft.core.particles.SimpleParticleType; -public class BlossomParticle extends TextureSheetParticle { +public class FallingPetalsParticle extends TextureSheetParticle { public float rotSpeed; public final float particleRandom; public final float spinAcceleration; - public BlossomParticle(ClientLevel level, double x, double y, double z, SpriteSet spriteSet) { + public FallingPetalsParticle(ClientLevel level, double x, double y, double z, SpriteSet spriteSet) { super(level, x, y, z); this.setSprite(spriteSet.get(random.nextInt(12), 12)); - this.rotSpeed = (float)Math.toRadians(random.nextBoolean() ? -30.0F : 30.0F); + this.rotSpeed = (float) Math.toRadians(random.nextBoolean() ? -30.0F : 30.0F); this.particleRandom = random.nextFloat(); - this.spinAcceleration = (float)Math.toRadians(random.nextBoolean() ? -5.0F : 5.0F); + this.spinAcceleration = (float) Math.toRadians(random.nextBoolean() ? -5.0F : 5.0F); this.lifetime = 300; this.gravity = 7.5E-4F; float f = this.random.nextBoolean() ? 0.05F : 0.075F; @@ -28,10 +28,10 @@ public ParticleRenderType getRenderType() { return ParticleRenderType.PARTICLE_SHEET_OPAQUE; } - public record Factory(SpriteSet spriteSet) implements ParticleProvider { + public record FloweringOakProvider(SpriteSet spriteSet) implements ParticleProvider { public Particle createParticle(SimpleParticleType parameters, ClientLevel level, double x, double y, double z, double r, double g, double b) { - return new BlossomParticle(level, x, y, z, spriteSet); + return new FallingPetalsParticle(level, x, y, z, spriteSet); } } diff --git a/src/main/java/dev/yurisuika/blossom/config/Options.java b/src/main/java/dev/yurisuika/blossom/config/Options.java index 3c9bd51d..326ca83f 100644 --- a/src/main/java/dev/yurisuika/blossom/config/Options.java +++ b/src/main/java/dev/yurisuika/blossom/config/Options.java @@ -14,9 +14,9 @@ public class Options { public Value value = new Value( - new Blossoming(0.2F, 10.0D), - new Fruiting(0.2F, 10.0D), - new Harvesting(3, 0.5714286F) + new Blossoming(0.2F), + new Fruiting(0.2F), + new Harvesting(0.5714286F, 3) ); public Filter filter = new Filter( new Temperature(-2.0F, 2.0F), diff --git a/src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java b/src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java new file mode 100644 index 00000000..4464b0d4 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java @@ -0,0 +1,20 @@ +package dev.yurisuika.blossom.core.particles; + +import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class BlossomParticleTypes { + + public static final DeferredRegister> PARTICLES = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, "blossom"); + + public static final RegistryObject FLOWERING_OAK_LEAVES = PARTICLES.register("flowering_oak_leaves", () -> new SimpleParticleType(false)); + + public static void register(IEventBus eventBus) { + PARTICLES.register(eventBus); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/EntityMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/EntityMixin.java new file mode 100644 index 00000000..4fec2f87 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/EntityMixin.java @@ -0,0 +1,20 @@ +package dev.yurisuika.blossom.mixin.world.entity; + +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Shadow + public abstract Level level(); + + @Final + @Shadow + protected RandomSource random; + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeAccessor.java b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeAccessor.java deleted file mode 100644 index eea2fb10..00000000 --- a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package dev.yurisuika.blossom.mixin.world.entity.animal; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.animal.Bee; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Bee.class) -public interface BeeAccessor { - - @Accessor("savedFlowerPos") - void setSavedFlowerPos(BlockPos savedFlowerPos); - -} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeInvoker.java b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeInvoker.java index 2410b89d..557eb206 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeInvoker.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeInvoker.java @@ -1,5 +1,6 @@ package dev.yurisuika.blossom.mixin.world.entity.animal; +import net.minecraft.core.BlockPos; import net.minecraft.world.entity.animal.Bee; import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @@ -18,4 +19,13 @@ public interface BeeInvoker { @Invoker("getCropsGrownSincePollination") int invokeGetCropsGrownSincePollination(); + @Invoker("isTooFarAway") + boolean invokeIsTooFarAway(BlockPos pos); + + @Invoker("pathfindRandomlyTowards") + void invokePathfindRandomlyTowards(BlockPos pos); + + @Invoker("closerThan") + boolean invokeCloserThan(BlockPos pos, int distance); + } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeMixin.java index 4ca6fd5a..23392229 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeMixin.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/animal/BeeMixin.java @@ -1,12 +1,23 @@ package dev.yurisuika.blossom.mixin.world.entity.animal; +import dev.yurisuika.blossom.mixin.world.entity.EntityMixin; import dev.yurisuika.blossom.mixin.world.entity.ai.goal.GoalInvoker; +import dev.yurisuika.blossom.world.entity.ai.goal.BlossomLeavesGoal; +import dev.yurisuika.blossom.world.entity.ai.goal.FruitLeavesGoal; +import dev.yurisuika.blossom.world.entity.ai.goal.GoToKnownLeavesGoal; +import dev.yurisuika.blossom.world.entity.animal.BeeInterface; import dev.yurisuika.blossom.world.level.block.FruitingLeavesBlock; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; -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.block.state.properties.IntegerProperty; @@ -18,15 +29,164 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Bee.class) -public abstract class BeeMixin { +public abstract class BeeMixin extends EntityMixin implements BeeInterface { + + @Unique + public BlossomLeavesGoal blossomLeavesGoal; + @Unique + public FruitLeavesGoal fruitLeavesGoal; + @Unique + public GoToKnownLeavesGoal goToKnownLeavesGoal; + @Unique + public BlockPos savedLeavesPos; + @Unique + public int remainingCooldownBeforeLocatingNewLeaves; + + @Unique + public void registerGoals(Bee bee) { + blossomLeavesGoal = new BlossomLeavesGoal(bee); + fruitLeavesGoal = new FruitLeavesGoal(bee); + goToKnownLeavesGoal = new GoToKnownLeavesGoal(bee); + bee.getGoalSelector().addGoal(4, getBlossomLeavesGoal()); + bee.getGoalSelector().addGoal(4, getFruitLeavesGoal()); + bee.getGoalSelector().addGoal(6, getGoToKnownLeavesGoal()); + } + + @Unique + public BlossomLeavesGoal getBlossomLeavesGoal() { + return blossomLeavesGoal; + } + + @Unique + public FruitLeavesGoal getFruitLeavesGoal() { + return fruitLeavesGoal; + } + + @Unique + public GoToKnownLeavesGoal getGoToKnownLeavesGoal() { + return goToKnownLeavesGoal; + } + + @Unique + public BlockPos getSavedLeavesPos() { + return savedLeavesPos; + } + + @Unique + public boolean hasSavedLeavesPos() { + return savedLeavesPos != null; + } + + @Unique + public void setSavedLeavesPos(BlockPos savedLeavesPos) { + this.savedLeavesPos = savedLeavesPos; + } + + @Unique + public void dropLeaves() { + setSavedLeavesPos(null); + remainingCooldownBeforeLocatingNewLeaves = Mth.nextInt(random, 20, 60); + } + + @Unique + public boolean areLeavesValid(BlockPos pos) { + return level().isLoaded(pos) && level().getBlockState(getSavedLeavesPos()).is(BlockTags.LEAVES); + } + + @Inject(method = "", at = @At("RETURN")) + private void injectInit(EntityType entityType, Level level, CallbackInfo ci) { + remainingCooldownBeforeLocatingNewLeaves = Mth.nextInt(random, 20, 60); + } + @Inject(method = "getWalkTargetValue", at = @At("HEAD"), cancellable = true) - private void injectGetPathfindingFavor(BlockPos pos, LevelReader level, CallbackInfoReturnable cir) { + private void injectGetWalkTargetValue(BlockPos pos, LevelReader level, CallbackInfoReturnable cir) { if (level.getBlockState(pos).getBlock() instanceof LeavesBlock) { cir.setReturnValue(2.0F); } } + @Inject(method = "addAdditionalSaveData", at = @At("HEAD")) + private void injectAddAdditionalSaveData(CompoundTag compound, CallbackInfo ci) { + if (hasSavedLeavesPos()) { + compound.put("leaves_pos", NbtUtils.writeBlockPos(getSavedLeavesPos())); + } + } + + @Inject(method = "readAdditionalSaveData", at = @At("HEAD")) + private void injectReadAdditionalSaveData(CompoundTag compound, CallbackInfo ci) { + if (compound.contains("leaves_pos")) { + setSavedLeavesPos(NbtUtils.readBlockPos(compound.getCompound("leaves_pos"))); + } + } + + @Inject(method = "getTravellingTicks", at = @At("RETURN"), cancellable = true) + private void injectGetTravellingTicks(CallbackInfoReturnable cir) { + cir.setReturnValue(Math.max(cir.getReturnValue(), getGoToKnownLeavesGoal().travellingTicks)); + } + + @Inject(method = "wantsToEnterHive", at = @At("HEAD"), cancellable = true) + private void injectWantsToEnterHive(CallbackInfoReturnable cir) { + if (getBlossomLeavesGoal().isBlossoming() || getFruitLeavesGoal().isBlossoming()) { + cir.setReturnValue(false); + } + } + + @Inject(method = "aiStep", at = @At("RETURN")) + private void injectAiStep(CallbackInfo ci) { + if (!level().isClientSide()) { + if (remainingCooldownBeforeLocatingNewLeaves > 0) { + --remainingCooldownBeforeLocatingNewLeaves; + } + } + } + + @Inject(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Animal;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private void injectHurt(DamageSource source, float amount, CallbackInfoReturnable cir) { + if (!level().isClientSide()) { + getBlossomLeavesGoal().stopBlossoming(); + getFruitLeavesGoal().stopBlossoming(); + } + } + + @Mixin(targets = "net.minecraft.world.entity.animal.Bee$1") + public abstract static class FlyingPathNavigationMixin { + + @Unique + public Bee entity; + + @Inject(method = "", at = @At(value = "TAIL")) + private void injectInit(Bee bee, Mob mob, Level level, CallbackInfo ci) { + this.entity = bee; + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/navigation/FlyingPathNavigation;tick()V"), cancellable = true) + private void injectTick(CallbackInfo ci) { + if (((BeeInterface) entity).getBlossomLeavesGoal().isBlossoming() || ((BeeInterface) entity).getFruitLeavesGoal().isBlossoming()) { + ci.cancel(); + } + } + + } + + @Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeeLookControl") + public abstract static class BeeLookControlMixin { + + @Unique + public Bee entity; + + @Inject(method = "", at = @At(value = "TAIL")) + private void injectInit(Bee bee, Mob mob, CallbackInfo ci) { + this.entity = bee; + } + + @Inject(method = "resetXRotOnTick", at = @At("RETURN"), cancellable = true) + private void injectResetXRotOnTick(CallbackInfoReturnable cir) { + cir.setReturnValue(cir.getReturnValue() || !((BeeInterface) entity).getBlossomLeavesGoal().isBlossoming() || !((BeeInterface) entity).getFruitLeavesGoal().isBlossoming()); + } + + } + @Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeeGrowCropGoal") public abstract static class BeeGrowCropGoalMixin { @@ -60,22 +220,4 @@ private void injectTick(CallbackInfo ci) { } - @Mixin(Bee.BeeGoToKnownFlowerGoal.class) - public abstract static class BeeGoToKnownFlowerGoalMixin { - - @Unique - public Bee entity; - - @Inject(method = "", at = @At(value = "TAIL")) - private void injectInit(Bee bee, CallbackInfo ci) { - this.entity = bee; - } - - @Inject(method = "wantsToGoToKnownFlower", at = @At("RETURN"), cancellable = true) - private void injectWantsToGoToKnownFlower(CallbackInfoReturnable cir) { - cir.setReturnValue(cir.getReturnValue() || (entity.level().getBlockState(entity.getSavedFlowerPos()).is(Blocks.OAK_LEAVES) && entity.hasNectar())); - } - - } - } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/state/BlockBehaviourMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/state/BlockBehaviourMixin.java index 3d26ba01..e96c412d 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/state/BlockBehaviourMixin.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/state/BlockBehaviourMixin.java @@ -1,20 +1,32 @@ package dev.yurisuika.blossom.mixin.world.level.block.state; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.LeavesBlock; 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.EntityCollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; 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(BlockBehaviour.class) public abstract class BlockBehaviourMixin { -// @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true) -// private void injectGetCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context, CallbackInfoReturnable cir) { -// if (context instanceof EntityCollisionContext) { -// if (((EntityCollisionContext) context).getEntity() instanceof Bee) { -// if (state.getBlock() instanceof LeavesBlock) { -// cir.setReturnValue(Shapes.empty()); -// } -// } -// } -// } + @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true) + private void injectGetCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context, CallbackInfoReturnable cir) { + if (context instanceof EntityCollisionContext) { + if (((EntityCollisionContext) context).getEntity() instanceof Bee) { + if (state.getBlock() instanceof LeavesBlock) { + cir.setReturnValue(Shapes.empty()); + } + } + } + } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/server/commands/BlossomCommand.java b/src/main/java/dev/yurisuika/blossom/server/commands/BlossomCommand.java index ed443ea5..0d31a630 100644 --- a/src/main/java/dev/yurisuika/blossom/server/commands/BlossomCommand.java +++ b/src/main/java/dev/yurisuika/blossom/server/commands/BlossomCommand.java @@ -2,7 +2,6 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; import dev.yurisuika.blossom.config.Options; @@ -53,58 +52,48 @@ public static void register(CommandDispatcher dispatcher, Co .then(Commands.literal("blossoming") .executes(commandContext -> { MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.blossoming.distance", Option.getBlossomingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.blossoming.query", chance, distance), true); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.blossoming.query", chance), true); return 1; }) .then(Commands.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) - .then(Commands.argument("distance", DoubleArgumentType.doubleArg(0.0D)) - .executes(commandContext -> { - Option.getValue().getFruiting().setChance(FloatArgumentType.getFloat(commandContext, "chance")); - Option.setBlossomingDistance(DoubleArgumentType.getDouble(commandContext, "distance")); - MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.blossoming.distance", Option.getBlossomingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.blossoming.set", chance, distance), true); - return 1; - }) - ) + .executes(commandContext -> { + Option.getValue().getFruiting().setChance(FloatArgumentType.getFloat(commandContext, "chance")); + MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.chance.tooltip")))); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.blossoming.set", chance), true); + return 1; + }) ) ) .then(Commands.literal("fruiting") .executes(commandContext -> { MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.fruiting.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.fruiting.distance", Option.getFruitingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.fruiting.query", chance, distance), false); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.fruiting.query", chance), false); return 1; }) .then(Commands.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) - .then(Commands.argument("distance", DoubleArgumentType.doubleArg(0.0D)) - .executes(commandContext -> { - Option.setFruitingChance(FloatArgumentType.getFloat(commandContext, "chance")); - Option.setFruitingDistance(DoubleArgumentType.getDouble(commandContext, "distance")); - MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.fruiting.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.fruiting.distance", Option.getFruitingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.fruiting.set", chance, distance), false); - return 1; - }) - ) + .executes(commandContext -> { + Option.setFruitingChance(FloatArgumentType.getFloat(commandContext, "chance")); + MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.fruiting.chance.tooltip")))); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.fruiting.set", chance), false); + return 1; + }) ) ) .then(Commands.literal("harvesting") .executes(commandContext -> { - MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.chance", Option.getHarvestingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.chance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.harvesting.query", bonus, chance), true); + MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.harvesting.query", chance, bonus), true); return 1; }) - .then(Commands.argument("bonus", IntegerArgumentType.integer(0)) - .then(Commands.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) + .then(Commands.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) + .then(Commands.argument("bonus", IntegerArgumentType.integer(0)) .executes(commandContext -> { - Option.setHarvestingBonus(IntegerArgumentType.getInteger(commandContext, "bonus")); Option.setHarvestingChance( FloatArgumentType.getFloat(commandContext, "chance")); - MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); + Option.setHarvestingBonus(IntegerArgumentType.getInteger(commandContext, "bonus")); MutableComponent chance = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.chance", Option.getHarvestingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.chance.tooltip")))); - commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.harvesting.set", bonus, chance), true); + MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); + commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.value.harvesting.set", chance, bonus), true); return 1; }) ) @@ -156,7 +145,7 @@ public static void register(CommandDispatcher dispatcher, Co .then(Commands.literal("dimension") .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent list = Component.translatable("commands.blossom.filter.dimension.whitelist.list", Arrays.toString(Option.getDimensionWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.dimension.whitelist.list.tooltip")))); + MutableComponent list = Component.literal(Arrays.toString(Option.getDimensionWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.dimension.whitelist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.filter.dimension.whitelist.query", list), false); return 1; @@ -200,7 +189,7 @@ public static void register(CommandDispatcher dispatcher, Co ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent list = Component.translatable("commands.blossom.filter.dimension.blacklist.list", Arrays.toString(Option.getDimensionBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.dimension.blacklist.list.tooltip")))); + MutableComponent list = Component.literal(Arrays.toString(Option.getDimensionBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.dimension.blacklist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.filter.dimension.blacklist.query", list), false); return 1; @@ -246,7 +235,7 @@ public static void register(CommandDispatcher dispatcher, Co .then(Commands.literal("biome") .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent list = Component.translatable("commands.blossom.filter.biome.whitelist.list", Arrays.toString(Option.getBiomeWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.biome.whitelist.list.tooltip")))); + MutableComponent list = Component.literal(Arrays.toString(Option.getBiomeWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.biome.whitelist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.filter.biome.whitelist.query", list), false); return 1; @@ -290,7 +279,7 @@ public static void register(CommandDispatcher dispatcher, Co ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent list = Component.translatable("commands.blossom.filter.biome.blacklist.list", Arrays.toString(Option.getBiomeBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.biome.blacklist.list.tooltip")))); + MutableComponent list = Component.literal(Arrays.toString(Option.getBiomeBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.filter.biome.blacklist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.filter.biome.blacklist.query", list), false); return 1; @@ -338,14 +327,14 @@ public static void register(CommandDispatcher dispatcher, Co .requires(source -> source.hasPermission(4)) .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.toggle.whitelist.toggle", Option.getWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.whitelist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.literal(String.valueOf(Option.getWhitelist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.whitelist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.toggle.whitelist.query", toggle), false); return 1; }) .then(Commands.argument("value", BoolArgumentType.bool()) .executes(commandContext -> { Option.setWhitelist(BoolArgumentType.getBool(commandContext, "value")); - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.toggle.whitelist.toggle", Option.getWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.whitelist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.literal(String.valueOf(Option.getWhitelist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.whitelist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.toggle.whitelist.set", toggle), false); return 1; }) @@ -353,14 +342,14 @@ public static void register(CommandDispatcher dispatcher, Co ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.toggle.blacklist.toggle", Option.getBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.blacklist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.literal(String.valueOf(Option.getBlacklist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.blacklist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.toggle.blacklist.query", toggle), false); return 1; }) .then(Commands.argument("value", BoolArgumentType.bool()) .executes(commandContext -> { Option.setBlacklist(BoolArgumentType.getBool(commandContext, "value")); - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.translatable("commands.blossom.toggle.blacklist.toggle", Option.getBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.blacklist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(Component.literal(String.valueOf(Option.getBlacklist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("commands.blossom.toggle.blacklist.tooltip")))); commandContext.getSource().sendSuccess(() -> Component.translatable("commands.blossom.toggle.blacklist.set", toggle), false); return 1; }) diff --git a/src/main/java/dev/yurisuika/blossom/tags/BlossomBlockTags.java b/src/main/java/dev/yurisuika/blossom/tags/BlossomBlockTags.java new file mode 100644 index 00000000..e776c1f7 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/tags/BlossomBlockTags.java @@ -0,0 +1,12 @@ +package dev.yurisuika.blossom.tags; + +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +public class BlossomBlockTags { + + public static final TagKey LEAVED_FLOWERS = TagKey.create(Registries.BLOCK, ResourceLocation.tryParse("blossom:leaved_flowers")); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/tags/BlossomItemTags.java b/src/main/java/dev/yurisuika/blossom/tags/BlossomItemTags.java new file mode 100644 index 00000000..5a5b1124 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/tags/BlossomItemTags.java @@ -0,0 +1,12 @@ +package dev.yurisuika.blossom.tags; + +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +public class BlossomItemTags { + + public static final TagKey LEAVED_FLOWERS = TagKey.create(Registries.ITEM, ResourceLocation.tryParse("blossom:leaved_flowers")); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/util/Validate.java b/src/main/java/dev/yurisuika/blossom/util/Validate.java index 0bd7af62..ce5d8cb2 100644 --- a/src/main/java/dev/yurisuika/blossom/util/Validate.java +++ b/src/main/java/dev/yurisuika/blossom/util/Validate.java @@ -9,11 +9,9 @@ public class Validate { public static void checkBounds() { Option.setBlossomingChance(Math.max(Math.min(Option.getBlossomingChance(), 1.0F), 0.0F)); - Option.setBlossomingDistance(Math.max(Option.getBlossomingDistance(), 0.0D)); Option.setFruitingChance(Math.max(Math.min(Option.getFruitingChance(), 1.0F), 0.0F)); - Option.setFruitingDistance(Math.max(Option.getFruitingDistance(), 0.0D)); - Option.setHarvestingBonus(Math.max(Option.getHarvestingBonus(), 0)); Option.setHarvestingChance(Math.max(Math.min(Option.getHarvestingChance(), 1.0F), 0.0F)); + Option.setHarvestingBonus(Math.max(Option.getHarvestingBonus(), 0)); float temperatureMin = Math.max(Math.min(Math.min(Option.getTemperatureMin(), 2.0F), Option.getTemperatureMax()), -2.0F); float temperatureMax = Math.max(Math.max(Math.min(Option.getTemperatureMax(), 2.0F), Option.getTemperatureMin()), -2.0F); diff --git a/src/main/java/dev/yurisuika/blossom/util/config/Option.java b/src/main/java/dev/yurisuika/blossom/util/config/Option.java index ad1f3b07..8bf4bb3f 100644 --- a/src/main/java/dev/yurisuika/blossom/util/config/Option.java +++ b/src/main/java/dev/yurisuika/blossom/util/config/Option.java @@ -42,15 +42,6 @@ public static void setBlossomingChance(float chance) { Config.saveConfig(); } - public static double getBlossomingDistance() { - return getBlossoming().getDistance(); - } - - public static void setBlossomingDistance(double distance) { - getBlossoming().setDistance(distance); - Config.saveConfig(); - } - public static Fruiting getFruiting() { return getValue().getFruiting(); } @@ -69,15 +60,6 @@ public static void setFruitingChance(float chance) { Config.saveConfig(); } - public static double getFruitingDistance() { - return getFruiting().getDistance(); - } - - public static void setFruitingDistance(double distance) { - getFruiting().setDistance(distance); - Config.saveConfig(); - } - public static Harvesting getHarvesting() { return getValue().getHarvesting(); } @@ -87,21 +69,21 @@ public static void setHarvesting(Harvesting harvesting) { Config.saveConfig(); } - public static int getHarvestingBonus() { - return getHarvesting().getBonus(); + public static float getHarvestingChance() { + return getHarvesting().getChance(); } - public static void setHarvestingBonus(int bonus) { - getHarvesting().setBonus(bonus); + public static void setHarvestingChance(float chance) { + getHarvesting().setChance(chance); Config.saveConfig(); } - public static float getHarvestingChance() { - return getHarvesting().getChance(); + public static int getHarvestingBonus() { + return getHarvesting().getBonus(); } - public static void setHarvestingChance(float chance) { - getHarvesting().setChance(chance); + public static void setHarvestingBonus(int bonus) { + getHarvesting().setBonus(bonus); Config.saveConfig(); } diff --git a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Blossoming.java b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Blossoming.java index 8aafc7d2..b5f854fa 100644 --- a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Blossoming.java +++ b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Blossoming.java @@ -3,11 +3,9 @@ public class Blossoming { public float chance; - public double distance; - public Blossoming(float chance, double distance) { + public Blossoming(float chance) { this.chance = chance; - this.distance = distance; } public float getChance() { @@ -17,13 +15,5 @@ public float getChance() { public void setChance(float chance) { this.chance = chance; } - - public double getDistance() { - return distance; - } - - public void setDistance(double distance) { - this.distance = distance; - } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Fruiting.java b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Fruiting.java index 36caf66d..97a2063e 100644 --- a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Fruiting.java +++ b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Fruiting.java @@ -3,11 +3,9 @@ public class Fruiting { public float chance; - public double distance; - public Fruiting(float chance, double distance) { + public Fruiting(float chance) { this.chance = chance; - this.distance = distance; } public float getChance() { @@ -18,12 +16,4 @@ public void setChance(float chance) { this.chance = chance; } - public double getDistance() { - return distance; - } - - public void setDistance(double distance) { - this.distance = distance; - } - } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Harvesting.java b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Harvesting.java index 6a96a761..3823815c 100644 --- a/src/main/java/dev/yurisuika/blossom/util/config/options/value/Harvesting.java +++ b/src/main/java/dev/yurisuika/blossom/util/config/options/value/Harvesting.java @@ -2,19 +2,11 @@ public class Harvesting { - public int bonus; public float chance; + public int bonus; - public Harvesting(int bonus, float chance) { - this.bonus = bonus; + public Harvesting(float chance, int bonus) { this.chance = chance; - } - - public int getBonus() { - return bonus; - } - - public void setBonus(int bonus) { this.bonus = bonus; } @@ -25,5 +17,13 @@ public float getChance() { public void setChance(float chance) { this.chance = chance; } + + public int getBonus() { + return bonus; + } + + public void setBonus(int bonus) { + this.bonus = bonus; + } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java deleted file mode 100644 index 17706cef..00000000 --- a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java +++ /dev/null @@ -1,315 +0,0 @@ -package dev.yurisuika.blossom.world.entity.ai.goal; - -import dev.yurisuika.blossom.Blossom; -import dev.yurisuika.blossom.mixin.world.entity.EntityAccessor; -import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; -import dev.yurisuika.blossom.mixin.world.entity.animal.BeeAccessor; -import dev.yurisuika.blossom.mixin.world.entity.animal.BeeInvoker; -import dev.yurisuika.blossom.mixin.world.level.biome.BiomeAccessor; -import dev.yurisuika.blossom.util.config.Option; -import dev.yurisuika.blossom.world.level.block.FloweringLeavesBlock; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.ai.goal.Goal; -import net.minecraft.world.entity.animal.Bee; -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.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.phys.Vec3; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; - -public class BlossomGoal extends Goal { - - public final Bee entity; - public final Predicate targetPredicate = state -> { - if (state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED)) { - return false; - } else { - return state.is(Blocks.OAK_LEAVES); - } - }; - public int blossomingTicks; - public int lastBlossomingTick; - public boolean running; - public Vec3 nextTarget; - public int ticks; - - public BlossomGoal(Bee bee) { - super(); - this.entity = bee; - this.setFlags(EnumSet.of(Flag.MOVE)); - } - - public boolean checkFilters() { - Holder dimension = entity.level().dimensionTypeRegistration(); - Holder biome = entity.level().getBiome(entity.blockPosition()); - float temperature = biome.value().getBaseTemperature(); - float downfall = ((BiomeAccessor) (Object) biome.value()).getClimateSettings().downfall(); - - AtomicBoolean whitelist = new AtomicBoolean(false); - if (Option.getWhitelist()) { - Arrays.stream(Option.getDimensionWhitelist()).forEach(entry -> { - if (entry.startsWith("#")) { - TagKey tag = TagKey.create(Registries.DIMENSION_TYPE, new ResourceLocation(entry.substring(1))); - if (Objects.nonNull(tag)) { - if (dimension.is(tag)) { - whitelist.set(true); - } - } - } else if (Objects.equals(entry, dimension.unwrapKey().get().location().toString())) { - whitelist.set(true); - } - }); - Arrays.stream(Option.getBiomeWhitelist()).forEach(entry -> { - if (entry.startsWith("#")) { - TagKey tag = TagKey.create(Registries.BIOME, new ResourceLocation(entry.substring(1))); - if (Objects.nonNull(tag)) { - if (biome.is(tag)) { - whitelist.set(true); - } - } - } else if (Objects.equals(entry, biome.unwrapKey().get().location().toString())) { - whitelist.set(true); - } - }); - } - - AtomicBoolean blacklist = new AtomicBoolean(true); - if (Option.getBlacklist()) { - Arrays.stream(Option.getDimensionBlacklist()).forEach(entry -> { - if (entry.startsWith("#")) { - TagKey tag = TagKey.create(Registries.DIMENSION_TYPE, new ResourceLocation(entry.substring(1))); - if (Objects.nonNull(tag)) { - if (dimension.is(tag)) { - blacklist.set(false); - } - } - } else if (Objects.equals(entry, dimension.unwrapKey().get().location().toString())) { - blacklist.set(false); - } - }); - Arrays.stream(Option.getBiomeBlacklist()).forEach(entry -> { - if (entry.startsWith("#")) { - TagKey tag = TagKey.create(Registries.BIOME, new ResourceLocation(entry.substring(1))); - if (Objects.nonNull(tag)) { - if (biome.is(tag)) { - blacklist.set(false); - } - } - } else if (Objects.equals(entry, biome.unwrapKey().get().location().toString())) { - blacklist.set(false); - } - }); - } - - if (temperature >= Option.getTemperatureMin() && temperature <= Option.getTemperatureMax()) { - if (downfall >= Option.getDownfallMin() && downfall <= Option.getDownfallMax()) { - if (!Option.getWhitelist() && !Option.getBlacklist()) { - return true; - } - if (Option.getWhitelist() && Option.getBlacklist()) { - return whitelist.get() && blacklist.get(); - } else if (Option.getWhitelist()) { - return whitelist.get(); - } else if (Option.getBlacklist()) { - return blacklist.get(); - } - } - } - return false; - } - - public boolean canBeeStart() { - if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { - return false; - } - if (((EntityAccessor) entity).getRandom().nextFloat() > Option.getBlossomingChance()) { - return false; - } - if (entity.level().isRaining()) { - return false; - } - Optional optional = findTarget(); - if (optional.isPresent()) { - if (entity.hasNectar()) { - if (((BeeInvoker) entity).invokeIsHiveValid()) { - ((BeeAccessor) entity).setSavedFlowerPos(optional.get()); - ((MobAccessor) entity).getNavigation().moveTo(entity.getSavedFlowerPos().getX() + 0.5D, entity.getSavedFlowerPos().getY() + 0.5D, entity.getSavedFlowerPos().getZ() + 0.5D, 1.2000000476837158D); - return true; - } else { - return false; - } - } else { - return false; - } - } - return false; - } - - public boolean canBeeContinue() { - if (!running) { - return false; - } - if (!entity.hasSavedFlowerPos()) { - return false; - } - if (entity.getSavedFlowerPos() == null) { - return false; - } - if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { - return false; - } - if (entity.level().isRaining()) { - return false; - } - if (completed()) { - return ((EntityAccessor) entity).getRandom().nextFloat() < 0.2F; - } - if (entity.tickCount % 20 == 0 && !isTarget(entity.getSavedFlowerPos())) { - ((BeeAccessor) entity).setSavedFlowerPos(null); - return false; - } - return true; - } - - public boolean completed() { - return blossomingTicks > 400; - } - - public boolean isPollinating() { - return running; - } - - public void stopPollinating() { - running = false; - } - - public void start() { - blossomingTicks = 0; - ticks = 0; - lastBlossomingTick = 0; - running = true; - } - - public void stop() { - if (completed()) { - BlockPos blockPos = entity.getSavedFlowerPos(); - if (blockPos != null) { - BlockState blockState = entity.level().getBlockState(blockPos); - if (blockState.getBlock() == Blocks.OAK_LEAVES) { - entity.level().levelEvent(2005, blockPos, 0); - entity.level().setBlockAndUpdate(blockPos, Blossom.FLOWERING_OAK_LEAVES.get().defaultBlockState() - .setValue(FloweringLeavesBlock.DISTANCE, blockState.getValue(FloweringLeavesBlock.DISTANCE)) - .setValue(FloweringLeavesBlock.PERSISTENT, blockState.getValue(FloweringLeavesBlock.PERSISTENT)) - .setValue(FloweringLeavesBlock.WATERLOGGED, blockState.getValue(FloweringLeavesBlock.WATERLOGGED)) - ); - ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination(); - } - } - } - running = false; - ((MobAccessor) entity).getNavigation().stop(); - } - - public boolean requiresUpdateEveryTick() { - return true; - } - - public boolean canUse() { - return canBeeStart() && !entity.isAngry() && checkFilters(); - } - - public boolean canContinueToUse() { - return canBeeContinue() && !entity.isAngry() && checkFilters(); - } - - public void tick() { - ++ticks; - if (ticks > 600) { - ((BeeAccessor) entity).setSavedFlowerPos(null); - } else { - if (entity.getSavedFlowerPos() != null) { - Vec3 vec3 = Vec3.atBottomCenterOf(entity.getSavedFlowerPos()).add(0.0D, 0.6000000238418579D, 0.0D); - if (vec3.distanceTo(entity.position()) > 1.0) { - nextTarget = vec3; - moveToNextTarget(); - } else { - if (nextTarget == null) { - nextTarget = vec3; - } - boolean close = entity.position().distanceTo(nextTarget) <= 0.1D; - boolean chance = true; - if (!close && ticks > 600) { - ((BeeAccessor) entity).setSavedFlowerPos(null); - } else { - if (close) { - if (((EntityAccessor) entity).getRandom().nextInt(25) == 0) { - nextTarget = new Vec3(vec3.x() + (double)getRandomOffset(), vec3.y(), vec3.z() + (double)getRandomOffset()); - ((MobAccessor) entity).getNavigation().stop(); - } else { - chance = false; - } - entity.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z()); - } - if (chance) { - moveToNextTarget(); - } - ++blossomingTicks; - if (((EntityAccessor) entity).getRandom().nextFloat() < 0.05F && blossomingTicks > lastBlossomingTick + 60) { - lastBlossomingTick = blossomingTicks; - entity.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F); - } - } - } - } - } - } - - public boolean isTarget(BlockPos pos) { - return entity.level().isLoaded(pos) && entity.level().getBlockState(pos).is(Blocks.OAK_LEAVES); - } - - public void moveToNextTarget() { - entity.getMoveControl().setWantedPosition(nextTarget.x(), nextTarget.y(), nextTarget.z(), 0.3499999940395355D); - } - - public float getRandomOffset() { - return (((EntityAccessor) entity).getRandom().nextFloat() * 2.0F - 1.0F) * 0.33333334F; - } - - public Optional findTarget() { - return findTarget(targetPredicate, Option.getBlossomingDistance()); - } - - public Optional findTarget(Predicate predicate, double searchDistance) { - BlockPos blockPos = entity.blockPosition(); - MutableBlockPos mutableBlockPos = new MutableBlockPos(); - for(int i = 0; (double)i <= searchDistance; i = i > 0 ? -i : 1 - i) { - for(int j = 0; (double)j < searchDistance; ++j) { - for(int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { - for(int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { - mutableBlockPos.setWithOffset(blockPos, k, i - 1, l); - if (blockPos.closerThan(mutableBlockPos, searchDistance) && predicate.test(entity.level().getBlockState(mutableBlockPos))) { - return Optional.of(mutableBlockPos); - } - } - } - } - } - return Optional.empty(); - } - -} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java new file mode 100644 index 00000000..18070dcc --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java @@ -0,0 +1,263 @@ +package dev.yurisuika.blossom.world.entity.ai.goal; + +import dev.yurisuika.blossom.mixin.world.entity.EntityAccessor; +import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; +import dev.yurisuika.blossom.mixin.world.entity.animal.BeeInvoker; +import dev.yurisuika.blossom.mixin.world.level.biome.BiomeAccessor; +import dev.yurisuika.blossom.util.config.Option; +import dev.yurisuika.blossom.world.entity.animal.BeeInterface; +import dev.yurisuika.blossom.world.level.block.BlossomBlocks; +import dev.yurisuika.blossom.world.level.block.FloweringLeavesBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.level.biome.Biome; +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.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.phys.Vec3; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; + +public class BlossomLeavesGoal extends Goal { + + public final Bee entity; + public Predicate validBlocks; + public int successfulBlossomingTicks; + public int lastSoundPlayedTick; + public boolean blossoming; + public Vec3 hoverPos; + public int blossomingTicks; + public float goalChance; + + public BlossomLeavesGoal(Bee bee) { + super(); + this.entity = bee; + this.setFlags(EnumSet.of(Flag.MOVE)); + this.validBlocks = state -> (!state.hasProperty(BlockStateProperties.WATERLOGGED) || !state.getValue(BlockStateProperties.WATERLOGGED)) && state.is(Blocks.OAK_LEAVES); + this.goalChance = Option.getBlossomingChance(); + } + + public boolean checkFilters() { + Holder dimension = entity.level().dimensionTypeRegistration(); + Holder biome = entity.level().getBiome(entity.blockPosition()); + float temperature = biome.value().getBaseTemperature(); + float downfall = ((BiomeAccessor) (Object) biome.value()).getClimateSettings().downfall(); + + AtomicBoolean whitelist = new AtomicBoolean(false); + if (Option.getWhitelist()) { + Arrays.stream(Option.getDimensionWhitelist()).filter(entry -> entry.startsWith("#") && dimension.is(TagKey.create(Registries.DIMENSION_TYPE, new ResourceLocation(entry.substring(1)))) || Objects.equals(entry, dimension.unwrapKey().get().location().toString())).map(entry -> true).forEach(whitelist::set); + Arrays.stream(Option.getBiomeWhitelist()).filter(entry -> entry.startsWith("#") && biome.is(TagKey.create(Registries.BIOME, new ResourceLocation(entry.substring(1)))) || Objects.equals(entry, biome.unwrapKey().get().location().toString())).map(entry -> true).forEach(whitelist::set); + } + + AtomicBoolean blacklist = new AtomicBoolean(true); + if (Option.getBlacklist()) { + Arrays.stream(Option.getDimensionBlacklist()).filter(entry -> entry.startsWith("#") && dimension.is(TagKey.create(Registries.DIMENSION_TYPE, new ResourceLocation(entry.substring(1)))) || Objects.equals(entry, dimension.unwrapKey().get().location().toString())).map(entry -> false).forEach(blacklist::set); + Arrays.stream(Option.getBiomeBlacklist()).filter(entry -> entry.startsWith("#") && biome.is(TagKey.create(Registries.BIOME, new ResourceLocation(entry.substring(1)))) || Objects.equals(entry, biome.unwrapKey().get().location().toString())).map(entry -> false).forEach(blacklist::set); + } + + if (temperature >= Option.getTemperatureMin() && temperature <= Option.getTemperatureMax()) { + if (downfall >= Option.getDownfallMin() && downfall <= Option.getDownfallMax()) { + if (!Option.getWhitelist() && !Option.getBlacklist()) { + return true; + } + if (Option.getWhitelist() && Option.getBlacklist()) { + return whitelist.get() && blacklist.get(); + } else if (Option.getWhitelist()) { + return whitelist.get(); + } else if (Option.getBlacklist()) { + return blacklist.get(); + } + } + } + return false; + } + + public boolean canBeeUse() { + if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { + return false; + } + if (((EntityAccessor) entity).getRandom().nextFloat() > goalChance) { + return false; + } + if (entity.level().isRaining()) { + return false; + } + if (findNearbyLeaves().isEmpty()) { + return false; + } + if (!entity.hasNectar()) { + return false; + } + if (!((BeeInvoker) entity).invokeIsHiveValid()) { + return false; + } + ((BeeInterface) entity).setSavedLeavesPos(findNearbyLeaves().get()); + ((MobAccessor) entity).getNavigation().moveTo(((BeeInterface) entity).getSavedLeavesPos().getX() + 0.5D, ((BeeInterface) entity).getSavedLeavesPos().getY() + 0.5D, ((BeeInterface) entity).getSavedLeavesPos().getZ() + 0.5D, 1.2000000476837158D); + return true; + } + + public boolean canBeeContinueToUse() { + if (!blossoming) { + return false; + } + if (!((BeeInterface) entity).hasSavedLeavesPos()) { + return false; + } + if (((BeeInterface) entity).getSavedLeavesPos() == null) { + return false; + } + if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { + return false; + } + if (entity.level().isRaining()) { + return false; + } + if (hasBlossomedLongEnough()) { + return ((EntityAccessor) entity).getRandom().nextFloat() < 0.2F; + } + if (entity.tickCount % 20 == 0 && !((BeeInterface) entity).areLeavesValid(((BeeInterface) entity).getSavedLeavesPos())) { + ((BeeInterface) entity).setSavedLeavesPos(null); + return false; + } + return true; + } + + public boolean hasBlossomedLongEnough() { + return successfulBlossomingTicks > 400; + } + + public boolean isBlossoming() { + return blossoming; + } + + public void stopBlossoming() { + blossoming = false; + } + + public void start() { + successfulBlossomingTicks = 0; + blossomingTicks = 0; + lastSoundPlayedTick = 0; + blossoming = true; + } + + public void stop() { + if (hasBlossomedLongEnough()) { + BlockPos blockPos = ((BeeInterface) entity).getSavedLeavesPos(); + if (blockPos != null) { + BlockState blockState = entity.level().getBlockState(blockPos); + if (blockState.getBlock() == Blocks.OAK_LEAVES) { + entity.level().levelEvent(2005, blockPos, 0); + entity.level().setBlockAndUpdate(blockPos, BlossomBlocks.FLOWERING_OAK_LEAVES.get().defaultBlockState() + .setValue(FloweringLeavesBlock.DISTANCE, blockState.getValue(LeavesBlock.DISTANCE)) + .setValue(FloweringLeavesBlock.PERSISTENT, blockState.getValue(LeavesBlock.PERSISTENT)) + .setValue(FloweringLeavesBlock.WATERLOGGED, blockState.getValue(LeavesBlock.WATERLOGGED)) + ); + ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination(); + } + } + } + blossoming = false; + ((MobAccessor) entity).getNavigation().stop(); + } + + public boolean requiresUpdateEveryTick() { + return true; + } + + public boolean canUse() { + return canBeeUse() && !entity.isAngry() && checkFilters(); + } + + public boolean canContinueToUse() { + return canBeeContinueToUse() && !entity.isAngry() && checkFilters(); + } + + public void tick() { + ++blossomingTicks; + if (blossomingTicks > 600) { + ((BeeInterface) entity).setSavedLeavesPos(null); + } else { + if (((BeeInterface) entity).getSavedLeavesPos() != null) { + Vec3 vec3 = Vec3.atBottomCenterOf(((BeeInterface) entity).getSavedLeavesPos()).add(0.0D, 0.6000000238418579D, 0.0D); + if (vec3.distanceTo(entity.position()) > 1.0D) { + hoverPos = vec3; + setWantedPos(); + } else { + if (hoverPos == null) { + hoverPos = vec3; + } + boolean close = entity.position().distanceTo(hoverPos) <= 0.1D; + boolean chance = true; + if (!close && blossomingTicks > 600) { + ((BeeInterface) entity).setSavedLeavesPos(null); + } else { + if (close) { + if (((EntityAccessor) entity).getRandom().nextInt(25) == 0) { + hoverPos = new Vec3(vec3.x() + getRandomOffset(), vec3.y(), vec3.z() + getRandomOffset()); + ((MobAccessor) entity).getNavigation().stop(); + } else { + chance = false; + } + entity.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z()); + } + if (chance) { + setWantedPos(); + } + ++successfulBlossomingTicks; + if (((EntityAccessor) entity).getRandom().nextFloat() < 0.05F && successfulBlossomingTicks > lastSoundPlayedTick + 60) { + lastSoundPlayedTick = successfulBlossomingTicks; + entity.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F); + } + } + } + } + } + } + + public void setWantedPos() { + entity.getMoveControl().setWantedPosition(hoverPos.x(), hoverPos.y(), hoverPos.z(), 0.3499999940395355D); + } + + + public float getRandomOffset() { + return (((EntityAccessor) entity).getRandom().nextFloat() * 2.0F - 1.0F) * 0.33333334F; + } + + public Optional findNearbyLeaves() { + return findNearestBlock(validBlocks, 10.0D); + } + + public Optional findNearestBlock(Predicate predicate, double distance) { + BlockPos blockPos = entity.blockPosition(); + MutableBlockPos mutableBlockPos = new MutableBlockPos(); + for (int i = 0; i <= distance; i = i > 0 ? -i : 1 - i) { + for (int j = 0; j < distance; ++j) { + for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { + for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { + mutableBlockPos.setWithOffset(blockPos, k, i - 1, l); + if (blockPos.closerThan(mutableBlockPos, distance) && predicate.test(entity.level().getBlockState(mutableBlockPos))) { + return Optional.of(mutableBlockPos); + } + } + } + } + } + return Optional.empty(); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitGoal.java b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitGoal.java deleted file mode 100644 index 5a87c2c8..00000000 --- a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitGoal.java +++ /dev/null @@ -1,94 +0,0 @@ -package dev.yurisuika.blossom.world.entity.ai.goal; - -import dev.yurisuika.blossom.Blossom; -import dev.yurisuika.blossom.mixin.world.entity.EntityAccessor; -import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; -import dev.yurisuika.blossom.mixin.world.entity.animal.BeeAccessor; -import dev.yurisuika.blossom.mixin.world.entity.animal.BeeInvoker; -import dev.yurisuika.blossom.util.config.Option; -import dev.yurisuika.blossom.world.level.block.FloweringLeavesBlock; -import dev.yurisuika.blossom.world.level.block.FruitingLeavesBlock; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.animal.Bee; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -import java.util.Optional; -import java.util.function.Predicate; - -public class FruitGoal extends BlossomGoal { - - public final Predicate targetPredicate = state -> { - if (state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED)) { - return false; - } else { - if (state.is(Blossom.FLOWERING_OAK_LEAVES.get())) { - return state.getValue(BlockStateProperties.AGE_3) >= 3; - } else { - return false; - } - } - }; - - public FruitGoal(Bee bee) { - super(bee); - } - - public boolean canBeeStart() { - if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { - return false; - } - if (((EntityAccessor) entity).getRandom().nextFloat() > Option.getFruitingChance()) { - return false; - } - if (entity.level().isRaining()) { - return false; - } - Optional optional = findTarget(); - if (optional.isPresent()) { - if (entity.hasNectar()) { - if (((BeeInvoker) entity).invokeIsHiveValid()) { - ((BeeAccessor) entity).setSavedFlowerPos(optional.get()); - ((MobAccessor) entity).getNavigation().moveTo(entity.getSavedFlowerPos().getX() + 0.5D, entity.getSavedFlowerPos().getY() + 0.5D, entity.getSavedFlowerPos().getZ() + 0.5D, 1.2000000476837158D); - return true; - } else { - return false; - } - } else { - return false; - } - } - return false; - } - - public void stop() { - if (completed()) { - BlockPos blockPos = entity.getSavedFlowerPos(); - if (blockPos != null) { - BlockState blockState = entity.level().getBlockState(blockPos); - if (blockState.getBlock() == Blossom.FLOWERING_OAK_LEAVES.get()) { - if (blockState.getValue(BlockStateProperties.AGE_3) >= 3) { - entity.level().levelEvent(2005, blockPos, 0); - entity.level().setBlockAndUpdate(blockPos, Blossom.FRUITING_OAK_LEAVES.get().defaultBlockState() - .setValue(FruitingLeavesBlock.DISTANCE, blockState.getValue(FruitingLeavesBlock.DISTANCE)) - .setValue(FruitingLeavesBlock.PERSISTENT, blockState.getValue(FruitingLeavesBlock.PERSISTENT)) - .setValue(FruitingLeavesBlock.WATERLOGGED, blockState.getValue(FruitingLeavesBlock.WATERLOGGED)) - ); - ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination(); - } - } - } - } - running = false; - ((MobAccessor) entity).getNavigation().stop(); - } - - public boolean isTarget(BlockPos pos) { - return entity.level().isLoaded(pos) && entity.level().getBlockState(pos).getBlock() instanceof FloweringLeavesBlock; - } - - public Optional findTarget() { - return findTarget(targetPredicate, Option.getFruitingDistance()); - } - -} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitLeavesGoal.java b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitLeavesGoal.java new file mode 100644 index 00000000..7f89076a --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitLeavesGoal.java @@ -0,0 +1,46 @@ +package dev.yurisuika.blossom.world.entity.ai.goal; + +import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; +import dev.yurisuika.blossom.mixin.world.entity.animal.BeeInvoker; +import dev.yurisuika.blossom.util.config.Option; +import dev.yurisuika.blossom.world.entity.animal.BeeInterface; +import dev.yurisuika.blossom.world.level.block.FloweringLeavesBlock; +import dev.yurisuika.blossom.world.level.block.FruitingLeavesBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +import java.util.stream.IntStream; + +public class FruitLeavesGoal extends BlossomLeavesGoal { + + public FruitLeavesGoal(Bee bee) { + super(bee); + this.validBlocks = state -> (!state.hasProperty(BlockStateProperties.WATERLOGGED) || !state.getValue(BlockStateProperties.WATERLOGGED)) && (state.getBlock() instanceof FloweringLeavesBlock && state.getValue(BlockStateProperties.AGE_3) >= 3); + this.goalChance = Option.getFruitingChance(); + } + + public void stop() { + if (hasBlossomedLongEnough()) { + BlockPos blockPos = ((BeeInterface) entity).getSavedLeavesPos(); + if (blockPos != null) { + BlockState blockState = entity.level().getBlockState(blockPos); + if (blockState.getBlock() instanceof FloweringLeavesBlock) { + if (blockState.getValue(BlockStateProperties.AGE_3) >= 3) { + entity.level().levelEvent(2005, blockPos, 0); + entity.level().setBlockAndUpdate(blockPos, ((FloweringLeavesBlock) blockState.getBlock()).getPollinatedBlock().defaultBlockState() + .setValue(FruitingLeavesBlock.DISTANCE, blockState.getValue(FloweringLeavesBlock.DISTANCE)) + .setValue(FruitingLeavesBlock.PERSISTENT, blockState.getValue(FloweringLeavesBlock.PERSISTENT)) + .setValue(FruitingLeavesBlock.WATERLOGGED, blockState.getValue(FloweringLeavesBlock.WATERLOGGED)) + ); + IntStream.range(0, 10).forEach(i -> ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination()); + } + } + } + } + blossoming = false; + ((MobAccessor) entity).getNavigation().stop(); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/GoToKnownLeavesGoal.java b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/GoToKnownLeavesGoal.java new file mode 100644 index 00000000..d489d152 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/GoToKnownLeavesGoal.java @@ -0,0 +1,58 @@ +package dev.yurisuika.blossom.world.entity.ai.goal; + +import dev.yurisuika.blossom.mixin.world.entity.EntityAccessor; +import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; +import dev.yurisuika.blossom.mixin.world.entity.animal.BeeInvoker; +import dev.yurisuika.blossom.world.entity.animal.BeeInterface; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.animal.Bee; + +import java.util.EnumSet; + +public class GoToKnownLeavesGoal extends Goal { + + public final Bee entity; + public int travellingTicks; + + public GoToKnownLeavesGoal(Bee bee) { + super(); + this.entity = bee; + this.travellingTicks = ((EntityAccessor) entity).getRandom().nextInt(10); + this.setFlags(EnumSet.of(Flag.MOVE)); + } + + public boolean canUse() { + return ((BeeInterface) entity).getSavedLeavesPos() != null && !entity.hasRestriction() && entity.hasNectar() && ((BeeInterface) entity).areLeavesValid(((BeeInterface) entity).getSavedLeavesPos()) && !((BeeInvoker) entity).invokeCloserThan(((BeeInterface) entity).getSavedLeavesPos(), 2) && !entity.isAngry(); + } + + public boolean canContinueToUse() { + return canUse(); + } + + public void start() { + travellingTicks = 0; + super.start(); + } + + public void stop() { + travellingTicks = 0; + ((MobAccessor) entity).getNavigation().stop(); + ((MobAccessor) entity).getNavigation().resetMaxVisitedNodesMultiplier(); + } + + public void tick() { + if (((BeeInterface) entity).getSavedLeavesPos() != null) { + ++travellingTicks; + if (travellingTicks > adjustedTickDelay(2400)) { + ((BeeInterface) entity).dropLeaves(); + } else if (!((MobAccessor) entity).getNavigation().isInProgress()) { + if (((BeeInvoker) entity).invokeIsTooFarAway(((BeeInterface) entity).getSavedLeavesPos())) { + ((BeeInterface) entity).dropLeaves(); + } else { + ((BeeInvoker) entity).invokePathfindRandomlyTowards(((BeeInterface) entity).getSavedLeavesPos()); + } + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/entity/animal/BeeInterface.java b/src/main/java/dev/yurisuika/blossom/world/entity/animal/BeeInterface.java new file mode 100644 index 00000000..41271e25 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/entity/animal/BeeInterface.java @@ -0,0 +1,29 @@ +package dev.yurisuika.blossom.world.entity.animal; + +import dev.yurisuika.blossom.world.entity.ai.goal.BlossomLeavesGoal; +import dev.yurisuika.blossom.world.entity.ai.goal.FruitLeavesGoal; +import dev.yurisuika.blossom.world.entity.ai.goal.GoToKnownLeavesGoal; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.animal.Bee; + +public interface BeeInterface { + + void registerGoals(Bee bee); + + BlossomLeavesGoal getBlossomLeavesGoal(); + + FruitLeavesGoal getFruitLeavesGoal(); + + GoToKnownLeavesGoal getGoToKnownLeavesGoal(); + + BlockPos getSavedLeavesPos(); + + boolean hasSavedLeavesPos(); + + void setSavedLeavesPos(BlockPos savedLeavesPos); + + void dropLeaves(); + + boolean areLeavesValid(BlockPos pos); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java b/src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java new file mode 100644 index 00000000..a12aed55 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java @@ -0,0 +1,49 @@ +package dev.yurisuika.blossom.world.level.block; + +import dev.yurisuika.blossom.mixin.world.level.block.BlocksInvoker; +import net.minecraft.world.item.Items; +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.MapColor; +import net.minecraft.world.level.material.PushReaction; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class BlossomBlocks { + + public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "blossom"); + + public static final RegistryObject FRUITING_OAK_LEAVES = BLOCKS.register("fruiting_oak_leaves", () -> new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, BlockBehaviour.Properties.of() + .mapColor(MapColor.PLANT) + .strength(0.2F) + .randomTicks() + .sound(SoundType.GRASS) + .noOcclusion() + .isValidSpawn(BlocksInvoker::invokeOcelotOrParrot) + .isSuffocating(BlocksInvoker::invokeNever) + .isViewBlocking(BlocksInvoker::invokeNever) + .ignitedByLava() + .pushReaction(PushReaction.DESTROY) + .isRedstoneConductor(BlocksInvoker::invokeNever))); + public static final RegistryObject FLOWERING_OAK_LEAVES = BLOCKS.register("flowering_oak_leaves", () -> new FloweringLeavesBlock(Blocks.OAK_LEAVES, FRUITING_OAK_LEAVES.get(), BlockBehaviour.Properties.of() + .mapColor(MapColor.PLANT) + .strength(0.2F) + .randomTicks() + .sound(SoundType.GRASS) + .noOcclusion() + .isValidSpawn(BlocksInvoker::invokeOcelotOrParrot) + .isSuffocating(BlocksInvoker::invokeNever) + .isViewBlocking(BlocksInvoker::invokeNever) + .ignitedByLava() + .pushReaction(PushReaction.DESTROY) + .isRedstoneConductor(BlocksInvoker::invokeNever))); + + public static void register(IEventBus eventBus) { + BLOCKS.register(eventBus); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/level/block/FloweringLeavesBlock.java b/src/main/java/dev/yurisuika/blossom/world/level/block/FloweringLeavesBlock.java index 30d17701..3ea8eda7 100644 --- a/src/main/java/dev/yurisuika/blossom/world/level/block/FloweringLeavesBlock.java +++ b/src/main/java/dev/yurisuika/blossom/world/level/block/FloweringLeavesBlock.java @@ -1,6 +1,6 @@ package dev.yurisuika.blossom.world.level.block; -import dev.yurisuika.blossom.Blossom; +import dev.yurisuika.blossom.core.particles.BlossomParticleTypes; import dev.yurisuika.blossom.mixin.world.level.biome.BiomeAccessor; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; @@ -59,6 +59,14 @@ public FloweringLeavesBlock(Block shearedBlock, Block pollinatedBlock, Propertie registerDefaultState(stateDefinition.any().setValue(DISTANCE, 1).setValue(PERSISTENT, false).setValue(WATERLOGGED, false).setValue(AGE, 0).setValue(RIPENESS, 0)); } + public Block getShearedBlock() { + return shearedBlock; + } + + public Block getPollinatedBlock() { + return pollinatedBlock; + } + public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { return Shapes.empty(); } @@ -92,10 +100,10 @@ public int getMaxRipeness() { } public int getRipeness(BlockState state) { - return state.getValue(getRipenessProperty()); + return state.getValue(getRipenessProperty()); } - public boolean isRipe(BlockState state) { + public boolean isMaxRipeness(BlockState state) { return state.getValue(getRipenessProperty()) >= getMaxRipeness(); } @@ -104,7 +112,7 @@ public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random dropResources(state, level, pos); level.removeBlock(pos, false); } else if (state.getValue(WATERLOGGED)) { - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) @@ -132,20 +140,20 @@ public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random } else if (isMaxAge(state)) { int i = getRipeness(state); if (i < getMaxRipeness()) { - if (random.nextInt((int)(25.0F) + 1) == 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, i + 1), 2); + if (random.nextInt(25 + 1) == 0) { + level.setBlock(pos, state.setValue(RIPENESS, i + 1), 2); } } } - if (isRipe(state)) { - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + if (isMaxRipeness(state)) { + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) ); } if (!isMaxAge(state) && state.getValue(RIPENESS) > 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, 0), 2); + level.setBlock(pos, state.setValue(RIPENESS, 0), 2); } } @@ -159,11 +167,7 @@ public void applyGrowth(Level level, BlockPos pos, BlockState state) { if (i > j) { i = j; } - level.setBlock(pos, defaultBlockState().setValue(AGE, i) - .setValue(DISTANCE, state.getValue(DISTANCE)) - .setValue(PERSISTENT, state.getValue(PERSISTENT)) - .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - .setValue(RIPENESS, state.getValue(RIPENESS)), 2); + level.setBlock(pos, state.setValue(AGE, i), 2); } public int getGrowthAmount(Level level) { @@ -218,13 +222,13 @@ public FluidState getFluidState(BlockState state) { public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { super.animateTick(state, level, pos, random); - if (random.nextInt(10) != 0) { + if (random.nextInt(10 * (4 - getAge(state))) != 0) { return; } if (FloweringLeavesBlock.isFaceFull(level.getBlockState(pos.below()).getCollisionShape(level, pos.below()), Direction.UP)) { return; } - ParticleUtils.spawnParticleBelow(level, pos, random, Blossom.BLOSSOM.get()); + ParticleUtils.spawnParticleBelow(level, pos, random, BlossomParticleTypes.FLOWERING_OAK_LEAVES.get()); } public void createBlockStateDefinition(Builder builder) { @@ -257,15 +261,14 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player.awardStat(Stats.ITEM_USED.get(item)); } level.gameEvent(player, GameEvent.SHEAR, pos); - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) ); return InteractionResult.SUCCESS; - } else { - return InteractionResult.PASS; } + return InteractionResult.PASS; } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/level/block/FruitingLeavesBlock.java b/src/main/java/dev/yurisuika/blossom/world/level/block/FruitingLeavesBlock.java index 176bbfe1..201b8b9c 100644 --- a/src/main/java/dev/yurisuika/blossom/world/level/block/FruitingLeavesBlock.java +++ b/src/main/java/dev/yurisuika/blossom/world/level/block/FruitingLeavesBlock.java @@ -61,6 +61,14 @@ public FruitingLeavesBlock(Block shearedBlock, Item shearedItem, Properties prop registerDefaultState(stateDefinition.any().setValue(DISTANCE, 1).setValue(PERSISTENT, false).setValue(WATERLOGGED, false).setValue(AGE, 0).setValue(RIPENESS, 0)); } + public Block getShearedBlock() { + return shearedBlock; + } + + public Item getShearedItem() { + return shearedItem; + } + public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { return Shapes.empty(); } @@ -94,10 +102,10 @@ public int getMaxRipeness() { } public int getRipeness(BlockState state) { - return state.getValue(getRipenessProperty()); + return state.getValue(getRipenessProperty()); } - public boolean isRipe(BlockState state) { + public boolean isMaxRipeness(BlockState state) { return state.getValue(getRipenessProperty()) >= getMaxRipeness(); } @@ -106,7 +114,7 @@ public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random dropResources(state, level, pos); level.removeBlock(pos, false); } else if (state.getValue(WATERLOGGED)) { - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) @@ -124,31 +132,27 @@ public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random f = 5.0F; } if (random.nextInt((int) (25.0F / f) + 1) == 0) { - level.setBlock(pos, defaultBlockState().setValue(AGE, i + 1) - .setValue(DISTANCE, state.getValue(DISTANCE)) - .setValue(PERSISTENT, state.getValue(PERSISTENT)) - .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - .setValue(RIPENESS, state.getValue(RIPENESS)), 2); + level.setBlock(pos, state.setValue(AGE, i + 1), 2); } } } else if (isMaxAge(state)) { int i = getRipeness(state); if (i < getMaxRipeness()) { - if (random.nextInt((int)(25.0F) + 1) == 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, i + 1), 2); + if (random.nextInt(25 + 1) == 0) { + level.setBlock(pos, state.setValue(RIPENESS, i + 1), 2); } } } - if (isRipe(state)) { - dropFruit(level, pos, shearedItem, 0); - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + if (isMaxRipeness(state)) { + dropFruit(level, pos, getShearedItem(), 0); + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) ); } if (!isMaxAge(state) && state.getValue(RIPENESS) > 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, 0), 2); + level.setBlock(pos, state.setValue(RIPENESS, 0), 2); } } @@ -162,11 +166,7 @@ public void applyGrowth(Level level, BlockPos pos, BlockState state) { if (i > j) { i = j; } - level.setBlock(pos, defaultBlockState().setValue(AGE, i) - .setValue(DISTANCE, state.getValue(DISTANCE)) - .setValue(PERSISTENT, state.getValue(PERSISTENT)) - .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - .setValue(RIPENESS, state.getValue(RIPENESS)), 2); + level.setBlock(pos, state.setValue(AGE, i), 2); } public int getGrowthAmount(Level level) { @@ -245,7 +245,7 @@ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos public static void dropFruit(Level level, BlockPos pos, Item item, int bonus) { int count = 1; - for(int i = 0; i < Option.getHarvestingBonus() + bonus; i++) { + for (int i = 0; i < Option.getHarvestingBonus() + bonus; i++) { if (ThreadLocalRandom.current().nextFloat() <= Option.getHarvestingChance()) { count++; } @@ -255,26 +255,25 @@ public static void dropFruit(Level level, BlockPos pos, Item item, int bonus) { public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ItemStack itemStack = player.getItemInHand(hand); - if (isMaxAge(state)) { - Item item = itemStack.getItem(); - if (item instanceof ShearsItem) { - level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.CROP_BREAK, SoundSource.NEUTRAL, 1.0F, 1.0F); - dropFruit(level, pos, shearedItem, (itemStack.isEnchanted() && EnchantmentHelper.getEnchantments(itemStack).containsKey(Enchantments.BLOCK_FORTUNE)) ? EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, itemStack) : 0); - itemStack.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); - if (!level.isClientSide()) { - player.awardStat(Stats.ITEM_USED.get(item)); - } - level.gameEvent(player, GameEvent.SHEAR, pos); - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() - .setValue(DISTANCE, state.getValue(DISTANCE)) - .setValue(PERSISTENT, state.getValue(PERSISTENT)) - .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - ); + Item item = itemStack.getItem(); + if (item instanceof ShearsItem) { + level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.CROP_BREAK, SoundSource.NEUTRAL, 1.0F, 1.0F); + if (isMaxAge(state)) { + dropFruit(level, pos, getShearedItem(), (itemStack.isEnchanted() && EnchantmentHelper.getEnchantments(itemStack).containsKey(Enchantments.BLOCK_FORTUNE)) ? EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, itemStack) : 0); } + itemStack.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); + if (!level.isClientSide()) { + player.awardStat(Stats.ITEM_USED.get(item)); + } + level.gameEvent(player, GameEvent.SHEAR, pos); + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() + .setValue(DISTANCE, state.getValue(DISTANCE)) + .setValue(PERSISTENT, state.getValue(PERSISTENT)) + .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) + ); return InteractionResult.SUCCESS; - } else { - return InteractionResult.PASS; } + return InteractionResult.PASS; } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/world/level/item/BlossomItems.java b/src/main/java/dev/yurisuika/blossom/world/level/item/BlossomItems.java new file mode 100644 index 00000000..8f3b9f9b --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/level/item/BlossomItems.java @@ -0,0 +1,22 @@ +package dev.yurisuika.blossom.world.level.item; + +import dev.yurisuika.blossom.world.level.block.BlossomBlocks; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class BlossomItems { + + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, "blossom"); + + public static final RegistryObject FRUITING_OAK_LEAVES = ITEMS.register("fruiting_oak_leaves", () -> new BlockItem(BlossomBlocks.FRUITING_OAK_LEAVES.get(), new Item.Properties())); + public static final RegistryObject FLOWERING_OAK_LEAVES = ITEMS.register("flowering_oak_leaves", () -> new BlockItem(BlossomBlocks.FLOWERING_OAK_LEAVES.get(), new Item.Properties())); + + public static void register(IEventBus eventBus) { + ITEMS.register(eventBus); + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/lang/en_us.json b/src/main/resources/assets/blossom/lang/en_us.json index 3fc77287..b25bc549 100644 --- a/src/main/resources/assets/blossom/lang/en_us.json +++ b/src/main/resources/assets/blossom/lang/en_us.json @@ -5,26 +5,22 @@ "commands.blossom.config.reload": "Blossom config reloaded", "commands.blossom.config.reset": "Blossom config reset to defaults", - "commands.blossom.value.blossoming.query": "Blossoming is currently set to: %s %s", - "commands.blossom.value.blossoming.set": "Blossoming is now set to: %s %s", + "commands.blossom.value.blossoming.query": "Blossoming is currently set to: %s", + "commands.blossom.value.blossoming.set": "Blossoming is now set to: %s", "commands.blossom.value.blossoming.chance": "Chance: %s", "commands.blossom.value.blossoming.chance.tooltip": "Chance for bees to start blossoming flowering leaves.\n(min: 0.0, max: 1.0)", - "commands.blossom.value.blossoming.distance": "Distance: %s", - "commands.blossom.value.blossoming.distance.tooltip": "Distance bees will search for leaves to blossom.\n(min: 0.0)", - "commands.blossom.value.fruiting.query": "Fruiting is currently set to: %s %s", - "commands.blossom.value.fruiting.set": "Fruiting is now set to: %s %s", + "commands.blossom.value.fruiting.query": "Fruiting is currently set to: %s", + "commands.blossom.value.fruiting.set": "Fruiting is now set to: %s", "commands.blossom.value.fruiting.chance": "Chance: %s", "commands.blossom.value.fruiting.chance.tooltip": "Chance for bees to fertilize fruiting leaves.\n(min: 0.0, max: 1.0)", - "commands.blossom.value.fruiting.distance": "Distance: %s", - "commands.blossom.value.fruiting.distance.tooltip": "Distance bees will search for leaves to fruit.\n(min: 0.0)", "commands.blossom.value.harvesting.query": "Harvesting is currently set to: %s %s", "commands.blossom.value.harvesting.set": "Harvesting is now set to: %s %s", - "commands.blossom.value.harvesting.bonus": "Bonus: %s", - "commands.blossom.value.harvesting.bonus.tooltip": "Amount of bonus fruits to harvest.\n(min: 0)", "commands.blossom.value.harvesting.chance": "Chance: %s", "commands.blossom.value.harvesting.chance.tooltip": "Chance to harvest each bonus fruit.\n(min: 0.0, max: 1.0)", + "commands.blossom.value.harvesting.bonus": "Bonus: %s", + "commands.blossom.value.harvesting.bonus.tooltip": "Amount of bonus fruits to harvest.\n(min: 0)", "commands.blossom.filter.temperature.query": "Temperature is currently set to: %s %s", "commands.blossom.filter.temperature.set": "Temperature is now set to: %s %s", @@ -41,32 +37,28 @@ "commands.blossom.filter.downfall.max.tooltip": "Maximum downfall to allow blossoming.\n(min: 0.0, max: 1.0)", "commands.blossom.filter.dimension.whitelist.query": "Whitelisted dimensions: %s", - "commands.blossom.filter.dimension.whitelist.list": "%s", - "commands.blossom.filter.dimension.whitelist.list.tooltip": "Dimensions that allow blossoming.", + "commands.blossom.filter.dimension.whitelist.tooltip": "Dimensions that allow blossoming.", "commands.blossom.filter.dimension.whitelist.add": "Added dimension entry '%s' to whitelist", "commands.blossom.filter.dimension.whitelist.add.failed": "Dimension entry '%s' is already in whitelist", "commands.blossom.filter.dimension.whitelist.remove": "Removed dimension entry '%s' from whitelist", "commands.blossom.filter.dimension.whitelist.remove.failed": "Dimension entry '%s' is not in whitelist", "commands.blossom.filter.dimension.blacklist.query": "Blacklisted dimensions: %s", - "commands.blossom.filter.dimension.blacklist.list": "%s", - "commands.blossom.filter.dimension.blacklist.list.tooltip": "Dimensions that disallow blossoming.", + "commands.blossom.filter.dimension.blacklist.tooltip": "Dimensions that disallow blossoming.", "commands.blossom.filter.dimension.blacklist.add": "Added dimension entry '%s' to blacklist", "commands.blossom.filter.dimension.blacklist.add.failed": "Dimension entry '%s' is already in blacklist", "commands.blossom.filter.dimension.blacklist.remove": "Removed dimension entry '%s' from blacklist", "commands.blossom.filter.dimension.blacklist.remove.failed": "Dimension entry '%s' is not in blacklist", "commands.blossom.filter.biome.whitelist.query": "Whitelisted biomes: %s", - "commands.blossom.filter.biome.whitelist.list": "%s", - "commands.blossom.filter.biome.whitelist.list.tooltip": "Biomes that allow blossoming.", + "commands.blossom.filter.biome.whitelist.tooltip": "Biomes that allow blossoming.", "commands.blossom.filter.biome.whitelist.add": "Added biome entry '%s' to whitelist", "commands.blossom.filter.biome.whitelist.add.failed": "Biome entry '%s' is already in whitelist", "commands.blossom.filter.biome.whitelist.remove": "Removed biome entry '%s' from whitelist", "commands.blossom.filter.biome.whitelist.remove.failed": "Biome entry '%s' is not in whitelist", "commands.blossom.filter.biome.blacklist.query": "Blacklisted biomes: %s", - "commands.blossom.filter.biome.blacklist.list": "%s", - "commands.blossom.filter.biome.blacklist.list.tooltip": "Biomes that disallow blossoming.", + "commands.blossom.filter.biome.blacklist.tooltip": "Biomes that disallow blossoming.", "commands.blossom.filter.biome.blacklist.add": "Added biome entry '%s' to blacklist", "commands.blossom.filter.biome.blacklist.add.failed": "Biome entry '%s' is already in blacklist", "commands.blossom.filter.biome.blacklist.remove": "Removed entry '%s' from blacklist", @@ -74,11 +66,12 @@ "commands.blossom.toggle.whitelist.query": "Whitelist is currently set to: %s", "commands.blossom.toggle.whitelist.set": "Whitelist is now set to: %s", - "commands.blossom.toggle.whitelist.toggle": "%s", - "commands.blossom.toggle.whitelist.toggle.tooltip": "Whether blossoming is enabled in the whitelisted dimensions and biomes.", + "commands.blossom.toggle.whitelist.tooltip": "Whether blossoming is enabled in the whitelisted dimensions and biomes.", "commands.blossom.toggle.blacklist.query": "Blacklist is currently set to: %s", "commands.blossom.toggle.blacklist.set": "Blacklist is now set to: %s", - "commands.blossom.toggle.blacklist.toggle": "%s", - "commands.blossom.toggle.blacklist.toggle.tooltip": "Whether blossoming is disabled in the blacklisted dimensions and biomes" + "commands.blossom.toggle.blacklist.tooltip": "Whether blossoming is disabled in the blacklisted dimensions and biomes", + + "item.blossom.flowering_oak_leaves": "Flowering Oak Leaves", + "item.blossom.fruiting_oak_leaves": "Fruiting Oak Leaves" } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/particles/blossom.json b/src/main/resources/assets/blossom/particles/blossom.json deleted file mode 100644 index e2eaea58..00000000 --- a/src/main/resources/assets/blossom/particles/blossom.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "textures": [ - "blossom:blossom_0", - "blossom:blossom_1", - "blossom:blossom_2", - "blossom:blossom_3", - "blossom:blossom_4", - "blossom:blossom_5", - "blossom:blossom_6", - "blossom:blossom_7", - "blossom:blossom_8", - "blossom:blossom_9", - "blossom:blossom_10", - "blossom:blossom_11" - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/particles/flowering_oak_leaves.json b/src/main/resources/assets/blossom/particles/flowering_oak_leaves.json new file mode 100644 index 00000000..ef221437 --- /dev/null +++ b/src/main/resources/assets/blossom/particles/flowering_oak_leaves.json @@ -0,0 +1,16 @@ +{ + "textures": [ + "blossom:flowering_oak_0", + "blossom:flowering_oak_1", + "blossom:flowering_oak_2", + "blossom:flowering_oak_3", + "blossom:flowering_oak_4", + "blossom:flowering_oak_5", + "blossom:flowering_oak_6", + "blossom:flowering_oak_7", + "blossom:flowering_oak_8", + "blossom:flowering_oak_9", + "blossom:flowering_oak_10", + "blossom:flowering_oak_11" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_0.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_0.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_0.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_0.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_1.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_1.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_1.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_1.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_10.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_10.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_10.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_10.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_11.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_11.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_11.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_11.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_2.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_2.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_2.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_2.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_3.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_3.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_3.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_3.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_4.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_4.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_4.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_4.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_5.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_5.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_5.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_5.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_6.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_6.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_6.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_6.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_7.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_7.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_7.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_7.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_8.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_8.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_8.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_8.png diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_9.png b/src/main/resources/assets/blossom/textures/particle/flowering_oak_9.png similarity index 100% rename from src/main/resources/assets/blossom/textures/particle/blossom_9.png rename to src/main/resources/assets/blossom/textures/particle/flowering_oak_9.png diff --git a/src/main/resources/blossom.mixins.json b/src/main/resources/blossom.mixins.json index e91bd305..4dc33e4a 100644 --- a/src/main/resources/blossom.mixins.json +++ b/src/main/resources/blossom.mixins.json @@ -6,12 +6,14 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "world.entity.EntityAccessor", + "world.entity.EntityMixin", "world.entity.MobAccessor", - "world.entity.animal.BeeAccessor", + "world.entity.ai.goal.GoalInvoker", "world.entity.animal.BeeInvoker", "world.entity.animal.BeeMixin", - "world.entity.animal.BeeMixin$BeeGoToKnownFlowerGoalMixin", "world.entity.animal.BeeMixin$BeeGrowCropGoalMixin", + "world.entity.animal.BeeMixin$BeeLookControlMixin", + "world.entity.animal.BeeMixin$FlyingPathNavigationMixin", "world.level.biome.BiomeAccessor", "world.level.block.BlocksInvoker", "world.level.block.ComposterBlockInvoker", diff --git a/src/main/resources/data/blossom/loot_tables/blocks/flowering_oak_leaves.json b/src/main/resources/data/blossom/loot_tables/blocks/flowering_oak_leaves.json index 0d302075..ed231d21 100644 --- a/src/main/resources/data/blossom/loot_tables/blocks/flowering_oak_leaves.json +++ b/src/main/resources/data/blossom/loot_tables/blocks/flowering_oak_leaves.json @@ -39,33 +39,12 @@ "type": "minecraft:item", "conditions": [ { - "condition": "minecraft:all_of", - "terms": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "items": [ - "minecraft:shears" - ] - } - }, - { - "condition": "minecraft:inverted", - "term": { - "condition": "minecraft:match_tool", - "predicate": { - "enchantments": [ - { - "enchantment": "minecraft:silk_touch", - "levels": { - "min": 1 - } - } - ] - } - } - } - ] + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:shears" + ] + } } ], "name": "minecraft:oak_leaves" @@ -98,22 +77,19 @@ "bonus_rolls": 0.0, "conditions": [ { - "condition": "minecraft:any_of", - "terms": [ - { - "condition": "minecraft:inverted", - "term": { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:any_of", + "terms": [ + { "condition": "minecraft:match_tool", "predicate": { "items": [ "minecraft:shears" ] } - } - }, - { - "condition": "minecraft:inverted", - "term": { + }, + { "condition": "minecraft:match_tool", "predicate": { "enchantments": [ @@ -126,8 +102,8 @@ ] } } - } - ] + ] + } } ], "entries": [ @@ -165,5 +141,6 @@ ], "rolls": 1.0 } - ] + ], + "random_sequence": "blossom:flowering_oak_leaves" } \ No newline at end of file diff --git a/src/main/resources/data/blossom/loot_tables/blocks/fruiting_oak_leaves.json b/src/main/resources/data/blossom/loot_tables/blocks/fruiting_oak_leaves.json index 75c3ae5c..feba0686 100644 --- a/src/main/resources/data/blossom/loot_tables/blocks/fruiting_oak_leaves.json +++ b/src/main/resources/data/blossom/loot_tables/blocks/fruiting_oak_leaves.json @@ -39,33 +39,12 @@ "type": "minecraft:item", "conditions": [ { - "condition": "minecraft:all_of", - "terms": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "items": [ - "minecraft:shears" - ] - } - }, - { - "condition": "minecraft:inverted", - "term": { - "condition": "minecraft:match_tool", - "predicate": { - "enchantments": [ - { - "enchantment": "minecraft:silk_touch", - "levels": { - "min": 1 - } - } - ] - } - } - } - ] + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:shears" + ] + } } ], "name": "minecraft:oak_leaves" @@ -98,22 +77,19 @@ "bonus_rolls": 0.0, "conditions": [ { - "condition": "minecraft:any_of", - "terms": [ - { - "condition": "minecraft:inverted", - "term": { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:any_of", + "terms": [ + { "condition": "minecraft:match_tool", "predicate": { "items": [ "minecraft:shears" ] } - } - }, - { - "condition": "minecraft:inverted", - "term": { + }, + { "condition": "minecraft:match_tool", "predicate": { "enchantments": [ @@ -126,8 +102,8 @@ ] } } - } - ] + ] + } } ], "entries": [ @@ -216,5 +192,6 @@ ], "rolls": 1.0 } - ] + ], + "random_sequence": "blossom:fruiting_oak_leaves" } \ No newline at end of file diff --git a/src/main/resources/data/blossom/tags/blocks/leaved_flowers.json b/src/main/resources/data/blossom/tags/blocks/leaved_flowers.json new file mode 100644 index 00000000..fd984c3a --- /dev/null +++ b/src/main/resources/data/blossom/tags/blocks/leaved_flowers.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "blossom:flowering_oak_leaves" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/blossom/tags/items/leaved_flowers.json b/src/main/resources/data/blossom/tags/items/leaved_flowers.json new file mode 100644 index 00000000..fd984c3a --- /dev/null +++ b/src/main/resources/data/blossom/tags/items/leaved_flowers.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "blossom:flowering_oak_leaves" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/flowers.json b/src/main/resources/data/minecraft/tags/blocks/flowers.json index fd984c3a..b5f8727d 100644 --- a/src/main/resources/data/minecraft/tags/blocks/flowers.json +++ b/src/main/resources/data/minecraft/tags/blocks/flowers.json @@ -1,6 +1,6 @@ { "replace": false, "values": [ - "blossom:flowering_oak_leaves" + "#blossom:leaved_flowers" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/items/flowers.json b/src/main/resources/data/minecraft/tags/items/flowers.json index fd984c3a..b5f8727d 100644 --- a/src/main/resources/data/minecraft/tags/items/flowers.json +++ b/src/main/resources/data/minecraft/tags/items/flowers.json @@ -1,6 +1,6 @@ { "replace": false, "values": [ - "blossom:flowering_oak_leaves" + "#blossom:leaved_flowers" ] } \ No newline at end of file