From 5eb3771704f99d23aeefa94d3e3ff4020ce884df Mon Sep 17 00:00:00 2001 From: Nassim <28825609+KennyTV@users.noreply.github.com> Date: Mon, 9 Sep 2019 14:02:30 +0200 Subject: [PATCH] Fix no light for non full blocks (#1414) --- .../bukkit/platform/BukkitViaConfig.java | 5 ++ .../bungee/platform/BungeeViaConfig.java | 5 ++ .../ViaVersion/api/ViaVersionConfig.java | 7 ++ .../api/minecraft/chunks/ChunkSection.java | 10 ++- .../api/minecraft/chunks/NibbleArray.java | 4 +- .../Protocol1_14To1_13_2.java | 1 - .../data/MappingData.java | 20 +++-- .../packets/WorldPackets.java | 89 +++++++++++++++++++ .../resources/assets/viaversion/config.yml | 2 + .../sponge/platform/SpongeViaConfig.java | 5 ++ .../velocity/platform/VelocityViaConfig.java | 5 ++ 11 files changed, 144 insertions(+), 9 deletions(-) diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java index 8b2033918..b11198b0f 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java @@ -269,4 +269,9 @@ public class BukkitViaConfig extends Config implements ViaVersionConfig { public boolean is1_14HitboxFix() { return getBoolean("change-1_14-hitbox", false); } + + @Override + public boolean isNonFullBlockLightFix() { + return getBoolean("fix-non-full-blocklight", true); + } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java index d77ff934d..0ff0d5f1c 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java @@ -322,4 +322,9 @@ public class BungeeViaConfig extends Config implements ViaVersionConfig { public boolean is1_14HitboxFix() { return false; } + + @Override + public boolean isNonFullBlockLightFix() { + return getBoolean("fix-non-full-blocklight", true); + } } diff --git a/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java b/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java index d3b34cac4..b0c36be4b 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java @@ -337,4 +337,11 @@ public interface ViaVersionConfig { * @return True if enabled */ boolean is1_14HitboxFix(); + + /** + * Fixes non full blocks having 0 light for 1.14+ clients on sub 1.14 servers. + * + * @return True if enabled + */ + boolean isNonFullBlockLightFix(); } diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java index f0e585a77..166f86516 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java @@ -175,10 +175,18 @@ public class ChunkSection { return blockLight == null ? null : blockLight.getHandle(); } + public NibbleArray getBlockLightNibbleArray() { + return blockLight; + } + public byte[] getSkyLight() { return skyLight == null ? null : skyLight.getHandle(); } + public NibbleArray getSkyLightNibbleArray() { + return skyLight; + } + public void readBlockLight(ByteBuf input) { if (this.blockLight == null) { this.blockLight = new NibbleArray(LIGHT_LENGTH * 2); @@ -193,7 +201,7 @@ public class ChunkSection { input.readBytes(this.skyLight.getHandle()); } - private static int index(int x, int y, int z) { + public static int index(int x, int y, int z) { return y << 8 | z << 4 | x; } diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java index 4cfeddccc..3e1282214 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java @@ -30,7 +30,7 @@ public class NibbleArray { * @return The value at the given XYZ */ public byte get(int x, int y, int z) { - return get(y << 8 | z << 4 | x); + return get(ChunkSection.index(x, y, z)); } /** @@ -57,7 +57,7 @@ public class NibbleArray { * @param value Desired Value */ public void set(int x, int y, int z, int value) { - set(y << 8 | z << 4 | x, value); + set(ChunkSection.index(x, y, z), value); } /** diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java index 9a48579bc..34fb0c567 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java @@ -323,6 +323,5 @@ public class Protocol1_14To1_13_2 extends Protocol { userConnection.put(new EntityTracker(userConnection)); if (!userConnection.has(ClientWorld.class)) userConnection.put(new ClientWorld(userConnection)); - } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/MappingData.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/MappingData.java index f85760213..e203d1075 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/MappingData.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/MappingData.java @@ -11,11 +11,7 @@ import us.myles.ViaVersion.util.GsonUtil; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class MappingData { public static BiMap oldToNewItems = HashBiMap.create(); @@ -23,6 +19,7 @@ public class MappingData { public static BlockMappings blockMappings; public static SoundMappings soundMappings; public static Set motionBlocking; + public static Set nonFullBlocks; public static void init() { JsonObject mapping1_13_2 = loadData("mapping-1.13.2.json"); @@ -57,6 +54,19 @@ public class MappingData { MappingData.motionBlocking.add(id); } } + + if (Via.getConfig().isNonFullBlockLightFix()) { + nonFullBlocks = new HashSet<>(); + for (Map.Entry blockstates : mapping1_13_2.getAsJsonObject("blockstates").entrySet()) { + final String state = blockstates.getValue().getAsString(); + if (state.contains("_slab") || state.contains("_stairs") || state.contains("_wall[")) + nonFullBlocks.add(blockStateMappings.getNewBlock(Integer.parseInt(blockstates.getKey()))); + } + nonFullBlocks.add(blockStateMappings.getNewBlock(8163)); // grass path + for (int i = 3060; i <= 3067; i++) { // farmland + nonFullBlocks.add(blockStateMappings.getNewBlock(i)); + } + } } public static JsonObject loadData(String name) { diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java index c1d212082..251e117c3 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java @@ -4,10 +4,14 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.LongArrayTag; import com.google.common.primitives.Bytes; import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.entities.Entity1_14Types; import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; +import us.myles.ViaVersion.api.minecraft.BlockFace; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; +import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; @@ -164,6 +168,7 @@ public class WorldPackets { for (int s = 0; s < 16; s++) { ChunkSection section = chunk.getSections()[s]; if (section == null) continue; + boolean hasBlock = false; for (int i = 0; i < section.getPaletteSize(); i++) { int old = section.getPaletteEntry(i); @@ -177,6 +182,7 @@ public class WorldPackets { section.setNonAirBlocksCount(0); continue; } + int nonAirBlockCount = 0; for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { @@ -189,9 +195,15 @@ public class WorldPackets { if (MappingData.motionBlocking.contains(id)) { motionBlocking[x + z * 16] = y + s * 16 + 2; // Should be +1 (top of the block) but +2 works :tm: } + + // Manually update light for non full blocks (block light must not be sent) + if (Via.getConfig().isNonFullBlockLightFix() && MappingData.nonFullBlocks.contains(id)) { + setNonFullLight(chunk, section, s, x, y, z); + } } } } + section.setNonAirBlocksCount(nonAirBlockCount); } @@ -437,4 +449,81 @@ public class WorldPackets { return data; } + + private static void setNonFullLight(Chunk chunk, ChunkSection section, int ySection, int x, int y, int z) { + int skyLight = 0; + int blockLight = 0; + for (BlockFace blockFace : BlockFace.values()) { + NibbleArray skyLightArray = section.getSkyLightNibbleArray(); + NibbleArray blockLightArray = section.getBlockLightNibbleArray(); + int neighbourX = x + blockFace.getModX(); + int neighbourY = y + blockFace.getModY(); + int neighbourZ = z + blockFace.getModZ(); + + if (blockFace.getModX() != 0) { + // Another chunk, nothing we can do without an unnecessary amount of caching + if (neighbourX == 16 || neighbourX == -1) continue; + } else if (blockFace.getModY() != 0) { + if (neighbourY == 16 || neighbourY == -1) { + if (neighbourY == 16) { + ySection += 1; + neighbourY = 0; + } else { + ySection -= 1; + neighbourY = 15; + } + + if (ySection == 16 || ySection == -1) continue; + + ChunkSection newSection = chunk.getSections()[ySection]; + if (newSection == null) continue; + + skyLightArray = newSection.getSkyLightNibbleArray(); + blockLightArray = newSection.getBlockLightNibbleArray(); + } + } else if (blockFace.getModZ() != 0) { + // Another chunk, nothing we can do without an unnecessary amount of caching + if (neighbourZ == 16 || neighbourZ == -1) continue; + } + + if (blockLightArray != null && blockLight != 15) { + int neighbourBlockLight = blockLightArray.get(neighbourX, neighbourY, neighbourZ); + if (neighbourBlockLight == 15) { + blockLight = 14; + } else if (neighbourBlockLight > blockLight) { + blockLight = neighbourBlockLight - 1; // lower light level by one + } + } + if (skyLightArray != null && skyLight != 15) { + int neighbourSkyLight = skyLightArray.get(neighbourX, neighbourY, neighbourZ); + if (neighbourSkyLight == 15) { + if (blockFace.getModY() == 1) { + // Keep 15 if block is exposed to sky + skyLight = 15; + continue; + } + + skyLight = 14; + } else if (neighbourSkyLight > skyLight) { + skyLight = neighbourSkyLight - 1; // lower light level by one + } + } + } + + if (skyLight != 0) { + if (!section.hasSkyLight()) { + byte[] newSkyLight = new byte[2028]; + section.setSkyLight(newSkyLight); + } + + section.getSkyLightNibbleArray().set(x, y, z, skyLight); + } + if (blockLight != 0) { + section.getBlockLightNibbleArray().set(x, y, z, blockLight); + } + } + + private static long getChunkIndex(int x, int z) { + return ((x & 0x3FFFFFFL) << 38) | (z & 0x3FFFFFFL); + } } diff --git a/common/src/main/resources/assets/viaversion/config.yml b/common/src/main/resources/assets/viaversion/config.yml index 0a698b683..29ffa6a44 100644 --- a/common/src/main/resources/assets/viaversion/config.yml +++ b/common/src/main/resources/assets/viaversion/config.yml @@ -126,6 +126,8 @@ change-1_9-hitbox: false # WARNING: This gives 1.14+ players the ability to sneak under blocks, that players under that version cannot (sneaking in places that are only 1.5 blocks high)! # Another thing to remember is that those players might be missed by projectiles and other hits directed at the very top of their head whilst sneaking. change-1_14-hitbox: false +# Fixes 1.14+ clients on sub 1.14 servers having a light value of 0 for non full blocks. +fix-non-full-blocklight: true # # Enable serverside block-connections for 1.13+ clients serverside-blockconnections: false diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java index 045be1926..3637ef493 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java @@ -275,4 +275,9 @@ public class SpongeViaConfig extends Config implements ViaVersionConfig { public boolean is1_14HitboxFix() { return false; } + + @Override + public boolean isNonFullBlockLightFix() { + return getBoolean("fix-non-full-blocklight", true); + } } diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java index 1c86a21a9..ab4d184ef 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java @@ -328,4 +328,9 @@ public class VelocityViaConfig extends Config implements ViaVersionConfig { public boolean is1_14HitboxFix() { return false; } + + @Override + public boolean isNonFullBlockLightFix() { + return getBoolean("fix-non-full-blocklight", true); + } }