diff --git a/gradle.properties b/gradle.properties index f91597c..045cfa0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=26.3.27 +mod_version=26.3.28 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/main/java/dev/tggamesyt/szar/ChorusEndStone.java b/src/main/java/dev/tggamesyt/szar/ChorusEndStone.java new file mode 100644 index 0000000..dcc8f38 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/ChorusEndStone.java @@ -0,0 +1,84 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.Fertilizable; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; +import net.minecraft.world.WorldView; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.feature.*; + +import java.util.List; +import java.util.Optional; + +public class ChorusEndStone extends EndSpreadableBlock implements Fertilizable { + + public ChorusEndStone(Settings settings) { + super(settings); + } + + @Override + public boolean isFertilizable(WorldView world, BlockPos pos, BlockState state, boolean isClient) { + return world.getBlockState(pos.up()).isAir(); + } + + @Override + public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) { + return true; + } + + @Override + public void grow(ServerWorld world, Random random, BlockPos pos, BlockState state) { + BlockPos start = pos.up(); + + // your custom placed feature (we'll register this next) + var registry = world.getRegistryManager().get(RegistryKeys.PLACED_FEATURE); + + var smallChorusFeature = registry.getEntry(Szar.SMALL_CHORUS_PLACED); + + outer: + for (int i = 0; i < 128; i++) { + BlockPos target = start; + + for (int j = 0; j < i / 16; j++) { + target = target.add( + random.nextInt(3) - 1, + (random.nextInt(3) - 1) * random.nextInt(3) / 2, + random.nextInt(3) - 1 + ); + + if (!world.getBlockState(target.down()).isOf(this) + || world.getBlockState(target).isFullCube(world, target)) { + continue outer; + } + } + + BlockState targetState = world.getBlockState(target); + + if (targetState.isAir()) { + + // 🌟 Rare: spawn chorus flower (~1/12 chance) + if (random.nextInt(12) == 0) { + world.setBlockState(target, Blocks.CHORUS_FLOWER.getDefaultState()); + continue; + } + + // 🌿 Common: spawn your custom feature + if (smallChorusFeature.isPresent()) { + smallChorusFeature.get().value().generateUnregistered( + world, + world.getChunkManager().getChunkGenerator(), + random, + target + ); + } + } + } + } +} diff --git a/src/main/java/dev/tggamesyt/szar/EndSpreadableBlock.java b/src/main/java/dev/tggamesyt/szar/EndSpreadableBlock.java new file mode 100644 index 0000000..74e4701 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/EndSpreadableBlock.java @@ -0,0 +1,77 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.*; +import net.minecraft.registry.tag.FluidTags; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.WorldView; +import net.minecraft.world.chunk.light.ChunkLightProvider; + +public abstract class EndSpreadableBlock extends SnowyBlock { + + protected EndSpreadableBlock(Settings settings) { + super(settings); + } + + private static boolean canSurvive(BlockState state, WorldView world, BlockPos pos) { + BlockPos up = pos.up(); + BlockState upState = world.getBlockState(up); + + if (upState.isOf(Blocks.SNOW) && upState.get(SnowBlock.LAYERS) == 1) { + return true; + } + + if (upState.getFluidState().getLevel() == 8) { + return false; + } + + int opacity = ChunkLightProvider.getRealisticOpacity( + world, state, pos, upState, up, Direction.UP, + upState.getOpacity(world, up) + ); + + return opacity < world.getMaxLightLevel(); + } + + private static boolean canSpread(BlockState state, WorldView world, BlockPos pos) { + BlockPos up = pos.up(); + return canSurvive(state, world, pos) + && !world.getFluidState(up).isIn(FluidTags.WATER); + } + + @Override + public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + + // ❌ Decay (like grass → dirt) + if (!canSurvive(state, world, pos)) { + world.setBlockState(pos, Blocks.END_STONE.getDefaultState()); + return; + } + + // 🌱 Spread + if (world.getLightLevel(pos.up()) >= 9) { + BlockState spreadState = this.getDefaultState(); + + for (int i = 0; i < 4; i++) { + BlockPos target = pos.add( + random.nextInt(3) - 1, + random.nextInt(5) - 3, + random.nextInt(3) - 1 + ); + + if (world.getBlockState(target).isOf(Blocks.END_STONE) + && canSpread(spreadState, world, target)) { + + world.setBlockState( + target, + spreadState.with(SNOWY, + world.getBlockState(target.up()).isOf(Blocks.SNOW) + ) + ); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/SmallChorusBlock.java b/src/main/java/dev/tggamesyt/szar/SmallChorusBlock.java new file mode 100644 index 0000000..d32e0e0 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/SmallChorusBlock.java @@ -0,0 +1,18 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.BlockState; +import net.minecraft.block.PlantBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; + +public class SmallChorusBlock extends PlantBlock { + + public SmallChorusBlock(Settings settings) { + super(settings); + } + + @Override + protected boolean canPlantOnTop(BlockState floor, BlockView world, BlockPos pos) { + return floor.isOf(Szar.CHORUS_ENDSTONE); + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 4d4391b..206e989 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -386,6 +386,9 @@ public class Szar implements ModInitializer { entries.add(Szar.BEAN); entries.add(Szar.CAN_OF_BEANS); entries.add(Szar.ALMOND_WATER); + // end update + entries.add(Szar.CHORUS_ENDSTONE_ITEM); + entries.add(Szar.SMALL_CHORUS_ITEM); // blueprint stuff entries.add(BlueprintBlocks.BLUEPRINT); entries.add(BlueprintBlocks.BLUEPRINT_DOOR_ITEM); @@ -1026,7 +1029,7 @@ public class Szar implements ModInitializer { }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { dispatcher.register( - LiteralArgumentBuilder.literal("szar") + LiteralArgumentBuilder.literal(MOD_ID) .requires(context -> context.hasPermissionLevel(2)) // /szar ny @@ -1444,7 +1447,30 @@ public class Szar implements ModInitializer { public static final Identifier CHESS_CLOSE_SCREEN = new Identifier(MOD_ID, "chess_close"); public static final Map chessActivePlayers = new java.util.HashMap<>(); - + public static final RegistryKey> SMALL_CHORUS_CONFIGURED = + RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, new Identifier(MOD_ID, "small_chorus")); + public static final RegistryKey SMALL_CHORUS_PLACED = + RegistryKey.of(RegistryKeys.PLACED_FEATURE, new Identifier(MOD_ID, "small_chorus_patch")); + public static final Block CHORUS_ENDSTONE = Registry.register( + Registries.BLOCK, + new Identifier(MOD_ID, "chorus_endstone"), + new Block(FabricBlockSettings.copyOf(Blocks.END_STONE)) + ); + public static final Item CHORUS_ENDSTONE_ITEM = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "chorus_endstone"), + new BlockItem(CHORUS_ENDSTONE, new FabricItemSettings()) + ); + public static final Block SMALL_CHORUS = Registry.register( + Registries.BLOCK, + new Identifier(MOD_ID, "small_chorus"), + new SmallChorusBlock(FabricBlockSettings.copyOf(Blocks.GRASS)) + ); + public static final Item SMALL_CHORUS_ITEM = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "small_chorus"), + new BlockItem(SMALL_CHORUS, new FabricItemSettings()) + ); // Blocks public static final TrackerBlock TRACKER_BLOCK = Registry.register( Registries.BLOCK, new Identifier(MOD_ID, "tracker"), @@ -2532,7 +2558,7 @@ public class Szar implements ModInitializer { MinecraftServer server = serverPlayer.getServer(); if (server == null) return; - if (!advancement.equals("szar")) { + if (!advancement.equals(MOD_ID)) { grantAdvancement(player, "szar"); } diff --git a/src/main/java/dev/tggamesyt/szar/mixin/ChorusFlowerBlockMixin.java b/src/main/java/dev/tggamesyt/szar/mixin/ChorusFlowerBlockMixin.java new file mode 100644 index 0000000..a4fbeb7 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/mixin/ChorusFlowerBlockMixin.java @@ -0,0 +1,54 @@ +package dev.tggamesyt.szar.mixin; + +import dev.tggamesyt.szar.Szar; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ChorusFlowerBlock; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ChorusFlowerBlock.class) +public abstract class ChorusFlowerBlockMixin { + + @Unique + private static final TagKey ENDSTONES = + TagKey.of(RegistryKeys.BLOCK, new Identifier(Szar.MOD_ID, "endstones")); + + /** + * 🔥 Redirect EVERY BlockState.isOf call inside ChorusFlowerBlock + * and replace END_STONE checks with tag checks + */ + @Redirect( + method = { + "canPlaceAt", + "randomTick", + "generate*", + "scheduledTick" + }, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;isOf(Lnet/minecraft/block/Block;)Z" + ) + ) + private boolean replaceEndStoneChecks(BlockState state, Block block) { + + // Replace ONLY END_STONE checks + if (block == Blocks.END_STONE) { + return state.isIn(ENDSTONES); + } + + // Everything else stays vanilla + return state.isOf(block); + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/mixin/ChorusPlantBlockMixin.java b/src/main/java/dev/tggamesyt/szar/mixin/ChorusPlantBlockMixin.java new file mode 100644 index 0000000..4181394 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/mixin/ChorusPlantBlockMixin.java @@ -0,0 +1,46 @@ +package dev.tggamesyt.szar.mixin; + +import dev.tggamesyt.szar.Szar; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ChorusPlantBlock; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; +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.Redirect; + +@Mixin(ChorusPlantBlock.class) +public abstract class ChorusPlantBlockMixin { + + @Unique + private static final TagKey ENDSTONES = + TagKey.of(RegistryKeys.BLOCK, new Identifier(Szar.MOD_ID, "endstones")); + + /** + * 🔥 Replace ALL END_STONE checks in ChorusPlantBlock + */ + @Redirect( + method = { + "withConnectionProperties", + "getStateForNeighborUpdate", + "canPlaceAt" + }, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;isOf(Lnet/minecraft/block/Block;)Z" + ) + ) + private boolean replaceEndStoneChecks(BlockState state, Block block) { + + // Replace END_STONE with your tag + if (block == Blocks.END_STONE) { + return state.isIn(ENDSTONES); + } + + return state.isOf(block); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/blockstates/chorus_endstone.json b/src/main/resources/assets/szar/blockstates/chorus_endstone.json new file mode 100644 index 0000000..f359c52 --- /dev/null +++ b/src/main/resources/assets/szar/blockstates/chorus_endstone.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "szar:block/chorus_endstone" + } + } +} diff --git a/src/main/resources/assets/szar/blockstates/small_chorus.json b/src/main/resources/assets/szar/blockstates/small_chorus.json new file mode 100644 index 0000000..07a1be5 --- /dev/null +++ b/src/main/resources/assets/szar/blockstates/small_chorus.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "szar:block/small_chorus" + } + } +} diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index ac7d9c3..8e28c9b 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -198,5 +198,8 @@ "block.szar.blueprint_trapdoor": "Blueprint Trapdoor", "block.szar.blueprint_wall": "Blueprint Wall", "block.szar.blueprint_fence": "Blueprint Fence", - "item.szar.blueprint": "Blueprint" + "item.szar.blueprint": "Blueprint", + + "block.szar.chorus_endstone": "Chorus EndStone", + "block.szar.small_chorus": "Small Chorus" } diff --git a/src/main/resources/assets/szar/models/block/chorus_endstone.json b/src/main/resources/assets/szar/models/block/chorus_endstone.json new file mode 100644 index 0000000..bf03cf3 --- /dev/null +++ b/src/main/resources/assets/szar/models/block/chorus_endstone.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/cube_bottom_top", + "textures": { + "side": "szar:block/end_stone_grass", + "bottom": "szar:block/end_stone", + "top": "szar:block/chorus_top" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/models/block/small_chorus.json b/src/main/resources/assets/szar/models/block/small_chorus.json new file mode 100644 index 0000000..af80304 --- /dev/null +++ b/src/main/resources/assets/szar/models/block/small_chorus.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cross", + "textures": { + "cross": "szar:block/small_chorus" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/models/item/chorus_endstone.json b/src/main/resources/assets/szar/models/item/chorus_endstone.json new file mode 100644 index 0000000..7f03a4a --- /dev/null +++ b/src/main/resources/assets/szar/models/item/chorus_endstone.json @@ -0,0 +1,3 @@ +{ + "parent": "szar:block/chorus_endstone" +} diff --git a/src/main/resources/assets/szar/models/item/small_chorus.json b/src/main/resources/assets/szar/models/item/small_chorus.json new file mode 100644 index 0000000..3590cc8 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/small_chorus.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "szar:block/small_chorus" + } +} diff --git a/src/main/resources/assets/szar/textures/block/chorus_flower.png b/src/main/resources/assets/szar/textures/block/chorus_flower.png new file mode 100644 index 0000000..d075807 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_flower.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_flower_dead.png b/src/main/resources/assets/szar/textures/block/chorus_flower_dead.png new file mode 100644 index 0000000..21f3155 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_flower_dead.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_plant.png b/src/main/resources/assets/szar/textures/block/chorus_plant.png new file mode 100644 index 0000000..39924b9 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_plant.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_shuffle.png b/src/main/resources/assets/szar/textures/block/chorus_shuffle.png new file mode 100644 index 0000000..e6afb4d Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_shuffle.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_shuffle_topthingy.png b/src/main/resources/assets/szar/textures/block/chorus_shuffle_topthingy.png new file mode 100644 index 0000000..1c34484 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_shuffle_topthingy.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_top.png b/src/main/resources/assets/szar/textures/block/chorus_top.png new file mode 100644 index 0000000..bce54a7 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_top.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_top_final_ithink.png b/src/main/resources/assets/szar/textures/block/chorus_top_final_ithink.png new file mode 100644 index 0000000..499a9f7 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_top_final_ithink.png differ diff --git a/src/main/resources/assets/szar/textures/block/chorus_topthingy_forside.png b/src/main/resources/assets/szar/textures/block/chorus_topthingy_forside.png new file mode 100644 index 0000000..61eb7b4 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/chorus_topthingy_forside.png differ diff --git a/src/main/resources/assets/szar/textures/block/choruscolor.png b/src/main/resources/assets/szar/textures/block/choruscolor.png new file mode 100644 index 0000000..20b4e4e Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/choruscolor.png differ diff --git a/src/main/resources/assets/szar/textures/block/end_stone.png b/src/main/resources/assets/szar/textures/block/end_stone.png new file mode 100644 index 0000000..6d747c0 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/end_stone.png differ diff --git a/src/main/resources/assets/szar/textures/block/end_stone_grass.png b/src/main/resources/assets/szar/textures/block/end_stone_grass.png new file mode 100644 index 0000000..1a115fe Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/end_stone_grass.png differ diff --git a/src/main/resources/assets/szar/textures/block/grass_block_side_overlay.png b/src/main/resources/assets/szar/textures/block/grass_block_side_overlay.png new file mode 100644 index 0000000..4abf8fc Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/grass_block_side_overlay.png differ diff --git a/src/main/resources/assets/szar/textures/block/grass_block_top.png b/src/main/resources/assets/szar/textures/block/grass_block_top.png new file mode 100644 index 0000000..eaa7e45 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/grass_block_top.png differ diff --git a/src/main/resources/assets/szar/textures/block/lowkey_mightuse_ts.png b/src/main/resources/assets/szar/textures/block/lowkey_mightuse_ts.png new file mode 100644 index 0000000..03fbd11 Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/lowkey_mightuse_ts.png differ diff --git a/src/main/resources/assets/szar/textures/block/small_chorus.png b/src/main/resources/assets/szar/textures/block/small_chorus.png new file mode 100644 index 0000000..da6be8e Binary files /dev/null and b/src/main/resources/assets/szar/textures/block/small_chorus.png differ diff --git a/src/main/resources/data/szar/tags/blocks/endstones.json b/src/main/resources/data/szar/tags/blocks/endstones.json new file mode 100644 index 0000000..e0c0efa --- /dev/null +++ b/src/main/resources/data/szar/tags/blocks/endstones.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "minecraft:end_stone", + "szar:chorus_endstone" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/szar/worldgen/configured_feature/small_chorus.json b/src/main/resources/data/szar/worldgen/configured_feature/small_chorus.json new file mode 100644 index 0000000..45d9fe5 --- /dev/null +++ b/src/main/resources/data/szar/worldgen/configured_feature/small_chorus.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:random_patch", + "config": { + "feature": { + "feature": { + "type": "minecraft:simple_block", + "config": { + "to_place": { + "type": "minecraft:simple_state_provider", + "state": { + "Name": "szar:small_chorus_block" + } + } + } + }, + "placement": [ + { + "type": "minecraft:block_predicate_filter", + "predicate": { + "type": "minecraft:matching_blocks", + "blocks": "minecraft:air" + } + } + ] + }, + "tries": 32, + "xz_spread": 7, + "y_spread": 3 + } +} \ No newline at end of file diff --git a/src/main/resources/data/szar/worldgen/placed_feature/small_chorus_patch.json b/src/main/resources/data/szar/worldgen/placed_feature/small_chorus_patch.json new file mode 100644 index 0000000..0204271 --- /dev/null +++ b/src/main/resources/data/szar/worldgen/placed_feature/small_chorus_patch.json @@ -0,0 +1,9 @@ +{ + "feature": "szar:small_chorus", + "placement": [ + { "type": "minecraft:count", "count": 5 }, + { "type": "minecraft:in_square" }, + { "type": "minecraft:heightmap", "heightmap": "WORLD_SURFACE_WG" }, + { "type": "minecraft:biome" } + ] +} \ No newline at end of file diff --git a/src/main/resources/szar.mixins.json b/src/main/resources/szar.mixins.json index ff148ac..96eb005 100644 --- a/src/main/resources/szar.mixins.json +++ b/src/main/resources/szar.mixins.json @@ -4,6 +4,8 @@ "package": "dev.tggamesyt.szar.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "ChorusFlowerBlockMixin", + "ChorusPlantBlockMixin", "CraftingScreenHandlerMixin", "CraftingScreenHandlerMixin2", "EntityCollisionMixin",