backrooms

This commit is contained in:
2026-03-17 18:02:19 +01:00
parent 924c1a1bf8
commit 1511dd68ed
189 changed files with 886 additions and 138 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.17 mod_version=26.3.17.1
maven_group=dev.tggamesyt maven_group=dev.tggamesyt
archives_base_name=szar archives_base_name=szar
# Dependencies # Dependencies

View File

@@ -23,6 +23,7 @@ import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreens; import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactories;
import net.minecraft.client.render.entity.EmptyEntityRenderer; import net.minecraft.client.render.entity.EmptyEntityRenderer;
import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.FlyingItemEntityRenderer; import net.minecraft.client.render.entity.FlyingItemEntityRenderer;
@@ -361,10 +362,10 @@ public class SzarClient implements ClientModInitializer {
}); });
} }
); );
/*BlockEntityRendererRegistry.register( BlockEntityRendererFactories.register(
SLOT_MACHINE_BLOCKENTITY, Szar.TRACKER_BLOCK_ENTITY,
SlotMachineRenderer::new TGTrackerBlockRenderer::new
);*/ );
HandledScreens.register(Szar.SLOT_MACHINE_SCREEN_HANDLER_TYPE, SlotMachineScreen::new); HandledScreens.register(Szar.SLOT_MACHINE_SCREEN_HANDLER_TYPE, SlotMachineScreen::new);
HandledScreens.register(Szar.ROULETTE_SCREEN_HANDLER_TYPE, RouletteScreen::new); HandledScreens.register(Szar.ROULETTE_SCREEN_HANDLER_TYPE, RouletteScreen::new);
EntityRendererRegistry.register(Szar.BULLET, BulletRenderer::new); EntityRendererRegistry.register(Szar.BULLET, BulletRenderer::new);

View File

@@ -0,0 +1,72 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.Szar;
import dev.tggamesyt.szar.TrackerBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.client.render.WorldRenderer;
public class TGTrackerBlockRenderer implements BlockEntityRenderer<TrackerBlockEntity> {
private final ItemRenderer itemRenderer;
public TGTrackerBlockRenderer(BlockEntityRendererFactory.Context ctx) {
this.itemRenderer = ctx.getItemRenderer();
}
@Override
public void render(TrackerBlockEntity entity, float tickDelta, MatrixStack matrices,
VertexConsumerProvider vertexConsumers, int light, int overlay) {
MinecraftClient client = MinecraftClient.getInstance();
PlayerEntity player = client.player;
if (player == null) return;
boolean holding = player.getMainHandStack().isOf(Szar.TRACKER_BLOCK_ITEM.asItem())
|| player.getOffHandStack().isOf(Szar.TRACKER_BLOCK_ITEM.asItem());
if (!holding) return;
BlockPos pos = entity.getPos();
int lightLevel = WorldRenderer.getLightmapCoordinates(entity.getWorld(), pos);
// Use the actual camera yaw and pitch — this is what barrier does
// Camera yaw/pitch are already available from the camera object
float cameraYaw = client.gameRenderer.getCamera().getYaw();
float cameraPitch = client.gameRenderer.getCamera().getPitch();
matrices.push();
matrices.translate(0.5, 0.25, 0.5);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-cameraYaw));
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(cameraPitch));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180f));
matrices.scale(2f, 2f, 2f);
ItemStack stack = new ItemStack(Szar.TRACKER_BLOCK_ITEM.asItem());
BakedModel model = itemRenderer.getModel(stack, entity.getWorld(), null, 0);
itemRenderer.renderItem(
stack,
ModelTransformationMode.GROUND,
false,
matrices,
vertexConsumers,
lightLevel,
overlay,
model
);
matrices.pop();
}
}

View File

@@ -10,6 +10,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(GameRenderer.class) @Mixin(GameRenderer.class)

View File

