end update vol 1

This commit is contained in:
2026-03-28 18:05:20 +01:00
parent 7c779124dc
commit 0501d8ee09
33 changed files with 398 additions and 5 deletions

View File

@@ -6,7 +6,7 @@ minecraft_version=1.20.1
yarn_mappings=1.20.1+build.10 yarn_mappings=1.20.1+build.10
loader_version=0.18.3 loader_version=0.18.3
# Mod Properties # Mod Properties
mod_version=26.3.27 mod_version=26.3.28
maven_group=dev.tggamesyt maven_group=dev.tggamesyt
archives_base_name=szar archives_base_name=szar
# Dependencies # Dependencies

View File

@@ -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
);
}
}
}
}
}

View File

@@ -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)
)
);
}
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -386,6 +386,9 @@ public class Szar implements ModInitializer {
entries.add(Szar.BEAN); entries.add(Szar.BEAN);
entries.add(Szar.CAN_OF_BEANS); entries.add(Szar.CAN_OF_BEANS);
entries.add(Szar.ALMOND_WATER); entries.add(Szar.ALMOND_WATER);
// end update
entries.add(Szar.CHORUS_ENDSTONE_ITEM);
entries.add(Szar.SMALL_CHORUS_ITEM);
// blueprint stuff // blueprint stuff
entries.add(BlueprintBlocks.BLUEPRINT); entries.add(BlueprintBlocks.BLUEPRINT);
entries.add(BlueprintBlocks.BLUEPRINT_DOOR_ITEM); entries.add(BlueprintBlocks.BLUEPRINT_DOOR_ITEM);
@@ -1026,7 +1029,7 @@ public class Szar implements ModInitializer {
}); });
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register( dispatcher.register(
LiteralArgumentBuilder.<ServerCommandSource>literal("szar") LiteralArgumentBuilder.<ServerCommandSource>literal(MOD_ID)
.requires(context -> context.hasPermissionLevel(2)) .requires(context -> context.hasPermissionLevel(2))
// /szar ny // /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 Identifier CHESS_CLOSE_SCREEN = new Identifier(MOD_ID, "chess_close");
public static final Map<UUID, BlockPos> chessActivePlayers = new java.util.HashMap<>(); public static final Map<UUID, BlockPos> chessActivePlayers = new java.util.HashMap<>();
public static final RegistryKey<ConfiguredFeature<?, ?>> SMALL_CHORUS_CONFIGURED =
RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, new Identifier(MOD_ID, "small_chorus"));
public static final RegistryKey<PlacedFeature> 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 // Blocks
public static final TrackerBlock TRACKER_BLOCK = Registry.register( public static final TrackerBlock TRACKER_BLOCK = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "tracker"), Registries.BLOCK, new Identifier(MOD_ID, "tracker"),
@@ -2532,7 +2558,7 @@ public class Szar implements ModInitializer {
MinecraftServer server = serverPlayer.getServer(); MinecraftServer server = serverPlayer.getServer();
if (server == null) return; if (server == null) return;
if (!advancement.equals("szar")) { if (!advancement.equals(MOD_ID)) {
grantAdvancement(player, "szar"); grantAdvancement(player, "szar");
} }

View File

@@ -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<Block> 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);
}
}

View File

@@ -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<Block> 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);
}
}

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "szar:block/chorus_endstone"
}
}
}

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "szar:block/small_chorus"
}
}
}

View File

@@ -198,5 +198,8 @@
"block.szar.blueprint_trapdoor": "Blueprint Trapdoor", "block.szar.blueprint_trapdoor": "Blueprint Trapdoor",
"block.szar.blueprint_wall": "Blueprint Wall", "block.szar.blueprint_wall": "Blueprint Wall",
"block.szar.blueprint_fence": "Blueprint Fence", "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"
} }

View File

@@ -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"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "block/cross",
"textures": {
"cross": "szar:block/small_chorus"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "szar:block/chorus_endstone"
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "szar:block/small_chorus"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

View File

@@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"minecraft:end_stone",
"szar:chorus_endstone"
]
}

View File

@@ -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
}
}

View File

@@ -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" }
]
}

View File

@@ -4,6 +4,8 @@
"package": "dev.tggamesyt.szar.mixin", "package": "dev.tggamesyt.szar.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"ChorusFlowerBlockMixin",
"ChorusPlantBlockMixin",
"CraftingScreenHandlerMixin", "CraftingScreenHandlerMixin",
"CraftingScreenHandlerMixin2", "CraftingScreenHandlerMixin2",
"EntityCollisionMixin", "EntityCollisionMixin",