Skip to content

Commit

Permalink
feat(test): more tests for light system
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Nov 8, 2024
1 parent 560a74e commit 0f77de2
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 22 deletions.
7 changes: 7 additions & 0 deletions api/src/main/java/org/allaymc/api/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ default void disconnectAllPlayers(@MayContainTrKey String reason) {
*/
boolean isRunning();

/**
* Check if the server is starting.
*
* @return {@code true} if the server is starting, otherwise {@code false}.
*/
boolean isStarting();

/**
* Get the player storage.
*
Expand Down
50 changes: 40 additions & 10 deletions api/src/main/java/org/allaymc/api/world/service/LightService.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
package org.allaymc.api.world.service;

import org.allaymc.api.world.chunk.Chunk;

/**
* LightService is responsible for storing and calculating the light of a dimension.
*
* @author daoge_cmd
* @see <a href="https://minecraft.wiki/w/Light">Light</a>
*/
public interface LightService {
/**
* Get the skylight level at the specified position.
*
* @param x the x coordinate of the pos.
* @param y the y coordinate of the pos.
* @param z the z coordinate of the pos.
* @return the skylight level at the specified position.
*/
int getSkyLight(int x, int y, int z);

/**
* Get the internal light level at the specified position.
*
* @param x the x coordinate of the pos.
* @param y the y coordinate of the pos.
* @param z the z coordinate of the pos.
* @return the internal light level at the specified position.
*/
int getInternalLight(int x, int y, int z);

/**
* Get the internal skylight level at the specified position.
*
* @param x the x coordinate of the pos.
* @param y the y coordinate of the pos.
* @param z the z coordinate of the pos.
* @return the internal skylight level at the specified position.
*/
int getInternalSkyLight(int x, int y, int z);

/**
* Get the block light level at the specified position.
*
* @param x the x coordinate of the pos.
* @param y the y coordinate of the pos.
* @param z the z coordinate of the pos.
* @return the block light level at the specified position.
*/
int getBlockLight(int x, int y, int z);

void onBlockChange(int x, int y, int z, int lightEmission, int lightDampening);

void onChunkLoad(Chunk chunk);

void onChunkUnload(Chunk chunk);

/**
* Get the queued update count.
*
* @return the queued update count.
*/
int getQueuedUpdateCount();

int getLightDampening(int x, int y, int z);
}
8 changes: 7 additions & 1 deletion server/src/main/java/org/allaymc/server/AllayServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public final class AllayServer implements Server {
@Getter
private final AllayWorldPool worldPool = new AllayWorldPool();
private final AtomicBoolean isRunning = new AtomicBoolean(true);
private final AtomicBoolean isStarting = new AtomicBoolean(true);
private boolean isFullyStopped = false;
private final Object2ObjectMap<UUID, PlayerListPacket.Entry> playerListEntryMap = new Object2ObjectOpenHashMap<>();
@Getter
Expand Down Expand Up @@ -125,7 +126,7 @@ public final class AllayServer implements Server {
} catch (Throwable throwable) {
log.error("Error while ticking the server", throwable);
}
}).onStop(() -> {
}).onStart(() -> isStarting.set(false)).onStop(() -> {
try {
shutdownReally();
} catch (Throwable throwable) {
Expand Down Expand Up @@ -487,6 +488,11 @@ public boolean isRunning() {
return isRunning.get();
}

@Override
public boolean isStarting() {
return isStarting.get();
}

@Override
public String getCommandSenderName() {
return "Server";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ public void prepareCommandTree(CommandTree tree) {
player.sendText("BlockLight: " + lightService.getBlockLight(x, y, z));
player.sendText("SkyLight: " + lightService.getSkyLight(x, y, z));
player.sendText("InternalSkyLight: " + lightService.getInternalSkyLight(x, y, z));
player.sendText("LightDampening: " + lightService.getLightDampening(x, y, z));
player.sendText("QueuedUpdateCount: " + lightService.getQueuedUpdateCount());
return context.success();
}, SenderType.PLAYER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.allaymc.api.world.biome.BiomeType;
import org.allaymc.api.world.chunk.*;
import org.allaymc.api.world.storage.WorldStorage;
import org.allaymc.server.world.service.AllayLightService;
import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
Expand Down Expand Up @@ -410,7 +411,7 @@ public void beforeSetChunk(Dimension dimension) {
unsafeChunk.beforeSetChunk(dimension);
unsafeChunk.setBlockChangeCallback((x, y, z, blockState, layer) -> {
if (layer != 0) return;
dimension.getLightService().onBlockChange(x + (unsafeChunk.x << 4), y, z + (unsafeChunk.z << 4), blockState.getBlockStateData().lightEmission(), blockState.getBlockStateData().lightDampening());
((AllayLightService) dimension.getLightService()).onBlockChange(x + (unsafeChunk.x << 4), y, z + (unsafeChunk.z << 4), blockState.getBlockStateData().lightEmission(), blockState.getBlockStateData().lightDampening());
});
}

Expand All @@ -420,7 +421,7 @@ public void afterSetChunk(Dimension dimension) {
}
loaded = true;
unsafeChunk.afterSetChunk(dimension);
dimension.getLightService().onChunkLoad(this);
((AllayLightService) dimension.getLightService()).onChunkLoad(this);
}

public ChunkSection getOrCreateSection(int sectionY) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ public CompletableFuture<Boolean> unloadChunk(long chunkHash) {
entity.despawnFromAll();
((AllayEntityPhysicsService) dimension.getEntityPhysicsService()).removeEntity(entity);
});
((AllayLightService) dimension.getLightService()).onChunkUnload(chunk);

var future = new CompletableFuture<Boolean>();
worldStorage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ public int getInternalSkyLight(int x, int y, int z) {
return hasSkyLight ? Math.max(0, getSkyLight(x, y, z) - calculateSkylightReduction(dimension.getWorld().getWorldData().getTime(), dimension.getWorld().getWeathers())) : 0;
}

@Override
public void onBlockChange(int x, int y, int z, int lightEmission, int lightDampening) {
queue.add(() -> {
int oldLightHeight = hasSkyLight ? getLightHeight(x, z) : 0;
Expand All @@ -213,12 +212,10 @@ public void onBlockChange(int x, int y, int z, int lightEmission, int lightDampe
});
}

@Override
public void onChunkLoad(Chunk chunk) {
queue.add(() -> addChunk(chunk));
}

@Override
public void onChunkUnload(Chunk chunk) {
queue.add(() -> {
var hash = HashUtils.hashXZ(chunk.getX(), chunk.getZ());
Expand All @@ -237,8 +234,7 @@ public int getQueuedUpdateCount() {
return queue.size();
}

@Override
public int getLightDampening(int x, int y, int z) {
protected int getLightDampening(int x, int y, int z) {
return get(lightDampening, x, y, z, 0);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package org.allaymc.server.world.service;

import org.allaymc.api.server.Server;
import org.allaymc.api.world.Weather;
import org.allaymc.server.world.chunk.AllayUnsafeChunk;
import org.allaymc.testutils.AllayTestExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.util.Set;

Expand All @@ -10,8 +14,45 @@
/**
* @author daoge_cmd
*/
@ExtendWith(AllayTestExtension.class)
class AllayLightServiceTest {

@Test
void test() {
var dim = Server.getInstance().getWorldPool().getDefaultWorld().getOverWorld();
var lightService = new AllayLightService(dim);
for (int x = -3; x <= 3; x++) {
for (int z = -3; z <= 3; z++) {
lightService.addChunk(
AllayUnsafeChunk
.builder()
.emptyChunk(x, z, dim.getDimensionInfo())
.toSafeChunk()
);
}
}
tickLightService(lightService);
lightService.onBlockChange(0, 1, 0, 14, 0);
tickLightService(lightService);
assertEquals(14, lightService.getBlockLight(0, 1, 0));
assertEquals(13, lightService.getBlockLight(1, 1, 0));
assertEquals(13, lightService.getBlockLight(0, 1, 1));
assertEquals(13, lightService.getBlockLight(-1, 1, 0));
assertEquals(13, lightService.getBlockLight(0, 1, -1));
assertEquals(13, lightService.getBlockLight(0, 2, 0));

lightService.onBlockChange(2, 1, 0, 0, 15);
tickLightService(lightService);
assertEquals(0, lightService.getBlockLight(2, 1, 0));
assertEquals(9, lightService.getBlockLight(3, 1, 0));
}

protected static void tickLightService(AllayLightService lightService) {
while (lightService.getQueuedUpdateCount() > 0) {
lightService.tick();
}
}

@Test
void testCalculateSkylightReduction() {
assertEquals(11, AllayLightService.calculateSkylightReduction(13670, Set.of(Weather.CLEAR)));
Expand Down
13 changes: 10 additions & 3 deletions server/src/test/java/org/allaymc/testutils/AllayTestExtension.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.allaymc.testutils;

import org.allaymc.api.AllayAPI;
import org.allaymc.api.server.Server;
import org.allaymc.server.Allay;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
Expand All @@ -12,10 +13,16 @@
*/
public class AllayTestExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
public void beforeAll(ExtensionContext context) {
if (!AllayAPI.getInstance().isImplemented()) {
Allay.initI18n();
Allay.initAllay();
Thread.ofPlatform().name("Test Main Thread").start(() -> Allay.main(new String[]{}));
while (Server.getInstance() == null || Server.getInstance().isStarting()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

0 comments on commit 0f77de2

Please sign in to comment.