@@ -0,0 +1,235 @@
package dev.tggamesyt.szar;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.tggamesyt.szar.Szar;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.registry.RegistryCodecs;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.HeightLimitView;
import net.minecraft.world.Heightmap;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeKeys;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.biome.source.FixedBiomeSource;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.Blender;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.chunk.VerticalBlockSample;
import net.minecraft.world.gen.noise.NoiseConfig;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
public class BackroomsChunkGenerator extends ChunkGenerator {
// Y layout constants
private static final int FLOOR_Y = 4; // y=4 is the floor block
private static final int CEILING_Y = 9; // y=9 is the ceiling block (4 air blocks between: 5,6,7,8)
private static final int WALL_BASE_Y = 5; // y=5 is WALL_BOTTOM_BLOCK
private static final int WALL_TOP_Y = 8; // y=8 is top wall block (below ceiling)
// Glowstone grid spacing
private static final int GLOW_SPACING = 5;
public static final Codec<BackroomsChunkGenerator> CODEC =
RecordCodecBuilder.create(instance -> instance.group(
Biome.REGISTRY_CODEC
.fieldOf("biome")
.forGetter(g -> g.biomeEntry)
).apply(instance, BackroomsChunkGenerator::new));
private final RegistryEntry<Biome> biomeEntry;
public BackroomsChunkGenerator(RegistryEntry<Biome> biomeEntry) {
super(new FixedBiomeSource(biomeEntry));
this.biomeEntry = biomeEntry;
}
@Override
protected Codec<? extends ChunkGenerator> getCodec() {
return CODEC;
}
@Override
public CompletableFuture<Chunk> populateNoise(
Executor executor, Blender blender, NoiseConfig noiseConfig,
StructureAccessor structureAccessor, Chunk chunk) {
int chunkX = chunk.getPos().x;
int chunkZ = chunk.getPos().z;
for (int lx = 0; lx < 16; lx++) {
for (int lz = 0; lz < 16; lz++) {
int worldX = chunkX * 16 + lx;
int worldZ = chunkZ * 16 + lz;
// Deterministic per-column open/wall decision using world seed-like hash
boolean isOpen = isOpenSpace(worldX, worldZ);
// Floor — always placed
chunk.setBlockState(new BlockPos(lx, FLOOR_Y, lz),
Szar.PLASTIC.getDefaultState(), false);
// Below floor — fill with plastic so there's no void underneath
for (int y = 0; y < FLOOR_Y; y++) {
chunk.setBlockState(new BlockPos(lx, y, lz),
Szar.PLASTIC.getDefaultState(), false);
}
// Ceiling
boolean isGlowstone = isGlowstonePos(worldX, worldZ);
BlockState ceilingBlock = isGlowstone
? Blocks.GLOWSTONE.getDefaultState()
: Szar.CEILING.getDefaultState();
chunk.setBlockState(new BlockPos(lx, CEILING_Y, lz), ceilingBlock, false);
// Above ceiling — solid wall block fill so there's no void above
for (int y = CEILING_Y + 1; y < 64; y++) {
chunk.setBlockState(new BlockPos(lx, y, lz),
Szar.CEILING.getDefaultState(), false);
}
if (isOpen) {
// Air inside the room
for (int y = WALL_BASE_Y; y <= WALL_TOP_Y; y++) {
chunk.setBlockState(new BlockPos(lx, y, lz),
Blocks.AIR.getDefaultState(), false);
}
} else {
// Wall column
chunk.setBlockState(new BlockPos(lx, WALL_BASE_Y, lz),
Szar.WALL_BOTTOM_BLOCK.getDefaultState(), false);
for (int y = WALL_BASE_Y + 1; y <= WALL_TOP_Y; y++) {
chunk.setBlockState(new BlockPos(lx, y, lz),
Szar.WALL_BLOCK.getDefaultState(), false);
}
}
}
}
return CompletableFuture.completedFuture(chunk);
}
/**
* Determines if a world column is open space or a wall.
* Uses a combination of large-scale and small-scale noise simulation
* via a seeded hash to create wide rooms with occasional walls.
*/
private boolean isOpenSpace(int x, int z) {
// Smaller cells = more frequent walls
int cellSize = 8; // was 16
int cellX = Math.floorDiv(x, cellSize);
int cellZ = Math.floorDiv(z, cellSize);
int localX = Math.floorMod(x, cellSize);
int localZ = Math.floorMod(z, cellSize);
long cellHash = hash(cellX, cellZ);
// ~50% chance of vertical wall, ~50% chance of horizontal wall
boolean hasVerticalWall = (cellHash & 0x1) == 0;
boolean hasHorizontalWall = ((cellHash >> 1) & 0x1) == 0;
if (hasVerticalWall) {
int wallPos = 2 + (int) ((cellHash >> 4) & 0x3); // 2-5, keeps wall away from cell edge
int doorPos = (int) ((cellHash >> 8) & 0x7); // 0-7
int doorWidth = 2 + (int) ((cellHash >> 12) & 0x1); // 2-3 wide door
if (localX == wallPos) {
boolean inDoor = localZ >= doorPos && localZ < doorPos + doorWidth;
if (!inDoor) return false;
}
}
if (hasHorizontalWall) {
int wallPos = 2 + (int) ((cellHash >> 16) & 0x3);
int doorPos = (int) ((cellHash >> 20) & 0x7);
int doorWidth = 2 + (int) ((cellHash >> 24) & 0x1);
if (localZ == wallPos) {
boolean inDoor = localX >= doorPos && localX < doorPos + doorWidth;
if (!inDoor) return false;
}
}
return true;
}
private boolean isGlowstonePos(int x, int z) {
// Grid every GLOW_SPACING blocks, offset slightly so it's not always on chunk borders
return (Math.floorMod(x + 2, GLOW_SPACING) == 0)
&& (Math.floorMod(z + 2, GLOW_SPACING) == 0);
}
/**
* Simple integer hash for deterministic world generation.
* Not seeded — same world always generates the same backrooms.
* If you want seed-dependent generation, pass in world seed too.
*/
private long hash(int x, int z) {
long h = 374761393L;
h += x * 2654435761L;
h ^= h >> 17;
h += z * 2246822519L;
h ^= h >> 13;
h *= 3266489917L;
h ^= h >> 16;
return h & 0xFFFFFFFFL;
}
// --- Required overrides ---
@Override
public void carve(ChunkRegion chunk, long seed, NoiseConfig noiseConfig,
BiomeAccess access, StructureAccessor structureAccessor,
Chunk chunk2, GenerationStep.Carver carver) {}
@Override
public void buildSurface(ChunkRegion region, StructureAccessor structures,
NoiseConfig noiseConfig, Chunk chunk) {}
@Override
public void populateEntities(ChunkRegion region) {}
@Override
public int getWorldHeight() { return 64; }
@Override
public int getSeaLevel() { return -1; }
@Override
public int getMinimumY() { return 0; }
@Override
public int getHeight(int x, int z, Heightmap.Type heightmap,
HeightLimitView world, NoiseConfig noiseConfig) {
return CEILING_Y;
}
@Override
public VerticalBlockSample getColumnSample(int x, int z,
HeightLimitView world,
NoiseConfig noiseConfig) {
BlockState[] states = new BlockState[64];
for (int y = 0; y < 64; y++) {
if (y < FLOOR_Y) states[y] = Szar.PLASTIC.getDefaultState();
else if (y == FLOOR_Y) states[y] = Szar.PLASTIC.getDefaultState();
else if (y <= WALL_TOP_Y) states[y] = isOpenSpace(x, z)
? Blocks.AIR.getDefaultState()
: Szar.WALL_BLOCK.getDefaultState();
else if (y == CEILING_Y) states[y] = Szar.CEILING.getDefaultState();
else states[y] = Szar.CEILING.getDefaultState();
}
return new VerticalBlockSample(0, states);
}
@Override
public void getDebugHudText(List<String> text, NoiseConfig noiseConfig,
BlockPos pos) {}
}

