Let there be light

This commit is contained in:
KennyTV 2019-06-09 11:11:33 +02:00
parent 3f9e66bd7b
commit dc12f26f05
3 changed files with 179 additions and 26 deletions

View File

@ -10,13 +10,13 @@ import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.BlockItemPack
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.EntityPackets1_14; import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.EntityPackets1_14;
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.PlayerPackets1_14; import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.PlayerPackets1_14;
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.SoundPackets1_14; import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.SoundPackets1_14;
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.storage.ChunkLightStorage;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
@Getter @Getter
@ -49,7 +49,6 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol {
registerOutgoing(State.PLAY, 0x1B, 0x1C); registerOutgoing(State.PLAY, 0x1B, 0x1C);
registerOutgoing(State.PLAY, 0x54, 0x1D); registerOutgoing(State.PLAY, 0x54, 0x1D);
registerOutgoing(State.PLAY, 0x1C, 0x1E); registerOutgoing(State.PLAY, 0x1C, 0x1E);
registerOutgoing(State.PLAY, 0x1D, 0x1F);
registerOutgoing(State.PLAY, 0x1E, 0x20); registerOutgoing(State.PLAY, 0x1E, 0x20);
registerOutgoing(State.PLAY, 0x20, 0x21); registerOutgoing(State.PLAY, 0x20, 0x21);
@ -212,13 +211,63 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol {
public void registerMap() { public void registerMap() {
handler(new PacketHandler() { handler(new PacketHandler() {
@Override @Override
public void handle(PacketWrapper packetWrapper) throws Exception { public void handle(PacketWrapper wrapper) throws Exception {
packetWrapper.cancel(); // todo int x = wrapper.read(Type.VAR_INT);
} int z = wrapper.read(Type.VAR_INT);
}); int skyLightMask = wrapper.read(Type.VAR_INT);
} int blockLightMask = wrapper.read(Type.VAR_INT);
}); int emptySkyLightMask = wrapper.read(Type.VAR_INT);
int emptyBlockLightMask = wrapper.read(Type.VAR_INT);
byte[][] skyLight = new byte[16][];
// we don't need void and +256 light
if (isSet(skyLightMask, 0)) {
wrapper.read(Type.BYTE_ARRAY);
}
for (int i = 0; i < 16; i++) {
if (isSet(skyLightMask, i + 1)) {
Byte[] array = wrapper.read(Type.BYTE_ARRAY);
skyLight[i] = new byte[array.length];
for (int j = 0; j < array.length; j++) {
skyLight[i][j] = array[j];
}
} else if (isSet(emptySkyLightMask, i + 1)) {
skyLight[i] = ChunkLightStorage.EMPTY_LIGHT;
}
}
if (isSet(skyLightMask, 17)) {
wrapper.read(Type.BYTE_ARRAY);
}
byte[][] blockLight = new byte[18][];
if (isSet(blockLightMask, 0)) {
wrapper.read(Type.BYTE_ARRAY);
}
for (int i = 0; i < 16; i++) {
if (isSet(blockLightMask, i + 1)) {
Byte[] array = wrapper.read(Type.BYTE_ARRAY);
blockLight[i] = new byte[array.length];
for (int j = 0; j < array.length; j++) {
blockLight[i][j] = array[j];
}
} else if (isSet(emptyBlockLightMask, i + 1)) {
blockLight[i] = ChunkLightStorage.EMPTY_LIGHT;
}
}
if (isSet(skyLightMask, 17)) {
wrapper.read(Type.BYTE_ARRAY);
}
wrapper.user().get(ChunkLightStorage.class).setStoredLight(skyLight, blockLight, x, z);
wrapper.cancel();
}
private boolean isSet(int mask, int i) {
return (mask & (1 << i)) != 0;
}
});
}
});
//Incomming //Incomming
@ -298,5 +347,8 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol {
// Init protocol in EntityTracker // Init protocol in EntityTracker
user.get(EntityTracker.class).initProtocol(this); user.get(EntityTracker.class).initProtocol(this);
if (!user.has(ChunkLightStorage.class))
user.put(new ChunkLightStorage(user));
} }
} }

View File

