mirror of https://github.com/Minestom/Minestom.git
Fix Lighting Invalidation (#2041)
- Fix invalid lighting being sent to clients - Add cherry leaves to occludes - Fix lighting being generated when using loaded lighting - Send lighting to clients on block changes - Cleanup unused methods - Add sky lighting test for short grass
This commit is contained in:
parent
17fd82a5c1
commit
6e179dbd8a
|
@ -169,7 +169,7 @@ public class PlayerInit {
|
|||
});
|
||||
instanceContainer.setChunkSupplier(LightingChunk::new);
|
||||
instanceContainer.setTimeRate(0);
|
||||
instanceContainer.setTime(6000);
|
||||
instanceContainer.setTime(12000);
|
||||
|
||||
// var i2 = new InstanceContainer(UUID.randomUUID(), DimensionType.OVERWORLD, null, NamespaceID.from("minestom:demo"));
|
||||
// instanceManager.registerInstance(i2);
|
||||
|
|
|
@ -22,6 +22,7 @@ public final class ServerFlag {
|
|||
public static final int POOLED_BUFFER_SIZE = Integer.getInteger("minestom.pooled-buffer-size", 262_143);
|
||||
public static final int PLAYER_PACKET_PER_TICK = Integer.getInteger("minestom.packet-per-tick", 20);
|
||||
public static final int PLAYER_PACKET_QUEUE_SIZE = Integer.getInteger("minestom.packet-queue-size", 1000);
|
||||
public static final int SEND_LIGHT_AFTER_BLOCK_PLACEMENT_DELAY = Integer.getInteger("minestom.send-light-after-block-placement-delay", 100);
|
||||
|
||||
// Packet sending optimizations
|
||||
public static final boolean GROUPED_PACKET = PropertyUtils.getBoolean("minestom.grouped-packet", true);
|
||||
|
|
|
@ -284,6 +284,11 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
|
|||
*/
|
||||
protected void onLoad() {}
|
||||
|
||||
/**
|
||||
* Called when the chunk generator has finished generating the chunk.
|
||||
*/
|
||||
public void onGenerate() {}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + chunkX + ":" + chunkZ + "]";
|
||||
|
|
|
@ -298,7 +298,7 @@ public class InstanceContainer extends Instance {
|
|||
return CompletableFuture.completedFuture(chunk);
|
||||
} else {
|
||||
// Loader couldn't load the chunk, generate it
|
||||
return createChunk(chunkX, chunkZ);
|
||||
return createChunk(chunkX, chunkZ).whenComplete((c, a) -> c.onGenerate());
|
||||
}
|
||||
})
|
||||
// cache the retrieved chunk
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.server.instance;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.ServerFlag;
|
||||
import net.minestom.server.collision.Shape;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
|
@ -8,10 +9,7 @@ import net.minestom.server.instance.block.Block;
|
|||
import net.minestom.server.instance.block.BlockFace;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.instance.light.Light;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
||||
import net.minestom.server.network.packet.server.play.data.LightData;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
@ -26,6 +24,8 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static net.minestom.server.instance.light.LightCompute.emptyContent;
|
||||
|
||||
|
@ -41,9 +41,16 @@ public class LightingChunk extends DynamicChunk {
|
|||
|
||||
private int[] heightmap;
|
||||
final CachedPacket lightCache = new CachedPacket(this::createLightPacket);
|
||||
private LightData lightData;
|
||||
|
||||
boolean chunkLoaded = false;
|
||||
private int highestBlock;
|
||||
private boolean initialLightingSent = false;
|
||||
|
||||
private final ReentrantLock packetGenerationLock = new ReentrantLock();
|
||||
private final AtomicInteger resendTimer = new AtomicInteger(-1);
|
||||
private final int resendDelay = ServerFlag.SEND_LIGHT_AFTER_BLOCK_PLACEMENT_DELAY;
|
||||
|
||||
private boolean doneInit = false;
|
||||
|
||||
enum LightType {
|
||||
SKY,
|
||||
|
@ -67,6 +74,7 @@ public class LightingChunk extends DynamicChunk {
|
|||
Block.DARK_OAK_LEAVES.namespace(),
|
||||
Block.FLOWERING_AZALEA_LEAVES.namespace(),
|
||||
Block.JUNGLE_LEAVES.namespace(),
|
||||
Block.CHERRY_LEAVES.namespace(),
|
||||
Block.OAK_LEAVES.namespace(),
|
||||
Block.SPRUCE_LEAVES.namespace(),
|
||||
Block.SPAWNER.namespace(),
|
||||
|
@ -83,6 +91,7 @@ public class LightingChunk extends DynamicChunk {
|
|||
public void invalidate() {
|
||||
this.lightCache.invalidate();
|
||||
this.chunkCache.invalidate();
|
||||
this.lightData = null;
|
||||
}
|
||||
|
||||
public LightingChunk(@NotNull Instance instance, int chunkX, int chunkZ) {
|
||||
|
@ -107,8 +116,7 @@ public class LightingChunk extends DynamicChunk {
|
|||
if (neighborChunk == null) continue;
|
||||
|
||||
if (neighborChunk instanceof LightingChunk light) {
|
||||
light.lightCache.invalidate();
|
||||
light.chunkCache.invalidate();
|
||||
light.invalidate();
|
||||
}
|
||||
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
|
@ -132,6 +140,19 @@ public class LightingChunk extends DynamicChunk {
|
|||
if (chunkLoaded) {
|
||||
invalidateSection(coordinate);
|
||||
this.lightCache.invalidate();
|
||||
|
||||
if (doneInit) {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
|
||||
if (neighborChunk == null) continue;
|
||||
|
||||
if (neighborChunk instanceof LightingChunk light) {
|
||||
light.resendTimer.set(resendDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,10 +164,41 @@ public class LightingChunk extends DynamicChunk {
|
|||
@Override
|
||||
protected void onLoad() {
|
||||
chunkLoaded = true;
|
||||
doneInit = true;
|
||||
}
|
||||
|
||||
public boolean isLightingCalculated() {
|
||||
return initialLightingSent;
|
||||
@Override
|
||||
public void onGenerate() {
|
||||
super.onGenerate();
|
||||
|
||||
for (int section = minSection; section < maxSection; section++) {
|
||||
getSection(section).blockLight().invalidate();
|
||||
getSection(section).skyLight().invalidate();
|
||||
}
|
||||
|
||||
invalidate();
|
||||
|
||||
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
|
||||
if (neighborChunk == null) continue;
|
||||
|
||||
if (neighborChunk instanceof LightingChunk light) {
|
||||
for (int section = light.minSection; section < light.maxSection; section++) {
|
||||
light.getSection(section).blockLight().invalidate();
|
||||
light.getSection(section).skyLight().invalidate();
|
||||
}
|
||||
|
||||
light.invalidate();
|
||||
|
||||
light.resendTimer.set(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
doneInit = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -175,11 +227,11 @@ public class LightingChunk extends DynamicChunk {
|
|||
int height = maxY;
|
||||
while (height > minY) {
|
||||
Block block = getBlock(x, height, z, Condition.TYPE);
|
||||
if (block != Block.AIR) highestBlock = Math.max(highestBlock, height);
|
||||
if (checkSkyOcclusion(block)) break;
|
||||
height--;
|
||||
}
|
||||
heightmap[z << 4 | x] = (height + 1);
|
||||
if (height > highestBlock) highestBlock = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,93 +242,95 @@ public class LightingChunk extends DynamicChunk {
|
|||
|
||||
@Override
|
||||
protected LightData createLightData() {
|
||||
if (lightCache.isValid()) {
|
||||
ServerPacket packet = lightCache.packet(ConnectionState.PLAY);
|
||||
return ((UpdateLightPacket) packet).lightData();
|
||||
packetGenerationLock.lock();
|
||||
if (lightData != null) {
|
||||
packetGenerationLock.unlock();
|
||||
return lightData;
|
||||
}
|
||||
|
||||
synchronized (lightCache) {
|
||||
BitSet skyMask = new BitSet();
|
||||
BitSet blockMask = new BitSet();
|
||||
BitSet emptySkyMask = new BitSet();
|
||||
BitSet emptyBlockMask = new BitSet();
|
||||
List<byte[]> skyLights = new ArrayList<>();
|
||||
List<byte[]> blockLights = new ArrayList<>();
|
||||
BitSet skyMask = new BitSet();
|
||||
BitSet blockMask = new BitSet();
|
||||
BitSet emptySkyMask = new BitSet();
|
||||
BitSet emptyBlockMask = new BitSet();
|
||||
List<byte[]> skyLights = new ArrayList<>();
|
||||
List<byte[]> blockLights = new ArrayList<>();
|
||||
|
||||
Set<Chunk> combined = new HashSet<>();
|
||||
int chunkMin = instance.getDimensionType().getMinY();
|
||||
int chunkMin = instance.getDimensionType().getMinY();
|
||||
|
||||
int index = 0;
|
||||
for (Section section : sections) {
|
||||
boolean wasUpdatedBlock = false;
|
||||
boolean wasUpdatedSky = false;
|
||||
int highestNeighborBlock = instance.getDimensionType().getMinY();
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
|
||||
if (neighborChunk == null) continue;
|
||||
|
||||
if (section.blockLight().requiresUpdate()) {
|
||||
var needsSend = relightSection(instance, this.chunkX, index + minSection, chunkZ, LightType.BLOCK);
|
||||
combined.addAll(needsSend);
|
||||
wasUpdatedBlock = true;
|
||||
} else if (section.blockLight().requiresSend()) {
|
||||
wasUpdatedBlock = true;
|
||||
if (neighborChunk instanceof LightingChunk light) {
|
||||
light.getHeightmap();
|
||||
highestNeighborBlock = Math.max(highestNeighborBlock, light.highestBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (section.skyLight().requiresUpdate()) {
|
||||
var needsSend = relightSection(instance, this.chunkX, index + minSection, chunkZ, LightType.SKY);
|
||||
combined.addAll(needsSend);
|
||||
wasUpdatedSky = true;
|
||||
} else if (section.skyLight().requiresSend()) {
|
||||
wasUpdatedSky = true;
|
||||
}
|
||||
int index = 0;
|
||||
for (Section section : sections) {
|
||||
boolean wasUpdatedBlock = false;
|
||||
boolean wasUpdatedSky = false;
|
||||
|
||||
index++;
|
||||
if (section.blockLight().requiresUpdate()) {
|
||||
relightSection(instance, this.chunkX, index + minSection, chunkZ, LightType.BLOCK);
|
||||
wasUpdatedBlock = true;
|
||||
} else if (section.blockLight().requiresSend()) {
|
||||
wasUpdatedBlock = true;
|
||||
}
|
||||
|
||||
final byte[] skyLight = section.skyLight().array();
|
||||
final byte[] blockLight = section.blockLight().array();
|
||||
final int sectionMaxY = index * 16 + chunkMin;
|
||||
if (section.skyLight().requiresUpdate()) {
|
||||
relightSection(instance, this.chunkX, index + minSection, chunkZ, LightType.SKY);
|
||||
wasUpdatedSky = true;
|
||||
} else if (section.skyLight().requiresSend()) {
|
||||
wasUpdatedSky = true;
|
||||
}
|
||||
|
||||
if ((wasUpdatedSky) && this.instance.getDimensionType().isSkylightEnabled() && sectionMaxY <= (highestBlock + 16)) {
|
||||
if (skyLight.length != 0 && skyLight != emptyContent) {
|
||||
skyLights.add(skyLight);
|
||||
skyMask.set(index);
|
||||
} else {
|
||||
emptySkyMask.set(index);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
|
||||
if (wasUpdatedBlock) {
|
||||
if (blockLight.length != 0 && blockLight != emptyContent) {
|
||||
blockLights.add(blockLight);
|
||||
blockMask.set(index);
|
||||
} else {
|
||||
emptyBlockMask.set(index);
|
||||
}
|
||||
final byte[] skyLight = section.skyLight().array();
|
||||
final byte[] blockLight = section.blockLight().array();
|
||||
final int sectionMaxY = index * 16 + chunkMin;
|
||||
|
||||
if ((wasUpdatedSky) && this.instance.getDimensionType().isSkylightEnabled() && sectionMaxY <= (highestNeighborBlock + 16)) {
|
||||
if (skyLight.length != 0 && skyLight != emptyContent) {
|
||||
skyLights.add(skyLight);
|
||||
skyMask.set(index);
|
||||
} else {
|
||||
emptySkyMask.set(index);
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> {
|
||||
for (Chunk chunk : combined) {
|
||||
if (chunk instanceof LightingChunk light) {
|
||||
if (light.initialLightingSent) {
|
||||
light.lightCache.invalidate();
|
||||
light.chunkCache.invalidate();
|
||||
|
||||
// Compute Lighting. This will ensure lighting is computed even with no players
|
||||
lightCache.body(ConnectionState.PLAY);
|
||||
light.sendLighting();
|
||||
|
||||
light.sections.forEach(s -> {
|
||||
s.blockLight().setRequiresSend(true);
|
||||
s.skyLight().setRequiresSend(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (wasUpdatedBlock) {
|
||||
if (blockLight.length != 0 && blockLight != emptyContent) {
|
||||
blockLights.add(blockLight);
|
||||
blockMask.set(index);
|
||||
} else {
|
||||
emptyBlockMask.set(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.initialLightingSent = true;
|
||||
});
|
||||
this.lightData = new LightData(skyMask, blockMask,
|
||||
emptySkyMask, emptyBlockMask,
|
||||
skyLights, blockLights);
|
||||
|
||||
return new LightData(skyMask, blockMask,
|
||||
emptySkyMask, emptyBlockMask,
|
||||
skyLights, blockLights);
|
||||
packetGenerationLock.unlock();
|
||||
|
||||
return this.lightData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(long time) {
|
||||
super.tick(time);
|
||||
|
||||
if (doneInit && resendTimer.get() > 0) {
|
||||
if (resendTimer.decrementAndGet() == 0) {
|
||||
sendLighting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +398,7 @@ public class LightingChunk extends DynamicChunk {
|
|||
sections.add(new Vec(chunk.getChunkX(), section, chunk.getChunkZ()));
|
||||
}
|
||||
|
||||
lighting.lightCache.invalidate();
|
||||
lighting.chunkCache.invalidate();
|
||||
lighting.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ final class BlockLight implements Light {
|
|||
private byte[] contentPropagation;
|
||||
private byte[] contentPropagationSwap;
|
||||
|
||||
private boolean isValidBorders = false;
|
||||
private boolean isValidBorders = true;
|
||||
private boolean needsSend = true;
|
||||
|
||||
private Set<Point> toUpdateSet = new HashSet<>();
|
||||
|
@ -34,27 +34,6 @@ final class BlockLight implements Light {
|
|||
this.blockPalette = blockPalette;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void setInternalLighting(byte[] content) {
|
||||
this.content = content;
|
||||
this.isValidBorders = true;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void setExternalLighting(byte[] content) {
|
||||
this.contentPropagation = content;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public byte[] getInternalLighting() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public byte[] getExternalLighting() {
|
||||
return contentPropagation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Point> flip() {
|
||||
if (this.contentPropagationSwap != null)
|
||||
|
@ -164,12 +143,6 @@ final class BlockLight implements Light {
|
|||
return lightSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFrom(byte @NotNull [] array) {
|
||||
if (array.length == 0) this.content = null;
|
||||
else this.content = array.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Light calculateInternal(Instance instance, int chunkX, int sectionY, int chunkZ) {
|
||||
Chunk chunk = instance.getChunk(chunkX, chunkZ);
|
||||
|
@ -223,7 +196,13 @@ final class BlockLight implements Light {
|
|||
|
||||
@Override
|
||||
public void set(byte[] copyArray) {
|
||||
this.content = copyArray.clone();
|
||||
if (copyArray.length == 0) {
|
||||
this.content = emptyContent;
|
||||
this.contentPropagation = emptyContent;
|
||||
} else {
|
||||
this.content = copyArray.clone();
|
||||
this.contentPropagation = this.content;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -233,11 +212,6 @@ final class BlockLight implements Light {
|
|||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiresSend(boolean b) {
|
||||
this.needsSend = b;
|
||||
}
|
||||
|
||||
private void clearCache() {
|
||||
this.contentPropagation = null;
|
||||
isValidBorders = true;
|
||||
|
|
|
@ -27,15 +27,12 @@ public interface Light {
|
|||
}
|
||||
|
||||
boolean requiresSend();
|
||||
void setRequiresSend(boolean b);
|
||||
|
||||
@ApiStatus.Internal
|
||||
byte[] array();
|
||||
|
||||
Set<Point> flip();
|
||||
|
||||
void copyFrom(byte @NotNull [] array);
|
||||
|
||||
@ApiStatus.Internal
|
||||
Light calculateExternal(Instance instance, Chunk chunk, int sectionY);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ final class SkyLight implements Light {
|
|||
private byte[] contentPropagation;
|
||||
private byte[] contentPropagationSwap;
|
||||
|
||||
private boolean isValidBorders = false;
|
||||
private boolean isValidBorders = true;
|
||||
private boolean needsSend = true;
|
||||
|
||||
private Set<Point> toUpdateSet = new HashSet<>();
|
||||
|
@ -160,12 +160,6 @@ final class SkyLight implements Light {
|
|||
return lightSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFrom(byte @NotNull [] array) {
|
||||
if (array.length == 0) this.content = null;
|
||||
else this.content = array.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Light calculateInternal(Instance instance, int chunkX, int sectionY, int chunkZ) {
|
||||
Chunk chunk = instance.getChunk(chunkX, chunkZ);
|
||||
|
@ -228,7 +222,13 @@ final class SkyLight implements Light {
|
|||
|
||||
@Override
|
||||
public void set(byte[] copyArray) {
|
||||
this.content = copyArray.clone();
|
||||
if (copyArray.length == 0) {
|
||||
this.content = emptyContent;
|
||||
this.contentPropagation = emptyContent;
|
||||
} else {
|
||||
this.content = copyArray.clone();
|
||||
this.contentPropagation = this.content;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,11 +238,6 @@ final class SkyLight implements Light {
|
|||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiresSend(boolean b) {
|
||||
this.needsSend = b;
|
||||
}
|
||||
|
||||
private void clearCache() {
|
||||
this.contentPropagation = null;
|
||||
isValidBorders = true;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
@ -7,12 +8,14 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
|||
|
||||
public class PlayerSkinTest {
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void validName() {
|
||||
var skin = PlayerSkin.fromUsername("jeb_");
|
||||
assertNotNull(skin);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void invalidName() {
|
||||
var skin = PlayerSkin.fromUsername("jfdsa84vvcxadubasdfcvn");
|
||||
|
|
|
@ -414,6 +414,25 @@ public class BlockLightMergeIntegrationTest {
|
|||
assertEquals(14, val);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void skylightShortGrass(Env env) {
|
||||
Instance instance = env.createFlatInstance();
|
||||
instance.setChunkSupplier(LightingChunk::new);
|
||||
for (int x = 4; x <= 7; x++) {
|
||||
for (int z = 6; z <= 8; z++) {
|
||||
instance.loadChunk(x, z).join();
|
||||
}
|
||||
}
|
||||
|
||||
instance.setBlock(94, 50, 128, Block.SHORT_GRASS);
|
||||
|
||||
LightingChunk.relight(instance, instance.getChunks());
|
||||
|
||||
var val = lightValSky(instance, new Vec(94, 50, 128));
|
||||
assertEquals(15, val);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skylightContained(Env env) {
|
||||
Instance instance = env.createFlatInstance();
|
||||
|
|
|
@ -159,8 +159,6 @@ public class LightParityIntegrationTest {
|
|||
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
|
||||
final BlockState blockState = section.get(x, y, z);
|
||||
String blockName = blockState.getName();
|
||||
if (blockName.equals("minecraft:grass"))
|
||||
blockName = "minecraft:short_grass";
|
||||
Block block = Objects.requireNonNull(Block.fromNamespaceId(blockName), blockName)
|
||||
.withProperties(blockState.getProperties());
|
||||
palette.set(x, y, z, block.stateId());
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.server.utils;
|
||||
|
||||
import net.minestom.server.utils.mojang.MojangUtils;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,6 +11,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||
|
||||
public class TestMojangUtils {
|
||||
private final UUID JEB_UUID = UUID.fromString("853c80ef-3c37-49fd-aa49-938b674adae6");
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testValidNameWorks() {
|
||||
var result = MojangUtils.fromUsername("jeb_");
|
||||
|
@ -17,12 +20,14 @@ public class TestMojangUtils {
|
|||
assertEquals("jeb_", result.get("name").getAsString());
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testInvalidNameReturnsNull() {
|
||||
var result = MojangUtils.fromUsername("jfdsa84vvcxadubasdfcvn"); // Longer than 16, always invalid
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testValidUuidWorks() {
|
||||
var result = MojangUtils.fromUuid(JEB_UUID.toString());
|
||||
|
@ -31,18 +36,21 @@ public class TestMojangUtils {
|
|||
assertEquals("853c80ef3c3749fdaa49938b674adae6", result.get("id").getAsString());
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testInvalidUuidReturnsNull() {
|
||||
var result = MojangUtils.fromUuid("853c80ef3c3749fdaa49938b674adae6a"); // Longer than 32, always invalid
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testNonExistentUuidReturnsNull() {
|
||||
var result = MojangUtils.fromUuid("00000000-0000-0000-0000-000000000000");
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testValidUUIDWorks() {
|
||||
var result = MojangUtils.fromUuid(JEB_UUID);
|
||||
|
@ -51,16 +59,19 @@ public class TestMojangUtils {
|
|||
assertEquals("853c80ef3c3749fdaa49938b674adae6", result.get("id").getAsString());
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testGetValidNameWorks() throws IOException {
|
||||
assertEquals(JEB_UUID, MojangUtils.getUUID("jeb_"));
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testGetValidUUIDWorks() throws IOException {
|
||||
assertEquals("jeb_", MojangUtils.getUsername(JEB_UUID));
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testGetInvalidNameThrows() {
|
||||
assertThrows(IOException.class, () -> MojangUtils.getUUID("a")); // Too short
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue