3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-10-03 08:21:06 +02:00

Fix a few chunk errors

This does not fix chunks on its own, they're still very much a work in progress, however this commit should hopefully resolve a few issues. The client might still crash due to some invalid mappings (most likely), but this should bring us one step closer.

With hardcoded values for the chunks, the client wouldn't crash (which leads me to the conclusion stated above) and on the occasions that it would not time out, the chunks were empty.

Co-authored-by: SupremeMortal <suprememortal@users.noreply.github.com>
Dieser Commit ist enthalten in:
RednedEpic 2019-09-08 15:46:10 -05:00 committet von RednedEpic
Ursprung bd8a00b5eb
Commit 383429d71b
5 geänderte Dateien mit 104 neuen und 97 gelöschten Zeilen

Datei anzeigen

@ -100,7 +100,7 @@ import org.geysermc.connector.network.translators.java.entity.spawn.JavaSpawnPla
import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator;
import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator;
import org.geysermc.connector.network.translators.java.scoreboard.JavaUpdateScoreTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaUpdateScoreTranslator;
import org.geysermc.connector.network.translators.java.world.JavaChunkDataPacket; import org.geysermc.connector.network.translators.java.world.JavaChunkDataTranslator;
import org.geysermc.connector.network.translators.java.world.JavaNotifyClientTranslator; import org.geysermc.connector.network.translators.java.world.JavaNotifyClientTranslator;
import org.geysermc.connector.network.translators.java.window.JavaOpenWindowTranslator; import org.geysermc.connector.network.translators.java.window.JavaOpenWindowTranslator;
import org.geysermc.connector.network.translators.java.window.JavaSetSlotTranslator; import org.geysermc.connector.network.translators.java.window.JavaSetSlotTranslator;
@ -168,7 +168,7 @@ public class TranslatorsInit {
Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator()); Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator());
Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator()); Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator());
Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataPacket()); Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataTranslator());
Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator()); Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator());
Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator()); Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator());
Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator());

Datei anzeigen

@ -1,55 +0,0 @@
package org.geysermc.connector.network.translators.java.world;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.geysermc.connector.console.GeyserLogger;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.utils.ChunkUtils;
import org.geysermc.connector.world.chunk.ChunkSection;
public class JavaChunkDataPacket extends PacketTranslator<ServerChunkDataPacket> {
@Override
public void translate(ServerChunkDataPacket packet, GeyserSession session) {
try {
byte[] buffer = new byte[32];
ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn());
int count = 0;
ChunkSection[] sections = chunkData.sections;
for (int i = sections.length - 1; i >= 0; i--) {
if (sections[i].isEmpty())
continue;
count = i + 1;
break;
}
for (int i = 0; i < count; i++) {
ChunkUtils.putBytes(count, buffer, new byte[]{(byte) 0});
ChunkSection section = chunkData.sections[i];
ByteBuf byteBuf = Unpooled.buffer();
section.writeToNetwork(byteBuf);
byte[] byteData = byteBuf.array();
ChunkUtils.putBytes(count, buffer, byteData);
}
LevelChunkPacket levelChunkPacket = new LevelChunkPacket();
levelChunkPacket.setSubChunksLength(16);
levelChunkPacket.setCachingEnabled(true);
levelChunkPacket.setChunkX(packet.getColumn().getX());
levelChunkPacket.setChunkZ(packet.getColumn().getZ());
levelChunkPacket.setData(buffer);
session.getUpstream().sendPacket(levelChunkPacket);
} catch (Exception ex) {
ex.printStackTrace();
}
GeyserLogger.DEFAULT.info("Sent chunk packet!");
}
}

Datei anzeigen

@ -0,0 +1,59 @@
package org.geysermc.connector.network.translators.java.world;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
import com.nukkitx.network.VarInts;
import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.geysermc.api.Geyser;
import org.geysermc.connector.console.GeyserLogger;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.utils.ChunkUtils;
import org.geysermc.connector.world.chunk.ChunkSection;
public class JavaChunkDataTranslator extends PacketTranslator<ServerChunkDataPacket> {
@Override
public void translate(ServerChunkDataPacket packet, GeyserSession session) {
// Not sure if this is safe or not, however without this the client usually times out
Geyser.getConnector().getGeneralThreadPool().execute(() -> {
try {
ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn());
ByteBuf byteBuf = Unpooled.buffer(32);
int count = 0;
ChunkSection[] sections = chunkData.sections;
for (int i = sections.length - 1; i >= 0; i--) {
if (sections[i].isEmpty())
continue;
count = i + 1;
break;
}
for (int i = 0; i < count; i++) {
ChunkSection section = chunkData.sections[i];
section.writeToNetwork(byteBuf);
}
byteBuf.writeBytes(chunkData.biomes); // Biomes - 256 bytes
byteBuf.writeByte(0); // Border blocks - Edu edition only
VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now
byte[] payload = new byte[byteBuf.writerIndex()];
byteBuf.readBytes(payload);
LevelChunkPacket levelChunkPacket = new LevelChunkPacket();
levelChunkPacket.setSubChunksLength(count);
levelChunkPacket.setCachingEnabled(false);
levelChunkPacket.setChunkX(packet.getColumn().getX());
levelChunkPacket.setChunkZ(packet.getColumn().getZ());
levelChunkPacket.setData(payload);
session.getUpstream().sendPacket(levelChunkPacket);
} catch (Exception ex) {
ex.printStackTrace();
}
GeyserLogger.DEFAULT.info("Sent chunk packet!");
});
}
}

