diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java index 760839394..b1172b884 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java @@ -32,18 +32,24 @@ public class PlayerSneakListener extends ViaBukkitListener { private boolean useCache; - public PlayerSneakListener(ViaVersionPlugin plugin, boolean is1_9Fix, boolean is1_14Fix) { + public PlayerSneakListener(ViaVersionPlugin plugin, boolean is1_9Fix, boolean is1_14Fix) throws ReflectiveOperationException { super(plugin, null); this.is1_9Fix = is1_9Fix; this.is1_14Fix = is1_14Fix; + + final String packageName = plugin.getServer().getClass().getPackage().getName(); + getHandle = Class.forName(packageName + ".entity.CraftPlayer").getMethod("getHandle"); + + final Class entityPlayerClass = Class.forName(packageName + .replace("org.bukkit.craftbukkit", "net.minecraft.server") + ".EntityPlayer"); try { - getHandle = Class.forName(plugin.getServer().getClass().getPackage().getName() + ".entity.CraftPlayer").getMethod("getHandle"); - setSize = Class.forName(plugin.getServer().getClass().getPackage().getName() - .replace("org.bukkit.craftbukkit", "net.minecraft.server") + ".EntityPlayer").getMethod("setSize", Float.TYPE, Float.TYPE); - } catch (ClassNotFoundException | NoSuchMethodException e) { - e.printStackTrace(); + setSize = entityPlayerClass.getMethod("setSize", Float.TYPE, Float.TYPE); + } catch (NoSuchMethodException e) { + // Don't catch this one + setSize = entityPlayerClass.getMethod("a", Float.TYPE, Float.TYPE); } + // From 1.9 upwards the server hitbox is set in every entity tick, so we have to reset it everytime if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_9.getId()) { sneaking = new WeakHashMap<>(); diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java index e1ca3ed94..0b2c1902c 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java @@ -84,7 +84,12 @@ public class BukkitViaLoader implements ViaPlatformLoader { if (ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_14.getId()) { boolean use1_9Fix = plugin.getConf().is1_9HitboxFix() && ProtocolRegistry.SERVER_PROTOCOL < ProtocolVersion.v1_9.getId(); if (use1_9Fix || plugin.getConf().is1_14HitboxFix()) { - storeListener(new PlayerSneakListener(plugin, use1_9Fix, plugin.getConf().is1_14HitboxFix())).register(); + try { + storeListener(new PlayerSneakListener(plugin, use1_9Fix, plugin.getConf().is1_14HitboxFix())).register(); + } catch (ReflectiveOperationException e) { + Via.getPlatform().getLogger().warning("Could not load hitbox fix - please report this on our GitHub"); + e.printStackTrace(); + } } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java index f6be5f922..90e6102ca 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java @@ -66,6 +66,10 @@ public class BungeeServerHandler implements Listener { // Set the handshake version every time someone connects to any server @EventHandler public void onServerConnect(ServerConnectEvent e) { + if (e.isCancelled()) { + return; + } + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); if (user == null) return; if (!user.has(BungeeStorage.class)) { diff --git a/common/src/main/java/us/myles/ViaVersion/AbstractViaConfig.java b/common/src/main/java/us/myles/ViaVersion/AbstractViaConfig.java index 58f3d2d5d..11bf5ebf8 100644 --- a/common/src/main/java/us/myles/ViaVersion/AbstractViaConfig.java +++ b/common/src/main/java/us/myles/ViaVersion/AbstractViaConfig.java @@ -238,6 +238,11 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf return getBoolean("change-1_14-hitbox", false); } + @Override + public boolean isNonFullBlockLightFix() { + return getBoolean("fix-non-full-blocklight", false); + } + @Override public boolean is1_15InstantRespawn() { return getBoolean("use-1_15-instant-respawn", false); 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 37694ada6..d0e3f099c 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java @@ -322,6 +322,13 @@ public interface ViaVersionConfig { */ 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(); + /** * Should 1.15 clients respawn instantly / without showing the death screen * diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java index 492a23706..78cc31906 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java @@ -15,7 +15,7 @@ public class Entity1_10Types { Optional type; if (isObject) - type = ObjectTypes.getPCEntity(typeID); + type = ObjectType.getPCEntity(typeID); else type = EntityType.findById(typeID); @@ -141,7 +141,7 @@ public class Entity1_10Types { @AllArgsConstructor @Getter - public enum ObjectTypes { + public enum ObjectType implements us.myles.ViaVersion.api.entities.ObjectType { BOAT(1, EntityType.BOAT), ITEM(2, EntityType.DROPPED_ITEM), AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), @@ -168,25 +168,25 @@ public class Entity1_10Types { SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); - private static final Map TYPES = new HashMap<>(); + private static final Map TYPES = new HashMap<>(); private final int id; private final EntityType type; static { - for (ObjectTypes type : ObjectTypes.values()) { + for (ObjectType type : ObjectType.values()) { TYPES.put(type.id, type); } } - public static Optional findById(int id) { + public static Optional findById(int id) { if (id == -1) return Optional.absent(); return Optional.fromNullable(TYPES.get(id)); } public static Optional getPCEntity(int id) { - Optional output = findById(id); + Optional output = findById(id); if (!output.isPresent()) return Optional.absent(); diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java index 358b69cdd..500ed0f7a 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java @@ -15,7 +15,7 @@ public class Entity1_11Types { Optional type; if (isObject) - type = ObjectTypes.getPCEntity(typeID); + type = ObjectType.getPCEntity(typeID); else type = EntityType.findById(typeID); @@ -169,7 +169,7 @@ public class Entity1_11Types { @AllArgsConstructor @Getter - public enum ObjectTypes { + public enum ObjectType implements us.myles.ViaVersion.api.entities.ObjectType { BOAT(1, EntityType.BOAT), ITEM(2, EntityType.DROPPED_ITEM), AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), @@ -198,25 +198,25 @@ public class Entity1_11Types { SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); - private static final Map TYPES = new HashMap<>(); + private static final Map TYPES = new HashMap<>(); private final int id; private final EntityType type; static { - for (ObjectTypes type : ObjectTypes.values()) { + for (ObjectType type : ObjectType.values()) { TYPES.put(type.id, type); } } - public static Optional findById(int id) { + public static Optional findById(int id) { if (id == -1) return Optional.absent(); return Optional.fromNullable(TYPES.get(id)); } public static Optional getPCEntity(int id) { - Optional output = findById(id); + Optional output = findById(id); if (!output.isPresent()) return Optional.absent(); diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java index bf2deac7e..a844e8ae7 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java @@ -25,7 +25,7 @@ public class Entity1_12Types { Optional type; if (isObject) - type = ObjectTypes.getPCEntity(typeID); + type = ObjectType.getPCEntity(typeID); else type = EntityType.findById(typeID); @@ -182,7 +182,7 @@ public class Entity1_12Types { @AllArgsConstructor @Getter - public enum ObjectTypes { + public enum ObjectType implements us.myles.ViaVersion.api.entities.ObjectType { BOAT(1, EntityType.BOAT), ITEM(2, EntityType.DROPPED_ITEM), AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), @@ -211,25 +211,25 @@ public class Entity1_12Types { SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); - private static final Map TYPES = new HashMap<>(); + private static final Map TYPES = new HashMap<>(); private final int id; private final EntityType type; static { - for (ObjectTypes type : ObjectTypes.values()) { + for (ObjectType type : ObjectType.values()) { TYPES.put(type.id, type); } } - public static Optional findById(int id) { + public static Optional findById(int id) { if (id == -1) return Optional.absent(); return Optional.fromNullable(TYPES.get(id)); } public static Optional getPCEntity(int id) { - Optional output = findById(id); + Optional output = findById(id); if (!output.isPresent()) return Optional.absent(); diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_13Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_13Types.java index 0ca70f176..253688ea3 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_13Types.java +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_13Types.java @@ -15,7 +15,7 @@ public class Entity1_13Types { Optional type; if (isObject) - type = ObjectTypes.getPCEntity(typeID); + type = ObjectType.getPCEntity(typeID); else type = EntityType.findById(typeID); @@ -224,7 +224,7 @@ public class Entity1_13Types { @AllArgsConstructor @Getter - public enum ObjectTypes { + public enum ObjectType implements us.myles.ViaVersion.api.entities.ObjectType { BOAT(1, EntityType.BOAT), ITEM(2, EntityType.ITEM), AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), @@ -254,25 +254,25 @@ public class Entity1_13Types { DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL), TRIDENT(94, EntityType.TRIDENT); - private static final Map TYPES = new HashMap<>(); + private static final Map TYPES = new HashMap<>(); private final int id; private final EntityType type; static { - for (ObjectTypes type : ObjectTypes.values()) { + for (ObjectType type : ObjectType.values()) { TYPES.put(type.id, type); } } - public static Optional findById(int id) { + public static Optional findById(int id) { if (id == -1) return Optional.absent(); return Optional.fromNullable(TYPES.get(id)); } public static Optional getPCEntity(int id) { - Optional output = findById(id); + Optional output = findById(id); if (!output.isPresent()) return Optional.absent(); diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/ObjectType.java b/common/src/main/java/us/myles/ViaVersion/api/entities/ObjectType.java new file mode 100644 index 000000000..df35e9abf --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/ObjectType.java @@ -0,0 +1,8 @@ +package us.myles.ViaVersion.api.entities; + +public interface ObjectType { + + int getId(); + + EntityType getType(); +} 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_13to1_12_2/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java index 53638d224..a66ea41bb 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java @@ -513,8 +513,12 @@ public class InventoryPackets { return "wdl:request"; case "bungeecord:main": return null; + case "FML|MP": + return "fml:mp"; + case "FML|HS": + return "fml:hs"; default: - return old.matches("([0-9a-z_.-]*:)?[0-9a-z_/.-]*") // Identifier regex + return old.matches("([0-9a-z_.-]+):([0-9a-z_/.-]+)") // Identifier regex ? old : null; } } @@ -723,7 +727,7 @@ public class InventoryPackets { } public static String getOldPluginChannelId(String newId) { - if (!newId.matches("([0-9a-z_.-]*:)?[0-9a-z_/.-]*")) { + if (!newId.matches("([0-9a-z_.-]+):([0-9a-z_/.-]+)")) { return null; // Not valid } int separatorIndex = newId.indexOf(':'); @@ -754,6 +758,10 @@ public class InventoryPackets { return "WDL|CONTROL"; case "wdl:request": return "WDL|REQUEST"; + case "fml:hs": + return "FML|HS"; + case "fml:mp": + return "FML:MP"; default: return newId.length() > 20 ? newId.substring(0, 20) : newId; } 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 0de0ac2df..b2e23bb5b 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 @@ -326,6 +326,5 @@ public class Protocol1_14To1_13_2 extends Protocol { userConnection.put(new EntityTracker1_14(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 b6594e4aa..96ca2ccd5 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 @@ -20,6 +20,7 @@ public class MappingData { public static Mappings blockMappings; public static Mappings soundMappings; public static Set motionBlocking; + public static Set nonFullBlocks; public static void init() { JsonObject mapping1_13_2 = MappingDataLoader.loadData("mapping-1.13.2.json"); @@ -54,5 +55,18 @@ public class MappingData { us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.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.getNewId(Integer.parseInt(blockstates.getKey()))); + } + nonFullBlocks.add(blockStateMappings.getNewId(8163)); // grass path + for (int i = 3060; i <= 3067; i++) { // farmland + nonFullBlocks.add(blockStateMappings.getNewId(i)); + } + } } } 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 131915bcd..f07009be9 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 @@ -2,12 +2,15 @@ package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets; 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; @@ -29,7 +32,7 @@ public class WorldPackets { private static final int VOID_AIR = MappingData.blockStateMappings.getNewId(8591); private static final int CAVE_AIR = MappingData.blockStateMappings.getNewId(8592); public static final int SERVERSIDE_VIEW_DISTANCE = 64; - private static final byte[] FULL_LIGHT = new byte[2048]; + private static final Byte[] FULL_LIGHT = new Byte[2048]; static { Arrays.fill(FULL_LIGHT, (byte) 0xff); @@ -164,6 +167,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 +181,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 +194,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); } @@ -223,22 +234,22 @@ public class WorldPackets { // not sending skylight/setting empty skylight causes client lag due to some weird calculations // only do this on the initial chunk send (not when chunk.isGroundUp() is false) if (chunk.isGroundUp()) - lightPacket.write(Type.BYTE_ARRAY, Bytes.asList(FULL_LIGHT).toArray(new Byte[0])); // chunk below 0 + lightPacket.write(Type.BYTE_ARRAY, FULL_LIGHT); // chunk below 0 for (ChunkSection section : chunk.getSections()) { if (section == null || !section.hasSkyLight()) { if (chunk.isGroundUp()) { - lightPacket.write(Type.BYTE_ARRAY, Bytes.asList(FULL_LIGHT).toArray(new Byte[0])); + lightPacket.write(Type.BYTE_ARRAY, FULL_LIGHT); } continue; } - lightPacket.write(Type.BYTE_ARRAY, Bytes.asList(section.getSkyLight()).toArray(new Byte[0])); + lightPacket.write(Type.BYTE_ARRAY, fromPrimitiveArray(section.getSkyLight())); } if (chunk.isGroundUp()) - lightPacket.write(Type.BYTE_ARRAY, Bytes.asList(FULL_LIGHT).toArray(new Byte[0])); // chunk above 255 + lightPacket.write(Type.BYTE_ARRAY, FULL_LIGHT); // chunk above 255 for (ChunkSection section : chunk.getSections()) { if (section == null) continue; - lightPacket.write(Type.BYTE_ARRAY, Bytes.asList(section.getBlockLight()).toArray(new Byte[0])); + lightPacket.write(Type.BYTE_ARRAY, fromPrimitiveArray(section.getBlockLight())); } EntityTracker1_14 entityTracker = wrapper.user().get(EntityTracker1_14.class); @@ -257,6 +268,14 @@ public class WorldPackets { lightPacket.send(Protocol1_14To1_13_2.class, true, true); } + + private Byte[] fromPrimitiveArray(byte[] bytes) { + Byte[] newArray = new Byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + newArray[i] = bytes[i]; + } + return newArray; + } }); } }); @@ -437,4 +456,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/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/Protocol1_15To1_14_4.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/Protocol1_15To1_14_4.java index bc725ada7..c2e662238 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/Protocol1_15To1_14_4.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/Protocol1_15To1_14_4.java @@ -13,7 +13,7 @@ import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.packets.EntityPackets; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.packets.InventoryPackets; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.packets.PlayerPackets; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.packets.WorldPackets; -import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker; +import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker1_15; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; public class Protocol1_15To1_14_4 extends Protocol { @@ -266,7 +266,7 @@ public class Protocol1_15To1_14_4 extends Protocol { @Override public void init(UserConnection userConnection) { - userConnection.put(new EntityTracker(userConnection)); + userConnection.put(new EntityTracker1_15(userConnection)); if (!userConnection.has(ClientWorld.class)) userConnection.put(new ClientWorld(userConnection)); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/EntityPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/EntityPackets.java index 9c76c258a..2f379f060 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/EntityPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/EntityPackets.java @@ -11,7 +11,7 @@ import us.myles.ViaVersion.api.type.types.version.Types1_14; import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.MetadataRewriter; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.Protocol1_15To1_14_4; -import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker; +import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker1_15; import java.util.UUID; @@ -44,7 +44,7 @@ public class EntityPackets { int typeId = wrapper.get(Type.VAR_INT, 1); Entity1_15Types.EntityType entityType = Entity1_15Types.getTypeFromId(getNewEntityId(typeId)); - wrapper.user().get(EntityTracker.class).addEntity(entityId, entityType); + wrapper.user().get(EntityTracker1_15.class).addEntity(entityId, entityType); wrapper.set(Type.VAR_INT, 1, entityType.getId()); if (entityType == Entity1_15Types.EntityType.FALLING_BLOCK) { @@ -68,7 +68,7 @@ public class EntityPackets { int typeId = wrapper.read(Type.VAR_INT); Entity1_15Types.EntityType entityType = Entity1_15Types.getTypeFromId(getNewEntityId(typeId)); - wrapper.user().get(EntityTracker.class).addEntity(entityId, entityType); + wrapper.user().get(EntityTracker1_15.class).addEntity(entityId, entityType); wrapper.write(Type.VAR_INT, entityType.getId()); wrapper.passthrough(Type.DOUBLE); @@ -98,7 +98,7 @@ public class EntityPackets { int typeId = wrapper.read(Type.VAR_INT); Entity1_15Types.EntityType entityType = Entity1_15Types.getTypeFromId(getNewEntityId(typeId)); - wrapper.user().get(EntityTracker.class).addEntity(entityId, entityType); + wrapper.user().get(EntityTracker1_15.class).addEntity(entityId, entityType); wrapper.write(Type.VAR_INT, entityType.getId()); wrapper.passthrough(Type.DOUBLE); @@ -122,7 +122,7 @@ public class EntityPackets { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityId = wrapper.get(Type.VAR_INT, 0); - Optional type = wrapper.user().get(EntityTracker.class).get(entityId); + Optional type = wrapper.user().get(EntityTracker1_15.class).getEntity(entityId); MetadataRewriter.handleMetadata(entityId, type.orNull(), wrapper.get(Types1_14.METADATA_LIST, 0), wrapper.user()); } }); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/PlayerPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/PlayerPackets.java index 5031a2435..b097ad0b0 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/PlayerPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/packets/PlayerPackets.java @@ -9,7 +9,7 @@ import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.remapper.ValueCreator; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.packets.State; -import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker; +import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage.EntityTracker1_15; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; public class PlayerPackets { @@ -49,7 +49,7 @@ public class PlayerPackets { @Override public void handle(PacketWrapper wrapper) throws Exception { Entity1_15Types.EntityType entType = Entity1_15Types.EntityType.PLAYER; - EntityTracker tracker = wrapper.user().get(EntityTracker.class); + EntityTracker1_15 tracker = wrapper.user().get(EntityTracker1_15.class); tracker.addEntity(wrapper.get(Type.INT, 0), entType); } }); @@ -62,7 +62,7 @@ public class PlayerPackets { clientChunks.setEnvironment(dimensionId); // Register Type ID - EntityTracker tracker = wrapper.user().get(EntityTracker.class); + EntityTracker1_15 tracker = wrapper.user().get(EntityTracker1_15.class); int entityId = wrapper.get(Type.INT, 0); tracker.addEntity(entityId, Entity1_15Types.EntityType.PLAYER); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker.java deleted file mode 100644 index 614a1e429..000000000 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker.java +++ /dev/null @@ -1,39 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage; - -import com.google.common.base.Optional; -import us.myles.ViaVersion.api.data.ExternalJoinGameListener; -import us.myles.ViaVersion.api.data.StoredObject; -import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.api.entities.Entity1_15Types; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class EntityTracker extends StoredObject implements ExternalJoinGameListener { - private final Map clientEntityTypes = new ConcurrentHashMap<>(); - - public EntityTracker(UserConnection user) { - super(user); - } - - public void removeEntity(int entityId) { - clientEntityTypes.remove(entityId); - } - - public void addEntity(int entityId, Entity1_15Types.EntityType type) { - clientEntityTypes.put(entityId, type); - } - - public boolean has(int entityId) { - return clientEntityTypes.containsKey(entityId); - } - - public Optional get(int id) { - return Optional.fromNullable(clientEntityTypes.get(id)); - } - - @Override - public void onExternalJoinGame(int playerEntityId) { - clientEntityTypes.put(playerEntityId, Entity1_15Types.EntityType.PLAYER); - } -} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker1_15.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker1_15.java new file mode 100644 index 000000000..0b800f638 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_15to1_14_4/storage/EntityTracker1_15.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.protocols.protocol1_15to1_14_4.storage; + +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_15Types; +import us.myles.ViaVersion.api.storage.EntityTracker; + +public class EntityTracker1_15 extends EntityTracker { + + public EntityTracker1_15(UserConnection user) { + super(user, Entity1_15Types.EntityType.PLAYER); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java index 1526d74b2..c795d1bfa 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java @@ -141,7 +141,15 @@ public class EntityPackets { // 1 - Slot ID map(Type.SHORT, new ValueTransformer(Type.VAR_INT) { @Override - public Integer transform(PacketWrapper wrapper, Short slot) { + public Integer transform(PacketWrapper wrapper, Short slot) throws Exception { + int entityId = wrapper.get(Type.VAR_INT, 0); + int receiverId = wrapper.user().get(EntityTracker1_9.class).getClientEntityId(); + // Normally, 0 = hand and 1-4 = armor + // ... but if the sent id is equal to the receiver's id, 0-3 will instead mark the armor slots + // (In 1.9+, every client treats the received the same: 0=hand, 1=offhand, 2-5=armor) + if (entityId == receiverId) { + return slot.intValue() + 2; + } return slot > 0 ? slot.intValue() + 1 : slot.intValue(); } }); diff --git a/common/src/main/resources/assets/viaversion/config.yml b/common/src/main/resources/assets/viaversion/config.yml index b377ae379..d5d3994b6 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 # Should 1.15+ clients respawn instantly / without showing a death screen? use-1_15-instant-respawn: false # diff --git a/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json b/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json index 7fcc2d5c3..265326831 100644 --- a/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json +++ b/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json @@ -1242,8 +1242,8 @@ "entity.Villager.librarian": "entity.minecraft.villager.librarian", "entity.Villager.cleric": "entity.minecraft.villager.cleric", "entity.Villager.armor": "entity.minecraft.villager.armorer", - "entity.Villager.weapon": "entity.minecraft.villager.weapon_smith", - "entity.Villager.tool": "entity.minecraft.villager.tool_smith", + "entity.Villager.weapon": "entity.minecraft.villager.weaponsmith", + "entity.Villager.tool": "entity.minecraft.villager.toolsmith", "entity.Villager.butcher": "entity.minecraft.villager.butcher", "entity.Villager.leather": "entity.minecraft.villager.leatherworker", "entity.Villager.nitwit": "entity.minecraft.villager.nitwit", @@ -2745,4 +2745,4 @@ "advancements.story.smelt_iron.description": null, "advancements.story.upgrade_tools.title": null, "advancements.story.upgrade_tools.description": null -} \ No newline at end of file +}