From 6f23736c92a36a573bf314ce418f3a2a6262466e Mon Sep 17 00:00:00 2001 From: yurisuika Date: Sun, 27 Aug 2023 22:45:34 -0700 Subject: [PATCH] 2.0.0 backport --- gradle.properties | 2 +- .../java/dev/yurisuika/blossom/Blossom.java | 137 +++++--- .../blossom/block/FloweringLeavesBlock.java | 168 ++++++---- .../blossom/block/FruitingLeavesBlock.java | 282 ++++++++++++++++ .../client/particle/BlossomParticle.java | 71 ++++ .../blossom/entity/ai/goal/BlossomGoal.java | 313 ++++++++++++++++++ .../blossom/entity/ai/goal/FruitGoal.java | 94 ++++++ .../mixin/block/AbstractBlockMixin.java | 31 ++ .../blossom/mixin/block/BlocksInvoker.java | 24 ++ .../blossom/mixin/block/LeavesBlockMixin.java | 2 +- .../blossom/mixin/entity/EntityAccessor.java | 14 + .../mixin/entity/MobEntityAccessor.java | 14 + .../mixin/entity/ai/goal/GoalInvoker.java | 13 + .../entity/passive/BeeEntityAccessor.java | 14 + .../entity/passive/BeeEntityInvoker.java | 8 + .../mixin/entity/passive/BeeEntityMixin.java | 120 ++----- .../server/command/BlossomCommand.java | 173 ++++++---- .../blockstates/flowering_oak_leaves.json | 67 ++-- .../blockstates/fruiting_oak_leaves.json | 44 +++ src/main/resources/assets/blossom/icon.png | Bin 0 -> 11515 bytes .../resources/assets/blossom/lang/en_us.json | 90 +++-- .../models/block/flowering_leaves.json | 109 ++++-- .../block/flowering_oak_leaves_stage0.json | 10 +- .../block/flowering_oak_leaves_stage1.json | 7 - .../block/flowering_oak_leaves_stage1a.json | 7 + .../block/flowering_oak_leaves_stage1b.json | 7 + .../block/flowering_oak_leaves_stage1c.json | 7 + .../block/flowering_oak_leaves_stage2.json | 7 - .../block/flowering_oak_leaves_stage2a.json | 7 + .../block/flowering_oak_leaves_stage2b.json | 7 + .../block/flowering_oak_leaves_stage2c.json | 7 + .../block/flowering_oak_leaves_stage2d.json | 7 + .../block/flowering_oak_leaves_stage2e.json | 7 + .../block/flowering_oak_leaves_stage2f.json | 7 + .../block/flowering_oak_leaves_stage3.json | 10 +- .../block/flowering_oak_leaves_stage4.json | 7 - .../block/flowering_oak_leaves_stage5.json | 7 - .../block/flowering_oak_leaves_stage6.json | 7 - .../block/flowering_oak_leaves_stage7.json | 7 - .../blossom/models/block/fruiting_leaves.json | 86 +++++ .../block/fruiting_oak_leaves_stage0.json | 7 + .../block/fruiting_oak_leaves_stage1.json | 7 + .../block/fruiting_oak_leaves_stage2.json | 7 + .../block/fruiting_oak_leaves_stage3.json | 7 + .../block/fruiting_oak_leaves_stage4.json | 7 + .../block/fruiting_oak_leaves_stage5.json | 7 + .../block/fruiting_oak_leaves_stage6.json | 7 + .../block/fruiting_oak_leaves_stage7.json | 7 + .../models/item/flowering_oak_leaves.json | 78 ++--- .../models/item/fruiting_oak_leaves.json | 53 +++ .../assets/blossom/particles/blossom.json | 16 + .../assets/blossom/shaders/block.properties | 4 +- .../block/flowering_oak_leaves_stage1.png | Bin 175 -> 0 bytes .../block/flowering_oak_leaves_stage1a.png | Bin 0 -> 175 bytes .../block/flowering_oak_leaves_stage1b.png | Bin 0 -> 154 bytes .../block/flowering_oak_leaves_stage1c.png | Bin 0 -> 171 bytes .../block/flowering_oak_leaves_stage2.png | Bin 226 -> 0 bytes .../block/flowering_oak_leaves_stage2a.png | Bin 0 -> 174 bytes .../block/flowering_oak_leaves_stage2b.png | Bin 0 -> 166 bytes .../block/flowering_oak_leaves_stage2c.png | Bin 0 -> 180 bytes .../block/flowering_oak_leaves_stage3.png | Bin 238 -> 175 bytes .../block/flowering_oak_leaves_stage4.png | Bin 244 -> 0 bytes .../block/flowering_oak_leaves_stage5.png | Bin 242 -> 0 bytes .../block/flowering_oak_leaves_stage6.png | Bin 335 -> 0 bytes .../block/flowering_oak_leaves_stage7.png | Bin 336 -> 0 bytes .../block/fruiting_oak_leaves_stage0.png | Bin 0 -> 162 bytes .../block/fruiting_oak_leaves_stage1.png | Bin 0 -> 157 bytes .../block/fruiting_oak_leaves_stage2.png | Bin 0 -> 231 bytes .../block/fruiting_oak_leaves_stage3.png | Bin 0 -> 217 bytes .../block/fruiting_oak_leaves_stage4.png | Bin 0 -> 227 bytes .../block/fruiting_oak_leaves_stage5.png | Bin 0 -> 227 bytes .../block/fruiting_oak_leaves_stage6.png | Bin 0 -> 339 bytes .../block/fruiting_oak_leaves_stage7.png | Bin 0 -> 333 bytes .../blossom/textures/particle/blossom_0.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_1.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_10.png | Bin 0 -> 173 bytes .../blossom/textures/particle/blossom_11.png | Bin 0 -> 173 bytes .../blossom/textures/particle/blossom_2.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_3.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_4.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_5.png | Bin 0 -> 175 bytes .../blossom/textures/particle/blossom_6.png | Bin 0 -> 173 bytes .../blossom/textures/particle/blossom_7.png | Bin 0 -> 173 bytes .../blossom/textures/particle/blossom_8.png | Bin 0 -> 173 bytes .../blossom/textures/particle/blossom_9.png | Bin 0 -> 173 bytes src/main/resources/blossom.mixins.json | 7 +- .../blocks/flowering_oak_leaves.json | 51 --- .../blocks/fruiting_oak_leaves.json | 203 ++++++++++++ .../minecraft/tags/blocks/bee_growables.json | 2 +- .../data/minecraft/tags/blocks/leaves.json | 3 +- .../data/minecraft/tags/items/leaves.json | 3 +- 91 files changed, 1971 insertions(+), 506 deletions(-) create mode 100644 src/main/java/dev/yurisuika/blossom/block/FruitingLeavesBlock.java create mode 100644 src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java create mode 100644 src/main/java/dev/yurisuika/blossom/entity/ai/goal/BlossomGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/entity/ai/goal/FruitGoal.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/block/AbstractBlockMixin.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/block/BlocksInvoker.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/entity/EntityAccessor.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/entity/MobEntityAccessor.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/entity/ai/goal/GoalInvoker.java create mode 100644 src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityAccessor.java create mode 100644 src/main/resources/assets/blossom/blockstates/fruiting_oak_leaves.json create mode 100644 src/main/resources/assets/blossom/icon.png delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1a.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1b.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1c.json delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2a.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2b.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2c.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2d.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2e.json create mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2f.json delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage4.json delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage5.json delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage6.json delete mode 100644 src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage7.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_leaves.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage0.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage1.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage2.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage3.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage4.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage5.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage6.json create mode 100644 src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage7.json create mode 100644 src/main/resources/assets/blossom/models/item/fruiting_oak_leaves.json create mode 100644 src/main/resources/assets/blossom/particles/blossom.json delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1a.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1b.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1c.png delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2a.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2b.png create mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2c.png delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage4.png delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage5.png delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage6.png delete mode 100644 src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage7.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage0.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage1.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage2.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage3.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage4.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage5.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage6.png create mode 100644 src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage7.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_0.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_1.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_10.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_11.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_2.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_3.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_4.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_5.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_6.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_7.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_8.png create mode 100644 src/main/resources/assets/blossom/textures/particle/blossom_9.png create mode 100644 src/main/resources/data/blossom/loot_tables/blocks/fruiting_oak_leaves.json diff --git a/gradle.properties b/gradle.properties index b8252f6..bd374b6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings = 1.19.2+build.28 mod_id = blossom mod_author = yurisuika -mod_version = 1.1.0 +mod_version = 2.0.0 maven_group = dev.yurisuika.blossom archives_base_name = blossom diff --git a/src/main/java/dev/yurisuika/blossom/Blossom.java b/src/main/java/dev/yurisuika/blossom/Blossom.java index c72bcfb..d473409 100644 --- a/src/main/java/dev/yurisuika/blossom/Blossom.java +++ b/src/main/java/dev/yurisuika/blossom/Blossom.java @@ -3,6 +3,11 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import dev.yurisuika.blossom.block.FloweringLeavesBlock; +import dev.yurisuika.blossom.block.FruitingLeavesBlock; +import dev.yurisuika.blossom.client.particle.BlossomParticle; +import dev.yurisuika.blossom.entity.ai.goal.BlossomGoal; +import dev.yurisuika.blossom.entity.ai.goal.FruitGoal; +import dev.yurisuika.blossom.mixin.block.BlocksInvoker; import dev.yurisuika.blossom.mixin.block.ComposterBlockInvoker; import dev.yurisuika.blossom.mixin.block.FireBlockInvoker; import dev.yurisuika.blossom.server.command.BlossomCommand; @@ -13,13 +18,20 @@ import net.minecraft.client.item.ModelPredicateProviderRegistry; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayers; +import net.minecraft.entity.Entity; +import net.minecraft.entity.passive.BeeEntity; import net.minecraft.item.*; import net.minecraft.nbt.NbtCompound; +import net.minecraft.particle.DefaultParticleType; +import net.minecraft.particle.ParticleType; +import net.minecraft.sound.BlockSoundGroup; import net.minecraft.util.Identifier; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RegisterColorHandlersEvent; +import net.minecraftforge.client.event.RegisterParticleProvidersEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.entity.EntityJoinLevelEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @@ -46,10 +58,9 @@ public class Blossom { public static class Config { public Value value = new Value( - new Value.Propagation(0.2F), - new Value.Fertilization(0.06666667F), - new Value.Pollination(1), - new Value.Fruit(3, 0.5714286F) + new Value.Blossoming(0.2F, 10.0D), + new Value.Fruiting(0.2F, 10.0D), + new Value.Harvesting(3, 0.5714286F) ); public Filter filter = new Filter( new Filter.Temperature(-2.0F, 2.0F), @@ -66,54 +77,46 @@ public static class Config { public static class Value { - public Propagation propagation; - public Fertilization fertilization; - public Pollination pollination; - public Fruit fruit; + public Blossoming blossoming; + public Fruiting fruiting; + public Harvesting harvesting; - public Value(Propagation propagation, Fertilization fertilization, Pollination pollination, Fruit fruit) { - this.propagation = propagation; - this.fertilization = fertilization; - this.pollination = pollination; - this.fruit = fruit; + public Value(Blossoming blossoming, Fruiting fruiting, Harvesting harvesting) { + this.blossoming = blossoming; + this.fruiting = fruiting; + this.harvesting = harvesting; } - public static class Propagation { + public static class Blossoming { public float chance; + public double distance; - public Propagation(float chance) { + public Blossoming(float chance, double distance) { this.chance = chance; + this.distance = distance; } } - public static class Fertilization { + public static class Fruiting { public float chance; + public double distance; - public Fertilization(float chance) { + public Fruiting(float chance, double distance) { this.chance = chance; + this.distance = distance; } } - public static class Pollination { - - public int age; - - public Pollination(int age) { - this.age = age; - } - - } - - public static class Fruit { + public static class Harvesting { public int bonus; public float chance; - public Fruit(int bonus, float chance) { + public Harvesting(int bonus, float chance) { this.bonus = bonus; this.chance = chance; } @@ -231,19 +234,20 @@ public static Config getConfig() { } public static void checkBounds() { - config.value.propagation.chance = Math.max(Math.min(config.value.propagation.chance, 1.0F), 0.0F); - config.value.fertilization.chance = Math.max(Math.min(config.value.fertilization.chance, 1.0F), 0.0F); - config.value.pollination.age = Math.max(Math.min(config.value.pollination.age, 7), 0); - config.value.fruit.bonus = Math.max(config.value.fruit.bonus, 0); - config.value.fruit.chance = Math.max(Math.min(config.value.fruit.chance, 1.0F), 0.0F); + config.value.blossoming.chance = Math.max(Math.min(config.value.blossoming.chance, 1.0F), 0.0F); + config.value.blossoming.distance = Math.max(config.value.blossoming.distance, 0.0D); + config.value.fruiting.chance = Math.max(Math.min(config.value.fruiting.chance, 1.0F), 0.0F); + config.value.fruiting.distance = Math.max(config.value.fruiting.distance, 0.0D); + config.value.harvesting.bonus = Math.max(config.value.harvesting.bonus, 0); + config.value.harvesting.chance = Math.max(Math.min(config.value.harvesting.chance, 1.0F), 0.0F); float temperatureMin = Math.max(Math.min(Math.min(config.filter.temperature.min, 2.0F), config.filter.temperature.max), -2.0F); float temperatureMax = Math.max(Math.max(Math.min(config.filter.temperature.max, 2.0F), config.filter.temperature.min), -2.0F); config.filter.temperature.min = temperatureMin; config.filter.temperature.max = temperatureMax; - float downfallMin = Math.max(Math.min(Math.min(config.filter.downfall.min, 2.0F), config.filter.downfall.max), -2.0F); - float downfallMax = Math.max(Math.max(Math.min(config.filter.downfall.max, 2.0F), config.filter.downfall.min), -2.0F); + float downfallMin = Math.max(Math.min(Math.min(config.filter.downfall.min, 1.0F), config.filter.downfall.max), 0.0F); + float downfallMax = Math.max(Math.max(Math.min(config.filter.downfall.max, 1.0F), config.filter.downfall.min), 0.0F); config.filter.downfall.min = downfallMin; config.filter.downfall.max = downfallMax; @@ -257,8 +261,26 @@ public static void checkBounds() { public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "blossom"); public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, "blossom"); - - public static final RegistryObject FLOWERING_OAK_LEAVES = register("flowering_oak_leaves", () -> new FloweringLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, AbstractBlock.Settings.copy(Blocks.OAK_LEAVES)), new Item.Settings()); + public static final DeferredRegister> PARTICLES = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, "blossom"); + + public static final RegistryObject FRUITING_OAK_LEAVES = register("fruiting_oak_leaves", () -> new FruitingLeavesBlock(Blocks.OAK_LEAVES, Items.APPLE, AbstractBlock.Settings.of(Material.LEAVES) + .strength(0.2f) + .ticksRandomly() + .sounds(BlockSoundGroup.GRASS) + .nonOpaque() + .allowsSpawning(BlocksInvoker::invokeCanSpawnOnLeaves) + .suffocates(BlocksInvoker::invokeNever) + .blockVision(BlocksInvoker::invokeNever)), new Item.Settings()); + public static final RegistryObject FLOWERING_OAK_LEAVES = register("flowering_oak_leaves", () -> new FloweringLeavesBlock(Blocks.OAK_LEAVES, Blossom.FRUITING_OAK_LEAVES.get(), AbstractBlock.Settings.of(Material.LEAVES) + .strength(0.2f) + .ticksRandomly() + .sounds(BlockSoundGroup.GRASS) + .nonOpaque() + .allowsSpawning(BlocksInvoker::invokeCanSpawnOnLeaves) + .suffocates(BlocksInvoker::invokeNever) + .blockVision(BlocksInvoker::invokeNever)), new Item.Settings()); + + public static RegistryObject BLOSSOM = PARTICLES.register("blossom", () -> new DefaultParticleType(false)); public static RegistryObject register(String name, Supplier supplier, Item.Settings settings) { RegistryObject block = BLOCKS.register(name, supplier); @@ -270,10 +292,19 @@ public static RegistryObject register(String name, Supplier public static class CommonForgeEvents { @SubscribeEvent - public static void registerCommands(RegisterCommandsEvent event) { + public static void registerCommandsEvents(RegisterCommandsEvent event) { BlossomCommand.register(event.getDispatcher(), event.getBuildContext(), event.getCommandSelection()); } + @SubscribeEvent + public static void entityJoinLevelEvents(EntityJoinLevelEvent event) { + Entity entity = event.getEntity(); + if (entity instanceof BeeEntity) { + ((BeeEntity)entity).getGoalSelector().add(4, new BlossomGoal((BeeEntity)entity)); + ((BeeEntity)entity).getGoalSelector().add(4, new FruitGoal((BeeEntity)entity)); + } + } + } @Mod.EventBusSubscriber(modid = "blossom", bus = Mod.EventBusSubscriber.Bus.MOD) @@ -282,8 +313,15 @@ public static class CommonModBusEvents { @SubscribeEvent public static void commonSetup(FMLCommonSetupEvent event) { ComposterBlockInvoker.invokeRegisterComposableItem(0.3F, Blossom.FLOWERING_OAK_LEAVES.get()); + ComposterBlockInvoker.invokeRegisterComposableItem(0.3F, Blossom.FRUITING_OAK_LEAVES.get()); ((FireBlockInvoker)Blocks.FIRE).invokeRegisterFlammableBlock(Blossom.FLOWERING_OAK_LEAVES.get(), 30, 60); + ((FireBlockInvoker) Blocks.FIRE).invokeRegisterFlammableBlock(Blossom.FRUITING_OAK_LEAVES.get(), 30, 60); + } + + @SubscribeEvent + public static void registerParticleProvidersEvents(RegisterParticleProvidersEvent event) { + MinecraftClient.getInstance().particleManager.registerFactory(BLOSSOM.get(), BlossomParticle.Factory::new); } } @@ -295,8 +333,18 @@ public static class ClientModBusEvents { @SubscribeEvent public static void clientSetup(FMLClientSetupEvent event) { RenderLayers.setRenderLayer(Blossom.FLOWERING_OAK_LEAVES.get(), RenderLayer.getCutout()); + RenderLayers.setRenderLayer(Blossom.FRUITING_OAK_LEAVES.get(), RenderLayer.getCutout()); ModelPredicateProviderRegistry.register(FLOWERING_OAK_LEAVES.get().asItem(), new Identifier("age"), (stack, world, entity, seed) -> { + NbtCompound nbtCompound = stack.getSubNbt("BlockStateTag"); + try { + if (nbtCompound != null && nbtCompound.get(FloweringLeavesBlock.AGE.getName()) != null) { + return (float)Integer.parseInt(nbtCompound.get(FloweringLeavesBlock.AGE.getName()).asString()) / 4.0F; + } + } catch (NumberFormatException ignored) {} + return 0.0F; + }); + ModelPredicateProviderRegistry.register(FRUITING_OAK_LEAVES.get().asItem(), new Identifier("age"), (stack, world, entity, seed) -> { NbtCompound nbtCompound = stack.getSubNbt("BlockStateTag"); try { if (nbtCompound != null && nbtCompound.get(FloweringLeavesBlock.AGE.getName()) != null) { @@ -308,13 +356,15 @@ public static void clientSetup(FMLClientSetupEvent event) { } @SubscribeEvent - public static void registerBlockColorProviders(final RegisterColorHandlersEvent.Block color) { - color.getBlockColors().registerColorProvider((state, world, pos, tintIndex) -> world != null && pos != null ? BiomeColors.getFoliageColor(world, pos) : FoliageColors.getColor(0.5, 1.0), Blossom.FLOWERING_OAK_LEAVES.get()); + public static void registerBlockColorHandlersEvents(RegisterColorHandlersEvent.Block event) { + event.getBlockColors().registerColorProvider((state, world, pos, tintIndex) -> world != null && pos != null ? BiomeColors.getFoliageColor(world, pos) : FoliageColors.getColor(0.5, 1.0), Blossom.FLOWERING_OAK_LEAVES.get()); + event.getBlockColors().registerColorProvider((state, world, pos, tintIndex) -> world != null && pos != null ? BiomeColors.getFoliageColor(world, pos) : FoliageColors.getColor(0.5, 1.0), Blossom.FRUITING_OAK_LEAVES.get()); } @SubscribeEvent - public static void registerItemColorProviders(final RegisterColorHandlersEvent.Item color) { - color.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : MinecraftClient.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().getDefaultState(), null, null, tintIndex), FLOWERING_OAK_LEAVES.get()); + public static void registerItemColorHandlersEvents(RegisterColorHandlersEvent.Item event) { + event.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : MinecraftClient.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().getDefaultState(), null, null, tintIndex), FLOWERING_OAK_LEAVES.get()); + event.getItemColors().register((stack, tintIndex) -> tintIndex > 0 ? -1 : MinecraftClient.getInstance().getBlockColors().getColor(((BlockItem) stack.getItem()).getBlock().getDefaultState(), null, null, tintIndex), FRUITING_OAK_LEAVES.get()); } } @@ -329,6 +379,7 @@ public Blossom() { BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus()); ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); + PARTICLES.register(FMLJavaModLoadingContext.get().getModEventBus()); } } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/block/FloweringLeavesBlock.java b/src/main/java/dev/yurisuika/blossom/block/FloweringLeavesBlock.java index ee91142..94956d7 100644 --- a/src/main/java/dev/yurisuika/blossom/block/FloweringLeavesBlock.java +++ b/src/main/java/dev/yurisuika/blossom/block/FloweringLeavesBlock.java @@ -1,14 +1,16 @@ package dev.yurisuika.blossom.block; -import dev.yurisuika.blossom.mixin.world.biome.BiomeAccessor; -import net.minecraft.block.*; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.enchantment.Enchantments; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Fertilizable; +import net.minecraft.block.LeavesBlock; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.FluidState; import net.minecraft.fluid.Fluids; -import net.minecraft.item.*; -import net.minecraft.particle.ParticleTypes; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ShearsItem; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; @@ -22,8 +24,8 @@ import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.random.Random; import net.minecraft.util.shape.VoxelShape; @@ -35,25 +37,25 @@ import net.minecraft.world.event.GameEvent; import java.util.OptionalInt; -import java.util.concurrent.ThreadLocalRandom; import static dev.yurisuika.blossom.Blossom.*; -public class FloweringLeavesBlock extends Block implements Fertilizable { +public class FloweringLeavesBlock extends LeavesBlock implements Fertilizable { public final Block shearedBlock; - public final Item shearedItem; + public final Block pollinatedBlock; public static final IntProperty DISTANCE = Properties.DISTANCE_1_7; public static final BooleanProperty PERSISTENT = Properties.PERSISTENT; public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; - public static final IntProperty AGE = Properties.AGE_7; + public static final IntProperty AGE = Properties.AGE_3; + public static final IntProperty RIPENESS = IntProperty.of("ripeness", 0, 7); - public FloweringLeavesBlock(Block shearedBlock, Item shearedItem, Settings settings) { + public FloweringLeavesBlock(Block shearedBlock, Block pollinatedBlock, Settings settings) { super(settings); this.shearedBlock = shearedBlock; - this.shearedItem = shearedItem; - this.setDefaultState(this.stateManager.getDefaultState().with(DISTANCE, 1).with(PERSISTENT, false).with(WATERLOGGED, false).with(AGE, 0)); + this.pollinatedBlock = pollinatedBlock; + setDefaultState(stateManager.getDefaultState().with(DISTANCE, 1).with(PERSISTENT, false).with(WATERLOGGED, false).with(AGE, 0).with(RIPENESS, 0)); } public VoxelShape getSidesShape(BlockState state, BlockView world, BlockPos pos) { @@ -61,7 +63,7 @@ public VoxelShape getSidesShape(BlockState state, BlockView world, BlockPos pos) } public boolean hasRandomTicks(BlockState state) { - return state.get(DISTANCE) == 7 || !this.isMature(state) || state.get(WATERLOGGED); + return true; } public IntProperty getAgeProperty() { @@ -69,19 +71,31 @@ public IntProperty getAgeProperty() { } public int getMaxAge() { - return 7; + return 3; } public int getAge(BlockState state) { - return state.get(this.getAgeProperty()); + return state.get(getAgeProperty()); } - public BlockState withAge(BlockState state, int age) { - return state.with(this.getAgeProperty(), age); + public boolean isMature(BlockState state) { + return state.get(getAgeProperty()) >= getMaxAge(); } - public boolean isMature(BlockState state) { - return state.get(this.getAgeProperty()) >= this.getMaxAge(); + public IntProperty getRipenessProperty() { + return RIPENESS; + } + + public int getMaxRipeness() { + return 7; + } + + public int getRipeness(BlockState state) { + return state.get(getRipenessProperty()); + } + + public boolean isRipe(BlockState state) { + return state.get(getRipenessProperty()) >= getMaxRipeness(); } public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { @@ -94,11 +108,11 @@ public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random .with(PERSISTENT, state.get(PERSISTENT)) .with(WATERLOGGED, state.get(WATERLOGGED)) ); - } else if (!this.isMature(state) && world.getBaseLightLevel(pos, 0) >= 9) { - int i = this.getAge(state); - if (i < this.getMaxAge()) { + } else if (!isMature(state) && world.getBaseLightLevel(pos, 0) >= 9) { + int i = getAge(state); + if (i < getMaxAge()) { float temperature = world.getBiome(pos).value().getTemperature(); - float downfall = ((BiomeAccessor)(Object)world.getBiome(pos).value()).getWeather().downfall(); + float downfall = world.getBiome(pos).value().getDownfall(); temperature += 2; float f = (downfall * temperature) / 4; f = ((4 - 1) * f) + 1; @@ -107,10 +121,31 @@ public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random f = 5.0F; } if (random.nextInt((int)(25.0F / f) + 1) == 0) { - world.setBlockState(pos, state.with(AGE, i + 1), 2); + world.setBlockState(pos, getDefaultState().with(AGE, i + 1) + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + .with(RIPENESS, state.get(RIPENESS)), 2); + } + } + } else if (isMature(state)) { + int i = getRipeness(state); + if (i < getMaxRipeness()) { + if (random.nextInt((int)(25.0F) + 1) == 0) { + world.setBlockState(pos, getDefaultState().with(RIPENESS, i + 1), 2); } } } + if (isRipe(state)) { + world.setBlockState(pos, shearedBlock.getDefaultState() + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + ); + } + if (!isMature(state) && state.get(RIPENESS) > 0) { + world.setBlockState(pos, getDefaultState().with(RIPENESS, 0), 2); + } } public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { @@ -118,12 +153,16 @@ public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Ran } public void applyGrowth(World world, BlockPos pos, BlockState state) { - int i = this.getAge(state) + this.getGrowthAmount(world); - int j = this.getMaxAge(); + int i = getAge(state) + getGrowthAmount(world); + int j = getMaxAge(); if (i > j) { i = j; } - world.setBlockState(pos, state.with(AGE, i), 2); + world.setBlockState(pos, getDefaultState().with(AGE, i) + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + .with(RIPENESS, state.get(RIPENESS)), 2); } public int getGrowthAmount(World world) { @@ -177,31 +216,29 @@ public FluidState getFluidState(BlockState state) { } public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) { - if (world.hasRain(pos.up())) { - if (random.nextInt(15) == 1) { - BlockPos blockPos = pos.down(); - BlockState blockState = world.getBlockState(blockPos); - if (!blockState.isOpaque() || !blockState.isSideSolidFullSquare(world, blockPos, Direction.UP)) { - double d = (double)pos.getX() + random.nextDouble(); - double e = (double)pos.getY() - 0.05D; - double f = (double)pos.getZ() + random.nextDouble(); - world.addParticle(ParticleTypes.DRIPPING_WATER, d, e, f, 0.0D, 0.0D, 0.0D); - } - } + super.randomDisplayTick(state, world, pos, random); + if (random.nextInt(10) != 0) { + return; + } + if (FloweringLeavesBlock.isFaceFullSquare(world.getBlockState(pos.down()).getCollisionShape(world, pos.down()), Direction.UP)) { + return; } + double d = (double)pos.getX() + random.nextDouble(); + double e = (double)pos.getY() - 0.05; + double f = (double)pos.getZ() + random.nextDouble(); + world.addParticle(BLOSSOM.get(), d, e, f, 0.0, 0.0, 0.0); } public void appendProperties(Builder builder) { - builder.add(DISTANCE, PERSISTENT, WATERLOGGED, AGE); + builder.add(DISTANCE, PERSISTENT, WATERLOGGED, AGE, RIPENESS); } public BlockState getPlacementState(ItemPlacementContext ctx) { - return updateDistanceFromLogs(this.getDefaultState().with(PERSISTENT, true).with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER).with(AGE, 0), ctx.getWorld(), ctx.getBlockPos()); + return updateDistanceFromLogs(getDefaultState().with(PERSISTENT, true).with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER).with(AGE, 0).with(RIPENESS, 0), ctx.getWorld(), ctx.getBlockPos()); } - @Override public boolean isFertilizable(BlockView world, BlockPos pos, BlockState state, boolean isClient) { - return !this.isMature(state); + return !isMature(state); } public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) { @@ -209,39 +246,26 @@ public boolean canGrow(World world, Random random, BlockPos pos, BlockState stat } public void grow(ServerWorld world, Random random, BlockPos pos, BlockState state) { - this.applyGrowth(world, pos, state); - } - - public static void dropFruit(World world, BlockPos pos, Item item, int bonus) { - int count = 1; - for(int i = 0; i < config.value.fruit.bonus + bonus; i++) { - if (ThreadLocalRandom.current().nextFloat() <= config.value.fruit.chance) { - count++; - } - } - dropStack(world, pos, new ItemStack(item, count)); + applyGrowth(world, pos, state); } public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack itemStack = player.getStackInHand(hand); - if (state.get(AGE) == 7) { - Item item = itemStack.getItem(); - if (item instanceof ShearsItem) { - world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_CROP_BREAK, SoundCategory.NEUTRAL, 1.0F, 1.0F); - dropFruit(world, pos, this.shearedItem, (itemStack.hasEnchantments() && EnchantmentHelper.get(itemStack).containsKey(Enchantments.FORTUNE)) ? EnchantmentHelper.getLevel(Enchantments.FORTUNE, itemStack) : 0); - itemStack.damage(1, player, (entity) -> { - entity.sendToolBreakStatus(hand); - }); - if (!world.isClient()) { - player.incrementStat(Stats.USED.getOrCreateStat(item)); - } - world.emitGameEvent(player, GameEvent.SHEAR, pos); - world.setBlockState(pos, this.shearedBlock.getDefaultState() - .with(DISTANCE, state.get(DISTANCE)) - .with(PERSISTENT, state.get(PERSISTENT)) - .with(WATERLOGGED, state.get(WATERLOGGED)) - ); + Item item = itemStack.getItem(); + if (item instanceof ShearsItem) { + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_CROP_BREAK, SoundCategory.NEUTRAL, 1.0F, 1.0F); + itemStack.damage(1, player, (entity) -> { + entity.sendToolBreakStatus(hand); + }); + if (!world.isClient()) { + player.incrementStat(Stats.USED.getOrCreateStat(item)); } + world.emitGameEvent(player, GameEvent.SHEAR, pos); + world.setBlockState(pos, shearedBlock.getDefaultState() + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + ); return ActionResult.SUCCESS; } else { return ActionResult.PASS; diff --git a/src/main/java/dev/yurisuika/blossom/block/FruitingLeavesBlock.java b/src/main/java/dev/yurisuika/blossom/block/FruitingLeavesBlock.java new file mode 100644 index 0000000..daa9a3c --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/block/FruitingLeavesBlock.java @@ -0,0 +1,282 @@ +package dev.yurisuika.blossom.block; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Fertilizable; +import net.minecraft.block.LeavesBlock; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ShearsItem; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.stat.Stats; +import net.minecraft.state.StateManager.Builder; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.IntProperty; +import net.minecraft.state.property.Properties; +import net.minecraft.tag.BlockTags; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.event.GameEvent; + +import java.util.OptionalInt; +import java.util.concurrent.ThreadLocalRandom; + +import static dev.yurisuika.blossom.Blossom.*; + +public class FruitingLeavesBlock extends LeavesBlock implements Fertilizable { + + public final Block shearedBlock; + public final Item shearedItem; + + public static final IntProperty DISTANCE = Properties.DISTANCE_1_7; + public static final BooleanProperty PERSISTENT = Properties.PERSISTENT; + public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; + public static final IntProperty AGE = Properties.AGE_7; + public static final IntProperty RIPENESS = IntProperty.of("ripeness", 0, 7); + + public FruitingLeavesBlock(Block shearedBlock, Item shearedItem, Settings settings) { + super(settings); + this.shearedBlock = shearedBlock; + this.shearedItem = shearedItem; + setDefaultState(stateManager.getDefaultState().with(DISTANCE, 1).with(PERSISTENT, false).with(WATERLOGGED, false).with(AGE, 0).with(RIPENESS, 0)); + } + + public VoxelShape getSidesShape(BlockState state, BlockView world, BlockPos pos) { + return VoxelShapes.empty(); + } + + public boolean hasRandomTicks(BlockState state) { + return true; + } + + public IntProperty getAgeProperty() { + return AGE; + } + + public int getMaxAge() { + return 7; + } + + public int getAge(BlockState state) { + return state.get(getAgeProperty()); + } + + public boolean isMature(BlockState state) { + return state.get(getAgeProperty()) >= getMaxAge(); + } + + public IntProperty getRipenessProperty() { + return RIPENESS; + } + + public int getMaxRipeness() { + return 7; + } + + public int getRipeness(BlockState state) { + return state.get(getRipenessProperty()); + } + + public boolean isRipe(BlockState state) { + return state.get(getRipenessProperty()) >= getMaxRipeness(); + } + + public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + if (!(Boolean)state.get(PERSISTENT) && state.get(DISTANCE) == 7) { + dropStacks(state, world, pos); + world.removeBlock(pos, false); + } else if (state.get(WATERLOGGED)) { + world.setBlockState(pos, shearedBlock.getDefaultState() + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + ); + } else if (!isMature(state) && world.getBaseLightLevel(pos, 0) >= 9) { + int i = getAge(state); + if (i < getMaxAge()) { + float temperature = world.getBiome(pos).value().getTemperature(); + float downfall = world.getBiome(pos).value().getDownfall(); + temperature += 2; + float f = (downfall * temperature) / 4; + f = ((4 - 1) * f) + 1; + Biome.Precipitation precipitation = world.getBiome(pos).value().getPrecipitation(); + if (world.isRaining() && precipitation == Biome.Precipitation.RAIN) { + f = 5.0F; + } + if (random.nextInt((int)(25.0F / f) + 1) == 0) { + world.setBlockState(pos, getDefaultState().with(AGE, i + 1) + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + .with(RIPENESS, state.get(RIPENESS)), 2); + } + } + } else if (isMature(state)) { + int i = getRipeness(state); + if (i < getMaxRipeness()) { + if (random.nextInt((int)(25.0F) + 1) == 0) { + world.setBlockState(pos, getDefaultState().with(RIPENESS, i + 1), 2); + } + } + } + if (isRipe(state)) { + dropFruit(world, pos, shearedItem, 0); + world.setBlockState(pos, shearedBlock.getDefaultState() + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + ); + } + if (!isMature(state) && state.get(RIPENESS) > 0) { + world.setBlockState(pos, getDefaultState().with(RIPENESS, 0), 2); + } + } + + public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + world.setBlockState(pos, updateDistanceFromLogs(state, world, pos), 3); + } + + public void applyGrowth(World world, BlockPos pos, BlockState state) { + int i = getAge(state) + getGrowthAmount(world); + int j = getMaxAge(); + if (i > j) { + i = j; + } + world.setBlockState(pos, getDefaultState().with(AGE, i) + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + .with(RIPENESS, state.get(RIPENESS)), 2); + } + + public int getGrowthAmount(World world) { + return MathHelper.nextInt(world.random, 2, 5); + } + + public int getOpacity(BlockState state, BlockView world, BlockPos pos) { + return 1; + } + + public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + if (state.get(WATERLOGGED)) { + world.createAndScheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + int i = getDistanceFromLog(neighborState) + 1; + if (i != 1 || state.get(DISTANCE) != i) { + world.createAndScheduleBlockTick(pos, this, 1); + } + return state; + } + + public static BlockState updateDistanceFromLogs(BlockState state, WorldAccess world, BlockPos pos) { + int i = 7; + Mutable mutable = new Mutable(); + for (Direction direction : Direction.values()) { + mutable.set(pos, direction); + i = Math.min(i, getDistanceFromLog(world.getBlockState(mutable)) + 1); + if (i == 1) { + break; + } + } + return state.with(DISTANCE, i); + } + + public static int getDistanceFromLog(BlockState state) { + return getOptionalDistanceFromLog(state).orElse(7); + } + + public static OptionalInt getOptionalDistanceFromLog(BlockState state) { + if (state.isIn(BlockTags.LOGS)) { + return OptionalInt.of(0); + } + if (state.contains(DISTANCE)) { + return OptionalInt.of(state.get(DISTANCE)); + } + return OptionalInt.empty(); + } + + public FluidState getFluidState(BlockState state) { + return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state); + } + + public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) { + super.randomDisplayTick(state, world, pos, random); + } + + public void appendProperties(Builder builder) { + builder.add(DISTANCE, PERSISTENT, WATERLOGGED, AGE, RIPENESS); + } + + public BlockState getPlacementState(ItemPlacementContext ctx) { + return updateDistanceFromLogs(getDefaultState().with(PERSISTENT, true).with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER).with(AGE, 0).with(RIPENESS, 0), ctx.getWorld(), ctx.getBlockPos()); + } + + public boolean isFertilizable(BlockView world, BlockPos pos, BlockState state, boolean isClient) { + return !isMature(state); + } + + public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) { + return true; + } + + public void grow(ServerWorld world, Random random, BlockPos pos, BlockState state) { + applyGrowth(world, pos, state); + } + + public static void dropFruit(World world, BlockPos pos, Item item, int bonus) { + int count = 1; + for(int i = 0; i < config.value.harvesting.bonus + bonus; i++) { + if (ThreadLocalRandom.current().nextFloat() <= config.value.harvesting.chance) { + count++; + } + } + dropStack(world, pos, new ItemStack(item, count)); + } + + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + ItemStack itemStack = player.getStackInHand(hand); + if (isMature(state)) { + Item item = itemStack.getItem(); + if (item instanceof ShearsItem) { + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_CROP_BREAK, SoundCategory.NEUTRAL, 1.0F, 1.0F); + dropFruit(world, pos, shearedItem, (itemStack.hasEnchantments() && EnchantmentHelper.get(itemStack).containsKey(Enchantments.FORTUNE)) ? EnchantmentHelper.getLevel(Enchantments.FORTUNE, itemStack) : 0); + itemStack.damage(1, player, (entity) -> { + entity.sendToolBreakStatus(hand); + }); + if (!world.isClient()) { + player.incrementStat(Stats.USED.getOrCreateStat(item)); + } + world.emitGameEvent(player, GameEvent.SHEAR, pos); + world.setBlockState(pos, shearedBlock.getDefaultState() + .with(DISTANCE, state.get(DISTANCE)) + .with(PERSISTENT, state.get(PERSISTENT)) + .with(WATERLOGGED, state.get(WATERLOGGED)) + ); + } + return ActionResult.SUCCESS; + } else { + return ActionResult.PASS; + } + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java b/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java new file mode 100644 index 0000000..c7a68c5 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/client/particle/BlossomParticle.java @@ -0,0 +1,71 @@ +package dev.yurisuika.blossom.client.particle; + +import net.minecraft.client.particle.*; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.DefaultParticleType; + +public class BlossomParticle extends SpriteBillboardParticle { + + public float wind; + public final float drift; + public final float gust; + + public BlossomParticle(ClientWorld world, double x, double y, double z, SpriteProvider spriteProvider) { + super(world, x, y, z); + float f; + this.setSprite(spriteProvider.getSprite(random.nextInt(12), 12)); + this.wind = (float)Math.toRadians(random.nextBoolean() ? -30.0F : 30.0F); + this.drift = random.nextFloat(); + this.gust = (float)Math.toRadians(random.nextBoolean() ? -5.0F : 5.0F); + this.maxAge = 300; + this.gravityStrength = 7.5E-4F; + this.scale = f = random.nextBoolean() ? 0.05F : 0.075F; + this.setBoundingBoxSpacing(f, f); + this.velocityMultiplier = 1.0F; + } + + public ParticleTextureSheet getType() { + return ParticleTextureSheet.PARTICLE_SHEET_OPAQUE; + } + + public record Factory(SpriteProvider spriteProvider) implements ParticleFactory { + + public Particle createParticle(DefaultParticleType parameters, ClientWorld world, double x, double y, double z, double r, double g, double b) { + return new BlossomParticle(world, x, y, z, spriteProvider); + } + + } + + public void tick() { + prevPosX = x; + prevPosY = y; + prevPosZ = z; + if (maxAge-- <= 0) { + markDead(); + } + if (dead) { + return; + } + float f = 300 - maxAge; + float g = Math.min(f / 300.0F, 1.0F); + double d = Math.cos(Math.toRadians(drift * 60.0F)) * 2.0D * Math.pow(g, 1.25D); + double e = Math.sin(Math.toRadians(drift * 60.0F)) * 2.0D * Math.pow(g, 1.25D); + velocityX += d * (double)0.0025F; + velocityZ += e * (double)0.0025F; + velocityY -= gravityStrength; + wind += gust / 20.0F; + prevAngle = angle; + angle += wind / 20.0F; + move(velocityX, velocityY, velocityZ); + if (onGround || maxAge < 299 && (velocityX == 0.0D || velocityZ == 0.0D)) { + markDead(); + } + if (dead) { + return; + } + velocityX *= velocityMultiplier; + velocityY *= velocityMultiplier; + velocityZ *= velocityMultiplier; + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/entity/ai/goal/BlossomGoal.java b/src/main/java/dev/yurisuika/blossom/entity/ai/goal/BlossomGoal.java new file mode 100644 index 0000000..3f24899 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/entity/ai/goal/BlossomGoal.java @@ -0,0 +1,313 @@ +package dev.yurisuika.blossom.entity.ai.goal; + +import dev.yurisuika.blossom.mixin.entity.EntityAccessor; +import dev.yurisuika.blossom.mixin.entity.MobEntityAccessor; +import dev.yurisuika.blossom.mixin.entity.passive.BeeEntityAccessor; +import dev.yurisuika.blossom.mixin.entity.passive.BeeEntityInvoker; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.entity.passive.BeeEntity; +import net.minecraft.sound.SoundEvents; +import net.minecraft.state.property.Properties; +import net.minecraft.tag.TagKey; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; + +import static dev.yurisuika.blossom.Blossom.*; +import static net.minecraft.block.LeavesBlock.*; + +public class BlossomGoal extends Goal { + + public final BeeEntity entity; + public final Predicate targetPredicate = (state) -> { + if (state.contains(Properties.WATERLOGGED) && state.get(Properties.WATERLOGGED)) { + return false; + } else { + return state.isOf(Blocks.OAK_LEAVES); + } + }; + public int blossomingTicks; + public int lastBlossomingTick; + public boolean running; + public Vec3d nextTarget; + public int ticks; + + public BlossomGoal(BeeEntity beeEntity) { + super(); + this.entity = beeEntity; + this.setControls(EnumSet.of(Control.MOVE)); + } + + public boolean checkFilters() { + RegistryEntry dimension = entity.getWorld().getDimensionEntry(); + RegistryEntry biome = entity.getWorld().getBiome(entity.getBlockPos()); + float temperature = biome.value().getTemperature(); + float downfall = biome.value().getDownfall(); + + AtomicBoolean whitelist = new AtomicBoolean(false); + if (config.toggle.whitelist) { + Arrays.stream(config.filter.dimension.whitelist).forEach(entry -> { + if (entry.startsWith("#")) { + TagKey tag = TagKey.of(Registry.DIMENSION_TYPE_KEY, new Identifier(entry.substring(1))); + if (tag != null) { + if (dimension.isIn(tag)) { + whitelist.set(true); + } + } + } else if (Objects.equals(entry, dimension.getKey().get().getValue().toString())) { + whitelist.set(true); + } + }); + Arrays.stream(config.filter.biome.whitelist).forEach(entry -> { + if (entry.startsWith("#")) { + TagKey tag = TagKey.of(Registry.BIOME_KEY, new Identifier(entry.substring(1))); + if (tag != null) { + if (biome.isIn(tag)) { + whitelist.set(true); + } + } + } else if (Objects.equals(entry, biome.getKey().get().getValue().toString())) { + whitelist.set(true); + } + }); + } + + AtomicBoolean blacklist = new AtomicBoolean(true); + if (config.toggle.blacklist) { + Arrays.stream(config.filter.dimension.blacklist).forEach(entry -> { + if (entry.startsWith("#")) { + TagKey tag = TagKey.of(Registry.DIMENSION_TYPE_KEY, new Identifier(entry.substring(1))); + if (tag != null) { + if (dimension.isIn(tag)) { + blacklist.set(false); + } + } + } else if (Objects.equals(entry, dimension.getKey().get().getValue().toString())) { + blacklist.set(false); + } + }); + Arrays.stream(config.filter.biome.blacklist).forEach(entry -> { + if (entry.startsWith("#")) { + TagKey tag = TagKey.of(Registry.BIOME_KEY, new Identifier(entry.substring(1))); + if (tag != null) { + if (biome.isIn(tag)) { + blacklist.set(false); + } + } + } else if (Objects.equals(entry, biome.getKey().get().getValue().toString())) { + blacklist.set(false); + } + }); + } + + if (temperature >= config.filter.temperature.min && temperature <= config.filter.temperature.max) { + if (downfall >= config.filter.downfall.min && downfall <= config.filter.downfall.max) { + if (!config.toggle.whitelist && !config.toggle.blacklist) { + return true; + } + if (config.toggle.whitelist && config.toggle.blacklist) { + return whitelist.get() && blacklist.get(); + } else if (config.toggle.whitelist) { + return whitelist.get(); + } else if (config.toggle.blacklist) { + return blacklist.get(); + } + } + } + return false; + } + + public boolean canBeeStart() { + if (((BeeEntityInvoker)entity).invokeGetCropsGrownSincePollination() >= 10) { + return false; + } + if (((EntityAccessor)entity).getRandom().nextFloat() > config.value.blossoming.chance) { + return false; + } + if (entity.getWorld().isRaining()) { + return false; + } + Optional optional = findTarget(); + if (optional.isPresent()) { + if (entity.hasNectar()) { + if (((BeeEntityInvoker)entity).invokeIsHiveValid()) { + ((BeeEntityAccessor)entity).setFlowerPos(optional.get()); + ((MobEntityAccessor)entity).getNavigation().startMovingTo((double)entity.getFlowerPos().getX() + 0.5, (double)entity.getFlowerPos().getY() + 0.5, (double)entity.getFlowerPos().getZ() + 0.5, 1.2000000476837158); + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; + } + + public boolean canBeeContinue() { + if (!running) { + return false; + } + if (!entity.hasFlower()) { + return false; + } + if (entity.getFlowerPos() == null) { + return false; + } + if (((BeeEntityInvoker)entity).invokeGetCropsGrownSincePollination() >= 10) { + return false; + } + if (entity.getWorld().isRaining()) { + return false; + } + if (completed()) { + return ((EntityAccessor) entity).getRandom().nextFloat() < 0.2F; + } + if (entity.age % 20 == 0 && !isTarget(entity.getFlowerPos())) { + ((BeeEntityAccessor)entity).setFlowerPos(null); + return false; + } + return true; + } + + public boolean completed() { + return blossomingTicks > 400; + } + + public boolean isRunning() { + return running; + } + + public void cancel() { + running = false; + } + + public void start() { + blossomingTicks = 0; + ticks = 0; + lastBlossomingTick = 0; + running = true; + } + + public void stop() { + if (completed()) { + BlockPos blockPos = entity.getFlowerPos(); + if (blockPos != null) { + BlockState blockState = entity.getWorld().getBlockState(blockPos); + if (blockState.getBlock() == Blocks.OAK_LEAVES) { + entity.getWorld().syncWorldEvent(2005, blockPos, 0); + entity.getWorld().setBlockState(blockPos, FLOWERING_OAK_LEAVES.get().getDefaultState() + .with(DISTANCE, blockState.get(DISTANCE)) + .with(PERSISTENT, blockState.get(PERSISTENT)) + .with(WATERLOGGED, blockState.get(WATERLOGGED)) + ); + ((BeeEntityInvoker)entity).invokeAddCropCounter(); + } + } + } + running = false; + ((MobEntityAccessor)entity).getNavigation().stop(); + } + + public boolean shouldRunEveryTick() { + return true; + } + + public boolean canStart() { + return canBeeStart() && !entity.hasAngerTime() && checkFilters(); + } + + public boolean shouldContinue() { + return canBeeContinue() && !entity.hasAngerTime() && checkFilters(); + } + + public void tick() { + ++ticks; + if (ticks > 600) { + ((BeeEntityAccessor)entity).setFlowerPos(null); + } else { + if (entity.getFlowerPos() != null) { + Vec3d vec3d = Vec3d.ofBottomCenter(entity.getFlowerPos()).add(0.0, 0.6000000238418579, 0.0); + if (vec3d.distanceTo(entity.getPos()) > 1.0) { + nextTarget = vec3d; + moveToNextTarget(); + } else { + if (nextTarget == null) { + nextTarget = vec3d; + } + boolean close = entity.getPos().distanceTo(nextTarget) <= 0.1; + boolean chance = true; + if (!close && ticks > 600) { + ((BeeEntityAccessor)entity).setFlowerPos(null); + } else { + if (close) { + if (((EntityAccessor)entity).getRandom().nextInt(25) == 0) { + nextTarget = new Vec3d(vec3d.getX() + (double)getRandomOffset(), vec3d.getY(), vec3d.getZ() + (double)getRandomOffset()); + ((MobEntityAccessor)entity).getNavigation().stop(); + } else { + chance = false; + } + entity.getLookControl().lookAt(vec3d.getX(), vec3d.getY(), vec3d.getZ()); + } + if (chance) { + moveToNextTarget(); + } + ++blossomingTicks; + if (((EntityAccessor)entity).getRandom().nextFloat() < 0.05F && blossomingTicks > lastBlossomingTick + 60) { + lastBlossomingTick = blossomingTicks; + entity.playSound(SoundEvents.ENTITY_BEE_POLLINATE, 1.0F, 1.0F); + } + } + } + } + } + } + + public boolean isTarget(BlockPos pos) { + return entity.getWorld().canSetBlock(pos) && entity.getWorld().getBlockState(pos).isOf(Blocks.OAK_LEAVES); + } + + public void moveToNextTarget() { + entity.getMoveControl().moveTo(nextTarget.getX(), nextTarget.getY(), nextTarget.getZ(), 0.3499999940395355); + } + + public float getRandomOffset() { + return (((EntityAccessor)entity).getRandom().nextFloat() * 2.0F - 1.0F) * 0.33333334F; + } + + public Optional findTarget() { + return findTarget(targetPredicate, config.value.blossoming.distance); + } + + public Optional findTarget(Predicate predicate, double searchDistance) { + BlockPos blockPos = entity.getBlockPos(); + BlockPos.Mutable mutable = new BlockPos.Mutable(); + 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) { + mutable.set(blockPos, k, i - 1, l); + if (blockPos.isWithinDistance(mutable, searchDistance) && predicate.test(entity.getWorld().getBlockState(mutable))) { + return Optional.of(mutable); + } + } + } + } + } + return Optional.empty(); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/entity/ai/goal/FruitGoal.java b/src/main/java/dev/yurisuika/blossom/entity/ai/goal/FruitGoal.java new file mode 100644 index 0000000..a4bb205 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/entity/ai/goal/FruitGoal.java @@ -0,0 +1,94 @@ +package dev.yurisuika.blossom.entity.ai.goal; + +import dev.yurisuika.blossom.block.FloweringLeavesBlock; +import dev.yurisuika.blossom.mixin.entity.EntityAccessor; +import dev.yurisuika.blossom.mixin.entity.MobEntityAccessor; +import dev.yurisuika.blossom.mixin.entity.passive.BeeEntityAccessor; +import dev.yurisuika.blossom.mixin.entity.passive.BeeEntityInvoker; +import net.minecraft.block.BlockState; +import net.minecraft.entity.passive.BeeEntity; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; + +import java.util.Optional; +import java.util.function.Predicate; + +import static dev.yurisuika.blossom.Blossom.*; +import static net.minecraft.block.LeavesBlock.*; + +public class FruitGoal extends BlossomGoal { + + public final Predicate targetPredicate = (state) -> { + if (state.contains(Properties.WATERLOGGED) && state.get(Properties.WATERLOGGED)) { + return false; + } else { + if (state.isOf(FLOWERING_OAK_LEAVES.get())) { + return state.get(Properties.AGE_3) >= 3; + } else { + return false; + } + } + }; + + public FruitGoal(BeeEntity beeEntity) { + super(beeEntity); + } + + public boolean canBeeStart() { + if (((BeeEntityInvoker)entity).invokeGetCropsGrownSincePollination() >= 10) { + return false; + } + if (((EntityAccessor)entity).getRandom().nextFloat() > config.value.fruiting.chance) { + return false; + } + if (entity.getWorld().isRaining()) { + return false; + } + Optional optional = findTarget(); + if (optional.isPresent()) { + if (entity.hasNectar()) { + if (((BeeEntityInvoker)entity).invokeIsHiveValid()) { + ((BeeEntityAccessor)entity).setFlowerPos(optional.get()); + ((MobEntityAccessor)entity).getNavigation().startMovingTo((double)entity.getFlowerPos().getX() + 0.5, (double)entity.getFlowerPos().getY() + 0.5, (double)entity.getFlowerPos().getZ() + 0.5, 1.2000000476837158); + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; + } + + public void stop() { + if (completed()) { + BlockPos blockPos = entity.getFlowerPos(); + if (blockPos != null) { + BlockState blockState = entity.getWorld().getBlockState(blockPos); + if (blockState.getBlock() == FLOWERING_OAK_LEAVES.get()) { + if (blockState.get(Properties.AGE_3) >= 3) { + entity.getWorld().syncWorldEvent(2005, blockPos, 0); + entity.getWorld().setBlockState(blockPos, FRUITING_OAK_LEAVES.get().getDefaultState() + .with(DISTANCE, blockState.get(DISTANCE)) + .with(PERSISTENT, blockState.get(PERSISTENT)) + .with(WATERLOGGED, blockState.get(WATERLOGGED)) + ); + ((BeeEntityInvoker)entity).invokeAddCropCounter(); + } + } + } + } + running = false; + ((MobEntityAccessor)entity).getNavigation().stop(); + } + + public boolean isTarget(BlockPos pos) { + return entity.getWorld().canSetBlock(pos) && entity.getWorld().getBlockState(pos).getBlock() instanceof FloweringLeavesBlock; + } + + public Optional findTarget() { + return findTarget(targetPredicate, config.value.fruiting.distance); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/block/AbstractBlockMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/block/AbstractBlockMixin.java new file mode 100644 index 0000000..186cd49 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/block/AbstractBlockMixin.java @@ -0,0 +1,31 @@ +package dev.yurisuika.blossom.mixin.block; + +import net.minecraft.block.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.passive.BeeEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(AbstractBlock.class) +public abstract class AbstractBlockMixin { + + @Inject(method = "getCollisionShape", at = @At("HEAD"), cancellable = true) + private void injectGetCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, CallbackInfoReturnable cir) { + Entity entity = null; + if (context instanceof EntityShapeContext) { + entity = ((EntityShapeContext)context).getEntity(); + if (entity instanceof BeeEntity) { + if (state.getBlock() instanceof LeavesBlock) { + cir.setReturnValue(VoxelShapes.empty()); + } + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/block/BlocksInvoker.java b/src/main/java/dev/yurisuika/blossom/mixin/block/BlocksInvoker.java new file mode 100644 index 0000000..53a9b30 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/block/BlocksInvoker.java @@ -0,0 +1,24 @@ +package dev.yurisuika.blossom.mixin.block; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Blocks.class) +public interface BlocksInvoker { + + @Invoker("never") + static boolean invokeNever(BlockState state, BlockView world, BlockPos pos) { + throw new AssertionError(); + } + + @Invoker("canSpawnOnLeaves") + static Boolean invokeCanSpawnOnLeaves(BlockState state, BlockView world, BlockPos pos, EntityType type) { + throw new AssertionError(); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/block/LeavesBlockMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/block/LeavesBlockMixin.java index 4e66a44..7426512 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/block/LeavesBlockMixin.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/block/LeavesBlockMixin.java @@ -10,7 +10,7 @@ import static net.minecraft.block.LeavesBlock.DISTANCE; @Mixin(LeavesBlock.class) -public class LeavesBlockMixin { +public abstract class LeavesBlockMixin { @Inject(method = "getDistanceFromLog(Lnet/minecraft/block/BlockState;)I", at = @At("RETURN"), cancellable = true) private static void injectDistance(BlockState state, CallbackInfoReturnable info) { diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/EntityAccessor.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/EntityAccessor.java new file mode 100644 index 0000000..a1cadae --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/EntityAccessor.java @@ -0,0 +1,14 @@ +package dev.yurisuika.blossom.mixin.entity; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.random.Random; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Entity.class) +public interface EntityAccessor { + + @Accessor + Random getRandom(); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/MobEntityAccessor.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/MobEntityAccessor.java new file mode 100644 index 0000000..3d13874 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/MobEntityAccessor.java @@ -0,0 +1,14 @@ +package dev.yurisuika.blossom.mixin.entity; + +import net.minecraft.entity.ai.pathing.EntityNavigation; +import net.minecraft.entity.mob.MobEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MobEntity.class) +public interface MobEntityAccessor { + + @Accessor + EntityNavigation getNavigation(); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/ai/goal/GoalInvoker.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/ai/goal/GoalInvoker.java new file mode 100644 index 0000000..5484755 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/ai/goal/GoalInvoker.java @@ -0,0 +1,13 @@ +package dev.yurisuika.blossom.mixin.entity.ai.goal; + +import net.minecraft.entity.ai.goal.Goal; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Goal.class) +public interface GoalInvoker { + + @Invoker("getTickCount") + int invokeGetTickCount(int ticks); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityAccessor.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityAccessor.java new file mode 100644 index 0000000..c5b38a0 --- /dev/null +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityAccessor.java @@ -0,0 +1,14 @@ +package dev.yurisuika.blossom.mixin.entity.passive; + +import net.minecraft.entity.passive.BeeEntity; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(BeeEntity.class) +public interface BeeEntityAccessor { + + @Accessor("flowerPos") + void setFlowerPos(BlockPos flowerPos); + +} \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityInvoker.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityInvoker.java index 5a489f9..3f15a89 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityInvoker.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityInvoker.java @@ -1,13 +1,21 @@ package dev.yurisuika.blossom.mixin.entity.passive; import net.minecraft.entity.passive.BeeEntity; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(BeeEntity.class) public interface BeeEntityInvoker { + @Intrinsic @Invoker("addCropCounter") void invokeAddCropCounter(); + @Invoker("isHiveValid") + boolean invokeIsHiveValid(); + + @Invoker("getCropsGrownSincePollination") + int invokeGetCropsGrownSincePollination(); + } \ No newline at end of file diff --git a/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityMixin.java b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityMixin.java index b71c210..93d7617 100644 --- a/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityMixin.java +++ b/src/main/java/dev/yurisuika/blossom/mixin/entity/passive/BeeEntityMixin.java @@ -1,55 +1,51 @@ package dev.yurisuika.blossom.mixin.entity.passive; -import dev.yurisuika.blossom.block.FloweringLeavesBlock; -import dev.yurisuika.blossom.mixin.world.biome.BiomeAccessor; +import dev.yurisuika.blossom.block.FruitingLeavesBlock; +import dev.yurisuika.blossom.mixin.entity.ai.goal.GoalInvoker; import net.minecraft.block.*; import net.minecraft.entity.passive.BeeEntity; import net.minecraft.state.property.IntProperty; -import net.minecraft.state.property.Properties; import net.minecraft.tag.BlockTags; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.WorldView; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; -import java.util.function.Predicate; - -import static dev.yurisuika.blossom.Blossom.*; -import static net.minecraft.block.LeavesBlock.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BeeEntity.class) -public class BeeEntityMixin { +public abstract class BeeEntityMixin { + + @Inject(method = "getPathfindingFavor", at = @At("HEAD"), cancellable = true) + private void injectGetPathfindingFavor(BlockPos pos, WorldView world, CallbackInfoReturnable cir) { + if (world.getBlockState(pos).getBlock() instanceof LeavesBlock) { + cir.setReturnValue(0.0F); + } + } @Mixin(targets = "net.minecraft.entity.passive.BeeEntity$GrowCropsGoal") - public static class GrowCropsGoalMixin { + public abstract static class GrowCropsGoalMixin { @Unique - private BeeEntity entity; + public BeeEntity entity; @Inject(method = "", at = @At(value = "TAIL")) - private void injectInit(BeeEntity entityType, CallbackInfo ci) { - entity = entityType; + private void injectInit(BeeEntity beeEntity, CallbackInfo ci) { + entity = beeEntity; } @Inject(method = "tick", at = @At(value = "HEAD")) private void injectTick(CallbackInfo ci) { - if (ThreadLocalRandom.current().nextDouble() <= config.value.fertilization.chance) { + if (entity.getRandom().nextInt(((GoalInvoker)this).invokeGetTickCount(30)) != 0) { for (int i = 1; i <= 2; ++i) { BlockPos blockPos = entity.getBlockPos().down(i); BlockState blockState = entity.getWorld().getBlockState(blockPos); if (blockState.isIn(BlockTags.BEE_GROWABLES)) { - if (blockState.getBlock() instanceof FloweringLeavesBlock floweringLeavesBlock) { - if (!floweringLeavesBlock.isMature(blockState)) { - IntProperty age = floweringLeavesBlock.getAgeProperty(); + if (blockState.getBlock() instanceof FruitingLeavesBlock fruitingLeavesBlock) { + if (!fruitingLeavesBlock.isMature(blockState)) { + IntProperty age = fruitingLeavesBlock.getAgeProperty(); entity.getWorld().syncWorldEvent(2005, blockPos, 0); entity.getWorld().setBlockState(blockPos, blockState.with(age, blockState.get(age) + 1)); ((BeeEntityInvoker)entity).invokeAddCropCounter(); @@ -58,76 +54,24 @@ private void injectTick(CallbackInfo ci) { } } } + } - RegistryEntry dimension = entity.getWorld().getDimensionEntry(); - RegistryEntry biome = entity.getWorld().getBiome(entity.getBlockPos()); - float temperature = biome.value().getTemperature(); - float downfall = ((BiomeAccessor)(Object)biome.value()).getWeather().downfall(); - - boolean whitelist = false; - if (Arrays.asList(config.filter.dimension.whitelist).contains(dimension.getKey().get().getValue().toString()) && dimension.getKey().isPresent()) { - if (Arrays.asList(config.filter.biome.whitelist).contains(biome.getKey().get().getValue().toString()) && biome.getKey().isPresent()) { - whitelist = true; - } - } + } - boolean blacklist = false; - if (!Arrays.asList(config.filter.dimension.blacklist).contains(dimension.getKey().get().getValue().toString()) && dimension.getKey().isPresent()) { - if (!Arrays.asList(config.filter.biome.blacklist).contains(biome.getKey().get().getValue().toString()) && biome.getKey().isPresent()) { - blacklist = true; - } - } + @Mixin(targets = "net.minecraft.entity.passive.BeeEntity$MoveToFlowerGoal") + public abstract static class MoveToFlowerGoalMixin { - boolean enabled = false; - if (temperature >= config.filter.temperature.min && temperature <= config.filter.temperature.max) { - if (downfall >= config.filter.downfall.min && downfall <= config.filter.downfall.max) { - if (config.toggle.whitelist && config.toggle.blacklist) { - if (whitelist && blacklist) { - enabled = true; - } - } else if (config.toggle.whitelist) { - if (whitelist) { - enabled = true; - } - } else if (config.toggle.blacklist) { - if (blacklist) { - enabled = true; - } - } else { - enabled = true; - } - } - } + @Unique + public BeeEntity entity; - if (enabled) { - if (ThreadLocalRandom.current().nextDouble() <= config.value.propagation.chance) { - for (int i = 1; i <= 2; ++i) { - BlockPos blockPos = entity.getBlockPos().down(i); - BlockState blockState = entity.getWorld().getBlockState(blockPos); - if (Arrays.stream(Direction.values()).anyMatch(direction -> !entity.getWorld().getBlockState(blockPos.offset(direction)).getMaterial().isSolid())) { - if (blockState.getBlock() == Blocks.OAK_LEAVES) { - entity.getWorld().syncWorldEvent(2005, blockPos, 0); - entity.getWorld().setBlockState(blockPos, FLOWERING_OAK_LEAVES.get().getDefaultState() - .with(DISTANCE, blockState.get(DISTANCE)) - .with(PERSISTENT, blockState.get(PERSISTENT)) - .with(WATERLOGGED, blockState.get(WATERLOGGED)) - ); - ((BeeEntityInvoker)entity).invokeAddCropCounter(); - } - } - } - } - } + @Inject(method = "", at = @At(value = "TAIL")) + private void injectInit(BeeEntity beeEntity, CallbackInfo ci) { + entity = beeEntity; } - } - - @Mixin(targets = "net.minecraft.entity.passive.BeeEntity$PollinateGoal") - public abstract static class PollinateGoalMixin { - - @ModifyArg(method = "getFlower", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/BeeEntity$PollinateGoal;findFlower(Ljava/util/function/Predicate;D)Ljava/util/Optional;"), index = 0) - private Predicate modifyGetFlower(Predicate predicate) { - return predicate.and((state) -> state.getBlock() instanceof FloweringLeavesBlock ? state.get(Properties.AGE_7) <= config.value.pollination.age : true); + @Inject(method = "shouldMoveToFlower", at = @At("RETURN"), cancellable = true) + private void injectTick(CallbackInfoReturnable cir) { + cir.setReturnValue(cir.getReturnValue() || (entity.getWorld().getBlockState(entity.getFlowerPos()).isOf(Blocks.OAK_LEAVES) && entity.hasNectar())); } } diff --git a/src/main/java/dev/yurisuika/blossom/server/command/BlossomCommand.java b/src/main/java/dev/yurisuika/blossom/server/command/BlossomCommand.java index 448a0fa..819174c 100644 --- a/src/main/java/dev/yurisuika/blossom/server/command/BlossomCommand.java +++ b/src/main/java/dev/yurisuika/blossom/server/command/BlossomCommand.java @@ -8,7 +8,11 @@ import net.minecraft.command.argument.RegistryPredicateArgumentType; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; +import net.minecraft.text.Texts; +import net.minecraft.util.Formatting; import net.minecraft.util.registry.Registry; import org.apache.commons.lang3.ArrayUtils; @@ -26,6 +30,7 @@ public static void register(CommandDispatcher dispatcher, C .then(literal("reload") .executes(context -> { loadConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.config.reload"), true); return 1; }) @@ -33,10 +38,9 @@ public static void register(CommandDispatcher dispatcher, C .then(literal("reset") .executes(context -> { config.value = new Value( - new Value.Propagation(0.2F), - new Value.Fertilization(0.06666667F), - new Value.Pollination(1), - new Value.Fruit(3, 0.5714286F) + new Value.Blossoming(0.2F, 10.0D), + new Value.Fruiting(0.2F, 10.0D), + new Value.Harvesting(3, 0.5714286F) ); config.filter = new Filter( new Filter.Temperature(-2.0F, 2.0F), @@ -49,6 +53,7 @@ public static void register(CommandDispatcher dispatcher, C false ); saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.config.reset"), true); return 1; }) @@ -56,62 +61,74 @@ public static void register(CommandDispatcher dispatcher, C ) .then(literal("value") .requires(source -> source.hasPermissionLevel(4)) - .then(literal("propagation") + .then(literal("blossoming") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.propagation.query", config.value.propagation.chance), false); + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.blossoming.chance", config.value.blossoming.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.chance.tooltip")))); + MutableText distance = Texts.bracketed(Text.translatable("commands.blossom.value.blossoming.distance", config.value.blossoming.distance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.distance.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.blossoming.query", chance, distance), true); return 1; }) .then(CommandManager.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) - .executes(context -> { - config.value.propagation.chance = FloatArgumentType.getFloat(context, "chance"); - saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.propagation.set", config.value.propagation.chance), true); - return 1; - }) + .then(CommandManager.argument("distance", DoubleArgumentType.doubleArg(0.0D)) + .executes(context -> { + config.value.blossoming.chance = FloatArgumentType.getFloat(context, "chance"); + config.value.blossoming.distance = DoubleArgumentType.getDouble(context, "distance"); + saveConfig(); + + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.blossoming.chance", config.value.blossoming.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.chance.tooltip")))); + MutableText distance = Texts.bracketed(Text.translatable("commands.blossom.value.blossoming.distance", config.value.blossoming.distance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.distance.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.blossoming.set", chance, distance), true); + return 1; + }) + ) ) ) - .then(literal("fertilization") + .then(literal("fruiting") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fertilization.query", config.value.fertilization.chance), false); + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.fruiting.chance", config.value.fruiting.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.fruiting.chance.tooltip")))); + MutableText distance = Texts.bracketed(Text.translatable("commands.blossom.value.fruiting.distance", config.value.fruiting.distance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.fruiting.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fruiting.query", chance, distance), false); return 1; }) .then(CommandManager.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) - .executes(context -> { - config.value.fertilization.chance = FloatArgumentType.getFloat(context, "chance"); - saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fertilization.set", config.value.fertilization.chance), true); - return 1; - }) - ) - ) - .then(literal("pollination") - .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.pollination.query", config.value.pollination.age), false); - return 1; - }) - .then(CommandManager.argument("age", IntegerArgumentType.integer(0, 7)) - .executes(context -> { - config.value.pollination.age = IntegerArgumentType.getInteger(context, "age"); - saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.pollination.set", config.value.pollination.age), true); - return 1; - }) + .then(CommandManager.argument("distance", DoubleArgumentType.doubleArg(0.0D)) + .executes(context -> { + config.value.fruiting.chance = FloatArgumentType.getFloat(context, "chance"); + config.value.fruiting.distance = DoubleArgumentType.getDouble(context, "distance"); + saveConfig(); + + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.fruiting.chance", config.value.fruiting.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.fruiting.chance.tooltip")))); + MutableText distance = Texts.bracketed(Text.translatable("commands.blossom.value.fruiting.distance", config.value.fruiting.distance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.blossoming.fruiting.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fruiting.set", chance, distance), false); + return 1; + }) + ) ) ) - .then(literal("fruit") + .then(literal("harvesting") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fruit.query", config.value.fruit.bonus, config.value.fruit.chance), false); + MutableText bonus = Texts.bracketed(Text.translatable("commands.blossom.value.harvesting.bonus", config.value.harvesting.bonus)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); + + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.harvesting.chance", config.value.harvesting.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.harvesting.chance.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.harvesting.query", bonus, chance), true); return 1; }) .then(CommandManager.argument("bonus", IntegerArgumentType.integer(0)) .then(CommandManager.argument("chance", FloatArgumentType.floatArg(0.0F, 1.0F)) .executes(context -> { - int bonus = IntegerArgumentType.getInteger(context, "bonus"); - float chance = FloatArgumentType.getFloat(context, "chance"); - config.value.fruit.bonus = bonus; - config.value.fruit.chance = chance; + config.value.harvesting.bonus = IntegerArgumentType.getInteger(context, "bonus"); + config.value.harvesting.chance = FloatArgumentType.getFloat(context, "chance"); saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.value.fruit.set", bonus, chance), true); + + MutableText bonus = Texts.bracketed(Text.translatable("commands.blossom.value.harvesting.bonus", config.value.harvesting.bonus)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.harvesting.bonus.tooltip")))); + MutableText chance = Texts.bracketed(Text.translatable("commands.blossom.value.harvesting.chance", config.value.harvesting.chance)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.value.harvesting.chance.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.value.harvesting.set", bonus, chance), true); return 1; }) ) @@ -122,17 +139,22 @@ public static void register(CommandDispatcher dispatcher, C .requires(source -> source.hasPermissionLevel(4)) .then(literal("temperature") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.temperature.query", config.filter.temperature.min, config.filter.temperature.max), false); + MutableText min = Texts.bracketed(Text.translatable("commands.blossom.filter.temperature.min", config.filter.temperature.min)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.temperature.min.tooltip")))); + MutableText max = Texts.bracketed(Text.translatable("commands.blossom.filter.temperature.max", config.filter.temperature.max)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.temperature.max.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.temperature.query", min, max), false); return 1; }) .then(argument("min", FloatArgumentType.floatArg(-2.0F, 2.0F)) .then(argument("max", FloatArgumentType.floatArg(-2.0F, 2.0F)) .executes(context -> { - float min = Math.min(FloatArgumentType.getFloat(context, "min"), FloatArgumentType.getFloat(context, "max")); - float max = Math.max(FloatArgumentType.getFloat(context, "max"), FloatArgumentType.getFloat(context, "min")); - config.filter.temperature.min = min; - config.filter.temperature.max = max; + config.filter.temperature.min = Math.min(FloatArgumentType.getFloat(context, "min"), FloatArgumentType.getFloat(context, "max")); + config.filter.temperature.max = Math.max(FloatArgumentType.getFloat(context, "max"), FloatArgumentType.getFloat(context, "min")); saveConfig(); + + MutableText min = Texts.bracketed(Text.translatable("commands.blossom.filter.temperature.min", config.filter.temperature.min)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.temperature.min.tooltip")))); + MutableText max = Texts.bracketed(Text.translatable("commands.blossom.filter.temperature.max", config.filter.temperature.max)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.temperature.max.tooltip")))); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.temperature.set", min, max), false); return 1; }) @@ -141,18 +163,23 @@ public static void register(CommandDispatcher dispatcher, C ) .then(literal("downfall") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.downfall.query", config.filter.downfall.min, config.filter.downfall.max), false); + MutableText min = Texts.bracketed(Text.translatable("commands.blossom.filter.downfall.min", config.filter.downfall.min)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.downfall.min.tooltip")))); + MutableText max = Texts.bracketed(Text.translatable("commands.blossom.filter.downfall.max", config.filter.downfall.max)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.downfall.max.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.temperature.query", min, max), false); return 1; }) .then(argument("min", FloatArgumentType.floatArg(0.0F, 1.0F)) .then(argument("max", FloatArgumentType.floatArg(0.0F, 1.0F)) .executes(context -> { - float min = Math.min(FloatArgumentType.getFloat(context, "min"), FloatArgumentType.getFloat(context, "max")); - float max = Math.max(FloatArgumentType.getFloat(context, "max"), FloatArgumentType.getFloat(context, "min")); - config.filter.downfall.min = min; - config.filter.downfall.max = max; + config.filter.downfall.min = Math.min(FloatArgumentType.getFloat(context, "min"), FloatArgumentType.getFloat(context, "max")); + config.filter.downfall.max = Math.max(FloatArgumentType.getFloat(context, "max"), FloatArgumentType.getFloat(context, "min")); saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.downfall.set", min, max), false); + + MutableText min = Texts.bracketed(Text.translatable("commands.blossom.filter.downfall.min", config.filter.downfall.min)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.downfall.min.tooltip")))); + MutableText max = Texts.bracketed(Text.translatable("commands.blossom.filter.downfall.max", config.filter.downfall.max)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.downfall.max.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.temperature.set", min, max), false); return 1; }) ) @@ -161,7 +188,9 @@ public static void register(CommandDispatcher dispatcher, C .then(literal("dimension") .then(literal("whitelist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.whitelist.query", String.join(", ", config.filter.dimension.whitelist)), false); + MutableText list = Text.translatable("commands.blossom.filter.dimension.whitelist.list", Arrays.toString(config.filter.dimension.whitelist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.dimension.whitelist.list.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.whitelist.query", list), false); return 1; }) .then(literal("add") @@ -175,6 +204,7 @@ public static void register(CommandDispatcher dispatcher, C config.filter.dimension.whitelist = ArrayUtils.add(config.filter.dimension.whitelist, dimension); Arrays.sort(config.filter.dimension.whitelist); saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.whitelist.add", dimension), false); return 1; } @@ -196,6 +226,7 @@ public static void register(CommandDispatcher dispatcher, C } } saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.whitelist.remove", dimension), false); return 1; } @@ -205,7 +236,9 @@ public static void register(CommandDispatcher dispatcher, C ) .then(literal("blacklist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.blacklist.query", String.join(", ", config.filter.dimension.blacklist)), false); + MutableText list = Text.translatable("commands.blossom.filter.dimension.blacklist.list", Arrays.toString(config.filter.dimension.blacklist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.dimension.blacklist.list.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.blacklist.query", list), false); return 1; }) .then(literal("add") @@ -219,6 +252,7 @@ public static void register(CommandDispatcher dispatcher, C config.filter.dimension.blacklist = ArrayUtils.add(config.filter.dimension.blacklist, dimension); Arrays.sort(config.filter.dimension.blacklist); saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.blacklist.add", dimension), false); return 1; } @@ -240,6 +274,7 @@ public static void register(CommandDispatcher dispatcher, C } } saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.dimension.blacklist.remove", dimension), false); return 1; } @@ -251,7 +286,9 @@ public static void register(CommandDispatcher dispatcher, C .then(literal("biome") .then(literal("whitelist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.whitelist.query", String.join(", ", config.filter.biome.whitelist)), false); + MutableText list = Text.translatable("commands.blossom.filter.biome.whitelist.list", Arrays.toString(config.filter.biome.whitelist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.biome.whitelist.list.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.whitelist.query", list), false); return 1; }) .then(literal("add") @@ -265,6 +302,7 @@ public static void register(CommandDispatcher dispatcher, C config.filter.biome.whitelist = ArrayUtils.add(config.filter.biome.whitelist, biome); Arrays.sort(config.filter.biome.whitelist); saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.whitelist.add", biome), false); return 1; } @@ -286,6 +324,7 @@ public static void register(CommandDispatcher dispatcher, C } } saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.whitelist.remove", biome), false); return 1; } @@ -295,7 +334,9 @@ public static void register(CommandDispatcher dispatcher, C ) .then(literal("blacklist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.blacklist.query", String.join(", ", config.filter.biome.blacklist)), false); + MutableText list = Text.translatable("commands.blossom.filter.biome.blacklist.list", Arrays.toString(config.filter.biome.blacklist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.filter.biome.blacklist.list.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.blacklist.query", list), false); return 1; }) .then(literal("add") @@ -309,6 +350,7 @@ public static void register(CommandDispatcher dispatcher, C config.filter.biome.blacklist = ArrayUtils.add(config.filter.biome.blacklist, biome); Arrays.sort(config.filter.biome.blacklist); saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.blacklist.add", biome), false); return 1; } @@ -330,6 +372,7 @@ public static void register(CommandDispatcher dispatcher, C } } saveConfig(); + context.getSource().sendFeedback(Text.translatable("commands.blossom.filter.biome.blacklist.remove", biome), false); return 1; } @@ -343,28 +386,38 @@ public static void register(CommandDispatcher dispatcher, C .requires(source -> source.hasPermissionLevel(4)) .then(literal("whitelist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.whitelist.query", config.toggle.whitelist), false); + MutableText toggle = Texts.bracketed(Text.translatable("commands.blossom.toggle.whitelist.toggle", config.toggle.whitelist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.toggle.whitelist.toggle.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.whitelist.query", toggle), false); return 1; }) .then(argument("value", BoolArgumentType.bool()) .executes(context -> { config.toggle.whitelist = BoolArgumentType.getBool(context, "value"); saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.whitelist.set", config.toggle.whitelist), false); + + MutableText toggle = Texts.bracketed(Text.translatable("commands.blossom.toggle.whitelist.toggle", config.toggle.whitelist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.toggle.whitelist.toggle.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.whitelist.set", toggle), false); return 1; }) ) ) .then(literal("blacklist") .executes(context -> { - context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.blacklist.query", config.toggle.blacklist), false); + MutableText toggle = Texts.bracketed(Text.translatable("commands.blossom.toggle.blacklist.toggle", config.toggle.blacklist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.toggle.blacklist.toggle.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.blacklist.query", toggle), false); return 1; }) .then(argument("value", BoolArgumentType.bool()) .executes(context -> { config.toggle.blacklist = BoolArgumentType.getBool(context, "value"); saveConfig(); - context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.blacklist.set", config.toggle.blacklist), false); + + MutableText toggle = Texts.bracketed(Text.translatable("commands.blossom.toggle.blacklist.toggle", config.toggle.blacklist)).styled(style -> style.withColor(Formatting.GREEN).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.translatable("commands.blossom.toggle.blacklist.toggle.tooltip")))); + + context.getSource().sendFeedback(Text.translatable("commands.blossom.toggle.blacklist.set", toggle), false); return 1; }) ) diff --git a/src/main/resources/assets/blossom/blockstates/flowering_oak_leaves.json b/src/main/resources/assets/blossom/blockstates/flowering_oak_leaves.json index 8fd8f02..171224f 100644 --- a/src/main/resources/assets/blossom/blockstates/flowering_oak_leaves.json +++ b/src/main/resources/assets/blossom/blockstates/flowering_oak_leaves.json @@ -1,28 +1,45 @@ { - "multipart": [ - { "when": { "age": "0" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage0" } - }, - { "when": { "age": "1" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage1" } - }, - { "when": { "age": "2" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage2" } - }, - { "when": { "age": "3" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage3" } - }, - { "when": { "age": "4" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage4" } - }, - { "when": { "age": "5" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage5" } - }, - { "when": { "age": "6" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage6" } - }, - { "when": { "age": "7" }, - "apply": { "model": "blossom:block/flowering_oak_leaves_stage7" } - } + "variants": { + "age=0": [ + { + "model": "blossom:block/flowering_oak_leaves_stage0" + } + ], + "age=1": [ + { + "model": "blossom:block/flowering_oak_leaves_stage1a" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage1b" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage1c" + } + ], + "age=2": [ + { + "model": "blossom:block/flowering_oak_leaves_stage2a" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage2b" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage2c" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage2c" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage2a" + }, + { + "model": "blossom:block/flowering_oak_leaves_stage2b" + } + ], + "age=3": [ + { + "model": "blossom:block/flowering_oak_leaves_stage3" + } ] + } } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/blockstates/fruiting_oak_leaves.json b/src/main/resources/assets/blossom/blockstates/fruiting_oak_leaves.json new file mode 100644 index 0000000..9d32031 --- /dev/null +++ b/src/main/resources/assets/blossom/blockstates/fruiting_oak_leaves.json @@ -0,0 +1,44 @@ +{ + "variants": { + "age=0": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage0" + } + ], + "age=1": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage1" + } + ], + "age=2": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage2" + } + ], + "age=3": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage3" + } + ], + "age=4": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage4" + } + ], + "age=5": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage5" + } + ], + "age=6": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage6" + } + ], + "age=7": [ + { + "model": "blossom:block/fruiting_oak_leaves_stage7" + } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/icon.png b/src/main/resources/assets/blossom/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1a2b58edd032d3f41d855d451b04c16de92256c2 GIT binary patch literal 11515 zcmb7qd0bLy+rMdVPMg*^jWwdy(@Zu~YO8iMWZH&l)5^-sg`U(l*ElML0+p3*LeoYi zN@`_`OJc4BR8~|bXenrlRE7sdL4zZ*9p2+SzdznTe(&?}em;KS_}97bo9p^s-{n5L zB^W<-(od7@?Chql|8wm&J3D*y(cbR63Fw#ZNUIV38V7E}ueK`_VfyUsX4|b_yK4Ip z)}V}*utR?X8g96oJ8j^{!q#T{mlGP=iCqB`TX(qaoN;i?w$Yfzr-fU;Up%AX(V?*0 zALfTX$UC_2QeN2x{|z;3^IDdawXIs89=mG&&J*)4=CsXNUlo0zR`H7C@ap=sYI^RA zWqvO|{5&8SOxGF4V*zk;zFsBI2Gu->=}FfeF0`SS~i5${G;rH|Xz-q#va`_Iu^SR$64$y?)_>Mce;^mD)i|*#JZe zJ&%}rSRR=>B;`6tEO-FBqPwO9-cuF7}$l<%xI*Fi;{G@aS` z!gYwWgH6zz`RI9evitKF)G$PUeVU3cd14FtadFzedF%k}@S<15r$O0$#Oj-bkVuVn z=)gj+{@(A_*0BzB{*;%6YcH%J@S?=P84vam`fd=M)oey(rupxGcDDCP6g{xs zI-f*KiYyn4`&Q*uri)!kw0gi}7-Axp;`*>Rv`=dBd=e$0ua))>GiF-p0E?zGV6axT zVX!P&pNVTL^#WEXunXPDP_5G5#s}m26N;}?&WEU-ppE)S3vR0CPNBn|298#o1flP z2rl7QSYI~Zn$rEBYUuAGyO`(jiHHO*gVe+;Zc_18_(K*MtKfjQlXyxXU|;e&5OG;! z993UmyisBz+`I^D-addNSpsYK>1L!jgI+5s)F&^4f);(>$xnE=FWO5*>b~V!5fUa} z#J0w1uM}hQ@|HA zRwq@9&dPVuwn|h1K|iZJRV~0b{%UB5)Y%i7B$78BPw8UWlPI+;YswCsfR4M5BWNr# zjG&$6MzXFQwskLd!lsG4Dz=CxrT}mG50G;{_`crnQsF*wD=U6)Csz&;hkWoK+loQX z<@35*$Bg^(minCD3#hR(ES7*y82;S*b1i1r#k5y0cwZ*XK#x|h;mhyi-_3TMOQ!q* zHdo#ZjHP_|xQ0Wm?aX}gnXcjEb%q6#uwJ*6hN}xbbDP0szp>w2@!YEGm(tLcuY5FzqaF{Ac9VaWhlPD5;CQ)M>ECMC%crvh!8)Kbiu0LUA4f} zt*UgND{21FKZz}E9KL2#Lh#d~$|hFMgZ#=CU6>~m&hNihrb!b!QY>}A_iE$JnJt}M zNY1qORB@0Gc}6p4^yA8Kf;Ng`F6?62`R|{7&NjgMA>ZNA-hXafIN$xN#3lK+NYQ9l zhCU9N6$BA{n3qZYB6H{gla%yQ@{l1~f2Mb|XaK5FadIoSR4d`YMTOviPj>e~IwKS) z06(eC3um@Tt%e=*z7v!MUsLI$F2cAQnGq6!VT+&yM-jptwJ79DV_mZHjAbHGYz>hY zv8`%j?mtDEFX&=Qq9t6ZeUpY01H-G7xl-%K|NqPH)JaH#=i_l~Ku7 z-hQ3I-A4zb-L^VhP7;TQldkzGft6mu2?~ePwrvR=9woc(fu~#G=TY=d#V*rGKc={o z7J5E^X-Z0VH-7+r=dL$w^%3?HMG&qCd{McXz9Insx&6haaOtlDg`;nbs#r=B3Gb_Q zvy^S*8THcLx=}9Rp+>rSI6tp~fgbLj?c(Vvpam4POYNstvnrMEyB|j!*B?t@9pR)D|-RSmPY$ z3$?6A5#=kd6)}3vMF7-LRMDfU#XO8iraUiUQqSL*+tT6DSm1f%Juu|v==;{_6^KI7 z(w%*P;|DCH8CVRY>c2a9=q!cWAtkle0=&z;Mo-hu1p3Jgr0J0QBK$T4VU}=BH3@2? z7CfNSlcdGDE?cCOUH+)GoQkdg6(lTK2i_H> ziUB-`Y)uM&ez(e~r42pBgj=~*b9{L6!zXi9YQ5Bp?b6)gkz0BAPQ;=^#8173FKpam zHIm*hQp)|4s@X-!&L)$LH51b9Nh}v%jxlOf?@zbO!?JBFkRKv0AW>(=s6udS)2tNL zQ7-F2Wx-rO;jK#ShyksCfUtiIK-9$N>d|WybJuXVzbPP`mO65~MCz}KD3O46Z~1%~ z8BU^S1>!bVx4j_?mr#&v{{F9xgfhx1NuF}pJJ3;Zm=~>~!s)zjO6gTB{wWrBbGL3d zx2&P0kMhd}CEx@=qXiKN0>#n~B zspz03zGQ?XM)kM3zP=VrnOu*liAc^=oNhOGXJFI(i~m_044J)7?}g-vxJad#Ci`kG z>VgFa69@GAfi^MYs#a%69zB1QgD41sxvGaX?91>yC1wK2jFLg2Rd?&g+$~FNE6OcL zoSt%W*v+e6LupPQ70V*r;ILHH;V{2`mLMV|^VM(eU#(xn``(Z>>nw(<^b}!cIHNaJ zh8fRn$oU42e_X%RXuKJjns&fSZ=C2qJeof_O#>P7fLQ6?Q+3o7G4(4M6lSlLvN|0?d;I(Mnncju_3Eg@Fwgu)yIUOl%R-N+9z5c7} z<)@QnZY?OiDfEHlv`-gHm`#v5rjyCbH_8VD>m>}QoHyi`CB8fV^5K9WY`xTVl-`ARF*Tp7-Z?#f(sO@?t5 zVy(ia5m0yCenEin6;{BOArGF6OO_26n(b}l>to1Wp(=0$ub>n%3^ViWpuB?=4LxRT z>SL)K_bZLL%v2|dqASF?pOqfE^{=!VkF?Ttpg9Q(Hx!XgX@Rb9$@);=D0P_8-3KxY zJ)5Pp2%hM$Jn7nG!qU`eiR*=aQ)g6=+Wb2i!SQBR65%0T*9 zhSx_a=438XSmJt$&kw2_UPIRA6W)CLiyi%o%9qe87VbVD#P%!oCecsZD2ULa3)Yz< zCv0Z=J#O`TeE`*axQd4%5X;Lo%3I~jKC9SXq}pu42=ZN~MU@9UK=s*n#Yxdw=P>!C zL2E%xnp1u0I_QxqAl2Ebml=)Jd(kw66xVh>-?PTUcqx%gKOTr{F$I#XMis#m=a1i$ zxk1W}UJ5$pv#%(!&j*B)KzsTPm3E*QW$pJi@z_Z%LLIhRlQ?HX!0d_F!s+$R!ME?pWDT0&}LU;l?R z=3Mq7Y4!*BW`4t?xRlkB&UfTN{M|^=(Yqzo!3MHQgM5>6)V-T(S-MjN=SoNmxxo?! z?mo0-g-f z=-}Z_{f-!^zs>zKzcc?_LOUg5=Q}OSw!s~{<{U}{*8mMOCP%DZb%>dj zrjpf^_FaU9L9{<5HR(cPp~!W!h<3EHjAnY_#tEXWg;JvE)Q!dbwUKn`VQ|_xYF-4@A$UNfsd?-D#Wv_ATWfMQyVWnDPUd@qQGXqPiDm(f*&{;5ipM&}@m z{uY3rO}5kv2)L4+8{Kc) z=#QZ`$>_EW?vwx{CSjph9qO_0txxBmt!n3_ZeDM6^z^t4L$PfjKxArRz=J$ zUAfjGfJCy?X;mV|!^3-k1iiE|eyBi1*vb0b|#6E%>qeM~ zH~^xNhjxUMj1TIOf#TGQemAwGLe)_`Ww1f|mMo1oexIt6iFe&$peieGE+3|;Sk&zu z;P+h??b|00*Pt%cH{ciXuS2TR_$2I6lzep=yaTu+4r>DT2SzH5sf6;3dJs??psysGi`brdJ=1vnu3_&JC}~{BmW$pV zC7X^<=kZL`Hl;)BBd8|UwkcOIv{!+i;)@?Q`Mnj*3QWSPIMNtvKfZfnqP)#Df>G5EXQ_33*+%4GWz_NL&t1ii}jVU{2V zTMEMDQzH&oac0q+aJCvq^9pdBUGHJJTczlZMnwp;UnV-m@n{<6Vz`a>J;#g*62gzr zSYKc9i2c@kXEH}!=1f8~mEtzp=UhWi__%{W@_i*tNB7SV?X(nz$H2uFEH4brc1Pl__2`QIRu7P2SXN zjb(3|M_N=33YO^sIl~|Se9-!dZs73A+#p)W0IG~R(jvl`a$=V}DbmXetj?(rQF~_P zgT|Pputh~gHhUWp;t;%Ulvw}%U*m!1W8qg{;r3H5?%)*$)RoSp-Gid)&q6EfWK2QBs<%5qd z`JiYbnU9xvx-T(VeFN}8Bc)q;ywAk$7M7r=T7!1mSFWE5{~}6!C09$LZ@S_3;;T-x zjPX>+=x6Eq+5jPscsJkWbH4LSD#cRm*WVPMrzL?)Cj6lrQ6q=No_g~+BIxs*mk$1% zPiSbX`Rd3*CoIP1y$n$yDaa_54icZlL1t%0Kj5%#y2UahTtL~7Y}H*vQvJPdy)Of+ z>5ZTBlgy_|xWF`Y?YSAQ)KzzI`GNSEO-_-7Zq zH0G*DD)D|zb=DtU8c-k7c~d{sXkOZdIrU~;SR>jN1S_7|2X&(Ml9zEUV_}4?`0y|5 z^-TTaf^`$H(!t1?Mzf-6DhFZ46E3DPKO`n*(ij_1L)x!2$3m^i*MATzF_jU?rqPQC z0ymMZKG_+(5+mGI1W^6G_R{G`JH?uZ^;#7DlCUF%CLw2l*h+6a$OXo=0QL)@mqc@t z=#SLk7cVXb@!@^JPY0m*K(D7w_frN~*S~3-bRZ%OCf%IC1Od!YC4NkodRwa z(e5+@O1$TLx%HvvM9LEd5osAj{jhr|S&g-fwF|XTPn%`TM49fhd-*O~{FpJm8T7TK z22D9MzZRId+52jvF-WuAKYQ=>*EbC|0^+?Wp z`sk448%5x~AmLAeC)FktwKW`Q{E8&{>W)Hi!i2kfrTAqKp&C1bWPMqtsb22hOE8O@ zkvt{qWV$x<%(-5(OrP;GL6eWGY#Kq;4g9&hoLC2V$DJ2VToG^^8gHwY{rq40b;_lB z7Hyd$O>YPY7YyGy&q3Yp<3f`WWNYZw&p|xP z*MH=#@y)eTjL3sD5$(ZqD5t^|4J&4 z^iug0f0Qh29A<%);X_Yep_v{Y`mPpZefs(Wnt^aRp!#peGqf=>yj&IJYBY1|dZb}( zQYO3T7K65*+s%I%qCwU3JBuq1XNG5(Of6wk6A`|RrT{ur9rZ;Zy-kQGag zOd?2|_nx>VeS66I=_HB_lX7MyC?EG)!cyWhGB3*7iK)Rcwc=W;5Xm-={A#o zYtO$)BL7EJc?ymAd>}zWk5??cMbXaK{O$_M!pSD@q~PDDqck@|AgV~({V;}w%}5hv zO7~GFjq&?OJ^L;kYaGWNEGh&>a#S!`=TqFheS0i#0As4pn;b_uTA3d+)Y?mQ-9%DV z_*W@=!bV_sMVVlX-f)AWu!ls;@2JNd+j~_U(AXj-*+|kq19ou`1_c7b;T)&>bl$!b z{o;_D$+u#z=TyQHA20VPXKn%t&F%t^IuVLTlO5)YUmGp@eij8a(bG7{3;yCL-&D%* ztB0_w(%=>4pKrOsw?=b!T0LV8Muy5+N&QR|ypKB!jODCcRwn9K$DE;6Y`3$Ua)0bD zz}6AWB%!C^qi9u1Az<2#20%70J>BW|WyLFEu8PKmOt~TReGe#@;>g;r^3?EX{yn`$ z`auG;V`uR4>j=q_!tKQ-a{rh;wA(GFXi>0pKVVO9G&qOBhQoTX41y62tAJ+hafK~m z9cZuDYH*Ql;G}bD^-rL>^4G@G5y(!>t=JZf=@sk);dtwy)Y=|tN1496ZGTYrF3YE; zZ<7=FJ%Nmo?%|VV2>&8S{=n9#1 za`|%R+;r7d{M9_IpaQi$q-mLdN;IjAGqU=Xnc#pPTM;6jc#k#eX!)-xf@t2(bdjv- z#*kjG8`+ODhW>5PbwBIwL4}s+^NRXS1h(8zgi9x^infarPqaO4M@4F!)8T__HqM_P zMfw9$7Ih(Bu6<}y9q9zrdsJ862_@J^QCfgWA6fAmWESr0qe3ErQa+(qfLD?Ji(4-t zvbYf|xTJ`2SsG^%DU8OWx>$7eW6=-Q6k2`?m4jwICQvJ}-4i56vo`M7!j+4W!0~Zl9I)}iYezWcr-&gM1rxrUV`=kZi*?Rb^ zDXu8+Nk5KWDZ_(mhq*qz_d&^KZ*sgp{?@|~sSI<9tNEb1sz(grsB!uT{eSm)(ft%D zAsOxGl>eu!(FylXqHy&4 zF{n*}2-&UR53Dk&PFq>}jb37nlYEb}l?@_)e|a=&Rq?}V{6<6B&HG?A8cX}OXm~Rx@5O`dNx`ePrw0H2&uY2< z9kKYY`{5j<_ZOZeEJA1Cj@@qI)R`VuM&Xc=@d9e92;X_L9YXc1)y0%b**kv(QdEdl z7+Po}8gldnqvUV~%<-_87Hw6Uq*z>$%{}}ywT7548t$f*M~4`6w?uD}2l)f#y1*{- zU=k1A#M2K#Ay6B`NAcYOw+JxFH}zqLa?pI<2)b={;^U!I85yeD2O_7re3rj2nki0o zH%|XPO5ELau>Jjg94$oQ9j@0)b=0->z@!$f=1Lxl`qt{@HE+n)<7gV3@Fk1W4V!P5 z;OhW;M-5IrVckg^(}E4ob@>>#DTCL8;y2dq^qK5a^3(roY0-v`};~XNsMx`4CVX2Hol#TlLXH1SfJGn zM=bg&Lfm!m&<(eb)IC4{n3b-_XNvx~U^TZ}qN=5&K9>1QX&NU;Kp@c6M$`i8vSh?= zz|ln1-8jL%AB^KD_oXX8#b2<|fr9MTf@W*G9>3%sE%m^rB#k83W08u-g>U7}dYCE# z4|9V~x;K_xhADa$Z$P8#jHI_KZe@({e^dEEgeA;S+Fo`Y^&<>}4-MuVRSYn)8&u`w z&eU?RFD-ylSRSoXW~e)D!DF5YDMJPWu=vmB{biTn4zZB)D4%R`i`zB zTvG6{+_{SvNh1ks>LcYPdJRHFUHzj8&FiMw+zly+SwIV(a2ySnX$Pz>sAFKRfAdD& zT@La~bI8_H(W3el$Zf>@d0$>AfwP%*EF!tHLLhGE5ro@|OnLw;vbu-*1EYULRRdpF zm*YJYMDykIslnK{islHn7{)XbWnGX{M}`^O86?y5;70gHp&Ps zfG0hJI(T1c%GmR>AEZcOcMEbWr{{gxIwHs0=uK@;`cofuruRDI-7?(gdmYpb&>nWi zrv_A5n*htW)449ULixj(Cyk%~(91i@R7pII5(@Njj6w}e6_rrh)Ur6WG0HP~AvAzq z)=`Z4ppj|dl)dy#eV&h=zneIULq`kzl6H?xEBB7S2!Dwv;&ipS1_rgLyy|%ZL6uTo ztYjU#Gu8XsgaE*Art!G#YR?6WV*)Q2KGq}izgvk?jyL(rUNj}cZb*U)crp9D*)g>7YPJ3zZaz4UIC+IX(1;7l~Fsuw{} zB)sB3+vfg!1XypO$g)M!YtH$vq5w#B4V3fbU$>v{%L5tTfaoUFHVzQZHd>0g-g(9! z)4`uGxkdiql0!}C1v8Ve%b_qfNwm6ZZ<%JRcHD^hW>b?T3^n}E4g4P_PZ&yK%xEIk zf{8B$pI7yQUlixi(!w@@A*8(tdq=6(8 z>YLF>mU_U^$4gB_9o>FR4HviDt&y_U`e=9QK_{%y3}EkpNN_1z9NYog+qh}JwFAV{ zKE*SuPE92bUk44&v8A^ILa!pmwST zw|`Bx=r}FLdcFXPC@uFT(L4dS3@V;RDAhRoqXsY%Z_$7FY@0}GTb4B%jV7YS8NvSb z6jYdfQIaJsn8Z@C0KLNMZ8EnR5wHtm2W?=x3^g1|+s*bY9sumsqmg|!?o^|?&?7k6 zmw!2@_eo{08j{w%7t=}^=pR9+C-lh$2~|NsRj+Jw8jQ3~RmX9Ug6<~NX|!9vE_iL( I>OCj^8?p4bc>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/lang/en_us.json b/src/main/resources/assets/blossom/lang/en_us.json index d1f8290..8f9223c 100644 --- a/src/main/resources/assets/blossom/lang/en_us.json +++ b/src/main/resources/assets/blossom/lang/en_us.json @@ -1,54 +1,84 @@ { "block.blossom.flowering_oak_leaves": "Flowering Oak Leaves", + "block.blossom.fruiting_oak_leaves": "Fruiting Oak Leaves", "commands.blossom.config.reload": "Blossom config reloaded", "commands.blossom.config.reset": "Blossom config reset to defaults", - "commands.blossom.value.propagation.query": "Propagation is currently set to: (chance: %s)", - "commands.blossom.value.propagation.set": "Propagation is now set to: (chance: %s)", + "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.chance": "Chance: %s", + "commands.blossom.value.blossoming.chance.tooltip": "Chance for bees to start blossoming flowering leaves\n&7(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&7(min: 0.0)", - "commands.blossom.value.fertilization.query": "Fertilization is currently set to: (chance: %s)", - "commands.blossom.value.fertilization.set": "Fertilization is now set to: (chance: %s)", + "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.chance": "Chance: %s", + "commands.blossom.value.fruiting.chance.tooltip": "Chance for bees to fertilize fruiting leaves\n&7(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&7(min: 0.0)", - "commands.blossom.value.pollination.query": "Pollination is currently set to: (age: %s)", - "commands.blossom.value.pollination.set": "Pollination is now set to: (age: %s)", + "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&7(min: 0)", + "commands.blossom.value.harvesting.chance": "Chance: %s", + "commands.blossom.value.harvesting.chance.tooltip": "Chance to harvest each bonus fruit\n&7(min: 0.0, max: 1.0)", - "commands.blossom.value.fruit.query": "Fruit is currently set to: (bonus: %s, chance: %s)", - "commands.blossom.value.fruit.set": "Fruit is now set to: (bonus: %s, chance: %s)", + "commands.blossom.filter.temperature.query": "Temperature is currently set to: %s %s", + "commands.blossom.filter.temperature.set": "Temperature is now set to: %s %s", + "commands.blossom.filter.temperature.min": "Min: %s", + "commands.blossom.filter.temperature.min.tooltip": "Minimum temperature to allow blossoming\n&7(min: -2.0, max: 2.0)", + "commands.blossom.filter.temperature.max": "Max: %s", + "commands.blossom.filter.temperature.max.tooltip": "Maximum temperature to allow blossoming\n&7(min: -2.0, max: 2.0)", - "commands.blossom.filter.temperature.query": "Temperature is currently set to: (min: %s, max: %s)", - "commands.blossom.filter.temperature.set": "Temperature is now set to: (min: %s, max: %s)", - - "commands.blossom.filter.downfall.query": "Downfall is currently set to: (min: %s, max: %s)", - "commands.blossom.filter.downfall.set": "Downfall is now set to: (min: %s, max: %s)", + "commands.blossom.filter.downfall.query": "Downfall is currently set to: %s %s", + "commands.blossom.filter.downfall.set": "Downfall is now set to: %s %s", + "commands.blossom.filter.downfall.min": "Min: %s", + "commands.blossom.filter.downfall.min.tooltip": "Minimum downfall to allow blossoming\n&7(min: 0.0, max: 1.0)", + "commands.blossom.filter.downfall.max": "Max: %s", + "commands.blossom.filter.downfall.max.tooltip": "Maximum downfall to allow blossoming\n&7(min: 0.0, max: 1.0)", "commands.blossom.filter.dimension.whitelist.query": "Whitelisted dimensions: %s", - "commands.blossom.filter.dimension.whitelist.add": "Added dimension '%s' to whitelist", - "commands.blossom.filter.dimension.whitelist.add.failed": "Dimension '%s' is already in whitelist", - "commands.blossom.filter.dimension.whitelist.remove": "Removed dimension '%s' from whitelist", - "commands.blossom.filter.dimension.whitelist.remove.failed": "Dimension '%s' is not in whitelist", + "commands.blossom.filter.dimension.whitelist.list": "%s", + "commands.blossom.filter.dimension.whitelist.list.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.add": "Added dimension '%s' to blacklist", - "commands.blossom.filter.dimension.blacklist.add.failed": "Dimension '%s' is already in blacklist", - "commands.blossom.filter.dimension.blacklist.remove": "Removed dimension '%s' from blacklist", - "commands.blossom.filter.dimension.blacklist.remove.failed": "Dimension '%s' is not in blacklist", + "commands.blossom.filter.dimension.blacklist.list": "%s", + "commands.blossom.filter.dimension.blacklist.list.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.add": "Added biome '%s' to whitelist", - "commands.blossom.filter.biome.whitelist.add.failed": "Biome '%s' is already in whitelist", - "commands.blossom.filter.biome.whitelist.remove": "Removed biome '%s' from whitelist", - "commands.blossom.filter.biome.whitelist.remove.failed": "Biome '%s' is not in whitelist", + "commands.blossom.filter.biome.whitelist.list": "%s", + "commands.blossom.filter.biome.whitelist.list.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.add": "Added biome '%s' to blacklist", - "commands.blossom.filter.biome.blacklist.add.failed": "Biome '%s' is already in blacklist", - "commands.blossom.filter.biome.blacklist.remove": "Removed biome '%s' from blacklist", - "commands.blossom.filter.biome.blacklist.remove.failed": "Biome '%s' is not in blacklist", + "commands.blossom.filter.biome.blacklist.list": "%s", + "commands.blossom.filter.biome.blacklist.list.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", + "commands.blossom.filter.biome.blacklist.remove.failed": "Biome entry '%s' is not in blacklist", "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.blacklist.query": "Blacklist is currently set to: %s", - "commands.blossom.toggle.blacklist.set": "Blacklist is now 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" } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_leaves.json b/src/main/resources/assets/blossom/models/block/flowering_leaves.json index 4e9697a..b303f7e 100644 --- a/src/main/resources/assets/blossom/models/block/flowering_leaves.json +++ b/src/main/resources/assets/blossom/models/block/flowering_leaves.json @@ -1,29 +1,86 @@ -{ "parent": "block/block", - "textures": { - "particle": "#all" +{ + "parent": "block/block", + "textures": { + "particle": "#all" + }, + "elements": [ + { + "from": [0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "down" + }, + "up": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "up" + }, + "north": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "north" + }, + "south": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "south" + }, + "west": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "west" + }, + "east": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "east" + } + } }, - "elements": [ - { "from": [ 0, 0, 0 ], - "to": [ 16, 16, 16 ], - "faces": { - "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "down" }, - "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "up" }, - "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "north" }, - "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "south" }, - "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "west" }, - "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "east" } - } - }, - { "from": [ 0, 0, 0 ], - "to": [ 16, 16, 16 ], - "faces": { - "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "down" }, - "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "up" }, - "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "north" }, - "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "south" }, - "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "west" }, - "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#flowers", "cullface": "east" } - } + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "down" + }, + "up": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "up" + }, + "north": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "north" + }, + "south": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "south" + }, + "west": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "west" + }, + "east": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#flowers", + "cullface": "east" } - ] + } + } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage0.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage0.json index 49c4c6a..d5a63d1 100644 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage0.json +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage0.json @@ -1,7 +1,7 @@ { - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage0" - } + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage0" + } } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1.json deleted file mode 100644 index 9ba3282..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage1" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1a.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1a.json new file mode 100644 index 0000000..357e172 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1a.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage1a" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1b.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1b.json new file mode 100644 index 0000000..1e344fb --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1b.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage1b" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1c.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1c.json new file mode 100644 index 0000000..931e138 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage1c.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage1c" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2.json deleted file mode 100644 index 69863bd..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage2" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2a.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2a.json new file mode 100644 index 0000000..4cfaea8 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2a.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2a" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2b.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2b.json new file mode 100644 index 0000000..735f4b5 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2b.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2b" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2c.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2c.json new file mode 100644 index 0000000..d78364b --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2c.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2c" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2d.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2d.json new file mode 100644 index 0000000..735f4b5 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2d.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2b" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2e.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2e.json new file mode 100644 index 0000000..4cfaea8 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2e.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2a" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2f.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2f.json new file mode 100644 index 0000000..735f4b5 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage2f.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage2b" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage3.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage3.json index c4e7e91..eb8d46a 100644 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage3.json +++ b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage3.json @@ -1,7 +1,7 @@ { - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage3" - } + "parent": "blossom:block/flowering_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "flowers": "blossom:block/flowering_oak_leaves_stage3" + } } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage4.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage4.json deleted file mode 100644 index 012f5ca..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage4.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage4" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage5.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage5.json deleted file mode 100644 index 35951a5..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage5.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage5" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage6.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage6.json deleted file mode 100644 index 51d261e..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage6.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage6" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage7.json b/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage7.json deleted file mode 100644 index 31ef4f3..0000000 --- a/src/main/resources/assets/blossom/models/block/flowering_oak_leaves_stage7.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "blossom:block/flowering_leaves", - "textures": { - "all": "minecraft:block/oak_leaves", - "flowers": "blossom:block/flowering_oak_leaves_stage7" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_leaves.json b/src/main/resources/assets/blossom/models/block/fruiting_leaves.json new file mode 100644 index 0000000..5a0f68d --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_leaves.json @@ -0,0 +1,86 @@ +{ + "parent": "block/block", + "textures": { + "particle": "#all" + }, + "elements": [ + { + "from": [0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "down" + }, + "up": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "up" + }, + "north": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "north" + }, + "south": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "south" + }, + "west": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "west" + }, + "east": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#all", + "tintindex": 0, + "cullface": "east" + } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 16, 16 ], + "faces": { + "down": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "down" + }, + "up": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "up" + }, + "north": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "north" + }, + "south": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "south" + }, + "west": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "west" + }, + "east": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#fruit", + "cullface": "east" + } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage0.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage0.json new file mode 100644 index 0000000..e65e48b --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage0.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage0" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage1.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage1.json new file mode 100644 index 0000000..950a8d1 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage1.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage1" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage2.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage2.json new file mode 100644 index 0000000..511a77e --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage2.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage2" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage3.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage3.json new file mode 100644 index 0000000..664fb09 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage3.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage3" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage4.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage4.json new file mode 100644 index 0000000..dadf4a7 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage4.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage4" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage5.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage5.json new file mode 100644 index 0000000..8693a32 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage5.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage5" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage6.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage6.json new file mode 100644 index 0000000..2d129c9 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage6.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage6" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage7.json b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage7.json new file mode 100644 index 0000000..3802697 --- /dev/null +++ b/src/main/resources/assets/blossom/models/block/fruiting_oak_leaves_stage7.json @@ -0,0 +1,7 @@ +{ + "parent": "blossom:block/fruiting_leaves", + "textures": { + "all": "minecraft:block/oak_leaves", + "fruit": "blossom:block/fruiting_oak_leaves_stage7" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/item/flowering_oak_leaves.json b/src/main/resources/assets/blossom/models/item/flowering_oak_leaves.json index b3ce2ea..e175334 100644 --- a/src/main/resources/assets/blossom/models/item/flowering_oak_leaves.json +++ b/src/main/resources/assets/blossom/models/item/flowering_oak_leaves.json @@ -1,53 +1,29 @@ { - "parent": "blossom:block/flowering_oak_leaves_stage0", - "overrides": [ - { - "predicate": { - "age": 0.000 - }, - "model": "blossom:block/flowering_oak_leaves_stage0" - }, - { - "predicate": { - "age": 0.125 - }, - "model": "blossom:block/flowering_oak_leaves_stage1" - }, - { - "predicate": { - "age": 0.250 - }, - "model": "blossom:block/flowering_oak_leaves_stage2" - }, - { - "predicate": { - "age": 0.375 - }, - "model": "blossom:block/flowering_oak_leaves_stage3" - }, - { - "predicate": { - "age": 0.500 - }, - "model": "blossom:block/flowering_oak_leaves_stage4" - }, - { - "predicate": { - "age": 0.625 - }, - "model": "blossom:block/flowering_oak_leaves_stage5" - }, - { - "predicate": { - "age": 0.750 - }, - "model": "blossom:block/flowering_oak_leaves_stage6" - }, - { - "predicate": { - "age": 0.875 - }, - "model": "blossom:block/flowering_oak_leaves_stage7" - } - ] + "parent": "blossom:block/flowering_oak_leaves_stage3", + "overrides": [ + { + "predicate": { + "age": 0.0 + }, + "model": "blossom:block/flowering_oak_leaves_stage0" + }, + { + "predicate": { + "age": 0.25 + }, + "model": "blossom:block/flowering_oak_leaves_stage1a" + }, + { + "predicate": { + "age": 0.5 + }, + "model": "blossom:block/flowering_oak_leaves_stage2a" + }, + { + "predicate": { + "age": 0.75 + }, + "model": "blossom:block/flowering_oak_leaves_stage3" + } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/blossom/models/item/fruiting_oak_leaves.json b/src/main/resources/assets/blossom/models/item/fruiting_oak_leaves.json new file mode 100644 index 0000000..4f10534 --- /dev/null +++ b/src/main/resources/assets/blossom/models/item/fruiting_oak_leaves.json @@ -0,0 +1,53 @@ +{ + "parent": "blossom:block/fruiting_oak_leaves_stage7", + "overrides": [ + { + "predicate": { + "age": 0.000 + }, + "model": "blossom:block/fruiting_oak_leaves_stage0" + }, + { + "predicate": { + "age": 0.125 + }, + "model": "blossom:block/fruiting_oak_leaves_stage1" + }, + { + "predicate": { + "age": 0.250 + }, + "model": "blossom:block/fruiting_oak_leaves_stage2" + }, + { + "predicate": { + "age": 0.375 + }, + "model": "blossom:block/fruiting_oak_leaves_stage3" + }, + { + "predicate": { + "age": 0.500 + }, + "model": "blossom:block/fruiting_oak_leaves_stage4" + }, + { + "predicate": { + "age": 0.625 + }, + "model": "blossom:block/fruiting_oak_leaves_stage5" + }, + { + "predicate": { + "age": 0.750 + }, + "model": "blossom:block/fruiting_oak_leaves_stage6" + }, + { + "predicate": { + "age": 0.875 + }, + "model": "blossom:block/fruiting_oak_leaves_stage7" + } + ] +} \ 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 new file mode 100644 index 0000000..e2eaea5 --- /dev/null +++ b/src/main/resources/assets/blossom/particles/blossom.json @@ -0,0 +1,16 @@ +{ + "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/shaders/block.properties b/src/main/resources/assets/blossom/shaders/block.properties index 5481d31..14f5dd7 100644 --- a/src/main/resources/assets/blossom/shaders/block.properties +++ b/src/main/resources/assets/blossom/shaders/block.properties @@ -1,2 +1,2 @@ -block.10018 = blossom:flowering_oak_leaves -block.18 = blossom:flowering_oak_leaves \ No newline at end of file +block.10018 = blossom:flowering_oak_leaves blossom:fruiting_oak_leaves +block.18 = blossom:flowering_oak_leaves blossom:fruiting_oak_leaves \ No newline at end of file diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1.png deleted file mode 100644 index 1961c89015a6e7e1b84e66b3f6d474edba3d16bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|GCf@!Lo9l) zPTI)ZV8Fw|tGt1?I<3dU=fO2)gJ$!B zx!!p;YPmFI`58=mSG8k%qmmuxGwrKdmp66JSjyG2w0{0{_F41!@@8zU&GHqMIL+Cj W6|{I)^1N=Kr3{{~elF{r5}E)VzC6wV diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1a.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage1a.png new file mode 100644 index 0000000000000000000000000000000000000000..22b588fbfb89fad6f9a5fdaa14db0ff7c9943e37 GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|GCf@!Lo9le z6C{cr{J*#N|9}6PpX86FE8b+u&0S@cVbJ)$`uo5C|Ns8}4`QgVk($k@ANS{f`PonZ z|G&TQY1F`ZE^2dIV_=3Y^WlxjDV7c29{leXk2u`UIXh|1gIA$!ZLhDde6_-niQ$%# W*5fzZ^`(K9GI+ZBxvXYW|&d+-0czWY?%+wGEK2;*v7!%kfv$P T`B2jjXd#2AtDnm{r-UW|r`ALb literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2.png deleted file mode 100644 index 8718bf97d49dc031185f965dce18719aec7311ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|=6Jd|hFJ6_ zCrAV(ysX>%|L$p)|J80q|Jpk@PDna1Qao+M8|o{W7S1>IrxthyVo1;sXu<`z=01lRKySPK6sRx zQt|VNzUQo$?7OCO{)^ug|Gqxa`hIy{w>?Tp0483%IBI3gdK7aR{(2;6y4fOB0@;#@!dPueTIm{QL5aGu$b z&&|ogx@w8!N-5!Xqm9)^>jRmvzP6g5l39 W=bwT3b`ODeGI+ZBxvXphQg z3+o03rBHe9Ii-KCLS;=(FdV(uuFq&Fn0jbqGEa}wYe|V~YZOldl`$l}a|*o1Ve$fK O7lWs(pUXO@geCy8ZAC-? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2c.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage2c.png new file mode 100644 index 0000000000000000000000000000000000000000..c011f30778d288a0f198ee23eb56dd2a382affe1 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|@;qG}Lo9l) zPB_TfV8G+L*rGAJgz5Vm2}bo3rpgx1W+%?RU-)7vYv$Gk@25C?`cbp!KBJ(5+nnDa zxf~C#I>a+6HCQV&{eC^^0MGAj4DUjlKF*qvIU`)@>N1Af%6t9Qua4^o_bhGaxq5}a dIJjY-OyVNTUJ=*t4}mr_c)I$ztaD0e0ss+xMEL*! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage3.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage3.png index 173e91e98e9f60146532efcaaf0b8411ec7c0207..1961c89015a6e7e1b84e66b3f6d474edba3d16bc 100644 GIT binary patch delta 133 zcmV;00DAxK0j~j&F@9-DL_t(Ijn$H|4S+BV1Pvpw4SQycNKD|?BQS$EaK}+Zq5&b{ zC_x?`S;00000NkvXXu0mjfIH5LQ delta 197 zcmV;$06PD#0qy~iF@LB@L_t(IjbmUKQegj9{r?-63jL3d;`|R2V87^LWz)(>65k(JC z3F*wGUkt(mkVJ$Ih%(^O^Vg*$2cfHQRGX?KH*|L>{Z+dX4g-7Ax pr|yR!4S(*asK&7@sFaw<%P`N#rSwEgxF^u%44$rjF6*2UngD`1X1f3Y diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage5.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage5.png deleted file mode 100644 index b37dc9f31a5b87b3b94da44a66c1592b9a29d6f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|)_A%&hFJ6_ zCoC}E5tsYxf5oB`^%C&(?(B|8KWPu9)hKr`8S=4^zW8S45S&-?(wxPiC o{~PmW26fL)amEZew-jcE*$136G&9ZpfbM4SboFyt=akR{0DQ<@+W-In diff --git a/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage6.png b/src/main/resources/assets/blossom/textures/block/flowering_oak_leaves_stage6.png deleted file mode 100644 index 841214d893ac41d725694d4c12d299b773ca218a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 335 zcmV-V0kHmwP)Px$2}wjjR5*>LlD|sBP#i{2+Gc6MRA~_kwt|B==-S;kad+vHWO4Ta`UG7ZG8A09 zNQOd9pdby{T)4p|4cDRM;vXg?Q}!as z!?j36zzY&Qwgf|=L?H64tHj@sl3fX7v8eFMx# zJ#{?1z>PzWo>s=-2EgR{L;<*QNYWiJAN5o%z)WoMBB@3BA~WspC2n#>$F{VnMY=Nv z=v(jlZT;<1P?^8{RLc5VUdkL_WZb_bx>q@*AT4y+i{!8KDu?v8E10f70O;5jPx$3Q0skR5*>jl0iztKp2I;snIOjg;60cij+VU=^c83-lJFO8F~fr7`pDFXON(h zAqy8S0)Y~dX(GRiFu_`-69nIC7@_HyChmOj?uc(Xi|$)BojpVn6*ORJ9Ts4fA4tomKeo zL%%fEbjN`!XO;fXPUB8!5#%;IdgH*=%l49Xd;Yt}hV$|bHIP4Yz zB_ty@&UyHMN#~5jBTc@BW(EIbm=FK%zfyWdfssMdSJ?h*sO@o}6%3xPelF{r5}E*R Cg*F@j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage2.png b/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage2.png new file mode 100644 index 0000000000000000000000000000000000000000..21d3f64bb343c0e391966322fe49781501fdb65e GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|7J9lkhFJ6_ zCrD%*@aTFJyIJC&ef{AR8{QtMZ=1SXp(@hD@WB;Twzlo^|BY+@wh1IF9c|byFDWr^ zZ%V?0XG*T(YZ+|>qKhQ{o%S*`^62`LUf`{4SMad0;t`WdgM^8sq=dvj;kQgX81KYP zU{G>34rK_ei@kB|M|{u|`@<`}d3a2N1HKAOouC)<|NMs;@{{;3Fb1;ORG&Oh@cUna dw}Sx#gUC+ZtIe&x|A3BV@O1TaS?83{1ON$@R%QSI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage3.png b/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage3.png new file mode 100644 index 0000000000000000000000000000000000000000..0fbc624fba3b680ff91005c9685ec88a6213d050 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|CVRR#hFJ6_ zCrD%*@aTGU`7Y1@`Fj%+BFdW@6CXNu#EAv*SX51Ie0VmUtxf;FK$6cAi4V_=nGZiU z=i#x5S@L3$X#@MC7M8aEU5|Kpf|Pi8mMuNPu4f~_@63E+ii`LG-UknxSOo4e2G-q; zIQJpmi)9iYm)L?=idu?u_Z>c<@JUF>?L~tIv)ul~gdP7fHmE8{FfcH0Q~kW>R{l(& P^B6o`{an^LB{Ts5rQuFf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage4.png b/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage4.png new file mode 100644 index 0000000000000000000000000000000000000000..f18bc6dce51a4094aa2718eca612d3cfa881da56 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|=6bp~hFJ6_ zCoC}E5qt7OeLdUZdWrcHMb7>XC?kEpRKsZ!PY=s!nB}+)yE)x@2^t_6qHXKxbVzzmZFZqv8T%g zssz~hM9y%g{ixq9beU<J~J{mH(D?|KMZ7ZQw!pWsOfEd__Umj zt*(r%?YF$g#ZHz_TO|KI&s5&yV7uWAt7$<8tB*nY-aqFKD4aij;6lFdEJYoIW3AH# zssz~hM0AQ1fBe^yyv(%dlH-2U!}Xz#Y;Csuih8cok`FHBlss_g=^<|qB_-|)Ha#cU Z7;Xlb_-$sBRslMc!PC{xWt~$(697HSR73y( literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage6.png b/src/main/resources/assets/blossom/textures/block/fruiting_oak_leaves_stage6.png new file mode 100644 index 0000000000000000000000000000000000000000..79efd31730934a3b047ae33bfb7cc5b73c43977e GIT binary patch literal 339 zcmV-Z0j&OsP)Px$4M{{nR5*>jlCes|P#8u}%58-vLq~BCB#7W3_yE~k_dbD}-Sj;&y7>x@rfY`2 zfDj?brJLvw=#Un?x$ry0rq#AILGYVGxaWiK@WX#*(f7oRhLQxXEdRBdz{(%+`us$w z4fp3AX;d(s3sy&*xDK~|hr-EPx$2T4RhR5*>jlCes|P#A^38=@WJ;ML(S#i5Wv`VI~vxcCem1APLYp|2o5hOQ~3 z&mb8j8N|V%5-1V5N#u733Dgd~q2QVRqL(R}7)-0jzAvqFj^L6~qZkyK!#d0~8`?rFu}WP3;`egNOp%*ZvDA zGoegwZy-)k?=OSEZ^6w>*bk_aw=W=VEW` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_0.png b/src/main/resources/assets/blossom/textures/particle/blossom_0.png new file mode 100644 index 0000000000000000000000000000000000000000..9b10f569d6085629620ae681e0e3a2fce0cc60ea GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^%plAGA``#4_5vxEbVpxD28NA&HNOKV1NjmGJ|V6^ z`uom1@0Xwbcg^zulqvuB?*0Gb#sBZ$XEk)x0OdGJg8YIR{zJgkQz1q`F@fYnzcL`r z1H_zA%+?t5-UG-M@^oEal|F*7+KH8~+6nOT^D;V*+$^96G+pd5pztDnm{r-UW|dGgTe~DWM4f>yT*?&tMpt^Q;0W%i!ti=d#Wzp$P!o CTsJrX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_4.png b/src/main/resources/assets/blossom/textures/particle/blossom_4.png new file mode 100644 index 0000000000000000000000000000000000000000..1917b374544b5f57b09a5c5b50ac5b8f4c250f91 GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^%plAGA``#4_5vxEbVpxD28NA&HNOKV1NjmGJ|V6^ z`o+w{FS_^qyJq=+%9Q_m_x^wJ;{W&We@@Rb1Ilrf1o;Is{D*+6r$UT?VgkvDeq}(K z2Z%YLn5{A9y$6sj3S$!sV`E^r&7d3_8ZjLx%i!ti=d#Wzp$Py( Cw>66Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_6.png b/src/main/resources/assets/blossom/textures/particle/blossom_6.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4ed8e67f7a34a96b50bf5e16872a27fddffcf6 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^%plAGA``#4_5vxEbVpxD28NA&HNOKV1NjmGJ|V6^ z`uom1@0Xwbcg^zulqvuB?*0Gb#sBZ$XEk)x0OdGJg8YIR{zJgkQz1q`F@fYnzcL`r z1H_zA%+?t5-UB4(>Eal|F*7+KJv||TT{wq<(U8G#Pw2Enpd5pztDnm{r-UW|c^x+s literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/blossom/textures/particle/blossom_7.png b/src/main/resources/assets/blossom/textures/particle/blossom_7.png new file mode 100644 index 0000000000000000000000000000000000000000..1d0933694fc5254cd2227cc5026e6080368b0b55 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^%plAGA``#4_5vxEbVpxD28NA&HNOKV1NjmGJ|V6^ z`o+w{FS_^qyJq=+%9Q_m_x^wJ;{W&We@@Rb1Ilrf1o;Is{D*+6r$UT?VgkvDeq}(K z2Z%YLn5{A9y$49n)5S4_V`g$fa&kffv+x=QMs@}*gVpn7fN~6;u6{1-oD!MJDr;B3<$IRq}