Skip to content

Commit 2e08805

Browse files
committed
Preliminary testing with sublevel light
1 parent 2942182 commit 2e08805

10 files changed

Lines changed: 145 additions & 28 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package dev.ryanhcode.sable.command;
2+
3+
import com.mojang.brigadier.Command;
4+
import com.mojang.brigadier.CommandDispatcher;
5+
import dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer;
6+
import dev.ryanhcode.sable.api.sublevel.SubLevelContainer;
7+
import dev.ryanhcode.sable.sublevel.plot.LevelPlot;
8+
import net.minecraft.ChatFormatting;
9+
import net.minecraft.commands.CommandBuildContext;
10+
import net.minecraft.commands.CommandSourceStack;
11+
import net.minecraft.commands.Commands;
12+
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
13+
import net.minecraft.core.BlockPos;
14+
import net.minecraft.core.SectionPos;
15+
import net.minecraft.network.chat.Component;
16+
import net.minecraft.server.level.ServerLevel;
17+
import net.minecraft.world.level.LightLayer;
18+
import net.minecraft.world.level.lighting.LevelLightEngine;
19+
20+
public class SableLightCommand {
21+
22+
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher, final CommandBuildContext buildContext) {
23+
dispatcher.register(Commands.literal("light")
24+
.then(Commands.literal("get")
25+
.then(Commands.argument("pos", BlockPosArgument.blockPos())
26+
.executes(ctx -> {
27+
final CommandSourceStack source = ctx.getSource();
28+
29+
final BlockPos pos = BlockPosArgument.getBlockPos(ctx, "pos");
30+
31+
final ServerLevel level = source.getLevel();
32+
final ServerSubLevelContainer container = SubLevelContainer.getContainer(level);
33+
34+
final int chunkX = pos.getX() >> SectionPos.SECTION_BITS;
35+
final int chunkZ = pos.getZ() >> SectionPos.SECTION_BITS;
36+
37+
LevelLightEngine lightEngine = level.getLightEngine();
38+
if (container.inBounds(chunkX, chunkZ)) {
39+
final LevelPlot plot = container.getPlot(chunkX, chunkZ);
40+
if (plot != null) {
41+
lightEngine = plot.getLightEngine();
42+
}
43+
}
44+
45+
final int blockLight = lightEngine.getLayerListener(LightLayer.BLOCK).getLightValue(pos);
46+
final int skyLight = lightEngine.getLayerListener(LightLayer.SKY).getLightValue(pos);
47+
48+
source.sendSuccess(() -> Component.literal("Light at %d %d %d:\n".formatted(pos.getX(), pos.getY(), pos.getZ())).append(
49+
Component.literal(" %d block\n %d sky".formatted(blockLight, skyLight))
50+
.withStyle(ChatFormatting.GRAY)), false);
51+
return Command.SINGLE_SUCCESS;
52+
})
53+
))
54+
);
55+
}
56+
}

common/src/main/java/dev/ryanhcode/sable/mixin/plot/lighting/ClientPacketListenerMixin.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
1111
import org.spongepowered.asm.mixin.Mixin;
1212
import org.spongepowered.asm.mixin.injection.At;
13-
import org.spongepowered.asm.mixin.injection.Redirect;
1413

