mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-26 03:55:28 +01:00
Read/write palette based on block/biome size variables
This commit is contained in:
parent
c5e27b89af
commit
73093c0ff2
@ -116,6 +116,11 @@ public class IntArrayMappings implements Mappings {
|
||||
oldToNew[id] = newId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return oldToNew.length;
|
||||
}
|
||||
|
||||
public int[] getOldToNew() {
|
||||
return oldToNew;
|
||||
}
|
||||
|
@ -40,4 +40,6 @@ public interface Mappings {
|
||||
* @throws IndexOutOfBoundsException if the unmapped id is invalid
|
||||
*/
|
||||
void setNewId(int id, int newId);
|
||||
|
||||
int size();
|
||||
}
|
||||
|
@ -147,4 +147,8 @@ public interface EntityTracker {
|
||||
* @param currentWorld name of the current world
|
||||
*/
|
||||
void setCurrentWorld(String currentWorld);
|
||||
|
||||
int biomesSent();
|
||||
|
||||
void setBiomesSent(int biomesSent);
|
||||
}
|
||||
|
@ -23,15 +23,21 @@
|
||||
package com.viaversion.viaversion.api.minecraft.chunks;
|
||||
|
||||
public enum PaletteType {
|
||||
BLOCKS(8),
|
||||
BIOMES(2);
|
||||
BLOCKS(ChunkSection.SIZE, 8),
|
||||
BIOMES(4 * 4 * 4, 2);
|
||||
|
||||
private final int maxSize;
|
||||
private final int highestBitsPerValue;
|
||||
|
||||
PaletteType(final int highestBitsPerValue) {
|
||||
PaletteType(final int maxSize, final int highestBitsPerValue) {
|
||||
this.maxSize = maxSize;
|
||||
this.highestBitsPerValue = highestBitsPerValue;
|
||||
}
|
||||
|
||||
public int maxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
public int highestBitsPerValue() {
|
||||
return highestBitsPerValue;
|
||||
}
|
||||
|
@ -30,23 +30,28 @@ import io.netty.buffer.ByteBuf;
|
||||
|
||||
public final class ChunkSectionType1_18 extends Type<ChunkSection> {
|
||||
|
||||
public ChunkSectionType1_18() {
|
||||
private final PaletteType1_18 blockPaletteType;
|
||||
private final PaletteType1_18 biomePaletteType;
|
||||
|
||||
public ChunkSectionType1_18(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
|
||||
super("Chunk Section Type", ChunkSection.class);
|
||||
this.blockPaletteType = new PaletteType1_18(PaletteType.BLOCKS, globalPaletteBlockBits);
|
||||
this.biomePaletteType = new PaletteType1_18(PaletteType.BIOMES, globalPaletteBiomeBits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkSection read(final ByteBuf buffer) throws Exception {
|
||||
final ChunkSection chunkSection = new ChunkSectionImpl();
|
||||
chunkSection.setNonAirBlocksCount(buffer.readShort());
|
||||
chunkSection.addPalette(PaletteType.BLOCKS, Types1_18.BLOCK_PALETTE_TYPE.read(buffer));
|
||||
chunkSection.addPalette(PaletteType.BIOMES, Types1_18.BIOME_PALETTE_TYPE.read(buffer));
|
||||
chunkSection.addPalette(PaletteType.BLOCKS, blockPaletteType.read(buffer));
|
||||
chunkSection.addPalette(PaletteType.BIOMES, biomePaletteType.read(buffer));
|
||||
return chunkSection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ChunkSection section) throws Exception {
|
||||
buffer.writeShort(section.getNonAirBlocksCount());
|
||||
Types1_18.BLOCK_PALETTE_TYPE.write(buffer, section.palette(PaletteType.BLOCKS));
|
||||
Types1_18.BIOME_PALETTE_TYPE.write(buffer, section.palette(PaletteType.BIOMES));
|
||||
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
|
||||
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
|
||||
}
|
||||
}
|
||||
|
@ -22,29 +22,30 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.version;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPaletteImpl;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.type.PartialType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.CompactArrayUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType> {
|
||||
private static final int GLOBAL_PALETTE = 15;
|
||||
public final class PaletteType1_18 extends Type<DataPalette> {
|
||||
private final int globalPaletteBits;
|
||||
private final PaletteType type;
|
||||
|
||||
public PaletteType1_18(final PaletteType type) {
|
||||
super(type, DataPalette.class);
|
||||
public PaletteType1_18(final PaletteType type, final int globalPaletteBits) {
|
||||
super(DataPalette.class);
|
||||
this.globalPaletteBits = globalPaletteBits;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataPalette read(final ByteBuf buffer, final PaletteType type) throws Exception {
|
||||
public DataPalette read(final ByteBuf buffer) throws Exception {
|
||||
int bitsPerValue = buffer.readByte();
|
||||
final int originalBitsPerValue = bitsPerValue;
|
||||
|
||||
if (bitsPerValue > type.highestBitsPerValue()) {
|
||||
bitsPerValue = GLOBAL_PALETTE;
|
||||
bitsPerValue = globalPaletteBits;
|
||||
}
|
||||
|
||||
// Read palette
|
||||
@ -57,7 +58,7 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
return palette;
|
||||
}
|
||||
|
||||
if (bitsPerValue != GLOBAL_PALETTE) {
|
||||
if (bitsPerValue != globalPaletteBits) {
|
||||
final int paletteLength = Type.VAR_INT.readPrimitive(buffer);
|
||||
palette = new DataPaletteImpl(paletteLength);
|
||||
for (int i = 0; i < paletteLength; i++) {
|
||||
@ -71,7 +72,7 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
final long[] values = new long[Type.VAR_INT.readPrimitive(buffer)];
|
||||
if (values.length > 0) {
|
||||
final char valuesPerLong = (char) (64 / bitsPerValue);
|
||||
final int expectedLength = (ChunkSection.SIZE + valuesPerLong - 1) / valuesPerLong;
|
||||
final int expectedLength = (type.maxSize() + valuesPerLong - 1) / valuesPerLong;
|
||||
if (values.length != expectedLength) {
|
||||
throw new IllegalStateException("Palette data length (" + values.length + ") does not match expected length (" + expectedLength + ")! bitsPerValue=" + bitsPerValue + ", originalBitsPerValue=" + originalBitsPerValue);
|
||||
}
|
||||
@ -79,14 +80,14 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = buffer.readLong();
|
||||
}
|
||||
CompactArrayUtil.iterateCompactArrayWithPadding(bitsPerValue, ChunkSection.SIZE, values,
|
||||
bitsPerValue == GLOBAL_PALETTE ? palette::setIdAt : palette::setPaletteIndexAt);
|
||||
CompactArrayUtil.iterateCompactArrayWithPadding(bitsPerValue, type.maxSize(), values,
|
||||
bitsPerValue == globalPaletteBits ? palette::setIdAt : palette::setPaletteIndexAt);
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final PaletteType type, final DataPalette palette) throws Exception {
|
||||
public void write(final ByteBuf buffer, final DataPalette palette) throws Exception {
|
||||
int bitsPerValue;
|
||||
if (palette.size() > 1) {
|
||||
// 1, 2, and 3 bit linear palettes can't be read by the client
|
||||
@ -96,7 +97,7 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
}
|
||||
|
||||
if (bitsPerValue > type.highestBitsPerValue()) {
|
||||
bitsPerValue = GLOBAL_PALETTE;
|
||||
bitsPerValue = globalPaletteBits;
|
||||
}
|
||||
} else {
|
||||
bitsPerValue = 0;
|
||||
@ -111,7 +112,7 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
return;
|
||||
}
|
||||
|
||||
if (bitsPerValue != GLOBAL_PALETTE) {
|
||||
if (bitsPerValue != globalPaletteBits) {
|
||||
// Write pallete
|
||||
Type.VAR_INT.writePrimitive(buffer, palette.size());
|
||||
for (int i = 0; i < palette.size(); i++) {
|
||||
@ -119,7 +120,7 @@ public final class PaletteType1_18 extends PartialType<DataPalette, PaletteType>
|
||||
}
|
||||
}
|
||||
|
||||
final long[] data = CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, ChunkSection.SIZE, bitsPerValue == GLOBAL_PALETTE ? palette::idAt : palette::paletteIndexAt);
|
||||
final long[] data = CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.maxSize(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt);
|
||||
Type.VAR_INT.writePrimitive(buffer, data.length);
|
||||
for (final long l : data) {
|
||||
buffer.writeLong(l);
|
||||
|
@ -30,8 +30,5 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
|
||||
public final class Types1_18 {
|
||||
|
||||
public static final Type<ChunkSection> CHUNK_SECTION = new ChunkSectionType1_18();
|
||||
public static final Type<BlockEntity> BLOCK_ENTITY = new BlockEntityType1_18();
|
||||
public static final Type<DataPalette> BLOCK_PALETTE_TYPE = new PaletteType1_18(PaletteType.BLOCKS);
|
||||
public static final Type<DataPalette> BIOME_PALETTE_TYPE = new PaletteType1_18(PaletteType.BIOMES);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
private int currentWorldSectionHeight = 16;
|
||||
private int currentMinY;
|
||||
private String currentWorld;
|
||||
private int biomesSent = -1;
|
||||
|
||||
public EntityTrackerBase(UserConnection connection, @Nullable EntityType playerType) {
|
||||
this(connection, playerType, false);
|
||||
@ -147,4 +148,14 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
public void setCurrentWorld(final String currentWorld) {
|
||||
this.currentWorld = currentWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int biomesSent() {
|
||||
return biomesSent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiomesSent(int biomesSent) {
|
||||
this.biomesSent = biomesSent;
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ public final class EntityPackets extends EntityRewriter<Protocol1_18To1_17_1> {
|
||||
map(Type.NBT); // Current dimension data
|
||||
map(Type.STRING); // World
|
||||
handler(worldDataTrackerHandler(1));
|
||||
handler(biomeSizeTracker());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -38,6 +38,7 @@ import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.BlockEntityIds;
|
||||
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.Protocol1_18To1_17_1;
|
||||
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.storage.ChunkLightStorage;
|
||||
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type;
|
||||
import com.viaversion.viaversion.util.MathUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -166,7 +167,9 @@ public final class WorldPackets {
|
||||
}
|
||||
|
||||
final Chunk chunk = new Chunk1_18(oldChunk.getX(), oldChunk.getZ(), oldChunk.getSections(), oldChunk.getHeightMap(), blockEntities);
|
||||
wrapper.write(new Chunk1_18Type(tracker.currentWorldSectionHeight()), chunk);
|
||||
wrapper.write(new Chunk1_18Type(tracker.currentWorldSectionHeight(),
|
||||
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().size()),
|
||||
MathUtil.ceilLog2(tracker.biomesSent())), chunk);
|
||||
|
||||
// Get and remove light stored, there's only full chunk packets //TODO Only get, not remove if we find out people re-send full chunk packets without re-sending light
|
||||
final ChunkLightStorage lightStorage = wrapper.user().get(ChunkLightStorage.class);
|
||||
|
@ -19,12 +19,14 @@ package com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_18;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
|
||||
import com.viaversion.viaversion.api.type.types.version.ChunkSectionType1_18;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_18;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@ -32,11 +34,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class Chunk1_18Type extends Type<Chunk> {
|
||||
private final ChunkSectionType1_18 sectionType;
|
||||
private final int ySectionCount;
|
||||
|
||||
public Chunk1_18Type(final int ySectionCount) {
|
||||
public Chunk1_18Type(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
|
||||
super(Chunk.class);
|
||||
Preconditions.checkArgument(ySectionCount > 0);
|
||||
this.sectionType = new ChunkSectionType1_18(globalPaletteBlockBits, globalPaletteBiomeBits);
|
||||
this.ySectionCount = ySectionCount;
|
||||
}
|
||||
|
||||
@ -51,9 +55,12 @@ public final class Chunk1_18Type extends Type<Chunk> {
|
||||
final ChunkSection[] sections = new ChunkSection[ySectionCount];
|
||||
try {
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = Types1_18.CHUNK_SECTION.read(sectionsBuf);
|
||||
sections[i] = sectionType.read(sectionsBuf);
|
||||
}
|
||||
} finally {
|
||||
if (sectionsBuf.readableBytes() > 0) {
|
||||
Via.getPlatform().getLogger().warning("Found " + sectionsBuf.readableBytes() + " more bytes than expected while reading the chunk: " + chunkX + "/" + chunkZ);
|
||||
}
|
||||
sectionsBuf.release();
|
||||
}
|
||||
|
||||
@ -76,7 +83,7 @@ public final class Chunk1_18Type extends Type<Chunk> {
|
||||
final ByteBuf sectionBuffer = buffer.alloc().buffer();
|
||||
try {
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
Types1_18.CHUNK_SECTION.write(sectionBuffer, section);
|
||||
sectionType.write(sectionBuffer, section);
|
||||
}
|
||||
sectionBuffer.readerIndex(0);
|
||||
Type.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
|
||||
|
@ -19,6 +19,7 @@ package com.viaversion.viaversion.rewriter;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
@ -397,6 +398,15 @@ public abstract class EntityRewriter<T extends Protocol> extends RewriterBase<T>
|
||||
};
|
||||
}
|
||||
|
||||
public PacketHandler biomeSizeTracker() {
|
||||
return wrapper -> {
|
||||
final CompoundTag registry = wrapper.get(Type.NBT, 0);
|
||||
final CompoundTag biomeRegistry = registry.get("minecraft:worldgen/biome");
|
||||
final ListTag biomes = biomeRegistry.get("value");
|
||||
tracker(wrapper.user()).setBiomesSent(biomes.size());
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sub 1.14.1 methods
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2021 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.util;
|
||||
|
||||
public final class MathUtil {
|
||||
|
||||
/**
|
||||
* Primitive method to return the ceiled log to the base of 2 for the given number.
|
||||
*
|
||||
* @param i number to ceillog
|
||||
* @return ceiled log2 of the given number
|
||||
*/
|
||||
public static int ceilLog2(final int i) {
|
||||
int j = 1;
|
||||
int k = 0;
|
||||
while (j < i) {
|
||||
j *= 2;
|
||||
k++;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user