3
0
Mirror von https://github.com/ViaVersion/ViaBackwards.git synchronisiert 2024-12-26 16:12:43 +01:00

Handle world min_y value

Dieser Commit ist enthalten in:
KennyTV 2021-02-11 00:30:29 +01:00
Ursprung ab0406ba77
Commit b48edbde04
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 6BE3B555EBC5982B
4 geänderte Dateien mit 154 neuen und 30 gelöschten Zeilen

Datei anzeigen

@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class EntityTracker extends StoredObject { public class EntityTracker extends StoredObject {
private final Map<BackwardsProtocol, ProtocolEntityTracker> trackers = new ConcurrentHashMap<>(); private final Map<BackwardsProtocol, ProtocolEntityTracker> trackers = new ConcurrentHashMap<>();
private int currentWorldSectionHeight = 16; private int currentWorldSectionHeight = 16;
private int currentMinY;
public EntityTracker(UserConnection user) { public EntityTracker(UserConnection user) {
super(user); super(user);
@ -40,6 +41,9 @@ public class EntityTracker extends StoredObject {
return trackers; return trackers;
} }
/**
* @return amount of chunk sections of the current world (block height / 16)
*/
public int getCurrentWorldSectionHeight() { public int getCurrentWorldSectionHeight() {
return currentWorldSectionHeight; return currentWorldSectionHeight;
} }
@ -48,6 +52,17 @@ public class EntityTracker extends StoredObject {
this.currentWorldSectionHeight = currentWorldSectionHeight; this.currentWorldSectionHeight = currentWorldSectionHeight;
} }
/**
* @return absolute minimum y coordinate of the current world
*/
public int getCurrentMinY() {
return currentMinY;
}
public void setCurrentMinY(int currentMinY) {
this.currentMinY = currentMinY;
}
public static class ProtocolEntityTracker { public static class ProtocolEntityTracker {
private final Map<Integer, StoredEntity> entityMap = new ConcurrentHashMap<>(); private final Map<Integer, StoredEntity> entityMap = new ConcurrentHashMap<>();

Datei anzeigen

@ -262,15 +262,23 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends Re
protected PacketHandler getWorldDataTracker(int nbtIndex) { protected PacketHandler getWorldDataTracker(int nbtIndex) {
return wrapper -> { return wrapper -> {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
CompoundTag registryData = wrapper.get(Type.NBT, nbtIndex); CompoundTag registryData = wrapper.get(Type.NBT, nbtIndex);
Tag height = registryData.get("height"); Tag height = registryData.get("height");
if (!(height instanceof IntTag)) { if (height instanceof IntTag) {
int blockHeight = ((IntTag) height).getValue();
tracker.setCurrentWorldSectionHeight(blockHeight >> 4);
} else {
ViaBackwards.getPlatform().getLogger().warning("Height missing in dimension data: " + registryData); ViaBackwards.getPlatform().getLogger().warning("Height missing in dimension data: " + registryData);
return;
} }
int blockHeight = ((IntTag) height).getValue(); Tag minY = registryData.get("min_y");
wrapper.user().get(EntityTracker.class).setCurrentWorldSectionHeight(blockHeight >> 4); if (minY instanceof IntTag) {
tracker.setCurrentMinY(((IntTag) minY).getValue());
} else {
ViaBackwards.getPlatform().getLogger().warning("Min Y missing in dimension data: " + registryData);
}
}; };
} }

Datei anzeigen

@ -4,6 +4,7 @@ import nl.matsv.viabackwards.api.entities.storage.EntityTracker;
import nl.matsv.viabackwards.api.rewriters.TranslatableRewriter; import nl.matsv.viabackwards.api.rewriters.TranslatableRewriter;
import nl.matsv.viabackwards.protocol.protocol1_16_4to1_17.Protocol1_16_4To1_17; import nl.matsv.viabackwards.protocol.protocol1_16_4to1_17.Protocol1_16_4To1_17;
import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; import us.myles.ViaVersion.api.minecraft.BlockChangeRecord;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
@ -19,6 +20,7 @@ import us.myles.ViaVersion.protocols.protocol1_17to1_16_4.types.Chunk1_17Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import java.util.List; import java.util.List;
public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.ItemRewriter<Protocol1_16_4To1_17> { public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.ItemRewriter<Protocol1_16_4To1_17> {
@ -89,7 +91,7 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
}); });
// The Great Shrunkening // The Great Shrunkening
// Some chunk sections will be lost ¯\_()_/¯ // Chunk sections *will* be lost ¯\_()_/¯
protocol.registerOutgoing(ClientboundPackets1_17.UPDATE_LIGHT, new PacketRemapper() { protocol.registerOutgoing(ClientboundPackets1_17.UPDATE_LIGHT, new PacketRemapper() {
@Override @Override
public void registerMap() { public void registerMap() {
@ -97,28 +99,54 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
map(Type.VAR_INT); // Z map(Type.VAR_INT); // Z
map(Type.BOOLEAN); // Trust edges map(Type.BOOLEAN); // Trust edges
handler(wrapper -> { handler(wrapper -> {
int skyLightMask = cutLongArrayMask(wrapper.read(Type.LONG_ARRAY_PRIMITIVE)); EntityTracker tracker = wrapper.user().get(EntityTracker.class);
int blockLightMask = cutLongArrayMask(wrapper.read(Type.LONG_ARRAY_PRIMITIVE)); int startFromSection = Math.max(0, -(tracker.getCurrentMinY() >> 4));
wrapper.write(Type.VAR_INT, skyLightMask); // Sky light mask
wrapper.write(Type.VAR_INT, blockLightMask); // Block light mask
wrapper.write(Type.VAR_INT, cutLongArrayMask(wrapper.read(Type.LONG_ARRAY_PRIMITIVE)));// Empty sky light mask
wrapper.write(Type.VAR_INT, cutLongArrayMask(wrapper.read(Type.LONG_ARRAY_PRIMITIVE))); // Empty block light mask
writeLightArrays(wrapper, skyLightMask); long[] skyLightMask = wrapper.read(Type.LONG_ARRAY_PRIMITIVE);
writeLightArrays(wrapper, blockLightMask); long[] blockLightMask = wrapper.read(Type.LONG_ARRAY_PRIMITIVE);
int cutSkyLightMask = cutLightMask(skyLightMask, startFromSection);
int cutBlockLightMask = cutLightMask(blockLightMask, startFromSection);
wrapper.write(Type.VAR_INT, cutSkyLightMask);
wrapper.write(Type.VAR_INT, cutBlockLightMask);
long[] emptySkyLightMask = wrapper.read(Type.LONG_ARRAY_PRIMITIVE);
long[] emptyBlockLightMask = wrapper.read(Type.LONG_ARRAY_PRIMITIVE);
wrapper.write(Type.VAR_INT, cutLightMask(emptySkyLightMask, startFromSection));
wrapper.write(Type.VAR_INT, cutLightMask(emptyBlockLightMask, startFromSection));
writeLightArrays(wrapper, BitSet.valueOf(skyLightMask), cutSkyLightMask, startFromSection, tracker.getCurrentWorldSectionHeight());
writeLightArrays(wrapper, BitSet.valueOf(blockLightMask), cutBlockLightMask, startFromSection, tracker.getCurrentWorldSectionHeight());
}); });
} }
private void writeLightArrays(PacketWrapper wrapper, int bitMask) throws Exception { private void writeLightArrays(PacketWrapper wrapper, BitSet bitMask, int cutBitMask,
int startFromSection, int sectionHeight) throws Exception {
wrapper.read(Type.VAR_INT); // Length - throw it away wrapper.read(Type.VAR_INT); // Length - throw it away
List<byte[]> light = new ArrayList<>(); List<byte[]> light = new ArrayList<>();
for (int i = 0; i <= 17; i++) {
if (isSet(bitMask, i)) { // Remove lower bounds
for (int i = 0; i < startFromSection; i++) {
if (bitMask.get(i)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
}
// Add the important 18 sections
for (int i = 0; i < 18; i++) {
if (isSet(cutBitMask, i)) {
light.add(wrapper.read(Type.BYTE_ARRAY_PRIMITIVE)); light.add(wrapper.read(Type.BYTE_ARRAY_PRIMITIVE));
} }
} }
// Remove upper bounds
for (int i = startFromSection + 18; i < sectionHeight + 1; i++) {
if (bitMask.get(i)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
}
// Aaand we're done
for (byte[] bytes : light) { for (byte[] bytes : light) {
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, bytes); wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, bytes);
} }
@ -135,12 +163,17 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
map(Type.BOOLEAN); // Suppress light updates map(Type.BOOLEAN); // Suppress light updates
handler((wrapper) -> { handler((wrapper) -> {
// Cancel if above the 256 block limit // Cancel if above the 256 block limit
int chunkY = (int) (wrapper.get(Type.LONG, 0) << 44 >> 44); long chunkPos = wrapper.get(Type.LONG, 0);
if (chunkY > 15) { int chunkY = (int) (chunkPos << 44 >> 44);
int flattenedChunkY = getFlattenedYSection(wrapper.user(), chunkY);
if (flattenedChunkY < 0 || flattenedChunkY > 15) {
wrapper.cancel(); wrapper.cancel();
return; return;
} }
// Encode changed y pos
wrapper.set(Type.LONG, 0, encodeChunkPos(decodeChunkX(chunkPos), flattenedChunkY, decodeChunkZ(chunkPos)));
BlockChangeRecord[] records = wrapper.passthrough(Type.VAR_LONG_BLOCK_CHANGE_RECORD_ARRAY); BlockChangeRecord[] records = wrapper.passthrough(Type.VAR_LONG_BLOCK_CHANGE_RECORD_ARRAY);
for (BlockChangeRecord record : records) { for (BlockChangeRecord record : records) {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId())); record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
@ -154,7 +187,8 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
map(Type.POSITION1_14); map(Type.POSITION1_14);
map(Type.VAR_INT); map(Type.VAR_INT);
handler((wrapper) -> { handler((wrapper) -> {
if (wrapper.get(Type.POSITION1_14, 0).getY() >= 256) { int y = wrapper.get(Type.POSITION1_14, 0).getY();
if (y < 0 || y > 255) {
wrapper.cancel(); wrapper.cancel();
return; return;
} }
@ -168,18 +202,24 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
@Override @Override
public void registerMap() { public void registerMap() {
handler(wrapper -> { handler(wrapper -> {
int currentWorldSectionHeight = wrapper.user().get(EntityTracker.class).getCurrentWorldSectionHeight(); EntityTracker tracker = wrapper.user().get(EntityTracker.class);
int currentWorldSectionHeight = tracker.getCurrentWorldSectionHeight();
Chunk chunk = wrapper.read(new Chunk1_17Type(currentWorldSectionHeight)); Chunk chunk = wrapper.read(new Chunk1_17Type(currentWorldSectionHeight));
wrapper.write(new Chunk1_16_2Type(), chunk); wrapper.write(new Chunk1_16_2Type(), chunk);
chunk.setBiomeData(Arrays.copyOf(chunk.getBiomeData(), 1024)); // Cut sections
int startFromSection = Math.max(0, -(tracker.getCurrentMinY() >> 4));
chunk.setBiomeData(Arrays.copyOfRange(chunk.getBiomeData(), startFromSection * 64, (startFromSection * 64) + 1024));
// Cut down to int mask chunk.setBitmask(cutMask(chunk.getChunkMask(), startFromSection, false));
chunk.setBitmask(cutLongArrayMask(chunk.getChunkMask().toLongArray()));
chunk.setChunkMask(null); chunk.setChunkMask(null);
for (int i = 0; i < 16; i++) { // Only need to process the first 16 sections ChunkSection[] sections = Arrays.copyOfRange(chunk.getSections(), startFromSection, startFromSection + 16);
ChunkSection section = chunk.getSections()[i]; chunk.setSections(sections);
for (int i = 0; i < 16; i++) {
ChunkSection section = sections[i];
if (section == null) continue; if (section == null) continue;
for (int j = 0; j < section.getPaletteSize(); j++) { for (int j = 0; j < section.getPaletteSize(); j++) {
int old = section.getPaletteEntry(j); int old = section.getPaletteEntry(j);
@ -189,13 +229,72 @@ public class BlockItemPackets1_17 extends nl.matsv.viabackwards.api.rewriters.It
}); });
} }
}); });
protocol.registerOutgoing(ClientboundPackets1_17.BLOCK_ENTITY_DATA, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
int y = wrapper.passthrough(Type.POSITION1_14).getY();
if (y < 0 || y > 255) {
wrapper.cancel();
}
});
}
});
protocol.registerOutgoing(ClientboundPackets1_17.BLOCK_BREAK_ANIMATION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
handler(wrapper -> {
int y = wrapper.passthrough(Type.POSITION1_14).getY();
if (y < 0 || y > 255) {
wrapper.cancel();
}
});
}
});
} }
private int cutLongArrayMask(long[] mask) { private int cutLightMask(long[] mask, int startFromSection) {
if (mask.length == 0) return 0; if (mask.length == 0) return 0;
return cutMask(BitSet.valueOf(mask), startFromSection, true);
}
// Only keep the first 18 bits (16 sections + one above and below) private int cutMask(BitSet mask, int startFromSection, boolean lightMask) {
long l = mask[0]; int cutMask = 0;
return (int) (l & 0x3ffff); // Light masks have a section below and above the 16 main sections
int to = startFromSection + (lightMask ? 18 : 16);
for (int i = startFromSection, j = 0; i < to; i++, j++) {
if (mask.get(i)) {
cutMask |= (1 << j);
}
}
return cutMask;
}
private int getFlattenedYSection(UserConnection connection, int chunkSectionY) {
EntityTracker tracker = connection.get(EntityTracker.class);
return chunkSectionY + (tracker.getCurrentMinY() << 4);
}
private long encodeChunkPos(int chunkX, int chunkY, int chunkZ) {
long l = 0L;
l |= (chunkX & 0x3FFFFFL) << 42;
l |= (chunkY & 0xFFFFFL);
l |= (chunkZ & 0x3FFFFFL) << 20;
return l;
}
private int decodeChunkX(long chunkPos) {
return (int) (chunkPos >> 42);
}
private int decodeChunkY(long chunkPos) {
return (int) (chunkPos << 44 >> 44);
}
private int decodeChunkZ(long chunkPos) {
return (int) (chunkPos << 22 >> 42);
} }
} }

Datei anzeigen

@ -72,7 +72,9 @@ public class EntityPackets1_17 extends EntityRewriter<Protocol1_16_4To1_17> {
public void registerMap() { public void registerMap() {
map(Type.NBT); // Dimension data map(Type.NBT); // Dimension data
handler(getWorldDataTracker(0)); handler(getWorldDataTracker(0));
handler(wrapper -> reduceForExtendedHeight(wrapper.get(Type.NBT, 0), true)); handler(wrapper -> {
reduceForExtendedHeight(wrapper.get(Type.NBT, 0), true);
});
} }
}); });