Fix MemoryOptimizedClipboard

This commit is contained in:
dordsor21 2020-03-30 12:06:15 +01:00
parent 45e0d37889
commit 5197ed04ec

View File

@ -39,15 +39,14 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
private byte[] buffer = new byte[MainUtil.getMaxCompressedLength(BLOCK_SIZE)]; private byte[] buffer = new byte[MainUtil.getMaxCompressedLength(BLOCK_SIZE)];
private byte[] biomes = null; private byte[] biomes = null;
private final HashMap<IntegerTrio, CompoundTag> nbtMapLoc; private final HashMap<IntegerTrio, CompoundTag> nbtMap;
private final HashMap<Integer, CompoundTag> nbtMapIndex;
private int lastCombinedIdsI = -1; private int lastOrdinalsI = -1;
private byte[] lastCombinedIds; private byte[] lastOrdinals;
private boolean saveCombinedIds = false; private boolean saveOrdinals = false;
private int compressionLevel; private int compressionLevel;
@ -58,21 +57,10 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
public MemoryOptimizedClipboard(Region region, int compressionLevel) { public MemoryOptimizedClipboard(Region region, int compressionLevel) {
super(region.getDimensions()); super(region.getDimensions());
states = new byte[1 + (getVolume() >> BLOCK_SHIFT)][]; states = new byte[1 + (getVolume() >> BLOCK_SHIFT)][];
nbtMapLoc = new HashMap<>(); nbtMap = new HashMap<>();
nbtMapIndex = new HashMap<>();
this.compressionLevel = compressionLevel; this.compressionLevel = compressionLevel;
} }
public void convertTilesToIndex() {
if (nbtMapLoc.isEmpty()) {
return;
}
for (Map.Entry<IntegerTrio, CompoundTag> entry : nbtMapLoc.entrySet()) {
IntegerTrio key = entry.getKey();
setTile(getIndex(key.x, key.y, key.z), entry.getValue());
}
nbtMapLoc.clear();
}
@Override @Override
public boolean hasBiomes() { public boolean hasBiomes() {
@ -122,36 +110,31 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
return getBiome(getIndex(x, 0, z)); return getBiome(getIndex(x, 0, z));
} }
private CompoundTag getTag(int index) {
convertTilesToIndex();
return nbtMapIndex.get(index);
}
public int getOrdinal(int index) { public int getOrdinal(int index) {
int i = index >> BLOCK_SHIFT; int i = index >> BLOCK_SHIFT;
int li = (index & BLOCK_MASK) << 1; int li = (index & BLOCK_MASK) << 1;
if (i != lastCombinedIdsI) { if (i != lastOrdinalsI) {
saveCombinedIds(); saveOrdinals();
byte[] compressed = states[lastCombinedIdsI = i]; byte[] compressed = states[lastOrdinalsI = i];
if (compressed != null) { if (compressed != null) {
lastCombinedIds = MainUtil.decompress(compressed, lastCombinedIds, BLOCK_SIZE, compressionLevel); lastOrdinals = MainUtil.decompress(compressed, lastOrdinals, BLOCK_SIZE, compressionLevel);
} else { } else {
lastCombinedIds = null; lastOrdinals = null;
return 0; return 0;
} }
} }
if (lastCombinedIds == null) { if (lastOrdinals == null) {
return 0; return 0;
} }
int ordinal = ((lastCombinedIds[li] << 8) + lastCombinedIds[li + 1]); System.out.println(index + " " + (((lastOrdinals[li] & 0xFF) << 8) + (lastOrdinals[li + 1] & 0xFF)) + " " + lastOrdinals[li] + " " + lastOrdinals[li + 1]);
return ordinal; return (((lastOrdinals[li] & 0xFF) << 8) + (lastOrdinals[li + 1] & 0xFF));
} }
private void saveCombinedIds() { private void saveOrdinals() {
if (saveCombinedIds && lastCombinedIds != null) { if (saveOrdinals && lastOrdinals != null) {
states[lastCombinedIdsI] = MainUtil.compress(lastCombinedIds, buffer, compressionLevel); states[lastOrdinalsI] = MainUtil.compress(lastOrdinals, buffer, compressionLevel);
} }
saveCombinedIds = false; saveOrdinals = false;
} }
private int lastI; private int lastI;
@ -167,48 +150,34 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
return lastI; return lastI;
} }
public void setCombinedId(int index, int v) { public void setOrdinal(int index, int v) {
int i = getLocalIndex(index); int i = getLocalIndex(index);
if (i != lastCombinedIdsI) { if (i != lastOrdinalsI) {
saveCombinedIds(); saveOrdinals();
byte[] compressed = states[lastCombinedIdsI = i]; byte[] compressed = states[lastOrdinalsI = i];
if (compressed != null) { if (compressed != null) {
lastCombinedIds = MainUtil.decompress(compressed, lastCombinedIds, BLOCK_SIZE, compressionLevel); lastOrdinals = MainUtil.decompress(compressed, lastOrdinals, BLOCK_SIZE, compressionLevel);
} else { } else {
lastCombinedIds = null; lastOrdinals = null;
} }
} }
if (lastCombinedIds == null) { if (lastOrdinals == null) {
BlockType bt = BlockTypes.getFromStateId(v); BlockType bt = BlockTypes.getFromStateOrdinal(v);
if (bt.getMaterial().isAir()) { if (bt.getMaterial().isAir()) {
return; return;
} }
lastCombinedIds = new byte[BLOCK_SIZE]; lastOrdinals = new byte[BLOCK_SIZE];
} }
int li = (index & BLOCK_MASK) << 1; int li = (index & BLOCK_MASK) << 1;
lastCombinedIds[li] = (byte) ((v >>> 8) & 0xFF); lastOrdinals[li] = (byte) ((v >>> 8) & 0xFF);
lastCombinedIds[li + 1] = (byte) (v & 0xFF); lastOrdinals[li + 1] = (byte) (v & 0xFF);
saveCombinedIds = true; System.out.println(index + " " + v + " " + lastOrdinals[li] + " " + lastOrdinals[li + 1]);
saveOrdinals = true;
} }
@Override @Override
public Collection<CompoundTag> getTileEntities() { public Collection<CompoundTag> getTileEntities() {
convertTilesToIndex(); return nbtMap.values();
for (Map.Entry<Integer, CompoundTag> entry : nbtMapIndex.entrySet()) {
int index = entry.getKey();
CompoundTag tag = entry.getValue();
Map<String, Tag> values = tag.getValue();
if (!values.containsKey("x")) {
int y = index / getArea();
index -= y * getArea();
int z = index / getWidth();
int x = index - (z * getWidth());
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
}
}
return nbtMapIndex.values();
} }
private int ylast; private int ylast;
@ -226,22 +195,40 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
return getFullBlock(index); return getFullBlock(index);
} }
private BaseBlock toBaseBlock(BlockState state, int i) {
if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) {
CompoundTag nbt;
if (nbtMap.size() < 4) {
nbt = null;
for (Map.Entry<IntegerTrio, CompoundTag> entry : nbtMap.entrySet()) {
IntegerTrio trio = entry.getKey();
int index = getIndex(trio.x, trio.y, trio.z);
if (index == i) {
nbt = entry.getValue();
break;
}
}
} else {
int y = i / getArea();
int newI = i - y * getArea();
int z = newI / getWidth();
int x = newI - z * getWidth();
nbt = nbtMap.get(new IntegerTrio(x, y, z));
}
return state.toBaseBlock(nbt);
}
return state.toBaseBlock();
}
@Override @Override
public BaseBlock getFullBlock(int index) { public BaseBlock getFullBlock(int index) {
BlockState block = getBlock(index); return toBaseBlock(getBlock(index), index);
if (block.getMaterial().hasContainer()) {
CompoundTag nbt = getTag(index);
if (nbt != null) {
return block.toBaseBlock(nbt);
}
}
return block.toBaseBlock();
} }
@Override @Override
public BlockState getBlock(int index) { public BlockState getBlock(int index) {
int ordinal = getOrdinal(index); int combinedID = getOrdinal(index);
return BlockState.getFromOrdinal(ordinal); return BlockState.getFromOrdinal(combinedID);
} }
@Override @Override
@ -250,7 +237,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
} }
public int size() { public int size() {
saveCombinedIds(); saveOrdinals();
int total = 0; int total = 0;
for (byte[] array : states) { for (byte[] array : states) {
if (array != null) { if (array != null) {
@ -262,16 +249,11 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tag) { public boolean setTile(int x, int y, int z, CompoundTag tag) {
nbtMapLoc.put(new IntegerTrio(x, y, z), tag); nbtMap.put(new IntegerTrio(x, y, z), tag);
return true;
}
public boolean setTile(int index, CompoundTag tag) {
nbtMapIndex.put(index, tag);
Map<String, Tag> values = tag.getValue(); Map<String, Tag> values = tag.getValue();
values.remove("x"); values.put("x", new IntTag(x));
values.remove("y"); values.put("y", new IntTag(y));
values.remove("z"); values.put("z", new IntTag(z));
return true; return true;
} }
@ -282,11 +264,15 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(int index, B block) { public <B extends BlockStateHolder<B>> boolean setBlock(int index, B block) {
int combinedId = block.getInternalId(); int ordinal = block.getOrdinal();
setCombinedId(index, combinedId); setOrdinal(index, ordinal);
boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); boolean hasNbt = block instanceof BaseBlock && block.hasNbtData();
if (hasNbt) { if (hasNbt) {
setTile(index, block.getNbtData()); int y = index / getArea();
int newI = index- y * getArea();
int z = newI / getWidth();
int x = newI - z * getWidth();
setTile(x, y, z, block.getNbtData());
} }
return true; return true;
} }