light
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
package dev.tggamesyt.szar.client;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.BackroomsLightBlockEntity;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import net.minecraft.client.render.WorldRenderer;
|
||||||
|
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||||
|
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
public class BackroomsLightBlockEntityRenderer implements BlockEntityRenderer<BackroomsLightBlockEntity> {
|
||||||
|
|
||||||
|
// Your light texture
|
||||||
|
private static final Identifier TEXTURE =
|
||||||
|
new Identifier("szar", "textures/block/white.png");
|
||||||
|
|
||||||
|
public BackroomsLightBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(BackroomsLightBlockEntity entity, float tickDelta,
|
||||||
|
MatrixStack matrices, VertexConsumerProvider vertexConsumers,
|
||||||
|
int light, int overlay) {
|
||||||
|
|
||||||
|
float brightness = entity.brightness;
|
||||||
|
if (brightness <= 0.0f) return; // fully dark, don't render
|
||||||
|
|
||||||
|
BlockPos pos = entity.getPos();
|
||||||
|
int lightLevel = WorldRenderer.getLightmapCoordinates(entity.getWorld(), pos);
|
||||||
|
|
||||||
|
VertexConsumer consumer = vertexConsumers.getBuffer(
|
||||||
|
RenderLayer.getEntityCutoutNoCull(TEXTURE));
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
|
// Center on block, render on bottom face (light faces downward into room)
|
||||||
|
matrices.translate(0.5, 0.001, 0.5);
|
||||||
|
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||||
|
|
||||||
|
Matrix4f matrix = matrices.peek().getPositionMatrix();
|
||||||
|
|
||||||
|
// Apply brightness as color multiplier
|
||||||
|
int r = (int)(255 * brightness);
|
||||||
|
int g = (int)(255 * brightness);
|
||||||
|
int b = (int)(255 * brightness);
|
||||||
|
|
||||||
|
float s = 0.5f;
|
||||||
|
consumer.vertex(matrix, -s, -s, 0).color(r, g, b, 255)
|
||||||
|
.texture(0, 1).overlay(overlay).light(lightLevel)
|
||||||
|
.normal(0, -1, 0).next();
|
||||||
|
consumer.vertex(matrix, s, -s, 0).color(r, g, b, 255)
|
||||||
|
.texture(1, 1).overlay(overlay).light(lightLevel)
|
||||||
|
.normal(0, -1, 0).next();
|
||||||
|
consumer.vertex(matrix, s, s, 0).color(r, g, b, 255)
|
||||||
|
.texture(1, 0).overlay(overlay).light(lightLevel)
|
||||||
|
.normal(0, -1, 0).next();
|
||||||
|
consumer.vertex(matrix, -s, s, 0).color(r, g, b, 255)
|
||||||
|
.texture(0, 0).overlay(overlay).light(lightLevel)
|
||||||
|
.normal(0, -1, 0).next();
|
||||||
|
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -367,6 +367,9 @@ public class SzarClient implements ClientModInitializer {
|
|||||||
Szar.TRACKER_BLOCK_ENTITY,
|
Szar.TRACKER_BLOCK_ENTITY,
|
||||||
TGTrackerBlockRenderer::new
|
TGTrackerBlockRenderer::new
|
||||||
);
|
);
|
||||||
|
BlockEntityRendererFactories.register(
|
||||||
|
Szar.BACKROOMS_LIGHT_ENTITY,
|
||||||
|
BackroomsLightBlockEntityRenderer::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);
|
||||||
|
|||||||
@@ -92,16 +92,11 @@ public class BackroomsChunkGenerator extends ChunkGenerator {
|
|||||||
if (isGlowstone) {
|
if (isGlowstone) {
|
||||||
long lightRoll = hash(worldX * 53 + 7, worldZ * 47 + 13);
|
long lightRoll = hash(worldX * 53 + 7, worldZ * 47 + 13);
|
||||||
int roll = (int)(Math.abs(lightRoll) % 100);
|
int roll = (int)(Math.abs(lightRoll) % 100);
|
||||||
if (roll < 95) {
|
if (roll < 98) {
|
||||||
// 95% ON
|
// 98% ON (flickering determined by block entity in generateFeatures)
|
||||||
ceilingBlock = Szar.BACKROOMS_LIGHT.getDefaultState()
|
ceilingBlock = Szar.BACKROOMS_LIGHT.getDefaultState()
|
||||||
.with(BackroomsLightBlock.LIGHT_STATE,
|
.with(BackroomsLightBlock.LIGHT_STATE,
|
||||||
BackroomsLightBlock.LightState.ON);
|
BackroomsLightBlock.LightState.ON);
|
||||||
} else if (roll < 98) {
|
|
||||||
// 3% FLICKERING_ON
|
|
||||||
ceilingBlock = Szar.BACKROOMS_LIGHT.getDefaultState()
|
|
||||||
.with(BackroomsLightBlock.LIGHT_STATE,
|
|
||||||
BackroomsLightBlock.LightState.FLICKERING_ON);
|
|
||||||
} else {
|
} else {
|
||||||
// 2% missing — ceiling block, no light
|
// 2% missing — ceiling block, no light
|
||||||
ceilingBlock = Szar.CEILING.getDefaultState();
|
ceilingBlock = Szar.CEILING.getDefaultState();
|
||||||
@@ -273,9 +268,10 @@ public class BackroomsChunkGenerator extends ChunkGenerator {
|
|||||||
int chunkX = chunk.getPos().getStartX();
|
int chunkX = chunk.getPos().getStartX();
|
||||||
int chunkZ = chunk.getPos().getStartZ();
|
int chunkZ = chunk.getPos().getStartZ();
|
||||||
|
|
||||||
// Initialize wall block entities
|
|
||||||
for (int lx = 0; lx < 16; lx++) {
|
for (int lx = 0; lx < 16; lx++) {
|
||||||
for (int lz = 0; lz < 16; lz++) {
|
for (int lz = 0; lz < 16; lz++) {
|
||||||
|
|
||||||
|
// Initialize wall block entities
|
||||||
for (int y = 0; y < 64; y++) {
|
for (int y = 0; y < 64; y++) {
|
||||||
mutable.set(chunkX + lx, y, chunkZ + lz);
|
mutable.set(chunkX + lx, y, chunkZ + lz);
|
||||||
if (world.getBlockState(mutable).getBlock() instanceof WallBlock) {
|
if (world.getBlockState(mutable).getBlock() instanceof WallBlock) {
|
||||||
@@ -286,16 +282,20 @@ 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
|
// Initialize light block entities
|
||||||
|
mutable.set(chunkX + lx, 9, chunkZ + lz);
|
||||||
BlockState lightState = world.getBlockState(mutable);
|
BlockState lightState = world.getBlockState(mutable);
|
||||||
if (lightState.getBlock() instanceof BackroomsLightBlock) {
|
if (lightState.getBlock() instanceof BackroomsLightBlock) {
|
||||||
if (world.getBlockEntity(mutable) == null) {
|
// Always re-set to force block entity creation — no null check needed
|
||||||
world.setBlockState(mutable, lightState, Block.NOTIFY_ALL);
|
world.setBlockState(mutable, lightState, Block.NOTIFY_ALL);
|
||||||
}
|
BlockPos immutable = mutable.toImmutable();
|
||||||
if (world.getBlockEntity(mutable) instanceof BackroomsLightBlockEntity light) {
|
if (world.getBlockEntity(immutable) instanceof BackroomsLightBlockEntity light) {
|
||||||
|
long typeRoll = hash(chunkX + lx, chunkZ + lz);
|
||||||
|
light.isFlickering = (Math.abs(typeRoll) % 10) >= 8;
|
||||||
light.flickerOffset = (int)(Math.abs(hash(chunkX + lx, chunkZ + lz)) % 100);
|
light.flickerOffset = (int)(Math.abs(hash(chunkX + lx, chunkZ + lz)) % 100);
|
||||||
light.flickerTimer = light.flickerOffset; // stagger initial timers
|
light.flickerTimer = light.flickerOffset;
|
||||||
|
light.brightness = 1.0f;
|
||||||
light.markDirty();
|
light.markDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public class BackroomsLightBlock extends BlockWithEntity {
|
public class BackroomsLightBlock extends BlockWithEntity {
|
||||||
|
|
||||||
public enum LightState implements StringIdentifiable {
|
public enum LightState implements StringIdentifiable {
|
||||||
ON, OFF, FLICKERING_ON, FLICKERING_OFF;
|
ON, OFF;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String asString() {
|
public String asString() {
|
||||||
@@ -59,9 +59,6 @@ public class BackroomsLightBlock extends BlockWithEntity {
|
|||||||
|
|
||||||
// Light level based on state
|
// Light level based on state
|
||||||
public static int getLightLevel(BlockState state) {
|
public static int getLightLevel(BlockState state) {
|
||||||
return switch (state.get(LIGHT_STATE)) {
|
return state.get(LIGHT_STATE) == LightState.ON ? 15 : 0;
|
||||||
case ON, FLICKERING_ON -> 15;
|
|
||||||
case OFF, FLICKERING_OFF -> 0;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,12 +10,13 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class BackroomsLightBlockEntity extends BlockEntity {
|
public class BackroomsLightBlockEntity extends BlockEntity {
|
||||||
|
public float brightness = 1.0f; // 0.0 = black, 1.0 = full bright
|
||||||
// Random offset so each light flickers at different times
|
// Random offset so each light flickers at different times
|
||||||
public int flickerOffset = 0;
|
public int flickerOffset = 0;
|
||||||
// How many ticks until next state toggle during flicker
|
// How many ticks until next state toggle during flicker
|
||||||
public int flickerTimer = 0;
|
public int flickerTimer = 0;
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
public boolean isFlickering = false; // true for lights generated as flickering type
|
||||||
|
|
||||||
public BackroomsLightBlockEntity(BlockPos pos, BlockState state) {
|
public BackroomsLightBlockEntity(BlockPos pos, BlockState state) {
|
||||||
super(Szar.BACKROOMS_LIGHT_ENTITY, pos, state);
|
super(Szar.BACKROOMS_LIGHT_ENTITY, pos, state);
|
||||||
@@ -38,6 +39,7 @@ public class BackroomsLightBlockEntity extends BlockEntity {
|
|||||||
nbt.putInt("FlickerOffset", flickerOffset);
|
nbt.putInt("FlickerOffset", flickerOffset);
|
||||||
nbt.putInt("FlickerTimer", flickerTimer);
|
nbt.putInt("FlickerTimer", flickerTimer);
|
||||||
nbt.putBoolean("Initialized", initialized);
|
nbt.putBoolean("Initialized", initialized);
|
||||||
|
nbt.putFloat("Brightness", brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,6 +48,7 @@ public class BackroomsLightBlockEntity extends BlockEntity {
|
|||||||
flickerOffset = nbt.getInt("FlickerOffset");
|
flickerOffset = nbt.getInt("FlickerOffset");
|
||||||
flickerTimer = nbt.getInt("FlickerTimer");
|
flickerTimer = nbt.getInt("FlickerTimer");
|
||||||
initialized = nbt.getBoolean("Initialized");
|
initialized = nbt.getBoolean("Initialized");
|
||||||
|
brightness = nbt.getFloat("Brightness");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,23 +6,24 @@ import net.minecraft.server.MinecraftServer;
|
|||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.WorldChunk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class BackroomsLightManager {
|
public class BackroomsLightManager {
|
||||||
|
|
||||||
// Global event state
|
|
||||||
public enum GlobalEvent { NONE, FLICKER, BLACKOUT }
|
public enum GlobalEvent { NONE, FLICKER, BLACKOUT }
|
||||||
|
|
||||||
public static GlobalEvent currentEvent = GlobalEvent.NONE;
|
public static GlobalEvent currentEvent = GlobalEvent.NONE;
|
||||||
public static int eventTimer = 0; // ticks remaining in current event
|
public static int eventTimer = 0;
|
||||||
public static int cooldownTimer = 0; // ticks until next event check
|
public static int cooldownTimer = 3600;
|
||||||
|
|
||||||
// Flicker event duration: 3-8 seconds
|
|
||||||
private static final int FLICKER_DURATION_MIN = 60;
|
private static final int FLICKER_DURATION_MIN = 60;
|
||||||
private static final int FLICKER_DURATION_MAX = 160;
|
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_MIN = 1000;
|
||||||
private static final int BLACKOUT_MAX = 2000;
|
private static final int BLACKOUT_MAX = 2000;
|
||||||
// Check for new event every ~3 minutes
|
|
||||||
private static final int EVENT_COOLDOWN = 3600;
|
private static final int EVENT_COOLDOWN = 3600;
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
@@ -33,7 +34,6 @@ public class BackroomsLightManager {
|
|||||||
ServerWorld backrooms = server.getWorld(Szar.BACKROOMS_KEY);
|
ServerWorld backrooms = server.getWorld(Szar.BACKROOMS_KEY);
|
||||||
if (backrooms == null) return;
|
if (backrooms == null) return;
|
||||||
|
|
||||||
// Handle event timers
|
|
||||||
if (currentEvent != GlobalEvent.NONE) {
|
if (currentEvent != GlobalEvent.NONE) {
|
||||||
eventTimer--;
|
eventTimer--;
|
||||||
if (eventTimer <= 0) {
|
if (eventTimer <= 0) {
|
||||||
@@ -42,14 +42,12 @@ public class BackroomsLightManager {
|
|||||||
} else {
|
} else {
|
||||||
cooldownTimer--;
|
cooldownTimer--;
|
||||||
if (cooldownTimer <= 0) {
|
if (cooldownTimer <= 0) {
|
||||||
// Roll for new event
|
|
||||||
int roll = backrooms.random.nextInt(100);
|
int roll = backrooms.random.nextInt(100);
|
||||||
if (roll < 30) {
|
if (roll < 30) {
|
||||||
startBlackout(backrooms);
|
startBlackout(backrooms);
|
||||||
} else if (roll < 63) { // 30% blackout + 33% flicker
|
} else if (roll < 63) {
|
||||||
startFlicker(backrooms);
|
startFlicker(backrooms);
|
||||||
} else {
|
} else {
|
||||||
// No event — reset cooldown
|
|
||||||
cooldownTimer = EVENT_COOLDOWN;
|
cooldownTimer = EVENT_COOLDOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,79 +65,92 @@ public class BackroomsLightManager {
|
|||||||
currentEvent = GlobalEvent.BLACKOUT;
|
currentEvent = GlobalEvent.BLACKOUT;
|
||||||
eventTimer = BLACKOUT_MIN + world.random.nextInt(BLACKOUT_MAX - BLACKOUT_MIN);
|
eventTimer = BLACKOUT_MIN + world.random.nextInt(BLACKOUT_MAX - BLACKOUT_MIN);
|
||||||
cooldownTimer = EVENT_COOLDOWN;
|
cooldownTimer = EVENT_COOLDOWN;
|
||||||
|
// Set all lights to brightness 0
|
||||||
// Immediately turn off all ON lights in loaded chunks
|
forEachLightEntity(world, entity -> {
|
||||||
setAllLightsOff(world);
|
entity.brightness = 0.0f;
|
||||||
|
entity.markDirty();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void endEvent(ServerWorld world) {
|
private static void endEvent(ServerWorld world) {
|
||||||
if (currentEvent == GlobalEvent.BLACKOUT) {
|
// Restore all lights to full brightness
|
||||||
// Restore all lights
|
forEachLightEntity(world, entity -> {
|
||||||
setAllLightsOn(world);
|
entity.brightness = 1.0f;
|
||||||
}
|
entity.markDirty();
|
||||||
|
});
|
||||||
currentEvent = GlobalEvent.NONE;
|
currentEvent = GlobalEvent.NONE;
|
||||||
eventTimer = 0;
|
eventTimer = 0;
|
||||||
cooldownTimer = EVENT_COOLDOWN;
|
cooldownTimer = EVENT_COOLDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setAllLightsOff(ServerWorld world) {
|
// Called per-light from BackroomsLightBlockEntity.tick
|
||||||
forEachLight(world, (pos, state) -> {
|
public static void tickLight(World world, BlockPos pos, BlockState state,
|
||||||
|
BackroomsLightBlockEntity entity) {
|
||||||
|
if (currentEvent == GlobalEvent.BLACKOUT) return;
|
||||||
|
|
||||||
BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE);
|
BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE);
|
||||||
if (ls == BackroomsLightBlock.LightState.ON) {
|
if (ls == BackroomsLightBlock.LightState.OFF) return;
|
||||||
world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE,
|
|
||||||
BackroomsLightBlock.LightState.OFF));
|
boolean inFlickerEvent = currentEvent == GlobalEvent.FLICKER;
|
||||||
} else if (ls == BackroomsLightBlock.LightState.FLICKERING_ON) {
|
|
||||||
world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE,
|
// Always-flickering lights tick regardless of event
|
||||||
BackroomsLightBlock.LightState.FLICKERING_OFF));
|
// During flicker event, all ON lights also flicker
|
||||||
|
if (!entity.isFlickering && !inFlickerEvent) {
|
||||||
|
// Normal ON light, not in event — ensure full brightness
|
||||||
|
if (entity.brightness != 1.0f) {
|
||||||
|
entity.brightness = 1.0f;
|
||||||
|
entity.markDirty();
|
||||||
}
|
}
|
||||||
});
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setAllLightsOn(ServerWorld world) {
|
entity.flickerTimer--;
|
||||||
forEachLight(world, (pos, state) -> {
|
if (entity.flickerTimer > 0) return;
|
||||||
BackroomsLightBlock.LightState ls = state.get(BackroomsLightBlock.LIGHT_STATE);
|
|
||||||
if (ls == BackroomsLightBlock.LightState.OFF) {
|
// Random new brightness and timer
|
||||||
world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE,
|
float newBrightness;
|
||||||
BackroomsLightBlock.LightState.ON));
|
if (world.random.nextFloat() < 0.3f) {
|
||||||
} else if (ls == BackroomsLightBlock.LightState.FLICKERING_OFF) {
|
// 30% chance of a dim flicker
|
||||||
world.setBlockState(pos, state.with(BackroomsLightBlock.LIGHT_STATE,
|
newBrightness = 0.1f + world.random.nextFloat() * 0.4f;
|
||||||
BackroomsLightBlock.LightState.FLICKERING_ON));
|
} else {
|
||||||
}
|
// 70% chance of full or near-full
|
||||||
});
|
newBrightness = 0.7f + world.random.nextFloat() * 0.3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void forEachLight(ServerWorld world, java.util.function.BiConsumer<BlockPos, BlockState> consumer) {
|
entity.brightness = newBrightness;
|
||||||
for (net.minecraft.world.chunk.WorldChunk chunk : getLoadedChunks(world)) {
|
entity.flickerTimer = 2 + world.random.nextInt(8 + (entity.flickerOffset % 5));
|
||||||
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
entity.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void forEachLightEntity(ServerWorld world,
|
||||||
|
Consumer<BackroomsLightBlockEntity> consumer) {
|
||||||
|
for (WorldChunk chunk : getLoadedChunks(world)) {
|
||||||
int cx = chunk.getPos().getStartX();
|
int cx = chunk.getPos().getStartX();
|
||||||
int cz = chunk.getPos().getStartZ();
|
int cz = chunk.getPos().getStartZ();
|
||||||
|
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
||||||
for (int lx = 0; lx < 16; lx++) {
|
for (int lx = 0; lx < 16; lx++) {
|
||||||
for (int lz = 0; lz < 16; lz++) {
|
for (int lz = 0; lz < 16; lz++) {
|
||||||
// Ceiling Y in backrooms is 9
|
|
||||||
mutable.set(cx + lx, 9, cz + lz);
|
mutable.set(cx + lx, 9, cz + lz);
|
||||||
BlockState state = world.getBlockState(mutable);
|
if (world.getBlockEntity(mutable.toImmutable())
|
||||||
if (state.getBlock() instanceof BackroomsLightBlock) {
|
instanceof BackroomsLightBlockEntity entity) {
|
||||||
consumer.accept(mutable.toImmutable(), state);
|
consumer.accept(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static java.util.List<net.minecraft.world.chunk.WorldChunk> getLoadedChunks(ServerWorld world) {
|
private static List<WorldChunk> getLoadedChunks(ServerWorld world) {
|
||||||
java.util.List<net.minecraft.world.chunk.WorldChunk> chunks = new java.util.ArrayList<>();
|
List<WorldChunk> chunks = new ArrayList<>();
|
||||||
// Iterate over all players and collect chunks around them
|
|
||||||
for (net.minecraft.server.network.ServerPlayerEntity player : world.getPlayers()) {
|
for (net.minecraft.server.network.ServerPlayerEntity player : world.getPlayers()) {
|
||||||
int playerChunkX = (int) player.getX() >> 4;
|
int pcx = (int) player.getX() >> 4;
|
||||||
int playerChunkZ = (int) player.getZ() >> 4;
|
int pcz = (int) player.getZ() >> 4;
|
||||||
int viewDistance = world.getServer().getPlayerManager().getViewDistance();
|
int viewDistance = world.getServer().getPlayerManager().getViewDistance();
|
||||||
for (int cx = playerChunkX - viewDistance; cx <= playerChunkX + viewDistance; cx++) {
|
for (int cx = pcx - viewDistance; cx <= pcx + viewDistance; cx++) {
|
||||||
for (int cz = playerChunkZ - viewDistance; cz <= playerChunkZ + viewDistance; cz++) {
|
for (int cz = pcz - viewDistance; cz <= pcz + viewDistance; cz++) {
|
||||||
if (world.getChunkManager().isChunkLoaded(cx, cz)) {
|
if (world.getChunkManager().isChunkLoaded(cx, cz)) {
|
||||||
net.minecraft.world.chunk.WorldChunk chunk = world.getChunk(cx, cz);
|
WorldChunk chunk = world.getChunk(cx, cz);
|
||||||
if (!chunks.contains(chunk)) {
|
if (!chunks.contains(chunk)) chunks.add(chunk);
|
||||||
chunks.add(chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,67 +158,22 @@ public class BackroomsLightManager {
|
|||||||
return chunks;
|
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) {
|
public static void forceRestoreAllLights(ServerWorld world) {
|
||||||
setAllLightsOn(world);
|
forEachLightEntity(world, entity -> {
|
||||||
|
entity.brightness = 1.0f;
|
||||||
|
entity.markDirty();
|
||||||
|
});
|
||||||
|
currentEvent = GlobalEvent.NONE;
|
||||||
|
eventTimer = 0;
|
||||||
|
cooldownTimer = EVENT_COOLDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forceBlackout(ServerWorld world) {
|
public static void forceBlackout(ServerWorld world) {
|
||||||
setAllLightsOff(world);
|
forEachLightEntity(world, entity -> {
|
||||||
|
entity.brightness = 0.0f;
|
||||||
|
entity.markDirty();
|
||||||
|
});
|
||||||
|
currentEvent = GlobalEvent.BLACKOUT;
|
||||||
|
eventTimer = 3600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user