Datei anzeigen

@ -8,12 +8,8 @@ import org.geysermc.connector.network.translators.TranslatorsInit;
import org.geysermc.connector.network.translators.item.BedrockItem; import org.geysermc.connector.network.translators.item.BedrockItem;
import org.geysermc.connector.world.chunk.ChunkSection; import org.geysermc.connector.world.chunk.ChunkSection;
import java.util.Arrays;
public class ChunkUtils { public class ChunkUtils {
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public static ChunkData translateToBedrock(Column column) { public static ChunkData translateToBedrock(Column column) {
ChunkData chunkData = new ChunkData(); ChunkData chunkData = new ChunkData();
chunkData.sections = new ChunkSection[16]; chunkData.sections = new ChunkSection[16];
@ -21,6 +17,7 @@ public class ChunkUtils {
chunkData.sections[i] = new ChunkSection(); chunkData.sections[i] = new ChunkSection();
} }
/*
for (int y = 0; y < 256; y++) { for (int y = 0; y < 256; y++) {
int chunkY = y >> 4; int chunkY = y >> 4;
@ -37,55 +34,61 @@ public class ChunkUtils {
BlockStorage storage = chunk.getBlocks(); BlockStorage storage = chunk.getBlocks();
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
BlockState block = storage.get(x, y & 0xF, z); BlockState block = storage.get(x, chunkY, z);
if (block == null)
block = new BlockState(0);
BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block); BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block);
ChunkSection section = chunkData.sections[chunkY]; ChunkSection section = chunkData.sections[chunkY];
org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage(); //org.geysermc.connector.world.chunk.BlockStorage blockStorage = new org.geysermc.connector.world.chunk.BlockStorage();
blockStorage.setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId()); int runtimeId = GlobalBlockPalette.getOrCreateRuntimeId(bedrockBlock.getId(), bedrockBlock.getData());
section.setFullBlock(x, y >> 4, z, 0, runtimeId << 2 | bedrockBlock.getData());
section.getBlockStorageArray()[0] = blockStorage; //section.getBlockStorageArray()[0] = blockStorage;
section.getBlockStorageArray()[1] = blockStorage; //section.getBlockStorageArray()[1] = blockStorage;
} }
} }
} }
*/
for (int chunkY = 0; chunkY < 16; chunkY++) {
Chunk chunk = null;
try {
chunk = column.getChunks()[chunkY];
} catch (Exception ex) {
ex.printStackTrace();
}
if (chunk == null || chunk.isEmpty())
continue;
BlockStorage storage = chunk.getBlocks();
ChunkSection section = chunkData.sections[chunkY];
section.getBlockStorageArray()[0] = new org.geysermc.connector.world.chunk.BlockStorage();
section.getBlockStorageArray()[1] = new org.geysermc.connector.world.chunk.BlockStorage();
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
BlockState block = storage.get(x, y, z);
BedrockItem bedrockBlock = TranslatorsInit.getItemTranslator().getBedrockBlock(block);
section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), bedrockBlock.getId() << 4 | bedrockBlock.getData());
}
}
}
}
return chunkData; return chunkData;
} }
public static final class ChunkData { public static final class ChunkData {
public ChunkSection[] sections; public ChunkSection[] sections;
}
public static void putBytes(int count, byte[] buffer, byte[] bytes) { public byte[] biomes = new byte[256];
if (bytes == null) { public byte[] blockEntities = new byte[0];
return;
}
int minCapacity = count + bytes.length;
if ((minCapacity) - buffer.length > 0) {
int oldCapacity = buffer.length;
int newCapacity = oldCapacity << 1;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
if (newCapacity - MAX_ARRAY_SIZE > 0) {
newCapacity = hugeCapacity(minCapacity);
}
buffer = Arrays.copyOf(buffer, newCapacity);
}
System.arraycopy(bytes, 0, buffer, count, bytes.length);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
} }
} }

Datei anzeigen

@ -40,7 +40,7 @@ public class Toolbox {
ByteBuf b = Unpooled.buffer(); ByteBuf b = Unpooled.buffer();
VarInts.writeUnsignedInt(b, entries.size()); VarInts.writeUnsignedInt(b, entries.size());
for (Map<String, Object> e : entries) { for (Map<String, Object> e : entries) {
GlobalBlockPalette.registerMapping((int) e.get("id")); GlobalBlockPalette.registerMapping((int) e.get("id") << 4 | (int) e.get("data"));
BedrockUtils.writeString(b, (String) e.get("name")); BedrockUtils.writeString(b, (String) e.get("name"));
b.writeShortLE((int) e.get("data")); b.writeShortLE((int) e.get("data"));
b.writeShortLE((int) e.get("id")); b.writeShortLE((int) e.get("id"));