15-
@Mixin(ClientPacketListener.class)
14+
@Mixin(value = ClientPacketListener.class, priority = 1002)
1615
public class ClientPacketListenerMixin {
1716

1817
@WrapOperation(method = "handleLevelChunkWithLight", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;queueLightUpdate(Ljava/lang/Runnable;)V"))
@@ -27,5 +26,4 @@ public class ClientPacketListenerMixin {
2726

2827
original.call(instance, task);
2928
}
30-
3129
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package dev.ryanhcode.sable.mixin.plot.lighting;
2+
3+
import dev.ryanhcode.sable.mixinterface.plot.lighting.LevelLightEngineExtension;
4+
import net.minecraft.world.level.chunk.LightChunkGetter;
5+
import net.minecraft.world.level.lighting.LevelLightEngine;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Unique;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11+
12+
@Mixin(LevelLightEngine.class)
13+
public class LevelLightEngineMixin implements LevelLightEngineExtension {
14+
15+
@Unique
16+
private boolean sable$hasBlockLight;
17+
@Unique
18+
private boolean sable$hasSkylight;
19+
20+
@Inject(method = "<init>", at = @At("TAIL"))
21+
public void init(final LightChunkGetter lightChunkGetter, final boolean blockLight, final boolean skyLight, final CallbackInfo ci) {
22+
this.sable$hasBlockLight = blockLight;
23+
this.sable$hasSkylight = skyLight;
24+
}
25+
26+
@Override
27+
public boolean sable$hasBlockLight() {
28+
return this.sable$hasBlockLight;
29+
}
30+
31+
@Override
32+
public boolean sable$hasSkyight() {
33+
return this.sable$hasSkylight;
34+
}
35+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.ryanhcode.sable.mixinterface.plot.lighting;
2+
3+
public interface LevelLightEngineExtension {
4+
5+
boolean sable$hasBlockLight();
6+
7+
boolean sable$hasSkyight();
8+
}

common/src/main/java/dev/ryanhcode/sable/sublevel/plot/ServerLevelPlot.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import dev.ryanhcode.sable.api.sublevel.SubLevelContainer;
1010
import dev.ryanhcode.sable.companion.math.BoundingBox3i;
1111
import dev.ryanhcode.sable.index.SableTags;
12+
import dev.ryanhcode.sable.mixinterface.plot.lighting.LevelLightEngineExtension;
1213
import dev.ryanhcode.sable.mixinterface.plot.serialization.LevelChunkTicksExtension;
1314
import dev.ryanhcode.sable.platform.SablePlotPlatform;
1415
import dev.ryanhcode.sable.sublevel.ServerSubLevel;
@@ -61,6 +62,8 @@ public class ServerLevelPlot extends LevelPlot {
6162
Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()
6263
);
6364

65+
public static final boolean USE_SYNCHRONOUS_LIGHT_ENGINE = true;
66+
6467
/**
6568
* The light engine for this plot
6669
*/
@@ -89,9 +92,14 @@ public ServerLevelPlot(final SubLevelContainer plotContainer, final int x, final
8992
super(plotContainer, x, z, logSize, subLevel);
9093

9194
final Level level = subLevel.getLevel();
92-
final LevelLightEngine parentLightEngine = level.getLightEngine();
9395
final ChunkSource chunkSource = level.getChunkSource();
94-
this.lightEngine = new LevelLightEngine(chunkSource, parentLightEngine.blockEngine != null, parentLightEngine.skyEngine != null);
96+
97+
if (USE_SYNCHRONOUS_LIGHT_ENGINE) {
98+
final LevelLightEngineExtension parentLightEngine = (LevelLightEngineExtension) level.getLightEngine();
99+
this.lightEngine = new LevelLightEngine(chunkSource, parentLightEngine.sable$hasBlockLight(), parentLightEngine.sable$hasSkyight());
100+
} else {
101+
this.lightEngine = level.getLightEngine();
102+
}
95103
}
96104

97105
/**
@@ -122,15 +130,20 @@ private static void logLoadingErrors(final ChunkPos chunkPos, final int y, final
122130
Sable.LOGGER.error("Recoverable errors when loading plot section [{}, {}, {}]: {}", chunkPos.x, y, chunkPos.z, errorText);
123131
}
124132

133+
private void runLightUpdates() {
134+
if (USE_SYNCHRONOUS_LIGHT_ENGINE) {
135+
do {
136+
this.lightEngine.runLightUpdates();
137+
} while (this.lightEngine.hasLightWork());
138+
}
139+
}
140+
125141
/**
126142
* Ticks this plot, running lighting updates
127143
*/
128144
@Override
129145
public void tick() {
130-
do {
131-
this.lightEngine.runLightUpdates();
132-
} while (this.lightEngine.hasLightWork());
133-
146+
this.runLightUpdates();
134147
this.contraptions.removeIf(contraption -> !contraption.sable$isValid());
135148
}
136149

@@ -224,8 +237,8 @@ public void addChunkHolder(final ChunkPos localChunkPos, final PlotChunkHolder h
224237

225238
// Update the chunk map if one exists
226239
if (level.getChunkSource() instanceof final ServerChunkCache cache) {
227-
cache.chunkMap.updatingChunkMap.put(globalChunkPos.toLong(), holder);
228-
cache.chunkMap.modified = true;
240+
cache.chunkMap.updatingChunkMap.put(globalChunkPos.toLong(), holder);
241+
cache.chunkMap.modified = true;
229242
}
230243

231244
super.addChunkHolder(localChunkPos, holder, initializeLighting);
@@ -245,12 +258,9 @@ public void addChunkHolder(final ChunkPos localChunkPos, final PlotChunkHolder h
245258
level.entityManager.updateChunkStatus(chunk.getPos(), FullChunkStatus.ENTITY_TICKING);
246259
level.getChunkSource().chunkMap.onFullChunkStatusChange(globalChunkPos, FullChunkStatus.ENTITY_TICKING);
247260

248-
do {
249-
this.lightEngine.runLightUpdates();
250-
} while (this.lightEngine.hasLightWork());
261+
this.runLightUpdates();
251262

252263
final Iterable<ServerPlayer> players = this.container.getPlayersTracking(globalChunkPos);
253-
254264
for (final ServerPlayer player : players) {
255265
SubLevelPlayerChunkSender.sendChunk(player.connection::send, this.lightEngine, chunk);
256266
SubLevelPlayerChunkSender.sendChunkPoiData(level, chunk);
@@ -469,14 +479,16 @@ public void load(final CompoundTag tag) {
469479
.getOrThrow(ChunkSerializer.ChunkReadException::new);
470480

471481
final Registry<Biome> biomeRegistry = level.registryAccess().registryOrThrow(Registries.BIOME);
472-
final PalettedContainer<Holder<Biome>> biomeContainer = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(this.biome), PalettedContainer.Strategy.SECTION_BIOMES);
482+
final PalettedContainer<Holder<Biome>> biomeContainer =
483+
new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(this.biome), PalettedContainer.Strategy.SECTION_BIOMES);
473484

474485
sections[yIndex] = new LevelChunkSection(palettedContainer, biomeContainer);
475486

476487
final SectionPos sectionPos = SectionPos.of(global, level.getSectionYFromSectionIndex(yIndex));
477488

478-
final boolean hasBlockLight = this.lightEngine.blockEngine != null && sectionTag.contains("BlockLight", Tag.TAG_BYTE_ARRAY);
479-
final boolean hasSkyLight = this.lightEngine.skyEngine != null && level.dimensionType().hasSkyLight() && sectionTag.contains("SkyLight", Tag.TAG_BYTE_ARRAY);
489+
final LevelLightEngineExtension lightExt = (LevelLightEngineExtension) this.lightEngine;
490+
final boolean hasBlockLight = lightExt.sable$hasBlockLight() && sectionTag.contains("BlockLight", Tag.TAG_BYTE_ARRAY);
491+
final boolean hasSkyLight = lightExt.sable$hasSkyight() && level.dimensionType().hasSkyLight() && sectionTag.contains("SkyLight", Tag.TAG_BYTE_ARRAY);
480492
if (hasBlockLight || hasSkyLight) {
481493
if (!hasLit) {
482494
this.lightEngine.retainData(global, true);
@@ -554,9 +566,7 @@ public void load(final CompoundTag tag) {
554566
}
555567

556568
// Before we send the chunks, let's ensure our lighting data is complete
557-
do {
558-
this.lightEngine.runLightUpdates();
559-
} while (this.lightEngine.hasLightWork());
569+
this.runLightUpdates();
560570

561571
final SubLevelPhysicsSystem physicsSystem = ((ServerSubLevelContainer) this.container).physicsSystem();
562572

common/src/main/resources/sable.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@
186186
"plot.ServerLevelMixin",
187187
"plot.lighting.BlockAndTintGetterMixin",
188188
"plot.lighting.LevelChunkMixin",
189+
"plot.lighting.LevelLightEngineMixin",
189190
"plot.serialization.ChunkMapMixin",
190191
"plot.serialization.LevelChunkTicksMixin",
191192
"portal.EntityMixin",

fabric/src/main/java/dev/ryanhcode/sable/fabric/SableFabric.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import dev.ryanhcode.sable.SableCommonEvents;
55
import dev.ryanhcode.sable.SableConfig;
66
import dev.ryanhcode.sable.command.SableCommand;
7+
import dev.ryanhcode.sable.command.SableLightCommand;
78
import dev.ryanhcode.sable.command.argument.SubLevelSelectorModifiers;
89
import dev.ryanhcode.sable.index.SableAttributes;
910
import dev.ryanhcode.sable.physics.config.FloatingBlockMaterialDataHandler;
@@ -14,6 +15,7 @@
1415
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
1516
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
1617
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
18+
import net.fabricmc.loader.api.FabricLoader;
1719
import net.minecraft.core.Registry;
1820
import net.minecraft.core.registries.BuiltInRegistries;
1921
import net.minecraft.server.packs.PackType;
@@ -27,6 +29,9 @@ public void onInitialize() {
2729

2830
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
2931
SableCommand.register(dispatcher, registryAccess);
32+
if (FabricLoader.getInstance().isDevelopmentEnvironment()) {
33+
SableLightCommand.register(dispatcher, registryAccess);
34+
}
3035
});
3136

3237
SubLevelSelectorModifiers.registerModifiers();

fabric/src/main/resources/fabric.mod.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
},
4848
"breaks": {
4949
"sodium": "<${sodium_version}",
50-
"scalablelux": "*",
5150
"sablecompanion": "<${sable_companion_version}"
5251
}
5352
}

neoforge/src/main/java/dev/ryanhcode/sable/neoforge/SableNeoForge.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package dev.ryanhcode.sable.neoforge;
22

3+
import com.mojang.brigadier.CommandDispatcher;
34
import dev.ryanhcode.sable.Sable;
45
import dev.ryanhcode.sable.SableCommonEvents;
56
import dev.ryanhcode.sable.SableConfig;
67
import dev.ryanhcode.sable.command.SableCommand;
8+
import dev.ryanhcode.sable.command.SableLightCommand;
79
import dev.ryanhcode.sable.command.argument.SubLevelSelectorModifiers;
810
import dev.ryanhcode.sable.index.SableAttributes;
911
import dev.ryanhcode.sable.physics.config.FloatingBlockMaterialDataHandler;
1012
import dev.ryanhcode.sable.physics.config.block_properties.PhysicsBlockPropertiesDefinitionLoader;
1113
import dev.ryanhcode.sable.physics.config.dimension_physics.DimensionPhysicsData;
14+
import net.minecraft.commands.CommandBuildContext;
15+
import net.minecraft.commands.CommandSourceStack;
1216
import net.minecraft.core.registries.BuiltInRegistries;
1317
import net.minecraft.world.entity.ai.attributes.Attribute;
1418
import net.neoforged.bus.api.IEventBus;
@@ -17,6 +21,7 @@
1721
import net.neoforged.fml.common.Mod;
1822
import net.neoforged.fml.config.ModConfig;
1923
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
24+
import net.neoforged.fml.loading.FMLLoader;
2025
import net.neoforged.neoforge.common.NeoForge;
2126
import net.neoforged.neoforge.event.AddReloadListenerEvent;
2227
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
@@ -57,7 +62,12 @@ private void serverSetup(final FMLCommonSetupEvent event) {
5762
}
5863

5964
private void registerCommand(final RegisterCommandsEvent event) {
60-
SableCommand.register(event.getDispatcher(), event.getBuildContext());
65+
final CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
66+
final CommandBuildContext buildContext = event.getBuildContext();
67+
SableCommand.register(dispatcher, buildContext);
68+
if (!FMLLoader.isProduction()) {
69+
SableLightCommand.register(dispatcher, buildContext);
70+
}
6171
}
6272

6373
private void syncDataPack(final OnDatapackSyncEvent event) {

neoforge/src/main/resources/META-INF/neoforge.mods.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,5 @@ type = "incompatible"
6464
versionRange = "(,${sodium_version})"
6565
reason = "${mod_name} supports Sodium ${sodium_version} and above"
6666

67-
[[dependencies.sable]]
68-
modId = "scalablelux"
69-
type = "incompatible"
70-
71-
[[dependencies.sable]]
7267
modId = "littletiles"
7368
type = "incompatible"

0 commit comments

Comments
 (0)