2021-03-22 23:06:40 +01:00
|
|
|
/*
|
|
|
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
2023-01-12 12:45:53 +01:00
|
|
|
* Copyright (C) 2016-2023 ViaVersion and contributors
|
2021-03-22 23:06:40 +01:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
2021-04-26 20:52:34 +02:00
|
|
|
package com.viaversion.viaversion.protocols.protocol1_13to1_12_2.packets;
|
2017-12-12 00:39:34 +01:00
|
|
|
|
2018-01-06 15:23:49 +01:00
|
|
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
2021-03-15 10:28:29 +01:00
|
|
|
import com.github.steveice10.opennbt.tag.builtin.NumberTag;
|
2021-12-01 19:54:43 +01:00
|
|
|
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
|
|
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.api.Via;
|
2021-04-26 21:35:29 +02:00
|
|
|
import com.viaversion.viaversion.api.connection.UserConnection;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
|
|
|
|
import com.viaversion.viaversion.api.minecraft.Position;
|
|
|
|
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
|
|
|
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
2022-10-04 13:25:55 +02:00
|
|
|
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
|
|
|
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.Protocol;
|
2021-04-27 13:41:39 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
2021-04-26 21:16:10 +02:00
|
|
|
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
|
2021-04-26 20:52:34 +02:00
|
|
|
import com.viaversion.viaversion.api.type.Type;
|
|
|
|
import com.viaversion.viaversion.api.type.types.Particle;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.ConnectionData;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.ConnectionHandler;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.NamedSoundRewriter;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.ParticleRewriter;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.BlockEntityProvider;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.PaintingProvider;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
|
|
|
|
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type;
|
|
|
|
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.storage.ClientWorld;
|
2021-04-27 13:41:39 +02:00
|
|
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
|
|
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
2017-12-12 00:39:34 +01:00
|
|
|
|
2021-12-01 19:54:43 +01:00
|
|
|
import java.util.Iterator;
|
2018-07-21 11:18:14 +02:00
|
|
|
import java.util.List;
|
2019-09-21 11:57:28 +02:00
|
|
|
import java.util.Optional;
|
2018-07-21 11:18:14 +02:00
|
|
|
|
2017-12-12 00:39:34 +01:00
|
|
|
public class WorldPackets {
|
2021-10-07 12:26:14 +02:00
|
|
|
private static final IntSet VALID_BIOMES = new IntOpenHashSet(70, .99F);
|
2018-08-05 22:45:22 +02:00
|
|
|
|
|
|
|
static {
|
|
|
|
// Client will crash if it receives a invalid biome id
|
|
|
|
for (int i = 0; i < 50; i++) {
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(i);
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(127);
|
2018-08-05 22:45:22 +02:00
|
|
|
for (int i = 129; i <= 134; i++) {
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(i);
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(140);
|
|
|
|
VALID_BIOMES.add(149);
|
|
|
|
VALID_BIOMES.add(151);
|
2018-08-05 22:45:22 +02:00
|
|
|
for (int i = 155; i <= 158; i++) {
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(i);
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
|
|
|
for (int i = 160; i <= 167; i++) {
|
2020-06-08 12:27:34 +02:00
|
|
|
VALID_BIOMES.add(i);
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-04 19:42:26 +01:00
|
|
|
public static void register(Protocol1_13To1_12_2 protocol) {
|
2017-12-12 00:39:34 +01:00
|
|
|
// Outgoing packets
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.SPAWN_PAINTING, new PacketRemapper() {
|
2018-01-11 16:14:34 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
map(Type.VAR_INT); // 0 - Entity ID
|
|
|
|
map(Type.UUID); // 1 - Entity UUID
|
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
PaintingProvider provider = Via.getManager().getProviders().get(PaintingProvider.class);
|
|
|
|
String motive = wrapper.read(Type.STRING);
|
2018-01-11 16:14:34 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
Optional<Integer> id = provider.getIntByIdentifier(motive);
|
2018-01-11 16:14:34 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
if (!id.isPresent() && (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug())) {
|
|
|
|
Via.getPlatform().getLogger().warning("Could not find painting motive: " + motive + " falling back to default (0)");
|
2018-01-11 16:14:34 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
wrapper.write(Type.VAR_INT, id.orElse(0));
|
2018-01-11 16:14:34 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.BLOCK_ENTITY_DATA, new PacketRemapper() {
|
2018-01-06 15:23:49 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
map(Type.POSITION); // 0 - Location
|
|
|
|
map(Type.UNSIGNED_BYTE); // 1 - Action
|
|
|
|
map(Type.NBT); // 2 - NBT data
|
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
Position position = wrapper.get(Type.POSITION, 0);
|
|
|
|
short action = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
|
|
|
CompoundTag tag = wrapper.get(Type.NBT, 0);
|
2018-01-06 15:23:49 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
BlockEntityProvider provider = Via.getManager().getProviders().get(BlockEntityProvider.class);
|
|
|
|
int newId = provider.transform(wrapper.user(), position, tag, true);
|
2018-01-06 15:23:49 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
if (newId != -1) {
|
|
|
|
BlockStorage storage = wrapper.user().get(BlockStorage.class);
|
|
|
|
BlockStorage.ReplacementData replacementData = storage.get(position);
|
|
|
|
if (replacementData != null) {
|
|
|
|
replacementData.setReplacement(newId);
|
2018-01-06 15:23:49 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
2018-04-19 21:29:50 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
if (action == 5) { // Set type of flower in flower pot
|
|
|
|
wrapper.cancel(); // Removed
|
2018-01-06 15:23:49 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2017-12-24 13:20:09 +01:00
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.BLOCK_ACTION, new PacketRemapper() {
|
2018-07-22 22:51:18 +02:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
map(Type.POSITION); // Location
|
|
|
|
map(Type.UNSIGNED_BYTE); // Action Id
|
|
|
|
map(Type.UNSIGNED_BYTE); // Action param
|
|
|
|
map(Type.VAR_INT); // Block Id - /!\ NOT BLOCK STATE ID
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
Position pos = wrapper.get(Type.POSITION, 0);
|
|
|
|
short action = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
|
|
|
short param = wrapper.get(Type.UNSIGNED_BYTE, 1);
|
|
|
|
int blockId = wrapper.get(Type.VAR_INT, 0);
|
|
|
|
|
|
|
|
if (blockId == 25)
|
|
|
|
blockId = 73;
|
|
|
|
else if (blockId == 33)
|
|
|
|
blockId = 99;
|
|
|
|
else if (blockId == 29)
|
|
|
|
blockId = 92;
|
|
|
|
else if (blockId == 54)
|
|
|
|
blockId = 142;
|
|
|
|
else if (blockId == 146)
|
|
|
|
blockId = 305;
|
|
|
|
else if (blockId == 130)
|
|
|
|
blockId = 249;
|
|
|
|
else if (blockId == 138)
|
|
|
|
blockId = 257;
|
|
|
|
else if (blockId == 52)
|
|
|
|
blockId = 140;
|
|
|
|
else if (blockId == 209)
|
|
|
|
blockId = 472;
|
|
|
|
else if (blockId >= 219 && blockId <= 234)
|
|
|
|
blockId = blockId - 219 + 483;
|
|
|
|
|
|
|
|
if (blockId == 73) { // Note block
|
|
|
|
PacketWrapper blockChange = wrapper.create(0x0B); // block change
|
|
|
|
blockChange.write(Type.POSITION, pos);
|
|
|
|
blockChange.write(Type.VAR_INT, 249 + (action * 24 * 2) + (param * 2));
|
|
|
|
blockChange.send(Protocol1_13To1_12_2.class);
|
2018-07-22 22:51:18 +02:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
wrapper.set(Type.VAR_INT, 0, blockId);
|
2018-07-22 22:51:18 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.BLOCK_CHANGE, new PacketRemapper() {
|
2017-12-12 00:39:34 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
map(Type.POSITION);
|
|
|
|
map(Type.VAR_INT);
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
Position position = wrapper.get(Type.POSITION, 0);
|
|
|
|
int newId = toNewId(wrapper.get(Type.VAR_INT, 0));
|
2018-01-06 15:23:49 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
UserConnection userConnection = wrapper.user();
|
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
2018-11-17 15:45:37 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
ConnectionData.updateBlockStorage(userConnection, position.x(), position.y(), position.z(), newId);
|
|
|
|
newId = ConnectionData.connect(userConnection, position, newId);
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
wrapper.set(Type.VAR_INT, 0, checkStorage(wrapper.user(), position, newId));
|
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
|
|
|
// Workaround for packet order issue
|
|
|
|
wrapper.send(Protocol1_13To1_12_2.class);
|
|
|
|
wrapper.cancel();
|
|
|
|
ConnectionData.update(userConnection, position);
|
|
|
|
}
|
|
|
|
|
2017-12-12 00:39:34 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2017-12-24 13:20:09 +01:00
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.MULTI_BLOCK_CHANGE, new PacketRemapper() {
|
2017-12-12 00:39:34 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
2018-01-06 15:23:49 +01:00
|
|
|
map(Type.INT); // 0 - Chunk X
|
|
|
|
map(Type.INT); // 1 - Chunk Z
|
|
|
|
map(Type.BLOCK_CHANGE_RECORD_ARRAY); // 2 - Records
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
int chunkX = wrapper.get(Type.INT, 0);
|
|
|
|
int chunkZ = wrapper.get(Type.INT, 1);
|
|
|
|
UserConnection userConnection = wrapper.user();
|
|
|
|
BlockChangeRecord[] records = wrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0);
|
|
|
|
// Convert ids
|
|
|
|
for (BlockChangeRecord record : records) {
|
|
|
|
int newBlock = toNewId(record.getBlockId());
|
|
|
|
Position position = new Position(
|
|
|
|
record.getSectionX() + (chunkX * 16),
|
|
|
|
record.getY(),
|
|
|
|
record.getSectionZ() + (chunkZ * 16));
|
|
|
|
|
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
|
|
|
ConnectionData.updateBlockStorage(userConnection, position.x(), position.y(), position.z(), newBlock);
|
|
|
|
}
|
|
|
|
record.setBlockId(checkStorage(wrapper.user(), position, newBlock));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
2019-02-24 19:02:09 +01:00
|
|
|
for (BlockChangeRecord record : records) {
|
2022-08-15 11:58:57 +02:00
|
|
|
int blockState = record.getBlockId();
|
|
|
|
|
2018-01-06 15:23:49 +01:00
|
|
|
Position position = new Position(
|
2020-07-08 21:01:18 +02:00
|
|
|
record.getSectionX() + (chunkX * 16),
|
2019-11-22 19:13:02 +01:00
|
|
|
record.getY(),
|
2020-07-08 21:01:18 +02:00
|
|
|
record.getSectionZ() + (chunkZ * 16));
|
2018-11-17 15:45:37 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
ConnectionHandler handler = ConnectionData.getConnectionHandler(blockState);
|
|
|
|
if (handler != null) {
|
|
|
|
blockState = handler.connect(userConnection, position, blockState);
|
|
|
|
record.setBlockId(blockState);
|
2018-11-17 15:45:37 +01:00
|
|
|
}
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
// Workaround for packet order issue
|
|
|
|
wrapper.send(Protocol1_13To1_12_2.class);
|
|
|
|
wrapper.cancel();
|
2018-11-17 15:45:37 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
for (BlockChangeRecord record : records) {
|
|
|
|
Position position = new Position(
|
|
|
|
record.getSectionX() + (chunkX * 16),
|
|
|
|
record.getY(),
|
|
|
|
record.getSectionZ() + (chunkZ * 16));
|
|
|
|
ConnectionData.update(userConnection, position);
|
2018-11-17 15:45:37 +01:00
|
|
|
}
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
|
2017-12-12 00:39:34 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.EXPLOSION, new PacketRemapper() {
|
2020-05-05 19:49:59 +02:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
if (!Via.getConfig().isServersideBlockConnections())
|
|
|
|
return;
|
|
|
|
|
|
|
|
map(Type.FLOAT); // X
|
|
|
|
map(Type.FLOAT); // Y
|
|
|
|
map(Type.FLOAT); // Z
|
|
|
|
map(Type.FLOAT); // Radius
|
|
|
|
map(Type.INT); // Record Count
|
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
UserConnection userConnection = wrapper.user();
|
|
|
|
int x = (int) Math.floor(wrapper.get(Type.FLOAT, 0));
|
|
|
|
int y = (int) Math.floor(wrapper.get(Type.FLOAT, 1));
|
|
|
|
int z = (int) Math.floor(wrapper.get(Type.FLOAT, 2));
|
|
|
|
int recordCount = wrapper.get(Type.INT, 0);
|
|
|
|
Position[] records = new Position[recordCount];
|
|
|
|
|
|
|
|
for (int i = 0; i < recordCount; i++) {
|
|
|
|
Position position = new Position(
|
|
|
|
x + wrapper.passthrough(Type.BYTE),
|
|
|
|
(short) (y + wrapper.passthrough(Type.BYTE)),
|
|
|
|
z + wrapper.passthrough(Type.BYTE));
|
|
|
|
records[i] = position;
|
|
|
|
|
|
|
|
// Set to air
|
|
|
|
ConnectionData.updateBlockStorage(userConnection, position.x(), position.y(), position.z(), 0);
|
|
|
|
}
|
2020-05-05 19:49:59 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
// Workaround for packet order issue
|
|
|
|
wrapper.send(Protocol1_13To1_12_2.class);
|
|
|
|
wrapper.cancel();
|
2020-05-05 19:49:59 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
for (int i = 0; i < recordCount; i++) {
|
|
|
|
ConnectionData.update(userConnection, records[i]);
|
2020-05-05 19:49:59 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.UNLOAD_CHUNK, new PacketRemapper() {
|
2018-11-17 15:45:37 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
2018-12-05 20:08:55 +01:00
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
int x = wrapper.passthrough(Type.INT);
|
|
|
|
int z = wrapper.passthrough(Type.INT);
|
|
|
|
ConnectionData.blockConnectionProvider.unloadChunk(wrapper.user(), x, z);
|
2018-11-17 15:45:37 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.NAMED_SOUND, new PacketRemapper() {
|
2018-07-22 20:15:40 +02:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
|
|
|
map(Type.STRING);
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
String sound = wrapper.get(Type.STRING, 0).replace("minecraft:", "");
|
|
|
|
String newSoundId = NamedSoundRewriter.getNewId(sound);
|
|
|
|
wrapper.set(Type.STRING, 0, newSoundId);
|
2018-07-22 20:15:40 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2017-12-12 00:39:34 +01:00
|
|
|
|
2021-04-28 12:59:37 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.CHUNK_DATA, new PacketRemapper() {
|
2017-12-12 00:39:34 +01:00
|
|
|
@Override
|
|
|
|
public void registerMap() {
|
2022-08-15 11:58:57 +02:00
|
|
|
handler(wrapper -> {
|
|
|
|
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
|
|
|
BlockStorage storage = wrapper.user().get(BlockStorage.class);
|
|
|
|
|
|
|
|
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld);
|
|
|
|
Chunk1_13Type type1_13 = new Chunk1_13Type(clientWorld);
|
|
|
|
Chunk chunk = wrapper.read(type);
|
|
|
|
wrapper.write(type1_13, chunk);
|
|
|
|
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int s = 0; s < chunk.getSections().length; s++) {
|
|
|
|
ChunkSection section = chunk.getSections()[s];
|
|
|
|
if (section == null) continue;
|
|
|
|
DataPalette blocks = section.palette(PaletteType.BLOCKS);
|
2022-08-15 11:58:57 +02:00
|
|
|
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int p = 0; p < blocks.size(); p++) {
|
|
|
|
int old = blocks.idByIndex(p);
|
2022-08-15 11:58:57 +02:00
|
|
|
int newId = toNewId(old);
|
2022-10-04 13:25:55 +02:00
|
|
|
blocks.setIdByIndex(p, newId);
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
2019-02-23 13:01:40 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
storage:
|
|
|
|
{
|
|
|
|
if (chunk.isFullChunk()) {
|
|
|
|
boolean willSave = false;
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int p = 0; p < blocks.size(); p++) {
|
|
|
|
if (storage.isWelcome(blocks.idByIndex(p))) {
|
2022-08-15 11:58:57 +02:00
|
|
|
willSave = true;
|
2019-02-23 13:01:40 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
if (!willSave) break storage;
|
2019-02-23 13:01:40 +01:00
|
|
|
}
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int idx = 0; idx < ChunkSection.SIZE; idx++) {
|
|
|
|
int id = blocks.idAt(idx);
|
|
|
|
if (storage.isWelcome(id)) {
|
|
|
|
storage.store(new Position(ChunkSection.xFromIndex(idx) + (chunk.getX() << 4), ChunkSection.yFromIndex(idx) + (s << 4), ChunkSection.zFromIndex(idx) + (chunk.getZ() << 4)), id);
|
|
|
|
} else if (!chunk.isFullChunk()) { // Update
|
|
|
|
storage.remove(new Position(ChunkSection.xFromIndex(idx) + (chunk.getX() << 4), ChunkSection.yFromIndex(idx) + (s << 4), ChunkSection.zFromIndex(idx) + (chunk.getZ() << 4)));
|
2019-02-23 13:01:40 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
save_connections:
|
|
|
|
{
|
2022-10-04 13:25:55 +02:00
|
|
|
if (!Via.getConfig().isServersideBlockConnections() || !ConnectionData.needStoreBlocks()) break save_connections;
|
2019-02-23 13:01:40 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
if (!chunk.isFullChunk()) { // Update
|
2022-10-04 13:25:55 +02:00
|
|
|
ConnectionData.blockConnectionProvider.unloadChunkSection(wrapper.user(), chunk.getX(), s, chunk.getZ());
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
|
|
|
boolean willSave = false;
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int p = 0; p < blocks.size(); p++) {
|
|
|
|
if (ConnectionData.isWelcome(blocks.idByIndex(p))) {
|
2022-08-15 11:58:57 +02:00
|
|
|
willSave = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!willSave) break save_connections;
|
|
|
|
|
2022-10-04 13:25:55 +02:00
|
|
|
for (int idx = 0; idx < ChunkSection.SIZE; idx++) {
|
|
|
|
int id = blocks.idAt(idx);
|
|
|
|
if (ConnectionData.isWelcome(id)) {
|
|
|
|
int globalX = ChunkSection.xFromIndex(idx) + (chunk.getX() << 4);
|
|
|
|
int globalY = ChunkSection.yFromIndex(idx) + (s << 4);
|
|
|
|
int globalZ = ChunkSection.zFromIndex(idx) + (chunk.getZ() << 4);
|
|
|
|
ConnectionData.blockConnectionProvider.storeBlock(wrapper.user(), globalX, globalY, globalZ, id);
|
2018-01-06 15:23:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
2018-01-06 15:23:49 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
// Rewrite biome id 255 to plains
|
|
|
|
if (chunk.isBiomeData()) {
|
|
|
|
int latestBiomeWarn = Integer.MIN_VALUE;
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
int biome = chunk.getBiomeData()[i];
|
|
|
|
if (!VALID_BIOMES.contains(biome)) {
|
|
|
|
if (biome != 255 // is it generated naturally? *shrug*
|
|
|
|
&& latestBiomeWarn != biome) {
|
|
|
|
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
|
|
|
|
Via.getPlatform().getLogger().warning("Received invalid biome id " + biome);
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
latestBiomeWarn = biome;
|
2018-08-05 22:45:22 +02:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
chunk.getBiomeData()[i] = 1; // Plains
|
2018-07-20 15:26:56 +02:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
}
|
2018-07-20 15:26:56 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
// Rewrite BlockEntities to normal blocks
|
|
|
|
BlockEntityProvider provider = Via.getManager().getProviders().get(BlockEntityProvider.class);
|
|
|
|
final Iterator<CompoundTag> iterator = chunk.getBlockEntities().iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
|
|
CompoundTag tag = iterator.next();
|
|
|
|
int newId = provider.transform(wrapper.user(), null, tag, false);
|
|
|
|
if (newId != -1) {
|
|
|
|
int x = ((NumberTag) tag.get("x")).asInt();
|
|
|
|
int y = ((NumberTag) tag.get("y")).asInt();
|
|
|
|
int z = ((NumberTag) tag.get("z")).asInt();
|
2018-01-06 15:23:49 +01:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
Position position = new Position(x, (short) y, z);
|
|
|
|
// Store the replacement blocks for blockupdates
|
|
|
|
BlockStorage.ReplacementData replacementData = storage.get(position);
|
|
|
|
if (replacementData != null) {
|
|
|
|
replacementData.setReplacement(newId);
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2021-12-01 19:54:43 +01:00
|
|
|
|
2023-02-04 19:42:26 +01:00
|
|
|
chunk.getSections()[y >> 4].palette(PaletteType.BLOCKS).setIdAt(x & 0xF, y & 0xF, z & 0xF, newId);
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2019-04-27 18:03:53 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
final Tag idTag = tag.get("id");
|
|
|
|
if (idTag instanceof StringTag) {
|
|
|
|
// No longer block entities
|
|
|
|
final String id = ((StringTag) idTag).getValue();
|
|
|
|
if (id.equals("minecraft:noteblock") || id.equals("minecraft:flower_pot")) {
|
|
|
|
iterator.remove();
|
2019-04-27 19:03:48 +02:00
|
|
|
}
|
2019-04-27 18:03:53 +02:00
|
|
|
}
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2022-08-15 11:58:57 +02:00
|
|
|
|
|
|
|
if (Via.getConfig().isServersideBlockConnections()) {
|
|
|
|
ConnectionData.connectBlocks(wrapper.user(), chunk);
|
|
|
|
// Workaround for packet order issue
|
|
|
|
wrapper.send(Protocol1_13To1_12_2.class);
|
|
|
|
wrapper.cancel();
|
|
|
|
for (int i = 0; i < chunk.getSections().length; i++) {
|
|
|
|
ChunkSection section = chunk.getSections()[i];
|
|
|
|
if (section == null) continue;
|
|
|
|
ConnectionData.updateChunkSectionNeighbours(wrapper.user(), chunk.getX(), chunk.getZ(), i);
|
|
|
|
}
|
|
|
|
}
|
2017-12-12 00:39:34 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
protocol.registerClientbound(ClientboundPackets1_12_1.SPAWN_PARTICLE, new
|
|
|
|
|
|
|
|
PacketRemapper() {
|
2017-12-12 00:39:34 +01:00
|
|
|
@Override
|
2022-08-15 11:58:57 +02:00
|
|
|
public void registerMap() {
|
|
|
|
map(Type.INT); // 0 - Particle ID
|
|
|
|
map(Type.BOOLEAN); // 1 - Long Distance
|
|
|
|
map(Type.FLOAT); // 2 - X
|
|
|
|
map(Type.FLOAT); // 3 - Y
|
|
|
|
map(Type.FLOAT); // 4 - Z
|
|
|
|
map(Type.FLOAT); // 5 - Offset X
|
|
|
|
map(Type.FLOAT); // 6 - Offset Y
|
|
|
|
map(Type.FLOAT); // 7 - Offset Z
|
|
|
|
map(Type.FLOAT); // 8 - Particle Data
|
|
|
|
map(Type.INT); // 9 - Particle Count
|
|
|
|
|
|
|
|
handler(wrapper -> {
|
|
|
|
int particleId = wrapper.get(Type.INT, 0);
|
|
|
|
|
|
|
|
// Get the data (Arrays are overrated)
|
|
|
|
int dataCount = 0;
|
|
|
|
// Particles with 1 data [BlockCrack,BlockDust,FallingDust]
|
|
|
|
if (particleId == 37 || particleId == 38 || particleId == 46)
|
|
|
|
dataCount = 1;
|
|
|
|
// Particles with 2 data [IconCrack]
|
|
|
|
else if (particleId == 36)
|
|
|
|
dataCount = 2;
|
|
|
|
|
|
|
|
Integer[] data = new Integer[dataCount];
|
|
|
|
for (int i = 0; i < data.length; i++)
|
|
|
|
data[i] = wrapper.read(Type.VAR_INT);
|
|
|
|
|
|
|
|
Particle particle = ParticleRewriter.rewriteParticle(particleId, data);
|
|
|
|
|
|
|
|
// Cancel if null or completely removed
|
|
|
|
if (particle == null || particle.getId() == -1) {
|
|
|
|
wrapper.cancel();
|
|
|
|
return;
|
|
|
|
}
|
2018-04-04 21:09:54 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
//Handle reddust particle color
|
|
|
|
if (particle.getId() == 11) {
|
|
|
|
int count = wrapper.get(Type.INT, 1);
|
|
|
|
float speed = wrapper.get(Type.FLOAT, 6);
|
|
|
|
// Only handle for count = 0
|
|
|
|
if (count == 0) {
|
|
|
|
wrapper.set(Type.INT, 1, 1);
|
|
|
|
wrapper.set(Type.FLOAT, 6, 0f);
|
|
|
|
|
|
|
|
List<Particle.ParticleData> arguments = particle.getArguments();
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
//RGB values are represented by the X/Y/Z offset
|
|
|
|
float colorValue = wrapper.get(Type.FLOAT, i + 3) * speed;
|
|
|
|
if (colorValue == 0 && i == 0) {
|
|
|
|
// https://minecraft.gamepedia.com/User:Alphappy/reddust
|
|
|
|
colorValue = 1;
|
|
|
|
}
|
|
|
|
arguments.get(i).setValue(colorValue);
|
|
|
|
wrapper.set(Type.FLOAT, i + 3, 0f);
|
2019-02-02 14:21:19 +01:00
|
|
|
}
|
2018-07-29 13:14:17 +02:00
|
|
|
}
|
2018-07-21 11:18:14 +02:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
wrapper.set(Type.INT, 0, particle.getId());
|
|
|
|
for (Particle.ParticleData particleData : particle.getArguments())
|
|
|
|
wrapper.write(particleData.getType(), particleData.getValue());
|
2018-04-04 21:09:54 +02:00
|
|
|
|
2022-08-15 11:58:57 +02:00
|
|
|
});
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-24 13:20:09 +01:00
|
|
|
public static int toNewId(int oldId) {
|
2018-07-29 12:48:38 +02:00
|
|
|
if (oldId < 0) {
|
|
|
|
oldId = 0; // Some plugins use negative numbers to clear blocks, remap them to air.
|
|
|
|
}
|
2020-08-16 16:24:06 +02:00
|
|
|
int newId = Protocol1_13To1_12_2.MAPPINGS.getBlockMappings().getNewId(oldId);
|
2018-07-23 00:03:22 +02:00
|
|
|
if (newId != -1) {
|
2018-04-21 16:11:12 +02:00
|
|
|
return newId;
|
|
|
|
}
|
2020-08-16 16:24:06 +02:00
|
|
|
newId = Protocol1_13To1_12_2.MAPPINGS.getBlockMappings().getNewId(oldId & ~0xF); // Remove data
|
2018-07-23 00:03:22 +02:00
|
|
|
if (newId != -1) {
|
2019-11-26 20:14:56 +01:00
|
|
|
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
|
2018-08-21 17:26:04 +02:00
|
|
|
Via.getPlatform().getLogger().warning("Missing block " + oldId);
|
|
|
|
}
|
2018-04-21 16:11:12 +02:00
|
|
|
return newId;
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2019-11-26 20:14:56 +01:00
|
|
|
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
|
2018-08-21 17:26:04 +02:00
|
|
|
Via.getPlatform().getLogger().warning("Missing block completely " + oldId);
|
|
|
|
}
|
2018-04-21 16:11:12 +02:00
|
|
|
// Default stone
|
|
|
|
return 1;
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|
2018-01-05 15:50:01 +01:00
|
|
|
|
2018-01-06 15:23:49 +01:00
|
|
|
private static int checkStorage(UserConnection user, Position position, int newId) {
|
|
|
|
BlockStorage storage = user.get(BlockStorage.class);
|
|
|
|
if (storage.contains(position)) {
|
|
|
|
BlockStorage.ReplacementData data = storage.get(position);
|
|
|
|
|
|
|
|
if (data.getOriginal() == newId) {
|
|
|
|
if (data.getReplacement() != -1) {
|
|
|
|
return data.getReplacement();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
storage.remove(position);
|
|
|
|
// Check if the new id has to be stored
|
|
|
|
if (storage.isWelcome(newId))
|
|
|
|
storage.store(position, newId);
|
|
|
|
}
|
|
|
|
} else if (storage.isWelcome(newId))
|
|
|
|
storage.store(position, newId);
|
|
|
|
return newId;
|
|
|
|
}
|
2017-12-12 00:39:34 +01:00
|
|
|
}
|