Use old ids and byte[] + NibbleArray for block connections

This commit is contained in:
creeper123123321 2019-01-17 14:49:08 -02:00
parent f45a727396
commit f6d7976eff
No known key found for this signature in database
GPG Key ID: 0AC57D54786721D1
3 changed files with 54 additions and 16 deletions

View File

@ -67,11 +67,12 @@ public class NibbleArray {
* @param value The desired value * @param value The desired value
*/ */
public void set(int index, int value) { public void set(int index, int value) {
index /= 2;
if (index % 2 == 0) { if (index % 2 == 0) {
handle[index] = (byte) (handle[index] & 0xF0 | value & 0xF); index /= 2;
handle[index] = (byte) ((handle[index] & 0xF0) | (value & 0xF));
} else { } else {
handle[index] = (byte) (handle[index] & 0xF | (value & 0xF) << 4); index /= 2;
handle[index] = (byte) ((handle[index] & 0xF) | ((value & 0xF) << 4));
} }
} }

View File

@ -175,12 +175,13 @@ public class WorldPackets {
if (Via.getConfig().isServersideBlockConnections()) { if (Via.getConfig().isServersideBlockConnections()) {
UserConnection userConnection = wrapper.user(); UserConnection userConnection = wrapper.user();
ConnectionData.updateBlockStorage(userConnection, position, newId);
if (ConnectionData.connects(newId)) { if (ConnectionData.connects(newId)) {
newId = ConnectionData.connect(userConnection, position, newId); newId = ConnectionData.connect(userConnection, position, newId);
} }
ConnectionData.updateBlockStorage(userConnection, position, newId);
ConnectionData.update(userConnection, position); ConnectionData.update(userConnection, position);
} }

View File

@ -1,9 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage; package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.StoredObject; import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.WorldPackets;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -11,9 +15,10 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class BlockConnectionStorage extends StoredObject { public class BlockConnectionStorage extends StoredObject {
private Map<Long, short[]> blockStorage = createLongObjectMap(); private Map<Long, Pair<byte[], NibbleArray>> blockStorage = createLongObjectMap();
private static Constructor<?> fastUtilLongObjectHashMap; private static Constructor<?> fastUtilLongObjectHashMap;
private static HashMap<Short, Short> reverseBlockMappings;
static { static {
try { try {
@ -21,6 +26,11 @@ public class BlockConnectionStorage extends StoredObject {
Via.getPlatform().getLogger().info("Using FastUtil Long2ObjectOpenHashMap for block connections"); Via.getPlatform().getLogger().info("Using FastUtil Long2ObjectOpenHashMap for block connections");
} catch (ClassNotFoundException | NoSuchMethodException ignored) { } catch (ClassNotFoundException | NoSuchMethodException ignored) {
} }
reverseBlockMappings = new HashMap<>();
for (int i = 0; i < 4096; i++) {
int newBlock = MappingData.blockMappings.getNewBlock(i);
if (newBlock != -1) reverseBlockMappings.put((short) newBlock, (short) i);
}
} }
public BlockConnectionStorage(UserConnection user) { public BlockConnectionStorage(UserConnection user) {
@ -28,25 +38,48 @@ public class BlockConnectionStorage extends StoredObject {
} }
public void store(Position position, int blockState) { public void store(Position position, int blockState) {
Short mapping = reverseBlockMappings.get((short) blockState);
if (mapping == null) return;
blockState = mapping;
long pair = getChunkSectionIndex(position); long pair = getChunkSectionIndex(position);
short[] map = getChunkSection(pair); Pair<byte[], NibbleArray> map = getChunkSection(pair, (blockState & 0xF) != 0);
map[encodeBlockPos(position)] = (short) blockState; int blockIndex = encodeBlockPos(position);
map.getKey()[blockIndex] = (byte) (blockState >> 4);
NibbleArray nibbleArray = map.getValue();
if (nibbleArray != null) nibbleArray.set(blockIndex, blockState);
} }
public int get(Position position) { public int get(Position position) {
long pair = getChunkSectionIndex(position); long pair = getChunkSectionIndex(position);
short[] map = blockStorage.get(pair); Pair<byte[], NibbleArray> map = blockStorage.get(pair);
if (map == null) return 0; if (map == null) return 0;
short blockPosition = encodeBlockPos(position); short blockPosition = encodeBlockPos(position);
return map[blockPosition]; NibbleArray nibbleArray = map.getValue();
return WorldPackets.toNewId(
((map.getKey()[blockPosition] & 0xFF) << 4)
| (nibbleArray == null ? 0 : nibbleArray.get(blockPosition))
);
} }
public void remove(Position position) { public void remove(Position position) {
long pair = getChunkSectionIndex(position); long pair = getChunkSectionIndex(position);
short[] map = blockStorage.get(pair); Pair<byte[], NibbleArray> map = blockStorage.get(pair);
if (map == null) return; if (map == null) return;
map[encodeBlockPos(position)] = 0; int blockIndex = encodeBlockPos(position);
for (short entry : map) { NibbleArray nibbleArray = map.getValue();
if (nibbleArray != null) {
nibbleArray.set(blockIndex, 0);
boolean allZero = true;
for (int i = 0; i < 4096; i++) {
if (nibbleArray.get(i) != 0) {
allZero = false;
break;
}
}
if (allZero) map.setValue(null);
}
map.getKey()[blockIndex] = 0;
for (short entry : map.getKey()) {
if (entry != 0) return; if (entry != 0) return;
} }
blockStorage.remove(pair); blockStorage.remove(pair);
@ -62,12 +95,15 @@ public class BlockConnectionStorage extends StoredObject {
} }
} }
private short[] getChunkSection(long index) { private Pair<byte[], NibbleArray> getChunkSection(long index, boolean requireNibbleArray) {
short[] map = blockStorage.get(index); Pair<byte[], NibbleArray> map = blockStorage.get(index);
if (map == null) { if (map == null) {
map = new short[4096]; map = new Pair<>(new byte[4096], null);
blockStorage.put(index, map); blockStorage.put(index, map);
} }
if (map.getValue() == null && requireNibbleArray) {
map.setValue(new NibbleArray(4096));
}
return map; return map;
} }