View File

@@ -0,0 +1,21 @@
package dev.tggamesyt.szar;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
public class BackroomsChunkGeneratorConfig {
public static final Codec<BackroomsChunkGeneratorConfig> CODEC =
RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("floor_y").forGetter(c -> c.floorY)
).apply(instance, BackroomsChunkGeneratorConfig::new));
public static final BackroomsChunkGeneratorConfig DEFAULT =
new BackroomsChunkGeneratorConfig(4);
public final int floorY;
public BackroomsChunkGeneratorConfig(int floorY) {
this.floorY = floorY;
}
}

View File

@@ -4,6 +4,7 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -39,104 +40,103 @@ public class PortalBlock extends Block {
} }
@Override @Override
public void onEntityCollision(BlockState state, World world, BlockPos pos, public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
Entity entity) {
if (world.isClient) return; if (world.isClient) return;
if (!(entity instanceof ServerPlayerEntity player)) return; if (!(entity instanceof ServerPlayerEntity player)) return;
// Cooldown check — 3 seconds
long now = world.getTime(); long now = world.getTime();
Long last = cooldowns.get(player.getUuid()); Long last = cooldowns.get(player.getUuid());
if (last != null && now - last < 60) return; if (last != null && now - last < 60) return;
cooldowns.put(player.getUuid(), now); cooldowns.put(player.getUuid(), now);
// Find the TrackerBlock above (within 5 blocks)
TrackerBlockEntity tracker = findTrackerAbove(world, pos); TrackerBlockEntity tracker = findTrackerAbove(world, pos);
if (tracker == null) return; if (tracker == null) return;
MinecraftServer server = world.getServer(); MinecraftServer server = world.getServer();
if (server == null) return; if (server == null) return;
if (!tracker.isNetherSide) { // Detect dimension instead of reading isNetherSide
// --- OVERWORLD → NETHER --- if (world.getRegistryKey() == World.OVERWORLD) {
teleportToNether(player, tracker, server, pos); teleportToNether(player, tracker, server, pos);
} else { } else if (world.getRegistryKey() == Szar.BACKROOMS_KEY) {
// --- NETHER → OVERWORLD ---
teleportToOverworld(player, tracker, server); teleportToOverworld(player, tracker, server);
} }
} }
private void teleportToNether(ServerPlayerEntity player, TrackerBlockEntity tracker, private void teleportToNether(ServerPlayerEntity player, TrackerBlockEntity tracker,
MinecraftServer server, BlockPos portalPos) { MinecraftServer server, BlockPos portalPos) {
// Save return position (a few blocks above entry) // Save where this player entered — stored persistently so nether portal can read it
tracker.returnX = player.getX(); NbtCompound tag = getOrCreateCustomData(player);
tracker.returnY = player.getY() + 3; tag.putDouble("EntryX", player.getX());
tracker.returnZ = player.getZ(); tag.putDouble("EntryY", player.getY() + 6); // a few blocks above so they don't fall back in
tracker.markDirty(); tag.putDouble("EntryZ", player.getZ());
tag.putInt("OwnerTrackerX", tracker.getPos().getX());
tag.putInt("OwnerTrackerY", tracker.getPos().getY());
tag.putInt("OwnerTrackerZ", tracker.getPos().getZ());
// Save inventory // Save inventory
NbtList savedInventory = saveInventory(player); NbtList savedInventory = saveInventory(player);
saveInventoryToPlayer(player, savedInventory);
// Clear inventory // Clear inventory
player.getInventory().clear(); player.getInventory().clear();
// Register player as inside // Register player in tracker
tracker.addPlayer(player.getUuid()); tracker.addPlayer(player.getUuid());
// Teleport to nether // Teleport
ServerWorld nether = server.getWorld(World.NETHER); ServerWorld nether = server.getWorld(Szar.BACKROOMS_KEY);
if (nether == null) return; if (nether == null) return;
double netherX = player.getX(); double netherX = player.getX();
double netherZ = player.getZ(); double netherZ = player.getZ();
double netherY = findSafeY(nether, (int) netherX, (int) netherZ); double netherY = findSafeY(nether, (int) netherX, (int) netherZ);
// Store saved inventory in player's persistent data player.teleport(nether, netherX, netherY, netherZ,
NbtCompound persistent = player.writeNbt(new NbtCompound());
// We use a custom data attachment via the player's nbt
saveInventoryToPlayer(player, savedInventory);
// Store which overworld tracker owns this player
NbtCompound tag = getOrCreateCustomData(player);
tag.putInt("OwnerTrackerX", tracker.getPos().getX());
tag.putInt("OwnerTrackerY", tracker.getPos().getY());
tag.putInt("OwnerTrackerZ", tracker.getPos().getZ());
// Generate nether-side portal structure
BlockPos netherPortalPos = new BlockPos((int) netherX, (int) netherY, (int) netherZ);
generateNetherPortal(nether, netherPortalPos, tracker);
// Teleport
player.teleport(nether, netherX, netherY + 1, netherZ,
player.getYaw(), player.getPitch()); player.getYaw(), player.getPitch());
} }
private void teleportToOverworld(ServerPlayerEntity player, TrackerBlockEntity tracker, private void teleportToOverworld(ServerPlayerEntity player, TrackerBlockEntity netherTracker,
MinecraftServer server) { MinecraftServer server) {
// Restore inventory NbtCompound tag = getOrCreateCustomData(player);
restoreInventoryToPlayer(player); double returnX = tag.getDouble("EntryX");
double returnY = tag.getDouble("EntryY");
double returnZ = tag.getDouble("EntryZ");
// Remove from nether tracker // Read overworld tracker pos
tracker.removePlayer(player.getUuid()); BlockPos owTrackerPos = null;
if (tag.contains("OwnerTrackerX")) {
owTrackerPos = new BlockPos(
tag.getInt("OwnerTrackerX"),
tag.getInt("OwnerTrackerY"),
tag.getInt("OwnerTrackerZ")
);
}
PortalBlock.restoreInventory(player, server);
netherTracker.removePlayer(player.getUuid());
// Find overworld paired tracker and remove from that too
ServerWorld overworld = server.getWorld(World.OVERWORLD); ServerWorld overworld = server.getWorld(World.OVERWORLD);
if (overworld != null && tracker.pairedTrackerPos != null) { ServerWorld nether = server.getWorld(Szar.BACKROOMS_KEY);
if (overworld.getBlockEntity(tracker.pairedTrackerPos)
instanceof TrackerBlockEntity owTracker) { // Clean up nether side if empty
if (!netherTracker.hasPlayers() && nether != null) {
TrackerBlock.restoreAndCleanup(nether,
netherTracker.getPos(), netherTracker, server);
}
// Clean up overworld tracker too
if (owTrackerPos != null && overworld != null) {
if (overworld.getBlockEntity(owTrackerPos) instanceof TrackerBlockEntity owTracker) {
owTracker.removePlayer(player.getUuid()); owTracker.removePlayer(player.getUuid());
// If no players left, remove both trackers and their portal blocks
if (!owTracker.hasPlayers()) { if (!owTracker.hasPlayers()) {
removePortalStructure(overworld, tracker.pairedTrackerPos); TrackerBlock.restoreAndCleanup(overworld, owTrackerPos, owTracker, server);
removePortalStructure((ServerWorld) player.getWorld(), tracker.getPos());
} }
} }
} }
// Teleport back (a few blocks above entry) if (overworld == null) return;
player.teleport(overworld, player.teleport(overworld, returnX, returnY, returnZ,
tracker.returnX, tracker.returnY, tracker.returnZ,
player.getYaw(), player.getPitch()); player.getYaw(), player.getPitch());
} }
@@ -155,8 +155,9 @@ public class PortalBlock extends Block {
} }
private double findSafeY(ServerWorld world, int x, int z) { private double findSafeY(ServerWorld world, int x, int z) {
// Search from y=100 downward for solid ground with 2 air blocks above // For backrooms, search from y=8 downward only
for (int y = 100; y > 10; y--) { int startY = world.getRegistryKey() == Szar.BACKROOMS_KEY ? 8 : 100;
for (int y = startY; y > 1; y--) {
BlockPos feet = new BlockPos(x, y, z); BlockPos feet = new BlockPos(x, y, z);
BlockPos head = feet.up(); BlockPos head = feet.up();
BlockPos ground = feet.down(); BlockPos ground = feet.down();
@@ -166,35 +167,7 @@ public class PortalBlock extends Block {
return y; return y;
} }
} }
return 64; // fallback return 5; // fallback to inside the backrooms
}
private void generateNetherPortal(ServerWorld nether, BlockPos portalPos,
TrackerBlockEntity overworldTracker) {
// Place TrackerBlock 4 blocks above portal
BlockPos trackerPos = portalPos.up(4);
nether.setBlockState(trackerPos, Szar.TRACKER_BLOCK.getDefaultState());
if (nether.getBlockEntity(trackerPos) instanceof TrackerBlockEntity netherTracker) {
netherTracker.isNetherSide = true;
netherTracker.returnX = overworldTracker.returnX;
netherTracker.returnY = overworldTracker.returnY;
netherTracker.returnZ = overworldTracker.returnZ;
netherTracker.pairedTrackerPos = overworldTracker.getPos();
overworldTracker.pairedTrackerPos = trackerPos;
overworldTracker.markDirty();
netherTracker.markDirty();
}
// Place portal block at bottom
nether.setBlockState(portalPos, Szar.PORTAL_BLOCK.getDefaultState());
}
private void removePortalStructure(ServerWorld world, BlockPos trackerPos) {
// Remove tracker
world.removeBlock(trackerPos, false);
// Remove portal block (4 below)
world.removeBlock(trackerPos.down(4), false);
} }
// Inventory persistence via player NBT custom data // Inventory persistence via player NBT custom data
@@ -249,4 +222,45 @@ public class PortalBlock extends Block {
player.getServer().getWorld(World.OVERWORLD) player.getServer().getWorld(World.OVERWORLD)
).getOrCreatePlayerData(player.getUuid()); ).getOrCreatePlayerData(player.getUuid());
} }
// Change the signature in PortalBlock.java
public static void restoreInventory(ServerPlayerEntity player, MinecraftServer server) {
PortalDataState state = PortalDataState.getOrCreate(
server.getWorld(World.OVERWORLD)
);
NbtCompound tag = state.getOrCreatePlayerData(player.getUuid());
if (!tag.contains(INV_KEY)) return;
NbtList list = tag.getList(INV_KEY, 10);
// Build list of saved stacks
List<ItemStack> savedStacks = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
NbtCompound entry = list.getCompound(i);
ItemStack stack = ItemStack.fromNbt(entry);
if (!stack.isEmpty()) {
savedStacks.add(stack);
}
}
// Try to insert each saved stack into the current inventory
PlayerInventory inv = player.getInventory();
for (ItemStack saved : savedStacks) {
// insertStack tries to stack with existing items first, then finds empty slot
boolean inserted = inv.insertStack(saved);
if (!inserted || !saved.isEmpty()) {
// Inventory full — drop remainder at player's position
ItemEntity drop = new ItemEntity(
player.getWorld(),
player.getX(), player.getY(), player.getZ(),
saved.copy()
);
drop.setPickupDelay(0);
player.getWorld().spawnEntity(drop);
}
}
state.removePlayerData(player.getUuid());
}
} }

View File

@@ -172,7 +172,10 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "play_video"); new Identifier(MOD_ID, "play_video");
public static final Identifier CONFIG_SYNC = new Identifier(MOD_ID, "config_sync"); public static final Identifier CONFIG_SYNC = new Identifier(MOD_ID, "config_sync");
public static final RegistryKey<World> BACKROOMS_KEY = RegistryKey.of(
RegistryKeys.WORLD,
new Identifier(MOD_ID, "backrooms")
);
public static final Block SZAR_BLOCK = public static final Block SZAR_BLOCK =
new SzarBlock(); new SzarBlock();
public static final Block URANIUM_BLOCK = public static final Block URANIUM_BLOCK =
@@ -349,36 +352,6 @@ public class Szar implements ModInitializer {
.displayName(Text.translatable("itemgroup.szar_group")) .displayName(Text.translatable("itemgroup.szar_group"))
.icon(() -> new ItemStack(Szar.CANNABIS_ITEM)) // icon item .icon(() -> new ItemStack(Szar.CANNABIS_ITEM)) // icon item
.entries((displayContext, entries) -> { .entries((displayContext, entries) -> {
// drugs
entries.add(Szar.CANNABIS_ITEM);
entries.add(Szar.WEED_ITEM);
entries.add(Szar.WEED_JOINT_ITEM);
entries.add(Szar.CHEMICAL_WORKBENCH_ITEM);
// racism
entries.add(Szar.CIGANYBLOCK);
entries.add(Szar.NWORD_PASS);
entries.add(Szar.HITTER_SPAWNEGG);
entries.add(Szar.NAZI_SPAWNEGG);
entries.add(Szar.STALIN_SPAWNEGG);
entries.add(Szar.COMMUNIST_SPAWNEGG);
entries.add(Szar.NIGGER_SPAWNEGG);
entries.add(Szar.GYPSY_SPAWNEGG);
entries.add(Szar.TERRORIST_SPAWNEGG);
entries.add(Szar.POLICE_SPAWNEGG);
entries.add(Szar.KEY_ITEM);
entries.add(Szar.HANDCUFF_ITEM);
// crazy weponary
entries.add(Szar.BULLET_ITEM);
entries.add(Szar.AK47);
entries.add(Szar.REVOLVER);
entries.add(Szar.ATOM_DETONATOR);
entries.add(Szar.URANIUM_ORE);
entries.add(Szar.URANIUM);
entries.add(Szar.URANIUM_ROD);
entries.add(Szar.ATOM_CORE);
entries.add(Szar.ATOM);
entries.add(Szar.WHEEL);
entries.add(Szar.PLANE);
// random ahh silly stuff // random ahh silly stuff
entries.add(Szar.POPTART); entries.add(Szar.POPTART);
entries.add(Szar.NYAN_SPAWNEGG); entries.add(Szar.NYAN_SPAWNEGG);
@@ -391,13 +364,45 @@ public class Szar implements ModInitializer {
entries.add(Szar.ROULETTE); entries.add(Szar.ROULETTE);
entries.add(Szar.FIRTANA); entries.add(Szar.FIRTANA);
entries.add(Szar.HELLO_DISC); entries.add(Szar.HELLO_DISC);
entries.add(Szar.TRACKER_BLOCK_ITEM);
entries.add(Szar.PORTAL_BLOCK_ITEM);
entries.add(Szar.WALL_ITEM);
entries.add(Szar.WALL_BOTTOM_ITEM);
entries.add(Szar.CEILING_ITEM);
entries.add(Szar.PLASTIC_ITEM);
// crazy weponary
entries.add(Szar.BULLET_ITEM);
entries.add(Szar.AK47);
entries.add(Szar.REVOLVER);
entries.add(Szar.ATOM_DETONATOR);
entries.add(Szar.URANIUM_ORE);
entries.add(Szar.URANIUM);
entries.add(Szar.URANIUM_ROD);
entries.add(Szar.ATOM_CORE);
entries.add(Szar.ATOM);
entries.add(Szar.WHEEL);
entries.add(Szar.PLANE);
// drugs
entries.add(Szar.CANNABIS_ITEM);
entries.add(Szar.WEED_ITEM);
entries.add(Szar.WEED_JOINT_ITEM);
entries.add(Szar.CHEMICAL_WORKBENCH_ITEM);
// war guys
entries.add(Szar.HITTER_SPAWNEGG);
entries.add(Szar.NAZI_SPAWNEGG);
entries.add(Szar.STALIN_SPAWNEGG);
entries.add(Szar.COMMUNIST_SPAWNEGG);
entries.add(Szar.ERIKA_DISC); entries.add(Szar.ERIKA_DISC);
entries.add(Szar.USSR_DISC); entries.add(Szar.USSR_DISC);
// nsfw // racism
entries.add(Szar.FASZITEM); entries.add(Szar.CIGANYBLOCK);
entries.add(Szar.CNDM); entries.add(Szar.NWORD_PASS);
entries.add(Szar.LATEX); entries.add(Szar.NIGGER_SPAWNEGG);
entries.add(Szar.WHITE_LIQUID); entries.add(Szar.GYPSY_SPAWNEGG);
entries.add(Szar.TERRORIST_SPAWNEGG);
entries.add(Szar.POLICE_SPAWNEGG);
entries.add(Szar.KEY_ITEM);
entries.add(Szar.HANDCUFF_ITEM);
// niggerite shits at the end // niggerite shits at the end
entries.add(Szar.NIGGERITE_INGOT); entries.add(Szar.NIGGERITE_INGOT);
entries.add(Szar.NIGGERITE_SWORD); entries.add(Szar.NIGGERITE_SWORD);
@@ -410,12 +415,22 @@ public class Szar implements ModInitializer {
entries.add(Szar.NIGGERITE_LEGGINGS); entries.add(Szar.NIGGERITE_LEGGINGS);
entries.add(Szar.NIGGERITE_BOOTS); entries.add(Szar.NIGGERITE_BOOTS);
entries.add(Szar.NIGGERITE_BLOCK); entries.add(Szar.NIGGERITE_BLOCK);
// nsfw
entries.add(Szar.FASZITEM);
entries.add(Szar.CNDM);
entries.add(Szar.LATEX);
entries.add(Szar.WHITE_LIQUID);
}) })
.build() .build()
); );
private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>(); private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>();
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(
Registries.CHUNK_GENERATOR,
new Identifier(MOD_ID, "backrooms"),
BackroomsChunkGenerator.CODEC
);
ServerPlayNetworking.registerGlobalReceiver(AK47_SHOOT, (server, player, handler, buf, responseSender) -> { ServerPlayNetworking.registerGlobalReceiver(AK47_SHOOT, (server, player, handler, buf, responseSender) -> {
server.execute(() -> { server.execute(() -> {
ItemStack stack = player.getMainHandStack(); ItemStack stack = player.getMainHandStack();
@@ -1068,15 +1083,18 @@ public class Szar implements ModInitializer {
// 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"),
new TrackerBlock(FabricBlockSettings.create().noCollision().air()) new TrackerBlock(FabricBlockSettings.create()
// .air() makes it not render and not block light .noCollision()
.nonOpaque()
.strength(2f, 2f))
); );
public static final PortalBlock PORTAL_BLOCK = Registry.register( public static final PortalBlock PORTAL_BLOCK = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "portal"), Registries.BLOCK, new Identifier(MOD_ID, "portal"),
new PortalBlock(FabricBlockSettings.create().noCollision() new PortalBlock(FabricBlockSettings.create()
.strength(-1.0f) // indestructible by default, change if needed .noCollision()
.luminance(state -> 11)) // slight glow so you can see it .nonOpaque()
.strength(2f, 2f))
); );
// Block items (so you can place them) // Block items (so you can place them)
@@ -1097,6 +1115,42 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "tracker"), new Identifier(MOD_ID, "tracker"),
FabricBlockEntityTypeBuilder.create(TrackerBlockEntity::new, TRACKER_BLOCK).build() FabricBlockEntityTypeBuilder.create(TrackerBlockEntity::new, TRACKER_BLOCK).build()
); );
public static final Block WALL_BLOCK = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "wall"),
new Block(AbstractBlock.Settings.create())
);
public static final Block WALL_BOTTOM_BLOCK = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "wall_bottom"),
new Block(AbstractBlock.Settings.create())
);
public static final Block CEILING = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "ceiling"),
new Block(AbstractBlock.Settings.create())
);
public static final Block PLASTIC = Registry.register(
Registries.BLOCK, new Identifier(MOD_ID, "plastic"),
new Block(AbstractBlock.Settings.create())
);
public static final Item WALL_ITEM = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "wall"),
new BlockItem(WALL_BLOCK, new Item.Settings())
);
public static final Item WALL_BOTTOM_ITEM = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "wall_bottom"),
new BlockItem(WALL_BOTTOM_BLOCK, new Item.Settings())
);
public static final Item CEILING_ITEM = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "ceiling"),
new BlockItem(CEILING, new Item.Settings())
);
public static final Item PLASTIC_ITEM = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "plastic"),
new BlockItem(PLASTIC, new Item.Settings())
);
// In your ModItems or wherever you register items // In your ModItems or wherever you register items
public static final Item REVOLVER = Registry.register( public static final Item REVOLVER = Registry.register(

View File

@@ -1,13 +1,14 @@
package dev.tggamesyt.szar; package dev.tggamesyt.szar;
import net.minecraft.block.Block; import net.minecraft.block.*;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
@@ -15,6 +16,10 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class TrackerBlock extends Block implements BlockEntityProvider { public class TrackerBlock extends Block implements BlockEntityProvider {
public TrackerBlock(Settings settings) { public TrackerBlock(Settings settings) {
@@ -22,17 +27,37 @@ public class TrackerBlock extends Block implements BlockEntityProvider {
} }
// No hitbox // No hitbox
// 1x1x1 pixel cube — invisible in practice but gives particles a valid bounding box
private static final VoxelShape TINY = Block.createCuboidShape(7.9, 7.9, 7.9, 8.1, 8.1, 8.1);
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, public VoxelShape getOutlineShape(BlockState state, BlockView world,
BlockPos pos, ShapeContext ctx) { BlockPos pos, ShapeContext ctx) {
return VoxelShapes.empty(); if (ctx instanceof EntityShapeContext esc && esc.getEntity() instanceof PlayerEntity player) {
if (isHoldingTracker(player)) {
return VoxelShapes.fullCube();
}
}
// Too small to see or select, but has valid bounds so particle manager doesn't crash
return TINY;
} }
// No collision
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView world, public VoxelShape getCollisionShape(BlockState state, BlockView world,
BlockPos pos, ShapeContext ctx) { BlockPos pos, ShapeContext ctx) {
return VoxelShapes.empty(); return VoxelShapes.empty(); // never has collision, only outline
}
@Override
public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos) {
// This is what allows the player to actually target and break it
return VoxelShapes.fullCube();
}
private boolean isHoldingTracker(PlayerEntity player) {
return player.getMainHandStack().isOf(Szar.TRACKER_BLOCK_ITEM.asItem())
|| player.getOffHandStack().isOf(Szar.TRACKER_BLOCK_ITEM.asItem());
} }
@Nullable @Nullable
@@ -45,8 +70,59 @@ public class TrackerBlock extends Block implements BlockEntityProvider {
public void onPlaced(World world, BlockPos pos, BlockState state, public void onPlaced(World world, BlockPos pos, BlockState state,
@Nullable LivingEntity placer, ItemStack itemStack) { @Nullable LivingEntity placer, ItemStack itemStack) {
if (world.isClient) return; if (world.isClient) return;
if (!(world.getBlockEntity(pos) instanceof TrackerBlockEntity tracker)) return;
// Only auto-place portal if a player placed this tracker
if (!tracker.placedByPlayer) return;
BlockPos portalPos = pos.down(4); BlockPos portalPos = pos.down(4);
// Save the original block before replacing it
tracker.originalPortalBlock = world.getBlockState(portalPos);
tracker.markDirty();
world.setBlockState(portalPos, Szar.PORTAL_BLOCK.getDefaultState()); world.setBlockState(portalPos, Szar.PORTAL_BLOCK.getDefaultState());
} }
@Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
// In survival, only break if holding the special item
if (!world.isClient && world.getBlockEntity(pos) instanceof TrackerBlockEntity tracker) {
restoreAndCleanup(world, pos, tracker, world.getServer());
}
super.onBreak(world, pos, state, player);
}
public static void restoreAndCleanup(World world, BlockPos trackerPos,
TrackerBlockEntity tracker, MinecraftServer server) {
if (server == null) return;
// Kick all players tracked here back to overworld
Set<UUID> players = new HashSet<>(tracker.getPlayersInside());
for (UUID uuid : players) {
ServerPlayerEntity player = server.getPlayerManager().getPlayer(uuid);
if (player == null) continue;
PortalBlock.restoreInventory(player, server);
ServerWorld overworld = server.getWorld(World.OVERWORLD);
if (overworld != null) {
NbtCompound tag = PortalDataState.getOrCreate(overworld)
.getOrCreatePlayerData(uuid);
double rx = tag.getDouble("EntryX");
double ry = tag.getDouble("EntryY");
double rz = tag.getDouble("EntryZ");
player.teleport(overworld, rx, ry, rz, player.getYaw(), player.getPitch());
}
}
// Restore original block at portal position
BlockPos portalPos = trackerPos.down(4);
if (world.getBlockState(portalPos).getBlock() instanceof PortalBlock) {
world.setBlockState(portalPos, tracker.originalPortalBlock);
}
// Remove the tracker itself
world.removeBlock(trackerPos, false);
}
} }

View File

@@ -1,9 +1,11 @@
package dev.tggamesyt.szar; package dev.tggamesyt.szar;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList; import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.NbtString; import net.minecraft.nbt.NbtString;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -12,11 +14,12 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class TrackerBlockEntity extends BlockEntity { public class TrackerBlockEntity extends BlockEntity {
// Add these fields
public BlockState originalPortalBlock = Blocks.AIR.getDefaultState();
public boolean placedByPlayer = true; // false = auto-generated by the system
// The overworld entry coords (used by nether-side tracker to know where to send players back) // The overworld entry coords (used by nether-side tracker to know where to send players back)
public double returnX, returnY, returnZ; public double returnX, returnY, returnZ;
// Whether this tracker is in the nether or overworld // Whether this tracker is in the nether or overworld
public boolean isNetherSide = false;
// BlockPos of the paired tracker in the other dimension // BlockPos of the paired tracker in the other dimension
public BlockPos pairedTrackerPos = null; public BlockPos pairedTrackerPos = null;
@@ -51,7 +54,6 @@ public class TrackerBlockEntity extends BlockEntity {
nbt.putDouble("ReturnX", returnX); nbt.putDouble("ReturnX", returnX);
nbt.putDouble("ReturnY", returnY); nbt.putDouble("ReturnY", returnY);
nbt.putDouble("ReturnZ", returnZ); nbt.putDouble("ReturnZ", returnZ);
nbt.putBoolean("IsNetherSide", isNetherSide);
if (pairedTrackerPos != null) { if (pairedTrackerPos != null) {
nbt.putInt("PairedX", pairedTrackerPos.getX()); nbt.putInt("PairedX", pairedTrackerPos.getX());
@@ -64,6 +66,12 @@ public class TrackerBlockEntity extends BlockEntity {
list.add(NbtString.of(uuid.toString())); list.add(NbtString.of(uuid.toString()));
} }
nbt.put("PlayersInside", list); nbt.put("PlayersInside", list);
NbtCompound originalBlock = new NbtCompound();
BlockState.CODEC.encodeStart(NbtOps.INSTANCE, originalPortalBlock)
.result()
.ifPresent(nbt1 -> originalBlock.put("State", nbt1));
nbt.put("OriginalPortalBlock", originalBlock);
nbt.putBoolean("PlacedByPlayer", placedByPlayer);
} }
@Override @Override
@@ -72,7 +80,6 @@ public class TrackerBlockEntity extends BlockEntity {
returnX = nbt.getDouble("ReturnX"); returnX = nbt.getDouble("ReturnX");
returnY = nbt.getDouble("ReturnY"); returnY = nbt.getDouble("ReturnY");
returnZ = nbt.getDouble("ReturnZ"); returnZ = nbt.getDouble("ReturnZ");
isNetherSide = nbt.getBoolean("IsNetherSide");
if (nbt.contains("PairedX")) { if (nbt.contains("PairedX")) {
pairedTrackerPos = new BlockPos( pairedTrackerPos = new BlockPos(
@@ -87,5 +94,14 @@ public class TrackerBlockEntity extends BlockEntity {
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
playersInside.add(UUID.fromString(list.getString(i))); playersInside.add(UUID.fromString(list.getString(i)));
} }
if (nbt.contains("OriginalPortalBlock")) {
NbtCompound originalBlock = nbt.getCompound("OriginalPortalBlock");
if (originalBlock.contains("State")) {
BlockState.CODEC.parse(NbtOps.INSTANCE, originalBlock.get("State"))
.result()
.ifPresent(s -> originalPortalBlock = s);
}
}
placedByPlayer = nbt.getBoolean("PlacedByPlayer");
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -136,5 +136,13 @@
"item.szar.communist_spawn_egg":"Communist Spawn Egg", "item.szar.communist_spawn_egg":"Communist Spawn Egg",
"item.szar.ussr": "Music Disc", "item.szar.ussr": "Music Disc",
"item.szar.ussr.desc": "A. Alexandrov - USSR Anthem" "item.szar.ussr.desc": "A. Alexandrov - USSR Anthem",
"block.szar.tracker": "Portal Tracker Block",
"block.szar.portal": "Portal",
"block.szar.plastic": "Plastic",
"block.szar.ceiling": "Ceiling",
"block.szar.wall": "Wall",
"block.szar.wall_bottom": "Wall Bottom"
} }

View File

@@ -0,0 +1,55 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"texture_size": [512, 512],
"textures": {
"0": "szar:block/ceiling_tile_glitched_color",
"1": "szar:block/ceiling_tile_color",
"particle": "szar:block/ceiling_tile_color"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "north"},
"east": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "east"},
"south": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "south"},
"west": {"uv": [0, 0, 16, 16], "texture": "#0", "cullface": "west"},
"up": {"uv": [0, 0, 16, 16], "texture": "#1", "cullface": "up"},
"down": {"uv": [0, 0, 16, 16], "texture": "#1", "cullface": "down"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -135, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, -135, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"parent": "minecraft:block/cube_all",
"textures": {
"all": "szar:block/plastic"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "szar:block/portal"
}
}

View File

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

View File

@@ -0,0 +1,23 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"all": "szar:block/wall_block",
"particle": "szar:block/wall_block"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 16, 16], "texture": "#all", "cullface": "north"},
"east": {"uv": [0, 0, 16, 16], "texture": "#all", "cullface": "east"},
"south": {"uv": [0, 0, 16, 16], "texture": "#all", "cullface": "south"},
"west": {"uv": [0, 0, 16, 16], "texture": "#all", "cullface": "west"},
"up": {"uv": [0, 0, 16, 16], "texture": "#all"},
"down": {"uv": [0, 0, 16, 16], "texture": "#all", "cullface": "down"}
}
}
]
}

View File

@@ -0,0 +1,49 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"texture_size": [64, 64],
"textures": {
"2": "szar:block/wallpaper_bottom_block_texture",
"particle": "szar:block/wallpaper_bottom_block_texture"
},
"elements": [
{
"from": [-1, 0, -1],
"to": [17, 2, 17],
"faces": {
"north": {"uv": [0, 9, 4.5, 9.5], "texture": "#2"},
"east": {"uv": [0, 9.5, 4.5, 10], "texture": "#2"},
"south": {"uv": [0, 10, 4.5, 10.5], "texture": "#2"},
"west": {"uv": [0, 10.5, 4.5, 11], "texture": "#2"},
"up": {"uv": [4.5, 4.5, 0, 0], "texture": "#2"},
"down": {"uv": [4.5, 4.5, 0, 9], "texture": "#2"}
}
},
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [4.5, 0, 8.5, 4], "texture": "#2"},
"east": {"uv": [4.5, 4, 8.5, 8], "texture": "#2"},
"south": {"uv": [4.5, 8, 8.5, 12], "texture": "#2"},
"west": {"uv": [8.5, 0, 12.5, 4], "texture": "#2"},
"up": {"uv": [12.5, 8, 8.5, 4], "texture": "#2"},
"down": {"uv": [12.5, 8, 8.5, 12], "texture": "#2"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [80.5, 45, 0],
"scale": [0.3, 0.3, 0.3]
}
},
"groups": [
{
"name": "block",
"origin": [8, 8, 8],
"color": 0,
"children": [0, 1]
}
]
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Some files were not shown because too many files have changed in this diff Show More