Mirror von
https://github.com/ViaVersion/ViaBackwards.git
synchronisiert 2024-12-27 00:22:53 +01:00
Handle world min_y value
Dieser Commit ist enthalten in:
Ursprung
ab0406ba77
Commit
b48edbde04
@ -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<>();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren