Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-27 08:30:09 +01:00
Ursprung
533572e8cd
Commit
e7a0b4cf04
@ -230,6 +230,13 @@ public interface ViaVersionConfig {
|
||||
*/
|
||||
int getPistonReplacementId();
|
||||
|
||||
/**
|
||||
* Fix 1.9+ clients not rendering the far away chunks
|
||||
*
|
||||
* @return true to fix chunk borders
|
||||
*/
|
||||
boolean isChunkBorderFix();
|
||||
|
||||
/**
|
||||
* Force json transform
|
||||
*
|
||||
@ -417,7 +424,7 @@ public interface ViaVersionConfig {
|
||||
boolean isForcedUse1_17ResourcePack();
|
||||
|
||||
/**
|
||||
* Get the message that is sent when a user displays a resource pack prompt.
|
||||
* Get the message that is sent when a user displays a resource pack prompt.
|
||||
*
|
||||
* @return cached serialized component
|
||||
*/
|
||||
|
@ -33,6 +33,8 @@ public enum BlockFace {
|
||||
TOP((byte) 0, (byte) 1, (byte) 0, EnumAxis.Y),
|
||||
BOTTOM((byte) 0, (byte) -1, (byte) 0, EnumAxis.Y);
|
||||
|
||||
public static final BlockFace[] HORIZONTAL = new BlockFace[]{NORTH, SOUTH, EAST, WEST};
|
||||
|
||||
private static final Map<BlockFace, BlockFace> opposites = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
@ -20,41 +20,23 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.chunks;
|
||||
package com.viaversion.viaversion.api.type.types.minecraft;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
public abstract class BaseChunkBulkType extends Type<Chunk[]> {
|
||||
|
||||
public class Chunk1_8 extends BaseChunk {
|
||||
private boolean unloadPacket;
|
||||
|
||||
public Chunk1_8(int x, int z, boolean groundUp, int bitmask, ChunkSection[] sections, int[] biomeData, List<CompoundTag> blockEntities) {
|
||||
super(x, z, groundUp, false, bitmask, sections, biomeData, blockEntities);
|
||||
protected BaseChunkBulkType() {
|
||||
super(Chunk[].class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk unload.
|
||||
*
|
||||
* @param x coord
|
||||
* @param z coord
|
||||
*/
|
||||
public Chunk1_8(int x, int z) {
|
||||
this(x, z, true, 0, new ChunkSection[16], null, new ArrayList<>());
|
||||
this.unloadPacket = true;
|
||||
protected BaseChunkBulkType(String typeName) {
|
||||
super(typeName, Chunk[].class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this chunks have biome data
|
||||
*
|
||||
* @return True if the chunks has biome data
|
||||
*/
|
||||
public boolean hasBiomeData() {
|
||||
return biomeData != null && fullChunk;
|
||||
}
|
||||
|
||||
public boolean isUnloadPacket() {
|
||||
return unloadPacket;
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkBulkType.class;
|
||||
}
|
||||
}
|
@ -55,6 +55,15 @@ public class ChunkSectionType1_8 extends Type<ChunkSection> {
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, ChunkSection chunkSection) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int block = chunkSection.getFlatBlock(x, y, z);
|
||||
buffer.writeByte(block);
|
||||
buffer.writeByte(block >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
private boolean nmsPlayerTicking;
|
||||
private boolean replacePistons;
|
||||
private int pistonReplacementId;
|
||||
private boolean chunkBorderFix;
|
||||
private boolean autoTeam;
|
||||
private boolean forceJsonTransform;
|
||||
private boolean nbtArrayFix;
|
||||
@ -114,6 +115,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
nmsPlayerTicking = getBoolean("nms-player-ticking", true);
|
||||
replacePistons = getBoolean("replace-pistons", false);
|
||||
pistonReplacementId = getInt("replacement-piston-id", 0);
|
||||
chunkBorderFix = getBoolean("chunk-border-fix", false);
|
||||
autoTeam = getBoolean("auto-team", true);
|
||||
forceJsonTransform = getBoolean("force-json-transform", false);
|
||||
nbtArrayFix = getBoolean("chat-nbt-fix", true);
|
||||
@ -277,6 +279,11 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
return pistonReplacementId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkBorderFix() {
|
||||
return chunkBorderFix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoTeam() {
|
||||
// Collision has to be enabled first
|
||||
|
@ -17,11 +17,13 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.protocol1_10to1_9_3;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
|
||||
@ -30,8 +32,10 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.packets.InventoryPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.storage.ResourcePackTracker;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -145,6 +149,66 @@ public class Protocol1_10To1_9_3_4 extends AbstractProtocol<ClientboundPackets1_
|
||||
}
|
||||
});
|
||||
|
||||
// Join Game
|
||||
registerClientbound(ClientboundPackets1_9_3.JOIN_GAME, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.INT); // 0 - Entity ID
|
||||
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
|
||||
map(Type.INT); // 2 - Dimension
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
|
||||
int dimensionId = wrapper.get(Type.INT, 1);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Respawn
|
||||
registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.INT); // 0 - Dimension ID
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
|
||||
int dimensionId = wrapper.get(Type.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Chunk Data
|
||||
registerClientbound(ClientboundPackets1_9_3.CHUNK_DATA, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
Chunk chunk = wrapper.passthrough(new Chunk1_9_3_4Type(clientWorld));
|
||||
|
||||
if (Via.getConfig().isReplacePistons()) {
|
||||
int replacementId = Via.getConfig().getPistonReplacementId();
|
||||
for (ChunkSection section : chunk.getSections()) {
|
||||
if (section == null) continue;
|
||||
section.replacePaletteEntry(36, replacementId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Packet Send ResourcePack
|
||||
registerClientbound(ClientboundPackets1_9_3.RESOURCE_PACK, new PacketRemapper() {
|
||||
@Override
|
||||
@ -196,6 +260,10 @@ public class Protocol1_10To1_9_3_4 extends AbstractProtocol<ClientboundPackets1_
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
userConnection.put(new ResourcePackTracker());
|
||||
|
||||
if (!userConnection.has(ClientWorld.class)) {
|
||||
userConnection.put(new ClientWorld(userConnection));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -137,9 +137,9 @@ public class Protocol1_9_3To1_9_1_2 extends AbstractProtocol<ClientboundPackets1
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Type.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
package com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.minecraft.Environment;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
@ -27,7 +26,6 @@ import com.viaversion.viaversion.api.type.PartialType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@ -42,9 +40,6 @@ public class Chunk1_9_1_2Type extends PartialType<Chunk, ClientWorld> {
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf input, ClientWorld world) throws Exception {
|
||||
boolean replacePistons = world.getUser().getProtocolInfo().getPipeline().contains(Protocol1_10To1_9_3_4.class) && Via.getConfig().isReplacePistons();
|
||||
int replacementId = Via.getConfig().getPistonReplacementId();
|
||||
|
||||
int chunkX = input.readInt();
|
||||
int chunkZ = input.readInt();
|
||||
|
||||
@ -71,9 +66,6 @@ public class Chunk1_9_1_2Type extends PartialType<Chunk, ClientWorld> {
|
||||
if (world.getEnvironment() == Environment.NORMAL) {
|
||||
section.getLight().readSkyLight(input);
|
||||
}
|
||||
if (replacePistons) {
|
||||
section.replacePaletteEntry(36, replacementId);
|
||||
}
|
||||
}
|
||||
|
||||
int[] biomeData = groundUp ? new int[256] : null;
|
||||
|
@ -32,18 +32,11 @@ import com.viaversion.viaversion.api.rewriter.EntityRewriter;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetadataRewriter1_9To1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.EntityPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.InventoryPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.PlayerPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.SpawnPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.WorldPackets;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.*;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.*;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.CommandBlockStorage;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.EntityTracker1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.InventoryTracker;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.*;
|
||||
import com.viaversion.viaversion.util.GsonUtil;
|
||||
|
||||
public class Protocol1_9To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_9, ServerboundPackets1_8, ServerboundPackets1_9> {
|
||||
@ -152,6 +145,10 @@ public class Protocol1_9To1_8 extends AbstractProtocol<ClientboundPackets1_8, Cl
|
||||
userConnection.put(new InventoryTracker());
|
||||
// CommandBlock storage
|
||||
userConnection.put(new CommandBlockStorage());
|
||||
|
||||
if (!userConnection.has(ClientWorld.class)) {
|
||||
userConnection.put(new ClientWorld(userConnection));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.PlayerMovementMapper;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
||||
@ -189,12 +190,18 @@ public class PlayerPackets {
|
||||
tracker.setGameMode(GameMode.getById(wrapper.get(Type.UNSIGNED_BYTE, 0))); //Set player gamemode
|
||||
});
|
||||
|
||||
// Track player's dimension
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Type.BYTE, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
|
||||
// Gotta fake their op
|
||||
handler(wrapper -> {
|
||||
CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class);
|
||||
provider.sendPermission(wrapper.user());
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Scoreboard will be cleared when join game is received
|
||||
handler(wrapper -> {
|
||||
@ -300,22 +307,6 @@ public class PlayerPackets {
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_HEALTH, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.FLOAT); // 0 - Health
|
||||
handler(wrapper -> {
|
||||
float health = wrapper.get(Type.FLOAT, 0);
|
||||
if (health <= 0) {
|
||||
// Client unloads chunks on respawn, take note
|
||||
ClientChunks cc = wrapper.user().get(ClientChunks.class);
|
||||
cc.getBulkChunks().clear();
|
||||
cc.getLoadedChunks().clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.RESPAWN, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
@ -324,11 +315,19 @@ public class PlayerPackets {
|
||||
map(Type.UNSIGNED_BYTE); // 2 - GameMode
|
||||
map(Type.STRING); // 3 - Level Type
|
||||
|
||||
// Track player's dimension
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Type.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
}
|
||||
});
|
||||
|
||||
handler(wrapper -> {
|
||||
// Client unloads chunks on respawn, take note
|
||||
ClientChunks cc = wrapper.user().get(ClientChunks.class);
|
||||
cc.getBulkChunks().clear();
|
||||
cc.getLoadedChunks().clear();
|
||||
// Client unloads chunks on respawn
|
||||
wrapper.user().get(ClientChunks.class).getLoadedChunks().clear();
|
||||
|
||||
int gamemode = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
||||
EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class);
|
||||
|
@ -20,8 +20,11 @@ package com.viaversion.viaversion.protocols.protocol1_9to1_8.packets;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockFace;
|
||||
import com.viaversion.viaversion.api.minecraft.Position;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_8;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.DataItem;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
@ -29,8 +32,9 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.CustomByteType;
|
||||
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_1_2Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
||||
@ -40,10 +44,11 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.sounds.Effect;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.sounds.SoundEffect;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.EntityTracker1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.Chunk1_9to1_8Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.Chunk1_8Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.ChunkBulk1_8Type;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
public class WorldPackets {
|
||||
@ -132,22 +137,54 @@ public class WorldPackets {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
Chunk1_9to1_8Type type = new Chunk1_9to1_8Type(clientChunks);
|
||||
Chunk1_8 chunk = (Chunk1_8) wrapper.read(type);
|
||||
if (chunk.isUnloadPacket()) {
|
||||
wrapper.setPacketType(ClientboundPackets1_9.UNLOAD_CHUNK);
|
||||
Chunk chunk = wrapper.read(new Chunk1_8Type(clientWorld));
|
||||
|
||||
// Check if the chunk should be handled as an unload packet
|
||||
if (chunk.isFullChunk() && chunk.getBitmask() == 0) {
|
||||
wrapper.setPacketType(ClientboundPackets1_9.UNLOAD_CHUNK);
|
||||
wrapper.write(Type.INT, chunk.getX());
|
||||
wrapper.write(Type.INT, chunk.getZ());
|
||||
|
||||
// Remove commandBlocks on chunk unload
|
||||
CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class);
|
||||
provider.unloadChunk(wrapper.user(), chunk.getX(), chunk.getZ());
|
||||
|
||||
clientChunks.getLoadedChunks().remove(ClientChunks.toLong(chunk.getX(), chunk.getZ()));
|
||||
|
||||
// Unload the empty chunks
|
||||
if (Via.getConfig().isChunkBorderFix()) {
|
||||
for (BlockFace face : BlockFace.HORIZONTAL) {
|
||||
int chunkX = chunk.getX() + face.getModX();
|
||||
int chunkZ = chunk.getZ() + face.getModZ();
|
||||
if (!clientChunks.getLoadedChunks().contains(ClientChunks.toLong(chunkX, chunkZ))) {
|
||||
PacketWrapper unloadChunk = wrapper.create(ClientboundPackets1_9.UNLOAD_CHUNK);
|
||||
unloadChunk.write(Type.INT, chunkX);
|
||||
unloadChunk.write(Type.INT, chunkZ);
|
||||
unloadChunk.send(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wrapper.write(type, chunk);
|
||||
// eat any other data (Usually happens with unload packets)
|
||||
wrapper.write(new Chunk1_9_1_2Type(clientWorld), chunk);
|
||||
|
||||
clientChunks.getLoadedChunks().add(ClientChunks.toLong(chunk.getX(), chunk.getZ()));
|
||||
|
||||
// Send empty chunks surrounding the loaded chunk to force 1.9+ clients to render the new chunk
|
||||
if (Via.getConfig().isChunkBorderFix()) {
|
||||
for (BlockFace face : BlockFace.HORIZONTAL) {
|
||||
int chunkX = chunk.getX() + face.getModX();
|
||||
int chunkZ = chunk.getZ() + face.getModZ();
|
||||
if (!clientChunks.getLoadedChunks().contains(ClientChunks.toLong(chunkX, chunkZ))) {
|
||||
PacketWrapper emptyChunk = wrapper.create(ClientboundPackets1_9.CHUNK_DATA);
|
||||
Chunk c = new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], new int[256], new ArrayList<>());
|
||||
emptyChunk.write(new Chunk1_9_1_2Type(wrapper.user().get(ClientWorld.class)), c);
|
||||
emptyChunk.send(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wrapper.read(Type.REMAINING_BYTES);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -158,41 +195,29 @@ public class WorldPackets {
|
||||
public void registerMap() {
|
||||
handler(wrapper -> {
|
||||
wrapper.cancel(); // Cancel the packet from being sent
|
||||
|
||||
boolean skyLight = wrapper.read(Type.BOOLEAN);
|
||||
int count = wrapper.read(Type.VAR_INT);
|
||||
|
||||
ChunkBulkSection[] chunks = new ChunkBulkSection[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
chunks[i] = new ChunkBulkSection(wrapper, skyLight);
|
||||
}
|
||||
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
for (ChunkBulkSection chunk : chunks) {
|
||||
// Data is at the end
|
||||
CustomByteType customByteType = new CustomByteType(chunk.getLength());
|
||||
chunk.setData(wrapper.read(customByteType));
|
||||
Chunk[] chunks = wrapper.read(new ChunkBulk1_8Type(clientWorld));
|
||||
|
||||
clientChunks.getBulkChunks().add(ClientChunks.toLong(chunk.getX(), chunk.getZ())); // Store for later
|
||||
// Split into multiple chunk packets
|
||||
for (Chunk chunk : chunks) {
|
||||
PacketWrapper chunkData = wrapper.create(ClientboundPackets1_9.CHUNK_DATA);
|
||||
chunkData.write(new Chunk1_9_1_2Type(clientWorld), chunk);
|
||||
chunkData.send(Protocol1_9To1_8.class);
|
||||
|
||||
// Construct chunk packet
|
||||
ByteBuf buffer = null;
|
||||
try {
|
||||
buffer = wrapper.user().getChannel().alloc().buffer();
|
||||
clientChunks.getLoadedChunks().add(ClientChunks.toLong(chunk.getX(), chunk.getZ()));
|
||||
|
||||
Type.INT.write(buffer, chunk.getX());
|
||||
Type.INT.write(buffer, chunk.getZ());
|
||||
Type.BOOLEAN.write(buffer, true); // Always ground-up
|
||||
Type.UNSIGNED_SHORT.write(buffer, chunk.getBitMask());
|
||||
Type.VAR_INT.writePrimitive(buffer, chunk.getLength());
|
||||
customByteType.write(buffer, chunk.getData());
|
||||
|
||||
// Send through this protocol again
|
||||
PacketWrapper chunkPacket = PacketWrapper.create(ClientboundPackets1_8.CHUNK_DATA, buffer, wrapper.user());
|
||||
chunkPacket.send(Protocol1_9To1_8.class, false);
|
||||
} finally {
|
||||
if (buffer != null) {
|
||||
buffer.release();
|
||||
// Send empty chunks surrounding the loaded chunk to force 1.9+ clients to render the new chunk
|
||||
if (Via.getConfig().isChunkBorderFix()) {
|
||||
for (BlockFace face : BlockFace.HORIZONTAL) {
|
||||
int chunkX = chunk.getX() + face.getModX();
|
||||
int chunkZ = chunk.getZ() + face.getModZ();
|
||||
if (!clientChunks.getLoadedChunks().contains(ClientChunks.toLong(chunkX, chunkZ))) {
|
||||
PacketWrapper emptyChunk = wrapper.create(ClientboundPackets1_9.CHUNK_DATA);
|
||||
Chunk c = new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], new int[256], new ArrayList<>());
|
||||
emptyChunk.write(new Chunk1_9_1_2Type(wrapper.user().get(ClientWorld.class)), c);
|
||||
emptyChunk.send(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,14 +262,6 @@ public class WorldPackets {
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.POSITION);
|
||||
map(Type.VAR_INT);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* Incoming Packets */
|
||||
protocol.registerServerbound(ServerboundPackets1_9.UPDATE_SIGN, new PacketRemapper() {
|
||||
|
@ -25,21 +25,17 @@ import java.util.Set;
|
||||
|
||||
public class ClientChunks extends StoredObject {
|
||||
private final Set<Long> loadedChunks = Sets.newConcurrentHashSet();
|
||||
private final Set<Long> bulkChunks = Sets.newConcurrentHashSet();
|
||||
|
||||
public ClientChunks(UserConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
public static long toLong(int msw, int lsw) {
|
||||
return ((long) msw << 32) + lsw - -2147483648L;
|
||||
return ((long) msw << 32) + lsw + 2147483648L;
|
||||
}
|
||||
|
||||
public Set<Long> getLoadedChunks() {
|
||||
return loadedChunks;
|
||||
}
|
||||
|
||||
public Set<Long> getBulkChunks() {
|
||||
return bulkChunks;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.protocols.protocol1_9to1_8.types;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.Environment;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.type.PartialType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_8;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Chunk1_8Type extends PartialType<Chunk, ClientWorld> {
|
||||
|
||||
public Chunk1_8Type(ClientWorld param) {
|
||||
super(param, Chunk.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf input, ClientWorld world) throws Exception {
|
||||
final int chunkX = input.readInt();
|
||||
final int chunkZ = input.readInt();
|
||||
final boolean fullChunk = input.readBoolean();
|
||||
final int bitmask = input.readUnsignedShort();
|
||||
final int dataLength = Type.VAR_INT.readPrimitive(input);
|
||||
final byte[] data = new byte[dataLength];
|
||||
input.readBytes(data);
|
||||
|
||||
// Check if the chunk is an unload packet and return early
|
||||
if (fullChunk && bitmask == 0) {
|
||||
return new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>());
|
||||
}
|
||||
|
||||
return deserialize(chunkX, chunkZ, fullChunk, world.getEnvironment() == Environment.NORMAL, bitmask, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception {
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
output.writeBoolean(chunk.isFullChunk());
|
||||
output.writeShort(chunk.getBitmask());
|
||||
final byte[] data = serialize(chunk);
|
||||
Type.VAR_INT.writePrimitive(output, data.length);
|
||||
output.writeBytes(data);
|
||||
}
|
||||
|
||||
// Used for normal and bulk chunks
|
||||
public static Chunk deserialize(final int chunkX, final int chunkZ, final boolean fullChunk, final boolean skyLight, final int bitmask, final byte[] data) throws Exception {
|
||||
final ByteBuf input = Unpooled.wrappedBuffer(data);
|
||||
|
||||
final ChunkSection[] sections = new ChunkSection[16];
|
||||
int[] biomeData = null;
|
||||
|
||||
// Read blocks
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((bitmask & 1 << i) == 0) continue;
|
||||
sections[i] = Types1_8.CHUNK_SECTION.read(input);
|
||||
}
|
||||
|
||||
// Read block light
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((bitmask & 1 << i) == 0) continue;
|
||||
sections[i].getLight().readBlockLight(input);
|
||||
}
|
||||
|
||||
// Read sky light
|
||||
if (skyLight) {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((bitmask & 1 << i) == 0) continue;
|
||||
sections[i].getLight().readSkyLight(input);
|
||||
}
|
||||
}
|
||||
|
||||
// Read biome data
|
||||
if (fullChunk) {
|
||||
biomeData = new int[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
biomeData[i] = input.readUnsignedByte();
|
||||
}
|
||||
}
|
||||
input.release();
|
||||
|
||||
return new BaseChunk(chunkX, chunkZ, fullChunk, false, bitmask, sections, biomeData, new ArrayList<>());
|
||||
}
|
||||
|
||||
// Used for normal and bulk chunks
|
||||
public static byte[] serialize(final Chunk chunk) throws Exception {
|
||||
final ByteBuf output = Unpooled.buffer();
|
||||
|
||||
// Write blocks
|
||||
for (int i = 0; i < chunk.getSections().length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) == 0) continue;
|
||||
Types1_8.CHUNK_SECTION.write(output, chunk.getSections()[i]);
|
||||
}
|
||||
|
||||
// Write block light
|
||||
for (int i = 0; i < chunk.getSections().length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) == 0) continue;
|
||||
chunk.getSections()[i].getLight().writeBlockLight(output);
|
||||
}
|
||||
|
||||
// Write sky light
|
||||
for (int i = 0; i < chunk.getSections().length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) == 0) continue;
|
||||
if (chunk.getSections()[i].getLight().hasSkyLight()) chunk.getSections()[i].getLight().writeSkyLight(output);
|
||||
}
|
||||
|
||||
// Write biome data
|
||||
if (chunk.isFullChunk() && chunk.getBiomeData() != null) {
|
||||
for (int biome : chunk.getBiomeData()) {
|
||||
output.writeByte((byte) biome);
|
||||
}
|
||||
}
|
||||
final byte[] data = new byte[output.readableBytes()];
|
||||
output.readBytes(data);
|
||||
output.release();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
/*
|
||||
* 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.protocols.protocol1_9to1_8.types;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_8;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight;
|
||||
import com.viaversion.viaversion.api.type.PartialType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_8;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_9;
|
||||
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class Chunk1_9to1_8Type extends PartialType<Chunk, ClientChunks> {
|
||||
/**
|
||||
* Amount of sections in a chunks.
|
||||
*/
|
||||
public static final int SECTION_COUNT = 16;
|
||||
/**
|
||||
* size of each chunks section (16x16x16).
|
||||
*/
|
||||
private static final int SECTION_SIZE = 16;
|
||||
/**
|
||||
* Length of biome data.
|
||||
*/
|
||||
private static final int BIOME_DATA_LENGTH = 256;
|
||||
|
||||
public Chunk1_9to1_8Type(ClientChunks chunks) {
|
||||
super(chunks, Chunk.class);
|
||||
}
|
||||
|
||||
private static long toLong(int msw, int lsw) {
|
||||
return ((long) msw << 32) + lsw - -2147483648L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf input, ClientChunks param) throws Exception {
|
||||
boolean replacePistons = param.getUser().getProtocolInfo().getPipeline().contains(Protocol1_10To1_9_3_4.class) && Via.getConfig().isReplacePistons();
|
||||
int replacementId = Via.getConfig().getPistonReplacementId();
|
||||
|
||||
int chunkX = input.readInt();
|
||||
int chunkZ = input.readInt();
|
||||
long chunkHash = toLong(chunkX, chunkZ);
|
||||
boolean fullChunk = input.readByte() != 0;
|
||||
int bitmask = input.readUnsignedShort();
|
||||
int dataLength = Type.VAR_INT.readPrimitive(input);
|
||||
|
||||
// Data to be read
|
||||
BitSet usedSections = new BitSet(16);
|
||||
ChunkSection[] sections = new ChunkSection[16];
|
||||
int[] biomeData = null;
|
||||
|
||||
// Calculate section count from bitmask
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0) {
|
||||
usedSections.set(i);
|
||||
}
|
||||
}
|
||||
int sectionCount = usedSections.cardinality(); // the amount of sections set
|
||||
|
||||
// If the chunks is from a chunks bulk, it is never an unload packet
|
||||
// Other wise, if it has no data, it is :)
|
||||
boolean isBulkPacket = param.getBulkChunks().remove(chunkHash);
|
||||
if (sectionCount == 0 && fullChunk && !isBulkPacket && param.getLoadedChunks().contains(chunkHash)) {
|
||||
// This is a chunks unload packet
|
||||
param.getLoadedChunks().remove(chunkHash);
|
||||
return new Chunk1_8(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
int startIndex = input.readerIndex();
|
||||
param.getLoadedChunks().add(chunkHash); // mark chunks as loaded
|
||||
|
||||
// Read blocks
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set
|
||||
ChunkSection section = Types1_8.CHUNK_SECTION.read(input);
|
||||
sections[i] = section;
|
||||
|
||||
if (replacePistons) {
|
||||
section.replacePaletteEntry(36, replacementId);
|
||||
}
|
||||
}
|
||||
|
||||
// Read block light
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set, has no light
|
||||
sections[i].getLight().readBlockLight(input);
|
||||
}
|
||||
|
||||
// Read sky light
|
||||
int bytesLeft = dataLength - (input.readerIndex() - startIndex);
|
||||
if (bytesLeft >= ChunkSectionLight.LIGHT_LENGTH) {
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set, has no light
|
||||
sections[i].getLight().readSkyLight(input);
|
||||
bytesLeft -= ChunkSectionLight.LIGHT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
// Read biome data
|
||||
if (bytesLeft >= BIOME_DATA_LENGTH) {
|
||||
biomeData = new int[BIOME_DATA_LENGTH];
|
||||
for (int i = 0; i < BIOME_DATA_LENGTH; i++) {
|
||||
biomeData[i] = input.readByte() & 0xFF;
|
||||
}
|
||||
bytesLeft -= BIOME_DATA_LENGTH;
|
||||
}
|
||||
|
||||
// Check remaining bytes
|
||||
if (bytesLeft > 0) {
|
||||
Via.getPlatform().getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunks! (" + fullChunk + ")");
|
||||
}
|
||||
|
||||
// Return chunks
|
||||
return new Chunk1_8(chunkX, chunkZ, fullChunk, bitmask, sections, biomeData, new ArrayList<CompoundTag>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, ClientChunks param, Chunk input) throws Exception {
|
||||
if (!(input instanceof Chunk1_8)) throw new Exception("Incompatible chunk, " + input.getClass());
|
||||
|
||||
Chunk1_8 chunk = (Chunk1_8) input;
|
||||
// Write primary info
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
if (chunk.isUnloadPacket()) return;
|
||||
output.writeByte(chunk.isFullChunk() ? 0x01 : 0x00);
|
||||
Type.VAR_INT.writePrimitive(output, chunk.getBitmask());
|
||||
|
||||
ByteBuf buf = output.alloc().buffer();
|
||||
try {
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
ChunkSection section = chunk.getSections()[i];
|
||||
if (section == null) continue; // Section not set
|
||||
Types1_9.CHUNK_SECTION.write(buf, section);
|
||||
section.getLight().writeBlockLight(buf);
|
||||
|
||||
if (!section.getLight().hasSkyLight()) continue; // No sky light, we're done here.
|
||||
section.getLight().writeSkyLight(buf);
|
||||
}
|
||||
buf.readerIndex(0);
|
||||
Type.VAR_INT.writePrimitive(output, buf.readableBytes() + (chunk.hasBiomeData() ? 256 : 0));
|
||||
output.writeBytes(buf);
|
||||
} finally {
|
||||
buf.release(); // release buffer
|
||||
}
|
||||
|
||||
// Write biome data
|
||||
if (chunk.hasBiomeData()) {
|
||||
for (int biome : chunk.getBiomeData()) {
|
||||
output.writeByte((byte) biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.protocols.protocol1_9to1_8.types;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.type.PartialType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkBulkType;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ChunkBulk1_8Type extends PartialType<Chunk[], ClientWorld> {
|
||||
|
||||
private static final int BLOCKS_PER_SECTION = 16 * 16 * 16;
|
||||
private static final int BLOCKS_BYTES = BLOCKS_PER_SECTION * 2;
|
||||
private static final int LIGHT_BYTES = BLOCKS_PER_SECTION / 2;
|
||||
private static final int BIOME_BYTES = 16 * 16;
|
||||
|
||||
public ChunkBulk1_8Type(final ClientWorld clientWorld) {
|
||||
super(clientWorld, Chunk[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkBulkType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk[] read(ByteBuf input, ClientWorld world) throws Exception {
|
||||
final boolean skyLight = input.readBoolean();
|
||||
final int count = Type.VAR_INT.readPrimitive(input);
|
||||
final Chunk[] chunks = new Chunk[count];
|
||||
final ChunkBulkSection[] chunkInfo = new ChunkBulkSection[count];
|
||||
|
||||
// Read metadata
|
||||
for (int i = 0; i < chunkInfo.length; i++) {
|
||||
chunkInfo[i] = new ChunkBulkSection(input, skyLight);
|
||||
}
|
||||
// Read data
|
||||
for (int i = 0; i < chunks.length; i++) {
|
||||
final ChunkBulkSection chunkBulkSection = chunkInfo[i];
|
||||
chunkBulkSection.readData(input);
|
||||
chunks[i] = Chunk1_8Type.deserialize(chunkBulkSection.chunkX, chunkBulkSection.chunkZ, true, skyLight, chunkBulkSection.bitmask, chunkBulkSection.getData());
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, ClientWorld world, Chunk[] chunks) throws Exception {
|
||||
boolean skyLight = false;
|
||||
for (Chunk c : chunks) {
|
||||
for (ChunkSection section : c.getSections()) {
|
||||
if (section != null) {
|
||||
if (section.getLight().hasSkyLight()) {
|
||||
skyLight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output.writeBoolean(skyLight);
|
||||
Type.VAR_INT.writePrimitive(output, chunks.length);
|
||||
|
||||
// Write metadata
|
||||
for (Chunk c : chunks) {
|
||||
output.writeInt(c.getX());
|
||||
output.writeInt(c.getZ());
|
||||
output.writeShort(c.getBitmask());
|
||||
}
|
||||
// Write data
|
||||
for (Chunk c : chunks) {
|
||||
output.writeBytes(Chunk1_8Type.serialize(c));
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ChunkBulkSection {
|
||||
private final int chunkX;
|
||||
private final int chunkZ;
|
||||
private final int bitmask;
|
||||
private final byte[] data;
|
||||
|
||||
public ChunkBulkSection(final ByteBuf input, final boolean skyLight) {
|
||||
this.chunkX = input.readInt();
|
||||
this.chunkZ = input.readInt();
|
||||
this.bitmask = input.readUnsignedShort();
|
||||
final int setSections = Integer.bitCount(this.bitmask);
|
||||
this.data = new byte[setSections * (BLOCKS_BYTES + (skyLight ? 2 * LIGHT_BYTES : LIGHT_BYTES)) + BIOME_BYTES];
|
||||
}
|
||||
|
||||
public void readData(final ByteBuf input) {
|
||||
input.readBytes(this.data);
|
||||
}
|
||||
|
||||
public int getChunkX() {
|
||||
return this.chunkX;
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return this.chunkZ;
|
||||
}
|
||||
|
||||
public int getBitmask() {
|
||||
return this.bitmask;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -276,7 +276,7 @@ public abstract class EntityRewriter<T extends Protocol> extends RewriterBase<T>
|
||||
* @param entityType entity type
|
||||
* @param intType int type of the entity id
|
||||
*/
|
||||
public void registerTracker(ClientboundPacketType packetType, EntityType entityType, Type<?> intType) {
|
||||
public void registerTracker(ClientboundPacketType packetType, EntityType entityType, Type<? extends Integer> intType) {
|
||||
protocol.registerClientbound(packetType, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
|
@ -197,6 +197,8 @@ anti-xray-patch: true
|
||||
replace-pistons: false
|
||||
# What id should we replace with, default is air. (careful of players getting stuck standing on them)
|
||||
replacement-piston-id: 0
|
||||
# Fix 1.9+ clients not rendering the far away chunks and improve chunk rendering when moving fast (Increases network usage and decreases client fps slightly)
|
||||
chunk-border-fix: false
|
||||
# Force the string -> json transform
|
||||
force-json-transform: false
|
||||
# Minimize the cooldown animation in 1.8 servers
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren