From 301d87bb5e9f361324b1c1dad5bc9bd6d181347c Mon Sep 17 00:00:00 2001 From: TGGamesYT Date: Thu, 19 Mar 2026 18:11:32 +0100 Subject: [PATCH] backrooms 3 --- gradle.properties | 2 +- .../dev/tggamesyt/szar/AlmondWaterItem.java | 108 +++++++++ .../szar/BackroomsBarrelManager.java | 197 ++++++++++++---- .../szar/BackroomsChunkGenerator.java | 53 ++++- .../tggamesyt/szar/BackroomsLightBlock.java | 67 ++++++ .../szar/BackroomsLightBlockEntity.java | 60 +++++ .../tggamesyt/szar/BackroomsLightManager.java | 213 ++++++++++++++++++ .../java/dev/tggamesyt/szar/PortalBlock.java | 88 +++++++- src/main/java/dev/tggamesyt/szar/Szar.java | 112 +++++++++ .../szar/blockstates/backrooms_light.json | 8 + .../resources/assets/szar/lang/en_us.json | 4 +- .../models/block/backrooms_light_off.json | 6 + .../szar/models/block/backrooms_light_on.json | 6 + .../assets/szar/models/block/wall_bottom.json | 7 +- .../assets/szar/models/item/almond_water.json | 6 + .../szar/models/item/backrooms_light.json | 3 + .../assets/szar/textures/block/black.png | Bin 0 -> 558 bytes .../szar/textures/item/almond_water.png | Bin 0 -> 808 bytes .../data/szar/dimension_type/backrooms.json | 4 +- 19 files changed, 876 insertions(+), 68 deletions(-) create mode 100644 src/main/java/dev/tggamesyt/szar/AlmondWaterItem.java create mode 100644 src/main/java/dev/tggamesyt/szar/BackroomsLightBlock.java create mode 100644 src/main/java/dev/tggamesyt/szar/BackroomsLightBlockEntity.java create mode 100644 src/main/java/dev/tggamesyt/szar/BackroomsLightManager.java create mode 100644 src/main/resources/assets/szar/blockstates/backrooms_light.json create mode 100644 src/main/resources/assets/szar/models/block/backrooms_light_off.json create mode 100644 src/main/resources/assets/szar/models/block/backrooms_light_on.json create mode 100644 src/main/resources/assets/szar/models/item/almond_water.json create mode 100644 src/main/resources/assets/szar/models/item/backrooms_light.json create mode 100644 src/main/resources/assets/szar/textures/block/black.png create mode 100644 src/main/resources/assets/szar/textures/item/almond_water.png diff --git a/gradle.properties b/gradle.properties index a9f9785..a367cb3 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.18.3 +mod_version=26.3.19 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/main/java/dev/tggamesyt/szar/AlmondWaterItem.java b/src/main/java/dev/tggamesyt/szar/AlmondWaterItem.java new file mode 100644 index 0000000..ea3253d --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/AlmondWaterItem.java @@ -0,0 +1,108 @@ +package dev.tggamesyt.szar; + +import net.minecraft.advancement.criterion.Criteria; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffectCategory; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsage; +import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.stat.Stats; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.UseAction; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class AlmondWaterItem extends Item { + + public AlmondWaterItem(Settings settings) { + super(settings); + } + + @Override + public ItemStack finishUsing(ItemStack stack, World world, LivingEntity user) { + PlayerEntity player = user instanceof PlayerEntity ? (PlayerEntity) user : null; + + // Advancement trigger + if (player instanceof ServerPlayerEntity serverPlayer) { + Criteria.CONSUME_ITEM.trigger(serverPlayer, stack); + } + + if (!world.isClient) { + // Collect harmful effects first + List toRemove = new ArrayList<>(); + + for (StatusEffectInstance effect : user.getStatusEffects()) { + if (effect.getEffectType().getCategory() == StatusEffectCategory.HARMFUL) { + toRemove.add(effect); + } + } + + // Then remove them + for (StatusEffectInstance effect : toRemove) { + user.removeStatusEffect(effect.getEffectType()); + } + + // Hunger + saturation + if (player != null) { + player.getHungerManager().add(4, 0.6F); + } + } + + // Stats + stack handling + if (player != null) { + player.incrementStat(Stats.USED.getOrCreateStat(this)); + if (!player.getAbilities().creativeMode) { + stack.decrement(1); + } + } + + // Return glass bottle + if (player == null || !player.getAbilities().creativeMode) { + if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } + + if (player != null) { + player.getInventory().insertStack(new ItemStack(Items.GLASS_BOTTLE)); + } + } + + user.emitGameEvent(net.minecraft.world.event.GameEvent.DRINK); + return stack; + } + + @Override + public int getMaxUseTime(ItemStack stack) { + return 32; + } + + @Override + public UseAction getUseAction(ItemStack stack) { + return UseAction.DRINK; + } + + @Override + public SoundEvent getDrinkSound() { + return SoundEvents.ENTITY_GENERIC_DRINK; + } + + @Override + public SoundEvent getEatSound() { + return SoundEvents.ENTITY_GENERIC_DRINK; + } + + @Override + public TypedActionResult use(World world, PlayerEntity user, Hand hand) { + return ItemUsage.consumeHeldItem(world, user, hand); + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/BackroomsBarrelManager.java b/src/main/java/dev/tggamesyt/szar/BackroomsBarrelManager.java index c297524..ee01c7b 100644 --- a/src/main/java/dev/tggamesyt/szar/BackroomsBarrelManager.java +++ b/src/main/java/dev/tggamesyt/szar/BackroomsBarrelManager.java @@ -2,6 +2,7 @@ package dev.tggamesyt.szar; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.block.entity.BarrelBlockEntity; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.HungerManager; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -22,6 +23,16 @@ public class BackroomsBarrelManager { private static final Map> trackerBarrels = new HashMap<>(); private static final Map> foodBarrels = new HashMap<>(); + // Cooldown: world time when food was last taken from a barrel per player + private static final Map foodTakenCooldown = new HashMap<>(); + + // How far from ANY player a barrel must be to get cleared + private static final int CLEAR_RANGE = 32; + // Cooldown in ticks (20 ticks/sec * 60 sec = 1200) + private static final long FOOD_COOLDOWN_TICKS = 1200; + // Range to check for dropped food items on ground + private static final int DROPPED_FOOD_RANGE = 8; + public static void register() { ServerTickEvents.END_SERVER_TICK.register(BackroomsBarrelManager::tick); } @@ -30,7 +41,13 @@ public class BackroomsBarrelManager { ServerWorld backrooms = server.getWorld(Szar.BACKROOMS_KEY); if (backrooms == null) return; - for (ServerPlayerEntity player : backrooms.getPlayers()) { + List players = backrooms.getPlayers(); + + // --- Clear barrels too far from any player --- + clearDistantBarrels(backrooms, players, trackerBarrels, Szar.TRACKER_BLOCK_ITEM.asItem()); + clearDistantBarrels(backrooms, players, foodBarrels, null); + + for (ServerPlayerEntity player : players) { UUID uuid = player.getUuid(); // --- Walk tracking --- @@ -52,28 +69,71 @@ public class BackroomsBarrelManager { // --- Check if tracker barrels need clearing --- if (trackerBarrels.containsKey(uuid)) { - checkAndClearTrackerBarrels(backrooms, uuid); + checkAndClearBarrels(backrooms, uuid, trackerBarrels, + Szar.TRACKER_BLOCK_ITEM.asItem()); } // --- Check if food barrels need clearing --- if (foodBarrels.containsKey(uuid)) { - checkAndClearFoodBarrels(backrooms, uuid); + boolean anyTaken = checkFoodBarrelsTaken(backrooms, uuid); + if (anyTaken) { + // Clear all food from tracked barrels and start cooldown + clearAllFoodBarrels(backrooms, uuid); + foodTakenCooldown.put(uuid, backrooms.getTime()); + foodBarrels.remove(uuid); + } } // --- Hunger check (every 20 ticks) --- if (backrooms.getTime() % 20 == 0) { HungerManager hunger = player.getHungerManager(); - if (hunger.getFoodLevel() <= 10 && !hasAnyFood(player)) { - if (!foodBarrels.containsKey(uuid)) { - List nearby = getNearbyBarrels(backrooms, player, 16); - if (!nearby.isEmpty()) { - Set positions = new HashSet<>(); - for (BarrelBlockEntity barrel : nearby) { - placeItemInBarrel(barrel, new ItemStack(Szar.CAN_OF_BEANS)); - positions.add(barrel.getPos().toImmutable()); - } - foodBarrels.put(uuid, positions); + boolean isHungry = hunger.getFoodLevel() <= 10; + boolean hasFood = hasAnyFood(player); + boolean hasFoodOnGround = hasFoodDroppedNearby(backrooms, player); + long lastTaken = foodTakenCooldown.getOrDefault(uuid, -FOOD_COOLDOWN_TICKS); + boolean onCooldown = (backrooms.getTime() - lastTaken) < FOOD_COOLDOWN_TICKS; + + if (isHungry && !hasFood && !hasFoodOnGround && !onCooldown) { + // Ensure ALL nearby barrels have food, not just new ones + List nearby = getNearbyBarrels(backrooms, player, 16); + Set positions = foodBarrels.getOrDefault(uuid, new HashSet<>()); + + for (BarrelBlockEntity barrel : nearby) { + BlockPos bpos = barrel.getPos().toImmutable(); + // If this barrel doesn't have food yet, add it + if (!barrelHasItem(barrel, Szar.CAN_OF_BEANS.asItem()) + && !barrelHasItem(barrel, Szar.ALMOND_WATER.asItem())) { + Item foodItem = backrooms.random.nextBoolean() + ? Szar.CAN_OF_BEANS.asItem() + : Szar.ALMOND_WATER.asItem(); + placeItemInBarrel(barrel, new ItemStack(foodItem)); } + positions.add(bpos); + } + + // Also clear positions that are now out of range + positions.removeIf(bpos -> { + double d = player.squaredDistanceTo( + bpos.getX(), bpos.getY(), bpos.getZ()); + if (d > 16 * 16) { + if (backrooms.getBlockEntity(bpos) + instanceof BarrelBlockEntity b) { + removeItemFromBarrel(b, Szar.CAN_OF_BEANS.asItem()); + removeItemFromBarrel(b, Szar.ALMOND_WATER.asItem()); + } + return true; + } + return false; + }); + + if (!positions.isEmpty()) { + foodBarrels.put(uuid, positions); + } + } else if (onCooldown || hasFood || hasFoodOnGround) { + // If player now has food or is on cooldown, clear all food barrels + if (foodBarrels.containsKey(uuid)) { + clearAllFoodBarrels(backrooms, uuid); + foodBarrels.remove(uuid); } } } @@ -97,47 +157,98 @@ public class BackroomsBarrelManager { // Clean up data for players no longer in backrooms Set activePlayers = new HashSet<>(); - for (ServerPlayerEntity p : backrooms.getPlayers()) activePlayers.add(p.getUuid()); + for (ServerPlayerEntity p : players) activePlayers.add(p.getUuid()); lastX.keySet().retainAll(activePlayers); lastZ.keySet().retainAll(activePlayers); walkAccumulator.keySet().retainAll(activePlayers); walkThreshold.keySet().retainAll(activePlayers); foodBarrels.keySet().retainAll(activePlayers); trackerBarrels.keySet().retainAll(activePlayers); + foodTakenCooldown.keySet().retainAll(activePlayers); } - private static void checkAndClearTrackerBarrels(ServerWorld world, UUID uuid) { - Set positions = trackerBarrels.get(uuid); - if (positions == null) return; - - boolean anyTaken = false; + private static boolean checkFoodBarrelsTaken(ServerWorld world, UUID uuid) { + Set positions = foodBarrels.get(uuid); + if (positions == null) return false; for (BlockPos pos : positions) { if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { - if (!barrelHasItem(barrel, Szar.TRACKER_BLOCK_ITEM.asItem())) { - anyTaken = true; - break; + if (!barrelHasItem(barrel, Szar.CAN_OF_BEANS.asItem()) + && !barrelHasItem(barrel, Szar.ALMOND_WATER.asItem())) { + return true; } } } - - if (anyTaken) { - for (BlockPos pos : positions) { - if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { - removeItemFromBarrel(barrel, Szar.TRACKER_BLOCK_ITEM.asItem()); - } - } - trackerBarrels.remove(uuid); - } + return false; } - private static void checkAndClearFoodBarrels(ServerWorld world, UUID uuid) { + private static void clearAllFoodBarrels(ServerWorld world, UUID uuid) { Set positions = foodBarrels.get(uuid); if (positions == null) return; + for (BlockPos pos : positions) { + if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { + removeItemFromBarrel(barrel, Szar.CAN_OF_BEANS.asItem()); + removeItemFromBarrel(barrel, Szar.ALMOND_WATER.asItem()); + } + } + } + + private static boolean hasFoodDroppedNearby(ServerWorld world, ServerPlayerEntity player) { + Box box = player.getBoundingBox().expand(DROPPED_FOOD_RANGE); + List items = world.getEntitiesByClass(ItemEntity.class, box, e -> { + ItemStack stack = e.getStack(); + return stack.isFood() + || stack.isOf(Szar.CAN_OF_BEANS) + || stack.isOf(Szar.ALMOND_WATER); + }); + return !items.isEmpty(); + } + + private static void clearDistantBarrels(ServerWorld world, + List players, + Map> barrelMap, + Item item) { + Iterator>> iter = barrelMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry> entry = iter.next(); + Set positions = entry.getValue(); + + boolean allDistant = true; + for (BlockPos pos : positions) { + for (ServerPlayerEntity player : players) { + if (player.squaredDistanceTo(pos.getX(), pos.getY(), pos.getZ()) + <= CLEAR_RANGE * CLEAR_RANGE) { + allDistant = false; + break; + } + } + if (!allDistant) break; + } + + if (allDistant) { + for (BlockPos pos : positions) { + if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { + if (item != null) { + removeItemFromBarrel(barrel, item); + } else { + removeItemFromBarrel(barrel, Szar.CAN_OF_BEANS.asItem()); + removeItemFromBarrel(barrel, Szar.ALMOND_WATER.asItem()); + } + } + } + iter.remove(); + } + } + } + + private static void checkAndClearBarrels(ServerWorld world, UUID uuid, + Map> barrelMap, Item item) { + Set positions = barrelMap.get(uuid); + if (positions == null) return; boolean anyTaken = false; for (BlockPos pos : positions) { if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { - if (!barrelHasItem(barrel, Szar.CAN_OF_BEANS.asItem())) { + if (!barrelHasItem(barrel, item)) { anyTaken = true; break; } @@ -147,10 +258,10 @@ public class BackroomsBarrelManager { if (anyTaken) { for (BlockPos pos : positions) { if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { - removeItemFromBarrel(barrel, Szar.CAN_OF_BEANS.asItem()); + removeItemFromBarrel(barrel, item); } } - foodBarrels.remove(uuid); + barrelMap.remove(uuid); } } @@ -175,7 +286,8 @@ public class BackroomsBarrelManager { for (int i = 0; i < player.getInventory().size(); i++) { ItemStack stack = player.getInventory().getStack(i); if (!stack.isEmpty() && (stack.isFood() - || stack.isOf(Szar.CAN_OF_BEANS))) { + || stack.isOf(Szar.CAN_OF_BEANS) + || stack.isOf(Szar.ALMOND_WATER))) { return true; } } @@ -183,13 +295,14 @@ public class BackroomsBarrelManager { } private static void placeItemInBarrel(BarrelBlockEntity barrel, ItemStack item) { + List emptySlots = new ArrayList<>(); for (int i = 0; i < barrel.size(); i++) { - if (barrel.getStack(i).isEmpty()) { - barrel.setStack(i, item.copy()); - barrel.markDirty(); - return; - } + if (barrel.getStack(i).isEmpty()) emptySlots.add(i); } + if (emptySlots.isEmpty()) return; + int slot = emptySlots.get((int)(Math.random() * emptySlots.size())); + barrel.setStack(slot, item.copy()); + barrel.markDirty(); } private static List getNearbyBarrels(ServerWorld world, @@ -197,10 +310,8 @@ public class BackroomsBarrelManager { int radius) { List result = new ArrayList<>(); Box box = player.getBoundingBox().expand(radius); - BlockPos min = BlockPos.ofFloored(box.minX, box.minY, box.minZ); BlockPos max = BlockPos.ofFloored(box.maxX, box.maxY, box.maxZ); - for (BlockPos pos : BlockPos.iterate(min, max)) { if (world.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { result.add(barrel); diff --git a/src/main/java/dev/tggamesyt/szar/BackroomsChunkGenerator.java b/src/main/java/dev/tggamesyt/szar/BackroomsChunkGenerator.java index 19bf86a..bf29f6a 100644 --- a/src/main/java/dev/tggamesyt/szar/BackroomsChunkGenerator.java +++ b/src/main/java/dev/tggamesyt/szar/BackroomsChunkGenerator.java @@ -87,11 +87,28 @@ public class BackroomsChunkGenerator extends ChunkGenerator { Szar.PLASTIC.getDefaultState(), false); } - // Ceiling boolean isGlowstone = isGlowstonePos(worldX, worldZ); - BlockState ceilingBlock = isGlowstone - ? Blocks.GLOWSTONE.getDefaultState() - : Szar.CEILING.getDefaultState(); + BlockState ceilingBlock; + if (isGlowstone) { + long lightRoll = hash(worldX * 53 + 7, worldZ * 47 + 13); + int roll = (int)(Math.abs(lightRoll) % 100); + if (roll < 95) { + // 95% ON + ceilingBlock = Szar.BACKROOMS_LIGHT.getDefaultState() + .with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.ON); + } else if (roll < 98) { + // 3% FLICKERING_ON + ceilingBlock = Szar.BACKROOMS_LIGHT.getDefaultState() + .with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.FLICKERING_ON); + } else { + // 2% missing — ceiling block, no light + ceilingBlock = Szar.CEILING.getDefaultState(); + } + } else { + ceilingBlock = 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 @@ -106,10 +123,17 @@ public class BackroomsChunkGenerator extends ChunkGenerator { Blocks.AIR.getDefaultState(), false); } - // 1 in 40 chance of a barrel on the floor - // With this — 1 per ~40x40 block area: - long barrelHash = hash(worldX * 31 + 17, worldZ * 29 + 11); - if ((barrelHash % 1600) == 0) { + int cellX = Math.floorDiv(worldX, 40); + int cellZ = Math.floorDiv(worldZ, 40); + long cellHash = hash(cellX * 31 + 17, cellZ * 29 + 11); + + int barrelLocalX = (int)(cellHash & 0x1F) % 40; // 0-39 + int barrelLocalZ = (int)((cellHash >> 8) & 0x1F) % 40; // 0-39 + int cellStartX = cellX * 40; + int cellStartZ = cellZ * 40; + + if (worldX == cellStartX + barrelLocalX && worldZ == cellStartZ + barrelLocalZ + && isOpenSpace(worldX, worldZ)) { chunk.setBlockState(new BlockPos(lx, FLOOR_Y + 1, lz), Blocks.BARREL.getDefaultState(), false); } @@ -262,6 +286,19 @@ public class BackroomsChunkGenerator extends ChunkGenerator { } } } + // Inside the lx/lz loop in generateFeatures, after the wall block section: + mutable.set(chunkX + lx, 9, chunkZ + lz); // CEILING_Y = 9 + BlockState lightState = world.getBlockState(mutable); + if (lightState.getBlock() instanceof BackroomsLightBlock) { + if (world.getBlockEntity(mutable) == null) { + world.setBlockState(mutable, lightState, Block.NOTIFY_ALL); + } + if (world.getBlockEntity(mutable) instanceof BackroomsLightBlockEntity light) { + light.flickerOffset = (int)(Math.abs(hash(chunkX + lx, chunkZ + lz)) % 100); + light.flickerTimer = light.flickerOffset; // stagger initial timers + light.markDirty(); + } + } } } diff --git a/src/main/java/dev/tggamesyt/szar/BackroomsLightBlock.java b/src/main/java/dev/tggamesyt/szar/BackroomsLightBlock.java new file mode 100644 index 0000000..b31618c --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/BackroomsLightBlock.java @@ -0,0 +1,67 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.EnumProperty; +import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class BackroomsLightBlock extends BlockWithEntity { + + public enum LightState implements StringIdentifiable { + ON, OFF, FLICKERING_ON, FLICKERING_OFF; + + @Override + public String asString() { + return name().toLowerCase(); + } + } + + public static final EnumProperty LIGHT_STATE = + EnumProperty.of("light_state", LightState.class); + + public BackroomsLightBlock(Settings settings) { + super(settings); + setDefaultState(getStateManager().getDefaultState() + .with(LIGHT_STATE, LightState.ON)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(LIGHT_STATE); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BackroomsLightBlockEntity(pos, state); + } + + @Override + public BlockEntityTicker getTicker( + World world, BlockState state, BlockEntityType type) { + if (world.isClient) return null; + return type == Szar.BACKROOMS_LIGHT_ENTITY + ? (w, pos, s, be) -> BackroomsLightBlockEntity.tick( + w, pos, s, (BackroomsLightBlockEntity) be) + : null; + } + + // Light level based on state + public static int getLightLevel(BlockState state) { + return switch (state.get(LIGHT_STATE)) { + case ON, FLICKERING_ON -> 15; + case OFF, FLICKERING_OFF -> 0; + }; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/BackroomsLightBlockEntity.java b/src/main/java/dev/tggamesyt/szar/BackroomsLightBlockEntity.java new file mode 100644 index 0000000..172a848 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/BackroomsLightBlockEntity.java @@ -0,0 +1,60 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BackroomsLightBlockEntity extends BlockEntity { + + // Random offset so each light flickers at different times + public int flickerOffset = 0; + // How many ticks until next state toggle during flicker + public int flickerTimer = 0; + private boolean initialized = false; + + public BackroomsLightBlockEntity(BlockPos pos, BlockState state) { + super(Szar.BACKROOMS_LIGHT_ENTITY, pos, state); + } + + public static void tick(World world, BlockPos pos, BlockState state, + BackroomsLightBlockEntity entity) { + if (!entity.initialized) { + entity.flickerOffset = world.random.nextInt(100); + entity.initialized = true; + entity.markDirty(); + } + + BackroomsLightManager.tickLight(world, pos, state, entity); + } + + @Override + public void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + nbt.putInt("FlickerOffset", flickerOffset); + nbt.putInt("FlickerTimer", flickerTimer); + nbt.putBoolean("Initialized", initialized); + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + flickerOffset = nbt.getInt("FlickerOffset"); + flickerTimer = nbt.getInt("FlickerTimer"); + initialized = nbt.getBoolean("Initialized"); + } + + @Override + public NbtCompound toInitialChunkDataNbt() { + return createNbt(); + } + + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.create(this); + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/BackroomsLightManager.java b/src/main/java/dev/tggamesyt/szar/BackroomsLightManager.java new file mode 100644 index 0000000..0bdcf4b --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/BackroomsLightManager.java @@ -0,0 +1,213 @@ +package dev.tggamesyt.szar; + +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.block.BlockState; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BackroomsLightManager { + + // Global event state + public enum GlobalEvent { NONE, FLICKER, BLACKOUT } + + public static GlobalEvent currentEvent = GlobalEvent.NONE; + public static int eventTimer = 0; // ticks remaining in current event + public static int cooldownTimer = 0; // ticks until next event check + + // Flicker event duration: 3-8 seconds + private static final int FLICKER_DURATION_MIN = 60; + private static final int FLICKER_DURATION_MAX = 160; + // Blackout duration: 50-100 seconds + private static final int BLACKOUT_MIN = 1000; + private static final int BLACKOUT_MAX = 2000; + // Check for new event every ~3 minutes + private static final int EVENT_COOLDOWN = 3600; + + public static void register() { + ServerTickEvents.END_SERVER_TICK.register(BackroomsLightManager::tick); + } + + private static void tick(MinecraftServer server) { + ServerWorld backrooms = server.getWorld(Szar.BACKROOMS_KEY); + if (backrooms == null) return; + + // Handle event timers + if (currentEvent != GlobalEvent.NONE) { + eventTimer--; + if (eventTimer <= 0) { + endEvent(backrooms); + } + } else { + cooldownTimer--; + if (cooldownTimer <= 0) { + // Roll for new event + int roll = backrooms.random.nextInt(100); + if (roll < 30) { + startBlackout(backrooms); + } else if (roll < 63) { // 30% blackout + 33% flicker + startFlicker(backrooms); + } else { + // No event — reset cooldown + cooldownTimer = EVENT_COOLDOWN; + } + } + } + } + + private static void startFlicker(ServerWorld world) { + currentEvent = GlobalEvent.FLICKER; + eventTimer = FLICKER_DURATION_MIN + world.random.nextInt( + FLICKER_DURATION_MAX - FLICKER_DURATION_MIN); + cooldownTimer = EVENT_COOLDOWN; + } + + private static void startBlackout(ServerWorld world) { + currentEvent = GlobalEvent.BLACKOUT; + eventTimer = BLACKOUT_MIN + world.random.nextInt(BLACKOUT_MAX - BLACKOUT_MIN); + cooldownTimer = EVENT_COOLDOWN; + + // Immediately turn off all ON lights in loaded chunks + setAllLightsOff(world); + } + + private static void endEvent(ServerWorld world) { + if (currentEvent == GlobalEvent.BLACKOUT) { + // Restore all lights + setAllLightsOn(world); + } + currentEvent = GlobalEvent.NONE; + eventTimer = 0; + cooldownTimer = EVENT_COOLDOWN; + } + + private static void setAllLightsOff(ServerWorld world) { + forEachLight(world, (pos, state) -> { + BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE); + if (ls == BackroomsLightBlock.LightState.ON) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.OFF)); + } else if (ls == BackroomsLightBlock.LightState.FLICKERING_ON) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.FLICKERING_OFF)); + } + }); + } + + private static void setAllLightsOn(ServerWorld world) { + forEachLight(world, (pos, state) -> { + BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE); + if (ls == BackroomsLightBlock.LightState.OFF) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.ON)); + } else if (ls == BackroomsLightBlock.LightState.FLICKERING_OFF) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.FLICKERING_ON)); + } + }); + } + + private static void forEachLight(ServerWorld world, java.util.function.BiConsumer consumer) { + for (net.minecraft.world.chunk.WorldChunk chunk : getLoadedChunks(world)) { + BlockPos.Mutable mutable = new BlockPos.Mutable(); + int cx = chunk.getPos().getStartX(); + int cz = chunk.getPos().getStartZ(); + for (int lx = 0; lx < 16; lx++) { + for (int lz = 0; lz < 16; lz++) { + // Ceiling Y in backrooms is 9 + mutable.set(cx + lx, 9, cz + lz); + BlockState state = world.getBlockState(mutable); + if (state.getBlock() instanceof BackroomsLightBlock) { + consumer.accept(mutable.toImmutable(), state); + } + } + } + } + } + + private static java.util.List getLoadedChunks(ServerWorld world) { + java.util.List chunks = new java.util.ArrayList<>(); + // Iterate over all players and collect chunks around them + for (net.minecraft.server.network.ServerPlayerEntity player : world.getPlayers()) { + int playerChunkX = (int) player.getX() >> 4; + int playerChunkZ = (int) player.getZ() >> 4; + int viewDistance = world.getServer().getPlayerManager().getViewDistance(); + for (int cx = playerChunkX - viewDistance; cx <= playerChunkX + viewDistance; cx++) { + for (int cz = playerChunkZ - viewDistance; cz <= playerChunkZ + viewDistance; cz++) { + if (world.getChunkManager().isChunkLoaded(cx, cz)) { + net.minecraft.world.chunk.WorldChunk chunk = world.getChunk(cx, cz); + if (!chunks.contains(chunk)) { + chunks.add(chunk); + } + } + } + } + } + return chunks; + } + + // Called per-light from BackroomsLightBlockEntity.tick + public static void tickLight(World world, BlockPos pos, BlockState state, + BackroomsLightBlockEntity entity) { + BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE); + + // During blackout, lights are already set off — don't touch them + if (currentEvent == GlobalEvent.BLACKOUT) return; + + // Only flickering lights and lights during flicker events need ticking + boolean isFlickering = ls == BackroomsLightBlock.LightState.FLICKERING_ON + || ls == BackroomsLightBlock.LightState.FLICKERING_OFF; + boolean inFlickerEvent = currentEvent == GlobalEvent.FLICKER; + + if (!isFlickering && !inFlickerEvent) return; + + // Decrement timer + entity.flickerTimer--; + if (entity.flickerTimer > 0) return; + + // Toggle state and set new random timer + // Flickering lights: 2-8 ticks per toggle + // Event flicker: same but offset by entity's flickerOffset + int baseTime = 2 + world.random.nextInt(7); + + if (inFlickerEvent && !isFlickering) { + // Normal ON light during flicker event — toggle it + if (ls == BackroomsLightBlock.LightState.ON) { + // Apply offset so not all lights flicker simultaneously + if (entity.flickerTimer == 0 && world.getTime() % 3 == entity.flickerOffset % 3) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.OFF)); + entity.flickerTimer = baseTime; + entity.markDirty(); + } + return; + } else if (ls == BackroomsLightBlock.LightState.OFF + && currentEvent == GlobalEvent.FLICKER) { + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, + BackroomsLightBlock.LightState.ON)); + entity.flickerTimer = baseTime; + entity.markDirty(); + return; + } + } + + if (isFlickering) { + BackroomsLightBlock.LightState next = + ls == BackroomsLightBlock.LightState.FLICKERING_ON + ? BackroomsLightBlock.LightState.FLICKERING_OFF + : BackroomsLightBlock.LightState.FLICKERING_ON; + world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE, next)); + entity.flickerTimer = baseTime; + entity.markDirty(); + } + } + + public static void forceRestoreAllLights(ServerWorld world) { + setAllLightsOn(world); + } + + public static void forceBlackout(ServerWorld world) { + setAllLightsOff(world); + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/PortalBlock.java b/src/main/java/dev/tggamesyt/szar/PortalBlock.java index af8c433..5c89f7b 100644 --- a/src/main/java/dev/tggamesyt/szar/PortalBlock.java +++ b/src/main/java/dev/tggamesyt/szar/PortalBlock.java @@ -183,21 +183,17 @@ public class PortalBlock extends Block { if (owTrackerPos != null && overworld != null) { if (overworld.getBlockEntity(owTrackerPos) instanceof TrackerBlockEntity owTracker) { - // Resolve to root of the overworld group TrackerBlockEntity root = owTracker.getRoot(overworld); root.removePlayer(player.getUuid()); if (!root.hasPlayers()) { - // Collect and clean up all connected trackers List allTrackers = new ArrayList<>(); allTrackers.add(root.getPos()); for (BlockPos childPortal : root.getControlledPortals()) { allTrackers.add(childPortal.up(4)); } - for (BlockPos trackerPos : allTrackers) { - if (overworld.getBlockEntity(trackerPos) - instanceof TrackerBlockEntity te) { + if (overworld.getBlockEntity(trackerPos) instanceof TrackerBlockEntity te) { TrackerBlock.restoreAndCleanup(overworld, trackerPos, te, server); } } @@ -205,17 +201,95 @@ public class PortalBlock extends Block { } } - // Clean up backrooms tracker too if (!netherTracker.hasPlayers() && backrooms != null) { TrackerBlock.restoreAndCleanup(backrooms, netherTracker.getPos(), netherTracker, server); } if (overworld == null) return; - player.teleport(overworld, returnX, returnY, returnZ, + + // Find a safe landing spot — try entry coords first, then spiral, then spawn + BlockPos safePos = findSafeOverworldSpot(overworld, returnX, returnY, returnZ, player); + player.teleport(overworld, + safePos.getX() + 0.5, safePos.getY(), safePos.getZ() + 0.5, player.getYaw(), player.getPitch()); } + private BlockPos findSafeOverworldSpot(ServerWorld world, double baseX, double baseY, + double baseZ, ServerPlayerEntity player) { + int bx = (int) baseX; + int by = (int) baseY; + int bz = (int) baseZ; + + // Try exact entry position first + BlockPos exact = new BlockPos(bx, by, bz); + if (isSafeOverworld(world, exact)) return exact; + + // Try scanning Y up and down from entry Y at exact XZ + for (int dy = 0; dy <= 10; dy++) { + BlockPos up = new BlockPos(bx, by + dy, bz); + if (isSafeOverworld(world, up)) return up; + BlockPos down = new BlockPos(bx, by - dy, bz); + if (isSafeOverworld(world, down)) return down; + } + + // Spiral outward in XZ, scan Y at each spot + for (int radius = 1; radius <= 10; radius++) { + for (int dx = -radius; dx <= radius; dx++) { + for (int dz = -radius; dz <= radius; dz++) { + if (Math.abs(dx) != radius && Math.abs(dz) != radius) continue; + int cx = bx + dx; + int cz = bz + dz; + // Scan Y range at this XZ + for (int dy = 0; dy <= 10; dy++) { + BlockPos up = new BlockPos(cx, by + dy, cz); + if (isSafeOverworld(world, up)) return up; + BlockPos down = new BlockPos(cx, by - dy, cz); + if (isSafeOverworld(world, down)) return down; + } + } + } + } + + // Last resort — use player's spawn point + BlockPos spawnPos = player.getSpawnPointPosition(); + if (spawnPos != null) { + // Scan Y near spawn to make sure it's safe + for (int dy = 0; dy <= 10; dy++) { + BlockPos sp = new BlockPos(spawnPos.getX(), spawnPos.getY() + dy, spawnPos.getZ()); + if (isSafeOverworld(world, sp)) return sp; + } + return spawnPos; + } + + // Absolute fallback — world spawn + BlockPos worldSpawn = world.getSpawnPos(); + return new BlockPos(worldSpawn.getX(), + world.getTopY(net.minecraft.world.Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + worldSpawn.getX(), worldSpawn.getZ()), + worldSpawn.getZ()); + } + + private boolean isSafeOverworld(ServerWorld world, BlockPos feet) { + BlockPos head = feet.up(); + BlockPos ground = feet.down(); + // Ground must be solid, feet and head must be non-solid and not dangerous + if (world.getBlockState(ground).isSolidBlock(world, ground) + && !world.getBlockState(feet).isSolidBlock(world, feet) + && !world.getBlockState(head).isSolidBlock(world, head)) { + // Also check not standing in fire, lava, or cactus + net.minecraft.block.Block feetBlock = world.getBlockState(feet).getBlock(); + net.minecraft.block.Block groundBlock = world.getBlockState(ground).getBlock(); + if (feetBlock == net.minecraft.block.Blocks.LAVA) return false; + if (feetBlock == net.minecraft.block.Blocks.FIRE) return false; + if (feetBlock == net.minecraft.block.Blocks.CACTUS) return false; + if (groundBlock == net.minecraft.block.Blocks.LAVA) return false; + if (groundBlock instanceof net.minecraft.block.CactusBlock) return false; + return true; + } + return false; + } + // --- Helpers --- private TrackerBlockEntity findTrackerAbove(World world, BlockPos portalPos) { diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index fcc79bd..713f365 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -55,6 +55,7 @@ import net.minecraft.registry.tag.BiomeTags; import net.minecraft.registry.tag.BlockTags; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -370,6 +371,7 @@ public class Szar implements ModInitializer { entries.add(Szar.PLASTIC_ITEM); entries.add(Szar.BEAN); entries.add(Szar.CAN_OF_BEANS); + entries.add(Szar.ALMOND_WATER); // crazy weponary entries.add(Szar.BULLET_ITEM); entries.add(Szar.AK47); @@ -970,6 +972,90 @@ public class Szar implements ModInitializer { return 0; }) ); + dispatcher.register( + LiteralArgumentBuilder.literal("backroomlights") + .requires(context -> context.hasPermissionLevel(2)) + .then(CommandManager.literal("get") + .executes(context -> { + ServerCommandSource source = context.getSource(); + BackroomsLightManager.GlobalEvent event = BackroomsLightManager.currentEvent; + int timer = BackroomsLightManager.eventTimer; + + String mode = switch (event) { + case NONE -> "normal"; + case FLICKER -> "flickering"; + case BLACKOUT -> "blackout"; + }; + + if (event == BackroomsLightManager.GlobalEvent.NONE) { + int cooldown = BackroomsLightManager.cooldownTimer; + source.sendMessage(Text.literal( + "Current mode: §anormal§r — next event check in §e" + + cooldown + "§r ticks (" + + (cooldown / 20) + "s)" + )); + } else { + source.sendMessage(Text.literal( + "Current mode: §e" + mode + "§r — ends in §c" + + timer + "§r ticks (" + + (timer / 20) + "s)" + )); + } + return 1; + }) + ) + .then(CommandManager.literal("set") + .then(CommandManager.literal("normal") + .executes(context -> { + ServerCommandSource source = context.getSource(); + ServerWorld backrooms = source.getServer().getWorld(Szar.BACKROOMS_KEY); + if (backrooms == null) { + source.sendError(Text.literal("Backrooms dimension not found")); + return 0; + } + // End current event cleanly + BackroomsLightManager.currentEvent = BackroomsLightManager.GlobalEvent.NONE; + BackroomsLightManager.eventTimer = 0; + BackroomsLightManager.cooldownTimer = 3600; + // Restore all lights + BackroomsLightManager.forceRestoreAllLights(backrooms); + source.sendMessage(Text.literal("§aBackrooms lights set to normal")); + return 1; + }) + ) + .then(CommandManager.literal("flickering") + .executes(context -> { + ServerCommandSource source = context.getSource(); + ServerWorld backrooms = source.getServer().getWorld(Szar.BACKROOMS_KEY); + if (backrooms == null) { + source.sendError(Text.literal("Backrooms dimension not found")); + return 0; + } + BackroomsLightManager.currentEvent = BackroomsLightManager.GlobalEvent.FLICKER; + BackroomsLightManager.eventTimer = 3600; // 3 minutes default + BackroomsLightManager.cooldownTimer = 3600; + source.sendMessage(Text.literal("§eBackrooms lights set to flickering")); + return 1; + }) + ) + .then(CommandManager.literal("blackout") + .executes(context -> { + ServerCommandSource source = context.getSource(); + ServerWorld backrooms = source.getServer().getWorld(Szar.BACKROOMS_KEY); + if (backrooms == null) { + source.sendError(Text.literal("Backrooms dimension not found")); + return 0; + } + BackroomsLightManager.currentEvent = BackroomsLightManager.GlobalEvent.BLACKOUT; + BackroomsLightManager.eventTimer = 3600; + BackroomsLightManager.cooldownTimer = 3600; + BackroomsLightManager.forceBlackout(backrooms); + source.sendMessage(Text.literal("§4Backrooms lights set to blackout")); + return 1; + }) + ) + ) + ); }); Registry.register( Registries.PAINTING_VARIANT, @@ -1088,6 +1174,7 @@ public class Szar implements ModInitializer { new Identifier(MOD_ID, "overworld_portal")) ); BackroomsBarrelManager.register(); + BackroomsLightManager.register(); } // Blocks public static final TrackerBlock TRACKER_BLOCK = Registry.register( @@ -1715,6 +1802,31 @@ public class Szar implements ModInitializer { new Identifier(MOD_ID, "can_of_beans"), new CanOfBeansItem(new Item.Settings()) ); + public static final Item ALMOND_WATER = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "almond_water"), + new AlmondWaterItem(new Item.Settings()) + ); + public static final BackroomsLightBlock BACKROOMS_LIGHT = Registry.register( + Registries.BLOCK, new Identifier(MOD_ID, "backrooms_light"), + new BackroomsLightBlock(FabricBlockSettings.create() + .nonOpaque() + .luminance(state -> BackroomsLightBlock.getLightLevel(state)) + .strength(0.3f)) + ); + + public static final BlockItem BACKROOMS_LIGHT_ITEM = Registry.register( + Registries.ITEM, new Identifier(MOD_ID, "backrooms_light"), + new BlockItem(BACKROOMS_LIGHT, new FabricItemSettings()) + ); + + public static final BlockEntityType BACKROOMS_LIGHT_ENTITY = + Registry.register( + Registries.BLOCK_ENTITY_TYPE, + new Identifier(MOD_ID, "backrooms_light"), + FabricBlockEntityTypeBuilder.create(BackroomsLightBlockEntity::new, + BACKROOMS_LIGHT).build() + ); public static final SoundEvent BAITER = SoundEvent.of(new Identifier(MOD_ID, "baiter")); public static final Item BAITER_DISC = Registry.register( diff --git a/src/main/resources/assets/szar/blockstates/backrooms_light.json b/src/main/resources/assets/szar/blockstates/backrooms_light.json new file mode 100644 index 0000000..fa5149c --- /dev/null +++ b/src/main/resources/assets/szar/blockstates/backrooms_light.json @@ -0,0 +1,8 @@ +{ + "variants": { + "light_state=on": { "model": "szar:block/backrooms_light_on" }, + "light_state=off": { "model": "szar:block/backrooms_light_off" }, + "light_state=flickering_on": { "model": "szar:block/backrooms_light_on" }, + "light_state=flickering_off": { "model": "szar:block/backrooms_light_off" } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index a94745d..cc442e8 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -147,5 +147,7 @@ "block.szar.wall_bottom": "Wall Bottom", "item.szar.bean": "Bean", - "item.szar.can_of_beans": "Can of Beans" + "item.szar.can_of_beans": "Can of Beans", + "item.szar.almond_water": "Almond Water", + "block.szar.backrooms_light": "Light" } diff --git a/src/main/resources/assets/szar/models/block/backrooms_light_off.json b/src/main/resources/assets/szar/models/block/backrooms_light_off.json new file mode 100644 index 0000000..38e5f1d --- /dev/null +++ b/src/main/resources/assets/szar/models/block/backrooms_light_off.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "szar:block/black" + } +} diff --git a/src/main/resources/assets/szar/models/block/backrooms_light_on.json b/src/main/resources/assets/szar/models/block/backrooms_light_on.json new file mode 100644 index 0000000..7f1f918 --- /dev/null +++ b/src/main/resources/assets/szar/models/block/backrooms_light_on.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "szar:block/white" + } +} diff --git a/src/main/resources/assets/szar/models/block/wall_bottom.json b/src/main/resources/assets/szar/models/block/wall_bottom.json index 58122f0..d530b6f 100644 --- a/src/main/resources/assets/szar/models/block/wall_bottom.json +++ b/src/main/resources/assets/szar/models/block/wall_bottom.json @@ -1,6 +1,7 @@ { "format_version": "1.21.11", "credit": "Made with Blockbench", + "parent": "block/block", "texture_size": [64, 64], "textures": { "2": "szar:block/wallpaper_bottom_block_texture", @@ -32,12 +33,6 @@ } } ], - "display": { - "thirdperson_righthand": { - "rotation": [80.5, 45, 0], - "scale": [0.3, 0.3, 0.3] - } - }, "groups": [ { "name": "block", diff --git a/src/main/resources/assets/szar/models/item/almond_water.json b/src/main/resources/assets/szar/models/item/almond_water.json new file mode 100644 index 0000000..00b33a1 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/almond_water.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "szar:item/almond_water" + } +} diff --git a/src/main/resources/assets/szar/models/item/backrooms_light.json b/src/main/resources/assets/szar/models/item/backrooms_light.json new file mode 100644 index 0000000..5b748d6 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/backrooms_light.json @@ -0,0 +1,3 @@ +{ + "parent": "szar:block/backrooms_light_on" +} diff --git a/src/main/resources/assets/szar/textures/block/black.png b/src/main/resources/assets/szar/textures/block/black.png new file mode 100644 index 0000000000000000000000000000000000000000..1dd197ac24ef7c36cec69da1ca0d0cf465b470e6 GIT binary patch literal 558 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DjSL74G){)!Z!hW5;mh>{3jAFJg2T)o7U{G?R9irfOAY6b=y z`-+0Zwic-?7f?V97Du6s&rHqo20xNy} z^73-Ma$~*xqI7*jOG`_A10#JSBVC{h-Qvo;lEez#ykcdj0WPV<$wiq3C7Jno3Lpa$ zlk!VTY?Vq&GgGY664OkRQc_HHlM;ls47YguJQ{>uF6ifOi{PD zbs{}UK3djZt>nqvW6s4qD1-ZCERRDRmN*N_31y=g{ z<>lpi<;HsXMd|v6mX?v90`zGE;%B09k2gXakl<5wp<;IRwdJb`TMuUx6%m z$bfSMu!BgOy{wf-w*b2%3;W9{3;8CU zJm|^Acg{)Oy|B2rsPx5yNhdF!b+i&WxNu8%qr{SSmyNCy95RIiblhC07iVpl-W_}} zzv}z_>i>Jc^ZlEx8TzC5hPHRZ?sLkwr^n{53u6&*)Y-r8{N&>L%;vRMe}>d~Nd$g& z`dPSv?ZD~R6I_3XWq(jN)t|yJH7j^kx$?5m#H0=dxoXqZ+;4r9I+pG^3zGsk_uPgJsO{0qKLDmKzJNv~c**xc>zVBFf;QMX{iDNlJ=2Cr==59RVwNgnp|vd$@?2>@sID$f7_ literal 0 HcmV?d00001 diff --git a/src/main/resources/data/szar/dimension_type/backrooms.json b/src/main/resources/data/szar/dimension_type/backrooms.json index 596d4ce..46e1bb8 100644 --- a/src/main/resources/data/szar/dimension_type/backrooms.json +++ b/src/main/resources/data/szar/dimension_type/backrooms.json @@ -4,7 +4,7 @@ "coordinate_scale": 1.0, "has_skylight": false, "has_ceiling": true, - "ambient_light": 0.5, + "ambient_light": 0.0, "fixed_time": 18000, "monster_spawn_light_level": 0, "monster_spawn_block_light_limit": 0, @@ -16,5 +16,5 @@ "min_y": 0, "height": 64, "infiniburn": "#minecraft:infiniburn_overworld", - "effects": "minecraft:the_end" + "effects": "minecraft:overworld" } \ No newline at end of file