diff --git a/build.gradle b/build.gradle index 724311cd..c631df68 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id "fabric-loom" version "1.7-SNAPSHOT" + id "fabric-loom" version "1.9-SNAPSHOT" id "maven-publish" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index db4c3260..77e5f2a9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/Blossom.java b/src/main/java/dev/yurisuika/blossom/Blossom.java index f4d50be8..b263af6c 100644 --- a/src/main/java/dev/yurisuika/blossom/Blossom.java +++ b/src/main/java/dev/yurisuika/blossom/Blossom.java @@ -1,16 +1,16 @@ package dev.yurisuika.blossom; -import dev.yurisuika.blossom.client.particle.BlossomParticle; +import dev.yurisuika.blossom.client.particle.FallingPetalsParticle; +import dev.yurisuika.blossom.core.particles.BlossomParticleTypes; 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.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; @@ -18,170 +18,104 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; import net.fabricmc.fabric.api.registry.CompostingChanceRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BiomeColors; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.item.ItemProperties; -import net.minecraft.core.Registry; -import net.minecraft.core.particles.SimpleParticleType; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.animal.Bee; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; 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.material.MapColor; -import net.minecraft.world.level.material.PushReaction; import java.util.Objects; public class Blossom implements ModInitializer { - public static final Block FRUITING_OAK_LEAVES = new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, FabricBlockSettings.create() - .mapColor(MapColor.PLANT) - .strength(0.2F) - .ticksRandomly() - .sounds(SoundType.GRASS) - .nonOpaque() - .allowsSpawning(Blocks::ocelotOrParrot) - .suffocates(Blocks::never) - .blockVision(Blocks::never) - .burnable() - .pistonBehavior(PushReaction.DESTROY) - .solidBlock(Blocks::never)); - public static final Block FLOWERING_OAK_LEAVES = new FloweringLeavesBlock(Blocks.OAK_LEAVES, Blossom.FRUITING_OAK_LEAVES, FabricBlockSettings.create() - .mapColor(MapColor.PLANT) - .strength(0.2F) - .ticksRandomly() - .sounds(SoundType.GRASS) - .nonOpaque() - .allowsSpawning(Blocks::ocelotOrParrot) - .suffocates(Blocks::never) - .blockVision(Blocks::never) - .burnable() - .pistonBehavior(PushReaction.DESTROY) - .solidBlock(Blocks::never)); - - public static final SimpleParticleType BLOSSOM = FabricParticleTypes.simple(false); - - public static void registerBlocks() { - Registry.register(BuiltInRegistries.BLOCK, new ResourceLocation("blossom", "flowering_oak_leaves"), FLOWERING_OAK_LEAVES); - Registry.register(BuiltInRegistries.BLOCK, new ResourceLocation("blossom", "fruiting_oak_leaves"), FRUITING_OAK_LEAVES); - } - - public static void registerItems() { - Registry.register(BuiltInRegistries.ITEM, new ResourceLocation("blossom", "flowering_oak_leaves"), new BlockItem(FLOWERING_OAK_LEAVES, new Item.Properties())); - Registry.register(BuiltInRegistries.ITEM, new ResourceLocation("blossom", "fruiting_oak_leaves"), new BlockItem(FRUITING_OAK_LEAVES, new Item.Properties())); - } - - public static void registerParticles() { - Registry.register(BuiltInRegistries.PARTICLE_TYPE, new ResourceLocation("blossom", "blossom"), BLOSSOM); - } - public static void registerCompostables() { - CompostingChanceRegistry.INSTANCE.add(FLOWERING_OAK_LEAVES, 0.3F); - CompostingChanceRegistry.INSTANCE.add(FRUITING_OAK_LEAVES, 0.3F); + CompostingChanceRegistry.INSTANCE.add(BlossomBlocks.FRUITING_OAK_LEAVES, 0.3F); + CompostingChanceRegistry.INSTANCE.add(BlossomBlocks.FLOWERING_OAK_LEAVES, 0.3F); } public static void registerFlammables() { - FlammableBlockRegistry.getDefaultInstance().add(FLOWERING_OAK_LEAVES, 30, 60); - FlammableBlockRegistry.getDefaultInstance().add(FRUITING_OAK_LEAVES, 30, 60); + FlammableBlockRegistry.getDefaultInstance().add(BlossomBlocks.FRUITING_OAK_LEAVES, 30, 60); + FlammableBlockRegistry.getDefaultInstance().add(BlossomBlocks.FLOWERING_OAK_LEAVES, 30, 60); } - public static void registerItemGroupEvents() { - ItemGroupEvents.modifyEntriesEvent(CreativeModeTabs.NATURAL_BLOCKS).register(content -> { - content.addAfter(Items.FLOWERING_AZALEA_LEAVES, FLOWERING_OAK_LEAVES.asItem(), FRUITING_OAK_LEAVES.asItem()); - }); + public static void registerCreativeModeTabs() { + ItemGroupEvents.modifyEntriesEvent(CreativeModeTabs.NATURAL_BLOCKS).register(content -> content.addAfter(Items.FLOWERING_AZALEA_LEAVES, BlossomBlocks.FLOWERING_OAK_LEAVES.asItem(), BlossomBlocks.FRUITING_OAK_LEAVES.asItem())); + } + + public static void registerCommands() { + CommandRegistrationCallback.EVENT.register(BlossomCommand::register); } - public static void registerServerEntityEvents() { + public static void registerGoals() { ServerEntityEvents.ENTITY_LOAD.register((entity, level) -> { if (entity instanceof Bee) { - ((Bee) entity).getGoalSelector().addGoal(4, new BlossomGoal((Bee) entity)); - ((Bee) entity).getGoalSelector().addGoal(4, new FruitGoal((Bee) entity)); + ((BeeInterface) entity).registerGoals((Bee) entity); } }); } - public static void registerCommands() { - CommandRegistrationCallback.EVENT.register(BlossomCommand::register); - } - @Override public void onInitialize() { Config.loadConfig(); Validate.checkBounds(); - registerBlocks(); - registerItems(); - registerParticles(); + BlossomBlocks.register(); + BlossomItems.register(); + BlossomParticleTypes.register(); registerFlammables(); registerCompostables(); - registerItemGroupEvents(); - registerServerEntityEvents(); + registerCreativeModeTabs(); registerCommands(); + registerGoals(); } public static class Client implements ClientModInitializer { - @Environment(EnvType.CLIENT) - public static void registerParticleFactories() { - ParticleFactoryRegistry.getInstance().register(BLOSSOM, BlossomParticle.Factory::new); + public static void registerParticles() { + ParticleFactoryRegistry.getInstance().register(BlossomParticleTypes.FLOWERING_OAK_LEAVES, FallingPetalsParticle.FloweringOakProvider::new); } - @Environment(EnvType.CLIENT) public static void registerRenderLayers() { - BlockRenderLayerMap.INSTANCE.putBlock(FLOWERING_OAK_LEAVES, RenderType.cutout()); - BlockRenderLayerMap.INSTANCE.putBlock(FRUITING_OAK_LEAVES, RenderType.cutout()); + BlockRenderLayerMap.INSTANCE.putBlock(BlossomBlocks.FRUITING_OAK_LEAVES, RenderType.cutout()); + BlockRenderLayerMap.INSTANCE.putBlock(BlossomBlocks.FLOWERING_OAK_LEAVES, RenderType.cutout()); } - @Environment(EnvType.CLIENT) - public static void registerColorProviders() { - ColorProviderRegistry.BLOCK.register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), FLOWERING_OAK_LEAVES); - ColorProviderRegistry.BLOCK.register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), FRUITING_OAK_LEAVES); + public static void registerBlockColors() { + ColorProviderRegistry.BLOCK.register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), BlossomBlocks.FRUITING_OAK_LEAVES); + ColorProviderRegistry.BLOCK.register((state, level, pos, tintIndex) -> level != null && pos != null ? BiomeColors.getAverageFoliageColor(level, pos) : FoliageColor.get(0.5F, 1.0F), BlossomBlocks.FLOWERING_OAK_LEAVES); + } - ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), FLOWERING_OAK_LEAVES); - ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), FRUITING_OAK_LEAVES); + public static void registerItemColors() { + ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), BlossomBlocks.FRUITING_OAK_LEAVES); + ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : Minecraft.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().defaultBlockState(), null, null, tintIndex), BlossomBlocks.FLOWERING_OAK_LEAVES); } - @Environment(EnvType.CLIENT) - public static void registerModelPredicateProviders() { - ItemProperties.register(FLOWERING_OAK_LEAVES.asItem(), new ResourceLocation("age"), (stack, world, entity, seed) -> { + public static void registerItemProperties() { + ItemProperties.register(BlossomItems.FRUITING_OAK_LEAVES, 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.asItem(), new ResourceLocation("age"), (stack, world, entity, seed) -> { + ItemProperties.register(BlossomItems.FLOWERING_OAK_LEAVES, ResourceLocation.tryParse("age"), (stack, world, entity, seed) -> { CompoundTag tag = stack.getTagElement("BlockStateTag"); - try { - if (Objects.nonNull(tag) && Objects.nonNull(tag.get(FruitingLeavesBlock.AGE.getName()))) { - return Integer.parseInt(tag.get(FruitingLeavesBlock.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; }); } @Override public void onInitializeClient() { - registerParticleFactories(); + registerParticles(); registerRenderLayers(); - registerColorProviders(); - registerModelPredicateProviders(); + registerBlockColors(); + registerItemColors(); + registerItemProperties(); } } 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 74% 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 e75bf594..5fa33545 100644 --- a/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java +++ b/src/main/java/dev/yurisuika/blossom/client/particle/FallingPetalsParticle.java @@ -1,24 +1,21 @@ package dev.yurisuika.blossom.client.particle; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.*; import net.minecraft.core.particles.SimpleParticleType; -@Environment(EnvType.CLIENT) -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; @@ -31,11 +28,10 @@ public ParticleRenderType getRenderType() { return ParticleRenderType.PARTICLE_SHEET_OPAQUE; } - @Environment(EnvType.CLIENT) - 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..4d3dd61f --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java @@ -0,0 +1,17 @@ +package dev.yurisuika.blossom.core.particles; + +import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; +import net.minecraft.core.Registry; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; + +public class BlossomParticleTypes { + + public static final SimpleParticleType FLOWERING_OAK_LEAVES = FabricParticleTypes.simple(false); + + public static void register() { + Registry.register(BuiltInRegistries.PARTICLE_TYPE, ResourceLocation.tryParse("blossom:flowering_oak_leaves"), FLOWERING_OAK_LEAVES); + } + +} \ 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..35fc1fe3 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,165 @@ 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) { + setSavedLeavesPos(null); + 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 +221,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 ef4a8124..f6cd6e87 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.setBlossomingChance(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.setBlossomingChance(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; }) @@ -199,7 +188,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; }) @@ -244,7 +233,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; }) @@ -287,7 +276,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; }) @@ -334,14 +323,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; }) @@ -349,14 +338,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 7052b4ed..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.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..c5631ed8 --- /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.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 ee28ca76..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)) { - 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) { - if (blockState.getValue(BlockStateProperties.AGE_3) >= 3) { - entity.level().levelEvent(2005, blockPos, 0); - entity.level().setBlockAndUpdate(blockPos, Blossom.FRUITING_OAK_LEAVES.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..d2ce2d4d --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java @@ -0,0 +1,46 @@ +package dev.yurisuika.blossom.world.level.block; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +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.material.MapColor; +import net.minecraft.world.level.material.PushReaction; + +public class BlossomBlocks { + + public static final Block FRUITING_OAK_LEAVES = new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, FabricBlockSettings.create() + .mapColor(MapColor.PLANT) + .strength(0.2F) + .ticksRandomly() + .sounds(SoundType.GRASS) + .nonOpaque() + .allowsSpawning(Blocks::ocelotOrParrot) + .suffocates(Blocks::never) + .blockVision(Blocks::never) + .burnable() + .pistonBehavior(PushReaction.DESTROY) + .solidBlock(Blocks::never)); + public static final Block FLOWERING_OAK_LEAVES = new FloweringLeavesBlock(Blocks.OAK_LEAVES, FRUITING_OAK_LEAVES, FabricBlockSettings.create() + .mapColor(MapColor.PLANT) + .strength(0.2F) + .ticksRandomly() + .sounds(SoundType.GRASS) + .nonOpaque() + .allowsSpawning(Blocks::ocelotOrParrot) + .suffocates(Blocks::never) + .blockVision(Blocks::never) + .burnable() + .pistonBehavior(PushReaction.DESTROY) + .solidBlock(Blocks::never)); + + public static void register() { + Registry.register(BuiltInRegistries.BLOCK, ResourceLocation.tryParse("blossom:fruiting_oak_leaves"), FRUITING_OAK_LEAVES); + Registry.register(BuiltInRegistries.BLOCK, ResourceLocation.tryParse("blossom:flowering_oak_leaves"), FLOWERING_OAK_LEAVES); + } + +} \ 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 8c885b83..c9dd614b 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); + ParticleUtils.spawnParticleBelow(level, pos, random, BlossomParticleTypes.FLOWERING_OAK_LEAVES); } 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 2bc502f9..020c4eb4 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..b953021b --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/level/item/BlossomItems.java @@ -0,0 +1,20 @@ +package dev.yurisuika.blossom.world.level.item; + +import dev.yurisuika.blossom.world.level.block.BlossomBlocks; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; + +public class BlossomItems { + + public static final Item FRUITING_OAK_LEAVES = new BlockItem(BlossomBlocks.FRUITING_OAK_LEAVES, new Item.Properties()); + public static final Item FLOWERING_OAK_LEAVES = new BlockItem(BlossomBlocks.FLOWERING_OAK_LEAVES, new Item.Properties()); + + public static void register() { + Registry.register(BuiltInRegistries.ITEM, ResourceLocation.tryParse("blossom:fruiting_oak_leaves"), FRUITING_OAK_LEAVES); + Registry.register(BuiltInRegistries.ITEM, ResourceLocation.tryParse("blossom:flowering_oak_leaves"), FLOWERING_OAK_LEAVES); + } + +} \ 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 d9896678..fcbc653f 100644 --- a/src/main/resources/blossom.mixins.json +++ b/src/main/resources/blossom.mixins.json @@ -6,13 +6,14 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "world.entity.EntityAccessor", + "world.entity.EntityMixin", "world.entity.MobAccessor", "world.entity.ai.goal.GoalInvoker", - "world.entity.animal.BeeAccessor", "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.state.BlockBehaviourMixin" ], 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