@ -7,6 +7,7 @@ import nl.matsv.viabackwards.api.entities.types.AbstractEntityType;
import nl.matsv.viabackwards.api.entities.types.EntityType1_14; import nl.matsv.viabackwards.api.entities.types.EntityType1_14;
import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter; import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter;
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.storage.ChunkLightStorage;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; import us.myles.ViaVersion.api.minecraft.BlockChangeRecord;
import us.myles.ViaVersion.api.minecraft.Environment; import us.myles.ViaVersion.api.minecraft.Environment;
@ -18,7 +19,6 @@ import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_13_2;
import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketHandler;
import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.types.StringType;
import us.myles.ViaVersion.api.type.types.version.Types1_13; import us.myles.ViaVersion.api.type.types.version.Types1_13;
import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ChatRewriter; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ChatRewriter;
@ -34,19 +34,12 @@ import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.Tag; import us.myles.viaversion.libs.opennbt.tag.builtin.Tag;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class BlockItemPackets1_14 extends BlockItemRewriter<Protocol1_13_2To1_14> { public class BlockItemPackets1_14 extends BlockItemRewriter<Protocol1_13_2To1_14> {
private static String NBT_TAG_NAME = "ViaBackwards|" + Protocol1_13_2To1_14.class.getSimpleName(); private static String NBT_TAG_NAME = "ViaBackwards|" + Protocol1_13_2To1_14.class.getSimpleName();
private static byte[] fullLight = new byte[2048];
static {
Arrays.fill(fullLight, (byte) 0xFF);
}
@Override @Override
protected void registerPackets(Protocol1_13_2To1_14 protocol) { protected void registerPackets(Protocol1_13_2To1_14 protocol) {
// Open window // Open window
@ -504,17 +497,29 @@ public class BlockItemPackets1_14 extends BlockItemRewriter<Protocol1_13_2To1_14
Chunk chunk = wrapper.read(new Chunk1_14Type(clientWorld)); Chunk chunk = wrapper.read(new Chunk1_14Type(clientWorld));
wrapper.write(new Chunk1_13Type(clientWorld), chunk); wrapper.write(new Chunk1_13Type(clientWorld), chunk);
for (ChunkSection section : chunk.getSections()) { ChunkLightStorage.ChunkLight chunkLight = wrapper.user().get(ChunkLightStorage.class).getStoredLight(chunk.getX(), chunk.getZ());
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection section = chunk.getSections()[i];
if (section == null) continue; if (section == null) continue;
section.setBlockLight(fullLight); if (chunkLight == null) {
section.setBlockLight(ChunkLightStorage.FULL_LIGHT);
if (clientWorld.getEnvironment() == Environment.NORMAL) { if (clientWorld.getEnvironment() == Environment.NORMAL) {
section.setSkyLight(fullLight); section.setSkyLight(ChunkLightStorage.FULL_LIGHT);
} }
for (int i = 0; i < section.getPaletteSize(); i++) { } else {
int old = section.getPaletteEntry(i); final byte[] blockLight = chunkLight.getBlockLight()[i];
section.setBlockLight(blockLight != null ? blockLight : ChunkLightStorage.FULL_LIGHT);
if (clientWorld.getEnvironment() == Environment.NORMAL) {
final byte[] skyLight = chunkLight.getSkyLight()[i];
section.setSkyLight(skyLight != null ? skyLight : ChunkLightStorage.FULL_LIGHT);
}
}
for (int j = 0; j < section.getPaletteSize(); j++) {
int old = section.getPaletteEntry(j);
int newId = Protocol1_13_2To1_14.getNewBlockStateId(old); int newId = Protocol1_13_2To1_14.getNewBlockStateId(old);
section.setPaletteEntry(i, newId); section.setPaletteEntry(j, newId);
} }
} }
} }
@ -522,6 +527,21 @@ public class BlockItemPackets1_14 extends BlockItemRewriter<Protocol1_13_2To1_14
} }
}); });
// Uunload chunk
protocol.registerOutgoing(State.PLAY, 0x1D, 0x1F, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int x = wrapper.passthrough(Type.INT);
int z = wrapper.passthrough(Type.INT);
wrapper.user().get(ChunkLightStorage.class).unloadChunk(x, z);
}
});
}
});
// Effect packet // Effect packet
protocol.registerOutgoing(State.PLAY, 0x22, 0x23, new PacketRemapper() { protocol.registerOutgoing(State.PLAY, 0x22, 0x23, new PacketRemapper() {
@Override @Override
@ -600,6 +620,7 @@ public class BlockItemPackets1_14 extends BlockItemRewriter<Protocol1_13_2To1_14
int dimensionId = wrapper.get(Type.INT, 0); int dimensionId = wrapper.get(Type.INT, 0);
clientWorld.setEnvironment(dimensionId); clientWorld.setEnvironment(dimensionId);
wrapper.write(Type.UNSIGNED_BYTE, (short) 0); // todo - do we need to store it from difficulty packet? wrapper.write(Type.UNSIGNED_BYTE, (short) 0); // todo - do we need to store it from difficulty packet?
wrapper.user().get(ChunkLightStorage.class).clear();
} }
}); });
} }

View File

@ -0,0 +1,80 @@
package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.storage;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class ChunkLightStorage extends StoredObject {
public static final byte[] FULL_LIGHT = new byte[2048];
public static final byte[] EMPTY_LIGHT = new byte[2048];
private static Constructor<?> fastUtilLongObjectHashMap;
private final Map<Long, ChunkLight> storedLight = createLongObjectMap();
static {
Arrays.fill(FULL_LIGHT, (byte) 0xFF);
Arrays.fill(EMPTY_LIGHT, (byte) 0x0);
try {
fastUtilLongObjectHashMap = Class.forName("it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap").getConstructor();
} catch (ClassNotFoundException | NoSuchMethodException ignored) {
}
}
public ChunkLightStorage(UserConnection user) {
super(user);
}
public void setStoredLight(byte[][] skyLight, byte[][] blockLight, int x, int z) {
storedLight.put(getChunkSectionIndex(x, z), new ChunkLight(skyLight, blockLight));
}
public ChunkLight getStoredLight(int x, int z) {
return storedLight.get(getChunkSectionIndex(x, z));
}
public void clear() {
storedLight.clear();
}
public void unloadChunk(int x, int z) {
storedLight.remove(getChunkSectionIndex(x, z));
}
private long getChunkSectionIndex(int x, int z) {
return ((x & 0x3FFFFFFL) << 38) | (z & 0x3FFFFFFL);
}
private Map<Long, ChunkLight> createLongObjectMap() {
if (fastUtilLongObjectHashMap != null) {
try {
return (Map<Long, ChunkLight>) fastUtilLongObjectHashMap.newInstance();
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
return new HashMap<>();
}
public static class ChunkLight {
private final byte[][] skyLight;
private final byte[][] blockLight;
public ChunkLight(byte[][] skyLight, byte[][] blockLight) {
this.skyLight = skyLight;
this.blockLight = blockLight;
}
public byte[][] getSkyLight() {
return skyLight;
}
public byte[][] getBlockLight() {
return blockLight;
}
}
}