diff --git a/build.gradle b/build.gradle index b090d729..9727164f 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 6675a8f4..9073a793 100644 --- a/src/main/java/dev/yurisuika/blossom/Blossom.java +++ b/src/main/java/dev/yurisuika/blossom/Blossom.java @@ -1,99 +1,52 @@ package dev.yurisuika.blossom; -import dev.yurisuika.blossom.client.particle.BlossomParticle; -import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; -import dev.yurisuika.blossom.mixin.world.level.block.BlocksInvoker; +import dev.yurisuika.blossom.client.particle.FallingPetalsParticle; +import dev.yurisuika.blossom.core.particles.BlossomParticleTypes; import dev.yurisuika.blossom.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; import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; -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.core.Registry; -import net.minecraft.core.particles.SimpleParticleType; 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.CreativeModeTab; -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.Material; import java.util.Objects; public class Blossom implements ModInitializer { - public static final Block FRUITING_OAK_LEAVES = new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, FabricBlockSettings.of(Material.LEAVES) - .strength(0.2F) - .ticksRandomly() - .sounds(SoundType.GRASS) - .nonOpaque() - .allowsSpawning(BlocksInvoker::invokeOcelotOrParrot) - .suffocates(BlocksInvoker::invokeNever) - .blockVision(BlocksInvoker::invokeNever)); - public static final Block FLOWERING_OAK_LEAVES = new FloweringLeavesBlock(Blocks.OAK_LEAVES, Blossom.FRUITING_OAK_LEAVES, FabricBlockSettings.of(Material.LEAVES) - .strength(0.2F) - .ticksRandomly() - .sounds(SoundType.GRASS) - .nonOpaque() - .allowsSpawning(BlocksInvoker::invokeOcelotOrParrot) - .suffocates(BlocksInvoker::invokeNever) - .blockVision(BlocksInvoker::invokeNever)); - - public static final SimpleParticleType BLOSSOM = FabricParticleTypes.simple(false); - - public static void registerBlocks() { - Registry.register(Registry.BLOCK, new ResourceLocation("blossom", "flowering_oak_leaves"), FLOWERING_OAK_LEAVES); - Registry.register(Registry.BLOCK, new ResourceLocation("blossom", "fruiting_oak_leaves"), FRUITING_OAK_LEAVES); - } - - public static void registerItems() { - Registry.register(Registry.ITEM, new ResourceLocation("blossom", "flowering_oak_leaves"), new BlockItem(FLOWERING_OAK_LEAVES, new Item.Properties().tab(CreativeModeTab.TAB_DECORATIONS))); - Registry.register(Registry.ITEM, new ResourceLocation("blossom", "fruiting_oak_leaves"), new BlockItem(FRUITING_OAK_LEAVES, new Item.Properties().tab(CreativeModeTab.TAB_DECORATIONS))); - } - - public static void registerParticles() { - Registry.register(Registry.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 registerServerEntityEvents() { + public static void registerGoals() { ServerEntityEvents.ENTITY_LOAD.register((entity, level) -> { if (entity instanceof Bee) { - ((MobAccessor) entity).getGoalSelector().addGoal(4, new BlossomGoal((Bee) entity)); - ((MobAccessor) entity).getGoalSelector().addGoal(4, new FruitGoal((Bee) entity)); + ((BeeInterface) entity).registerGoals((Bee) entity); } }); } @@ -107,65 +60,54 @@ public void onInitialize() { Config.loadConfig(); Validate.checkBounds(); - registerBlocks(); - registerItems(); - registerParticles(); + BlossomBlocks.register(); + BlossomItems.register(); + BlossomParticleTypes.register(); registerFlammables(); registerCompostables(); - registerServerEntityEvents(); 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() { - FabricModelPredicateProviderRegistry.register(FLOWERING_OAK_LEAVES.asItem(), new ResourceLocation("age"), (stack, world, entity) -> { + public static void registerItemProperties() { + FabricModelPredicateProviderRegistry.register(BlossomItems.FRUITING_OAK_LEAVES, ResourceLocation.tryParse("age"), (stack, world, entity) -> { 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; }); - FabricModelPredicateProviderRegistry.register(FRUITING_OAK_LEAVES.asItem(), new ResourceLocation("age"), (stack, world, entity) -> { + FabricModelPredicateProviderRegistry.register(BlossomItems.FLOWERING_OAK_LEAVES, ResourceLocation.tryParse("age"), (stack, world, entity) -> { 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 73% 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 ec037a44..c7f2b4d2 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; @@ -30,17 +27,16 @@ public ParticleRenderType getRenderType() { return ParticleRenderType.PARTICLE_SHEET_OPAQUE; } - @Environment(EnvType.CLIENT) - public static class Factory implements ParticleProvider { + public static class FloweringOakProvider implements ParticleProvider { public final SpriteSet spriteSet; - public Factory(SpriteSet spriteSet) { + public FloweringOakProvider(SpriteSet spriteSet) { this.spriteSet = spriteSet; } 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..a52d1feb --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/core/particles/BlossomParticleTypes.java @@ -0,0 +1,16 @@ +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.resources.ResourceLocation; + +public class BlossomParticleTypes { + + public static final SimpleParticleType FLOWERING_OAK_LEAVES = FabricParticleTypes.simple(false); + + public static void register() { + Registry.register(Registry.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..986f74e5 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/entity/EntityMixin.java @@ -0,0 +1,21 @@ +package dev.yurisuika.blossom.mixin.world.entity; + +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; + +import java.util.Random; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Shadow + public Level level; + + @Final + @Shadow + protected Random 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 087e687b..b9e263c6 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,11 +1,24 @@ package dev.yurisuika.blossom.mixin.world.entity.animal; +import dev.yurisuika.blossom.mixin.world.entity.EntityMixin; +import dev.yurisuika.blossom.mixin.world.entity.MobAccessor; +import dev.yurisuika.blossom.tags.BlossomBlockTags; +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; @@ -17,15 +30,160 @@ 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); + ((MobAccessor) bee).getGoalSelector().addGoal(4, getBlossomLeavesGoal()); + ((MobAccessor) bee).getGoalSelector().addGoal(4, getFruitLeavesGoal()); + ((MobAccessor) 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 = "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 { @@ -45,7 +203,7 @@ private void injectTick(CallbackInfo ci) { BlockState blockState = entity.getCommandSenderWorld().getBlockState(blockPos); if (blockState.is(BlockTags.BEE_GROWABLES)) { if (blockState.getBlock() instanceof FruitingLeavesBlock) { - FruitingLeavesBlock fruitingLeavesBlock = (FruitingLeavesBlock)blockState.getBlock(); + FruitingLeavesBlock fruitingLeavesBlock = (FruitingLeavesBlock) blockState.getBlock(); if (!fruitingLeavesBlock.isMaxAge(blockState)) { IntegerProperty age = fruitingLeavesBlock.getAgeProperty(); entity.getCommandSenderWorld().levelEvent(2005, blockPos, 0); @@ -60,20 +218,12 @@ 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; - } + @Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeePollinateGoal") + public abstract static class BeePollinateGoalMixin { - @Inject(method = "wantsToGoToKnownFlower", at = @At("RETURN"), cancellable = true) - private void injectWantsToGoToKnownFlower(CallbackInfoReturnable cir) { - cir.setReturnValue(cir.getReturnValue() || (entity.getCommandSenderWorld().getBlockState(entity.getSavedFlowerPos()).is(Blocks.OAK_LEAVES) && entity.hasNectar())); + @Inject(method = "method_21819(Lnet/minecraft/world/level/block/state/BlockState;)Z", at = @At(value = "RETURN", ordinal = 2), cancellable = true) + private static void injectLambda(BlockState state, CallbackInfoReturnable cir) { + cir.setReturnValue(cir.getReturnValue() || state.is(BlossomBlockTags.LEAVED_FLOWERS)); } } 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 3f1afdf4..42e00d47 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,6 +1,6 @@ package dev.yurisuika.blossom.mixin.world.level.block.state; -import dev.yurisuika.blossom.world.level.block.EntityCollisionContextInterface; +import dev.yurisuika.blossom.world.phys.shapes.EntityCollisionContextInterface; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.animal.Bee; import net.minecraft.world.level.BlockGetter; diff --git a/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/EntityCollisionContextMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/world/phys/shapes/EntityCollisionContextMixin.java similarity index 87% rename from src/main/java/dev/yurisuika/blossom/mixin/world/level/block/EntityCollisionContextMixin.java rename to src/main/java/dev/yurisuika/blossom/mixin/world/phys/shapes/EntityCollisionContextMixin.java index 0c5ee8bb..7ff2c58c 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/world/level/block/EntityCollisionContextMixin.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/world/phys/shapes/EntityCollisionContextMixin.java @@ -1,6 +1,6 @@ -package dev.yurisuika.blossom.mixin.world.level.block; +package dev.yurisuika.blossom.mixin.world.phys.shapes; -import dev.yurisuika.blossom.world.level.block.EntityCollisionContextInterface; +import dev.yurisuika.blossom.world.phys.shapes.EntityCollisionContextInterface; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.shapes.EntityCollisionContext; import org.spongepowered.asm.mixin.Mixin; 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 b45e44fe..7f4c048b 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; @@ -16,10 +15,7 @@ import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.commands.synchronization.SuggestionProviders; import net.minecraft.core.Registry; -import net.minecraft.network.chat.ComponentUtils; -import net.minecraft.network.chat.HoverEvent; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.network.chat.*; import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.ArrayUtils; @@ -54,59 +50,48 @@ public static void register(CommandDispatcher dispatcher, bo .then(Commands.literal("blossoming") .executes(commandContext -> { MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.blossoming.distance", Option.getBlossomingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.blossoming.query", chance, distance), true); + commandContext.getSource().sendSuccess(new TranslatableComponent("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(new TranslatableComponent("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.blossoming.distance", Option.getBlossomingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.blossoming.set", chance, distance), true); - return 1; - }) - ) + .executes(commandContext -> { + Option.setBlossomingChance(FloatArgumentType.getFloat(commandContext, "chance")); + MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.blossoming.chance", Option.getBlossomingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.chance.tooltip")))); + commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.blossoming.set", chance), true); + return 1; + }) ) ) .then(Commands.literal("fruiting") .executes(commandContext -> { MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.fruiting.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.fruiting.distance", Option.getFruitingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.distance.tooltip")))); - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.fruiting.query", chance, distance), false); + commandContext.getSource().sendSuccess(new TranslatableComponent("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(new TranslatableComponent("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.fruiting.chance.tooltip")))); - MutableComponent distance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.fruiting.distance", Option.getFruitingDistance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.blossoming.distance.tooltip")))); - - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.fruiting.set", chance, distance), false); - return 1; - }) - ) + .executes(commandContext -> { + Option.setFruitingChance(FloatArgumentType.getFloat(commandContext, "chance")); + MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.fruiting.chance", Option.getFruitingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.fruiting.chance.tooltip")))); + commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.fruiting.set", chance), false); + return 1; + }) ) ) .then(Commands.literal("harvesting") .executes(commandContext -> { - MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.bonus.tooltip")))); MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.harvesting.chance", Option.getHarvestingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.chance.tooltip")))); - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.harvesting.query", bonus, chance), true); + MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.bonus.tooltip")))); + commandContext.getSource().sendSuccess(new TranslatableComponent("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(new TranslatableComponent("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.bonus.tooltip")))); + Option.setHarvestingBonus(IntegerArgumentType.getInteger(commandContext, "bonus")); MutableComponent chance = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.harvesting.chance", Option.getHarvestingChance())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.chance.tooltip")))); - commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.harvesting.set", bonus, chance), true); + MutableComponent bonus = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.value.harvesting.bonus", Option.getHarvestingBonus())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.value.harvesting.bonus.tooltip")))); + commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.value.harvesting.set", chance, bonus), true); return 1; }) ) @@ -158,7 +143,7 @@ public static void register(CommandDispatcher dispatcher, bo .then(Commands.literal("dimension") .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent list = new TranslatableComponent("commands.blossom.filter.dimension.whitelist.list", Arrays.toString(Option.getDimensionWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.dimension.whitelist.list.tooltip")))); + MutableComponent list = new TextComponent(Arrays.toString(Option.getDimensionWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.dimension.whitelist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.filter.dimension.whitelist.query", list), false); return 1; }) @@ -201,7 +186,7 @@ public static void register(CommandDispatcher dispatcher, bo ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent list = new TranslatableComponent("commands.blossom.filter.dimension.blacklist.list", Arrays.toString(Option.getDimensionBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.dimension.blacklist.list.tooltip")))); + MutableComponent list = new TextComponent(Arrays.toString(Option.getDimensionBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.dimension.blacklist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.filter.dimension.blacklist.query", list), false); return 1; }) @@ -246,7 +231,7 @@ public static void register(CommandDispatcher dispatcher, bo .then(Commands.literal("biome") .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent list = new TranslatableComponent("commands.blossom.filter.biome.whitelist.list", Arrays.toString(Option.getBiomeWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.biome.whitelist.list.tooltip")))); + MutableComponent list = new TextComponent(Arrays.toString(Option.getBiomeWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.biome.whitelist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.filter.biome.whitelist.query", list), false); return 1; }) @@ -291,7 +276,7 @@ public static void register(CommandDispatcher dispatcher, bo ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent list = new TranslatableComponent("commands.blossom.filter.biome.blacklist.list", Arrays.toString(Option.getBiomeBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.biome.blacklist.list.tooltip")))); + MutableComponent list = new TextComponent(Arrays.toString(Option.getBiomeBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.filter.biome.blacklist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.filter.biome.blacklist.query", list), false); return 1; }) @@ -340,14 +325,14 @@ public static void register(CommandDispatcher dispatcher, bo .requires(source -> source.hasPermission(4)) .then(Commands.literal("whitelist") .executes(commandContext -> { - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.toggle.whitelist.toggle", Option.getWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.whitelist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TextComponent(String.valueOf(Option.getWhitelist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.whitelist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("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(new TranslatableComponent("commands.blossom.toggle.whitelist.toggle", Option.getWhitelist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.whitelist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TextComponent(String.valueOf(Option.getWhitelist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.whitelist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("commands.blossom.toggle.whitelist.set", toggle), false); return 1; }) @@ -355,14 +340,14 @@ public static void register(CommandDispatcher dispatcher, bo ) .then(Commands.literal("blacklist") .executes(commandContext -> { - MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TranslatableComponent("commands.blossom.toggle.blacklist.toggle", Option.getBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.blacklist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TextComponent(String.valueOf(Option.getBlacklist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.blacklist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("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(new TranslatableComponent("commands.blossom.toggle.blacklist.toggle", Option.getBlacklist())).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.blacklist.toggle.tooltip")))); + MutableComponent toggle = ComponentUtils.wrapInSquareBrackets(new TextComponent(String.valueOf(Option.getBlacklist()))).withStyle(style -> style.withColor(ChatFormatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("commands.blossom.toggle.blacklist.tooltip")))); commandContext.getSource().sendSuccess(new TranslatableComponent("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..c482addf --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/tags/BlossomBlockTags.java @@ -0,0 +1,12 @@ +package dev.yurisuika.blossom.tags; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.Tag; +import net.minecraft.world.level.block.Block; + +public class BlossomBlockTags { + + public static final Tag LEAVED_FLOWERS = BlockTags.getAllTags().getTag(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..5cd28e0d --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/tags/BlossomItemTags.java @@ -0,0 +1,12 @@ +package dev.yurisuika.blossom.tags; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.Tag; +import net.minecraft.world.item.Item; + +public class BlossomItemTags { + + public static final Tag LEAVED_FLOWERS = ItemTags.getAllTags().getTag(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/BlossomLeavesGoal.java similarity index 51% rename from src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java rename to src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java index 70d8d3dd..84f4a55e 100644 --- a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomGoal.java +++ b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/BlossomLeavesGoal.java @@ -1,11 +1,11 @@ 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.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; @@ -15,6 +15,7 @@ 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.dimension.DimensionType; import net.minecraft.world.phys.Vec3; @@ -26,20 +27,23 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; -public class BlossomGoal extends Goal { +public class BlossomLeavesGoal extends Goal { public final Bee entity; - public final Predicate targetPredicate = state -> state.is(Blocks.OAK_LEAVES); + public Predicate validBlocks; + public int successfulBlossomingTicks; + public int lastSoundPlayedTick; + public boolean blossoming; + public Vec3 hoverPos; public int blossomingTicks; - public int lastBlossomingTick; - public boolean running; - public Vec3 nextTarget; - public int ticks; + public float goalChance; - public BlossomGoal(Bee bee) { + public BlossomLeavesGoal(Bee bee) { super(); this.entity = bee; this.setFlags(EnumSet.of(Flag.MOVE)); + this.validBlocks = state -> state.is(Blocks.OAK_LEAVES); + this.goalChance = Option.getBlossomingChance(); } public boolean checkFilters() { @@ -50,30 +54,14 @@ public boolean checkFilters() { AtomicBoolean whitelist = new AtomicBoolean(false); if (Option.getWhitelist()) { - Arrays.stream(Option.getDimensionWhitelist()).forEach(entry -> { - if (Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getKey(dimension).toString())) { - whitelist.set(true); - } - }); - Arrays.stream(Option.getBiomeWhitelist()).forEach(entry -> { - if (Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(biome).toString())) { - whitelist.set(true); - } - }); + Arrays.stream(Option.getDimensionWhitelist()).filter(entry -> Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getKey(dimension).toString())).map(entry -> true).forEach(whitelist::set); + Arrays.stream(Option.getBiomeWhitelist()).filter(entry -> Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(biome).toString())).map(entry -> true).forEach(whitelist::set); } AtomicBoolean blacklist = new AtomicBoolean(true); if (Option.getBlacklist()) { - Arrays.stream(Option.getDimensionBlacklist()).forEach(entry -> { - if (Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getKey(dimension).toString())) { - blacklist.set(false); - } - }); - Arrays.stream(Option.getBiomeBlacklist()).forEach(entry -> { - if (Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(biome).toString())) { - blacklist.set(false); - } - }); + Arrays.stream(Option.getDimensionBlacklist()).filter(entry -> Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getKey(dimension).toString())).map(entry -> false).forEach(blacklist::set); + Arrays.stream(Option.getBiomeBlacklist()).filter(entry -> Objects.equals(entry, entity.getCommandSenderWorld().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getKey(biome).toString())).map(entry -> false).forEach(blacklist::set); } if (temperature >= Option.getTemperatureMin() && temperature <= Option.getTemperatureMax()) { @@ -93,41 +81,38 @@ public boolean checkFilters() { return false; } - public boolean canBeeStart() { + public boolean canBeeUse() { if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { return false; } - if (((EntityAccessor) entity).getRandom().nextFloat() > Option.getBlossomingChance()) { + if (((EntityAccessor) entity).getRandom().nextFloat() > goalChance) { return false; } if (entity.getCommandSenderWorld().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; - } + if (!findNearbyLeaves().isPresent()) { + return false; } - 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 canBeeContinue() { - if (!running) { + public boolean canBeeContinueToUse() { + if (!blossoming) { return false; } - if (!entity.hasSavedFlowerPos()) { + if (!((BeeInterface) entity).hasSavedLeavesPos()) { return false; } - if (entity.getSavedFlowerPos() == null) { + if (((BeeInterface) entity).getSavedLeavesPos() == null) { return false; } if (((BeeInvoker) entity).invokeGetCropsGrownSincePollination() >= 10) { @@ -136,88 +121,84 @@ public boolean canBeeContinue() { if (entity.getCommandSenderWorld().isRaining()) { return false; } - if (completed()) { + if (hasBlossomedLongEnough()) { return ((EntityAccessor) entity).getRandom().nextFloat() < 0.2F; } - if (entity.tickCount % 20 == 0 && !isTarget(entity.getSavedFlowerPos())) { - ((BeeAccessor) entity).setSavedFlowerPos(null); + if (entity.tickCount % 20 == 0 && !((BeeInterface) entity).areLeavesValid(((BeeInterface) entity).getSavedLeavesPos())) { + ((BeeInterface) entity).setSavedLeavesPos(null); return false; } return true; } - public boolean completed() { - return blossomingTicks > 400; + public boolean hasBlossomedLongEnough() { + return successfulBlossomingTicks > 400; } - public boolean isPollinating() { - return running; + public boolean isBlossoming() { + return blossoming; } - public void stopPollinating() { - running = false; + public void stopBlossoming() { + blossoming = false; } public void start() { + successfulBlossomingTicks = 0; blossomingTicks = 0; - ticks = 0; - lastBlossomingTick = 0; - running = true; + lastSoundPlayedTick = 0; + blossoming = true; } public void stop() { - if (completed()) { - BlockPos blockPos = entity.getSavedFlowerPos(); + if (hasBlossomedLongEnough()) { + BlockPos blockPos = ((BeeInterface) entity).getSavedLeavesPos(); if (blockPos != null) { BlockState blockState = entity.getCommandSenderWorld().getBlockState(blockPos); if (blockState.getBlock() == Blocks.OAK_LEAVES) { entity.getCommandSenderWorld().levelEvent(2005, blockPos, 0); - entity.getCommandSenderWorld().setBlockAndUpdate(blockPos, Blossom.FLOWERING_OAK_LEAVES.defaultBlockState() - .setValue(FloweringLeavesBlock.DISTANCE, blockState.getValue(FloweringLeavesBlock.DISTANCE)) - .setValue(FloweringLeavesBlock.PERSISTENT, blockState.getValue(FloweringLeavesBlock.PERSISTENT)) + entity.getCommandSenderWorld().setBlockAndUpdate(blockPos, BlossomBlocks.FLOWERING_OAK_LEAVES.defaultBlockState() + .setValue(FloweringLeavesBlock.DISTANCE, blockState.getValue(LeavesBlock.DISTANCE)) + .setValue(FloweringLeavesBlock.PERSISTENT, blockState.getValue(LeavesBlock.PERSISTENT)) ); ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination(); } } } - running = false; + blossoming = false; ((MobAccessor) entity).getNavigation().stop(); } - public boolean requiresUpdateEveryTick() { - return true; - } - public boolean canUse() { - return canBeeStart() && !entity.isAngry() && checkFilters(); + return canBeeUse() && !entity.isAngry() && checkFilters(); } public boolean canContinueToUse() { - return canBeeContinue() && !entity.isAngry() && checkFilters(); + return canBeeContinueToUse() && !entity.isAngry() && checkFilters(); } public void tick() { - ++ticks; - if (ticks > 600) { - ((BeeAccessor) entity).setSavedFlowerPos(null); + ++blossomingTicks; + if (blossomingTicks > 600) { + ((BeeInterface) entity).setSavedLeavesPos(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(); + 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 (nextTarget == null) { - nextTarget = vec3; + if (hoverPos == null) { + hoverPos = vec3; } - boolean close = entity.position().distanceTo(nextTarget) <= 0.1D; + boolean close = entity.position().distanceTo(hoverPos) <= 0.1D; boolean chance = true; - if (!close && ticks > 600) { - ((BeeAccessor) entity).setSavedFlowerPos(null); + if (!close && blossomingTicks > 600) { + ((BeeInterface) entity).setSavedLeavesPos(null); } else { if (close) { if (((EntityAccessor) entity).getRandom().nextInt(25) == 0) { - nextTarget = new Vec3(vec3.x() + (double)getRandomOffset(), vec3.y(), vec3.z() + (double)getRandomOffset()); + hoverPos = new Vec3(vec3.x() + getRandomOffset(), vec3.y(), vec3.z() + getRandomOffset()); ((MobAccessor) entity).getNavigation().stop(); } else { chance = false; @@ -225,11 +206,11 @@ public void tick() { entity.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z()); } if (chance) { - moveToNextTarget(); + setWantedPos(); } - ++blossomingTicks; - if (((EntityAccessor) entity).getRandom().nextFloat() < 0.05F && blossomingTicks > lastBlossomingTick + 60) { - lastBlossomingTick = blossomingTicks; + ++successfulBlossomingTicks; + if (((EntityAccessor) entity).getRandom().nextFloat() < 0.05F && successfulBlossomingTicks > lastSoundPlayedTick + 60) { + lastSoundPlayedTick = successfulBlossomingTicks; entity.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F); } } @@ -238,31 +219,27 @@ public void tick() { } } - public boolean isTarget(BlockPos pos) { - return entity.getCommandSenderWorld().isLoaded(pos) && entity.getCommandSenderWorld().getBlockState(pos).is(Blocks.OAK_LEAVES); - } - - public void moveToNextTarget() { - entity.getMoveControl().setWantedPosition(nextTarget.x(), nextTarget.y(), nextTarget.z(), 0.3499999940395355D); + 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 findTarget() { - return findTarget(targetPredicate, Option.getBlossomingDistance()); + public Optional findNearbyLeaves() { + return findNearestBlock(validBlocks, 10.0D); } - public Optional findTarget(Predicate predicate, double searchDistance) { + public Optional findNearestBlock(Predicate predicate, double distance) { 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) { + 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, searchDistance) && predicate.test(entity.getCommandSenderWorld().getBlockState(mutableBlockPos))) { + if (blockPos.closerThan(mutableBlockPos, distance) && predicate.test(entity.getCommandSenderWorld().getBlockState(mutableBlockPos))) { return Optional.of(mutableBlockPos); } } 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 ee97049d..00000000 --- a/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitGoal.java +++ /dev/null @@ -1,89 +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.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.getCommandSenderWorld().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.getCommandSenderWorld().getBlockState(blockPos); - if (blockState.getBlock() == Blossom.FLOWERING_OAK_LEAVES) { - if (blockState.getValue(BlockStateProperties.AGE_3) >= 3) { - entity.getCommandSenderWorld().levelEvent(2005, blockPos, 0); - entity.getCommandSenderWorld().setBlockAndUpdate(blockPos, Blossom.FRUITING_OAK_LEAVES.defaultBlockState() - .setValue(FruitingLeavesBlock.DISTANCE, blockState.getValue(FruitingLeavesBlock.DISTANCE)) - .setValue(FruitingLeavesBlock.PERSISTENT, blockState.getValue(FruitingLeavesBlock.PERSISTENT)) - ); - ((BeeInvoker) entity).invokeIncrementNumCropsGrownSincePollination(); - } - } - } - } - running = false; - ((MobAccessor) entity).getNavigation().stop(); - } - - public boolean isTarget(BlockPos pos) { - return entity.getCommandSenderWorld().isLoaded(pos) && entity.getCommandSenderWorld().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..6c78146b --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/entity/ai/goal/FruitLeavesGoal.java @@ -0,0 +1,45 @@ +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.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.getCommandSenderWorld().getBlockState(blockPos); + if (blockState.getBlock() instanceof FloweringLeavesBlock) { + if (blockState.getValue(BlockStateProperties.AGE_3) >= 3) { + entity.getCommandSenderWorld().levelEvent(2005, blockPos, 0); + entity.getCommandSenderWorld().setBlockAndUpdate(blockPos, ((FloweringLeavesBlock) blockState.getBlock()).getPollinatedBlock().defaultBlockState() + .setValue(FruitingLeavesBlock.DISTANCE, blockState.getValue(FloweringLeavesBlock.DISTANCE)) + .setValue(FruitingLeavesBlock.PERSISTENT, blockState.getValue(FloweringLeavesBlock.PERSISTENT)) + ); + 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..9ee95e22 --- /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 > 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..4291935b --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/world/level/block/BlossomBlocks.java @@ -0,0 +1,37 @@ +package dev.yurisuika.blossom.world.level.block; + +import dev.yurisuika.blossom.mixin.world.level.block.BlocksInvoker; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.core.Registry; +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.Material; + +public class BlossomBlocks { + + public static final Block FRUITING_OAK_LEAVES = new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, FabricBlockSettings.of(Material.LEAVES) + .strength(0.2F) + .ticksRandomly() + .sounds(SoundType.GRASS) + .nonOpaque() + .allowsSpawning(BlocksInvoker::invokeOcelotOrParrot) + .suffocates(BlocksInvoker::invokeNever) + .blockVision(BlocksInvoker::invokeNever)); + public static final Block FLOWERING_OAK_LEAVES = new FloweringLeavesBlock(Blocks.OAK_LEAVES, FRUITING_OAK_LEAVES, FabricBlockSettings.of(Material.LEAVES) + .strength(0.2F) + .ticksRandomly() + .sounds(SoundType.GRASS) + .nonOpaque() + .allowsSpawning(BlocksInvoker::invokeOcelotOrParrot) + .suffocates(BlocksInvoker::invokeNever) + .blockVision(BlocksInvoker::invokeNever)); + + public static void register() { + Registry.register(Registry.BLOCK, ResourceLocation.tryParse("blossom:fruiting_oak_leaves"), FRUITING_OAK_LEAVES); + Registry.register(Registry.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 6e4bbbaf..786ffaa4 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 net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; @@ -53,6 +53,14 @@ public FloweringLeavesBlock(Block shearedBlock, Block pollinatedBlock, Propertie registerDefaultState(stateDefinition.any().setValue(DISTANCE, 1).setValue(PERSISTENT, 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(); } @@ -86,10 +94,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(); } @@ -119,19 +127,19 @@ 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)) ); } if (!isMaxAge(state) && state.getValue(RIPENESS) > 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, 0), 2); + level.setBlock(pos, state.setValue(RIPENESS, 0), 2); } } @@ -145,10 +153,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(RIPENESS, state.getValue(RIPENESS)), 2); + level.setBlock(pos, state.setValue(AGE, i), 2); } public int getGrowthAmount(Level level) { @@ -196,7 +201,7 @@ public static OptionalInt getOptionalDistanceFromLog(BlockState state) { public void animateTick(BlockState state, Level level, BlockPos pos, Random 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)) { @@ -205,7 +210,7 @@ public void animateTick(BlockState state, Level level, BlockPos pos, Random rand double d = pos.getX() + random.nextDouble(); double e = pos.getY() - 0.05D; double f = pos.getZ() + random.nextDouble(); - level.addParticle(Blossom.BLOSSOM, d, e, f, 0.0D, 0.0D, 0.0D); + level.addParticle(BlossomParticleTypes.FLOWERING_OAK_LEAVES, d, e, f, 0.0D, 0.0D, 0.0D); } public void createBlockStateDefinition(Builder builder) { @@ -233,20 +238,17 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player 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); - itemStack.hurtAndBreak(1, player, entity -> { - entity.broadcastBreakEvent(hand); - }); + itemStack.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); if (!level.isClientSide()) { player.awardStat(Stats.ITEM_USED.get(item)); } - level.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() + level.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() .setValue(DISTANCE, state.getValue(DISTANCE)) .setValue(PERSISTENT, state.getValue(PERSISTENT)) ); 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 885b40e4..f8daec14 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 @@ -56,6 +56,14 @@ public FruitingLeavesBlock(Block shearedBlock, Item shearedItem, Properties prop registerDefaultState(stateDefinition.any().setValue(DISTANCE, 1).setValue(PERSISTENT, 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(); } @@ -89,10 +97,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(); } @@ -113,29 +121,26 @@ 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(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)) ); } if (!isMaxAge(state) && state.getValue(RIPENESS) > 0) { - level.setBlock(pos, defaultBlockState().setValue(RIPENESS, 0), 2); + level.setBlock(pos, state.setValue(RIPENESS, 0), 2); } } @@ -149,10 +154,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(RIPENESS, state.getValue(RIPENESS)), 2); + level.setBlock(pos, state.setValue(AGE, i), 2); } public int getGrowthAmount(Level level) { @@ -224,7 +226,7 @@ public void performBonemeal(ServerLevel level, Random random, BlockPos pos, Bloc 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++; } @@ -234,26 +236,23 @@ 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.setBlockAndUpdate(pos, shearedBlock.defaultBlockState() - .setValue(DISTANCE, state.getValue(DISTANCE)) - .setValue(PERSISTENT, state.getValue(PERSISTENT)) - ); + 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.setBlockAndUpdate(pos, getShearedBlock().defaultBlockState() + .setValue(DISTANCE, state.getValue(DISTANCE)) + .setValue(PERSISTENT, state.getValue(PERSISTENT)) + ); 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..18a2fc85 --- /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.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +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().tab(CreativeModeTab.TAB_DECORATIONS)); + public static final Item FLOWERING_OAK_LEAVES = new BlockItem(BlossomBlocks.FLOWERING_OAK_LEAVES, new Item.Properties().tab(CreativeModeTab.TAB_DECORATIONS)); + + public static void register() { + Registry.register(Registry.ITEM, ResourceLocation.tryParse("blossom:fruiting_oak_leaves"), FRUITING_OAK_LEAVES); + Registry.register(Registry.ITEM, 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/EntityCollisionContextInterface.java b/src/main/java/dev/yurisuika/blossom/world/phys/shapes/EntityCollisionContextInterface.java similarity index 70% rename from src/main/java/dev/yurisuika/blossom/world/level/block/EntityCollisionContextInterface.java rename to src/main/java/dev/yurisuika/blossom/world/phys/shapes/EntityCollisionContextInterface.java index 177cd8d4..78ccec25 100644 --- a/src/main/java/dev/yurisuika/blossom/world/level/block/EntityCollisionContextInterface.java +++ b/src/main/java/dev/yurisuika/blossom/world/phys/shapes/EntityCollisionContextInterface.java @@ -1,5 +1,4 @@ -package dev.yurisuika.blossom.world.level.block; - +package dev.yurisuika.blossom.world.phys.shapes; import net.minecraft.world.entity.Entity; 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 85097140..028394b9 100644 --- a/src/main/resources/blossom.mixins.json +++ b/src/main/resources/blossom.mixins.json @@ -6,16 +6,18 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "world.entity.EntityAccessor", + "world.entity.EntityMixin", "world.entity.MobAccessor", - "world.entity.animal.BeeAccessor", "world.entity.animal.BeeInvoker", "world.entity.animal.BeeMixin", "world.entity.animal.BeeMixin$BeeGrowCropGoalMixin", - "world.entity.animal.BeeMixin$BeeGoToKnownFlowerGoalMixin", + "world.entity.animal.BeeMixin$BeeLookControlMixin", + "world.entity.animal.BeeMixin$BeePollinateGoalMixin", + "world.entity.animal.BeeMixin$FlyingPathNavigationMixin", "world.level.block.BlocksInvoker", - "world.level.block.EntityCollisionContextMixin", "world.level.block.LeavesBlockMixin", - "world.level.block.state.BlockBehaviourMixin" + "world.level.block.state.BlockBehaviourMixin", + "world.phys.shapes.EntityCollisionContextMixin" ], "client": [ ], 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 eaca9fac..702ee005 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 @@ -40,13 +40,7 @@ { "condition": "minecraft:match_tool", "predicate": { - "items": [ - "minecraft:shears" - ], - "enchantment": "minecraft:silk_touch", - "levels": { - "max": 0 - } + "item": "minecraft:shears" } } ], @@ -79,20 +73,17 @@ { "conditions": [ { - "condition": "minecraft:alternative", - "terms": [ - { - "condition": "minecraft:inverted", - "term": { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:alternative", + "terms": [ + { "condition": "minecraft:match_tool", "predicate": { "item": "minecraft:shears" } - } - }, - { - "condition": "minecraft:inverted", - "term": { + }, + { "condition": "minecraft:match_tool", "predicate": { "enchantments": [ @@ -105,8 +96,8 @@ ] } } - } - ] + ] + } } ], "entries": [ 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 62197ec2..4f422f68 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 @@ -40,13 +40,7 @@ { "condition": "minecraft:match_tool", "predicate": { - "items": [ - "minecraft:shears" - ], - "enchantment": "minecraft:silk_touch", - "levels": { - "max": 0 - } + "item": "minecraft:shears" } } ], @@ -79,20 +73,17 @@ { "conditions": [ { - "condition": "minecraft:alternative", - "terms": [ - { - "condition": "minecraft:inverted", - "term": { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:alternative", + "terms": [ + { "condition": "minecraft:match_tool", "predicate": { "item": "minecraft:shears" } - } - }, - { - "condition": "minecraft:inverted", - "term": { + }, + { "condition": "minecraft:match_tool", "predicate": { "enchantments": [ @@ -105,8 +96,8 @@ ] } } - } - ] + ] + } } ], "entries": [ 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