Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
Warn if server is using high/low dimension heights and remove translations on some strings
Dieser Commit ist enthalten in:
Ursprung
6b681213ed
Commit
bb20afb123
@ -89,7 +89,7 @@ public class ChunkCache {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk chunk = column.getChunks()[y >> 4];
|
Chunk chunk = column.getChunks()[(y >> 4) - getChunkMinY()];
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
chunk.set(x & 0xF, y & 0xF, z & 0xF, block);
|
chunk.set(x & 0xF, y & 0xF, z & 0xF, block);
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ public class ChunkCache {
|
|||||||
return BlockTranslator.JAVA_AIR_ID;
|
return BlockTranslator.JAVA_AIR_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk chunk = column.getChunks()[y >> 4];
|
Chunk chunk = column.getChunks()[(y >> 4) - getChunkMinY()];
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
return chunk.get(x & 0xF, y & 0xF, z & 0xF);
|
return chunk.get(x & 0xF, y & 0xF, z & 0xF);
|
||||||
}
|
}
|
||||||
@ -126,4 +126,8 @@ public class ChunkCache {
|
|||||||
long chunkPosition = MathUtils.chunkPositionToLong(chunkX, chunkZ);
|
long chunkPosition = MathUtils.chunkPositionToLong(chunkX, chunkZ);
|
||||||
chunks.remove(chunkPosition);
|
chunks.remove(chunkPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getChunkMinY() {
|
||||||
|
return minY >> 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ import com.nukkitx.nbt.NbtMap;
|
|||||||
import com.nukkitx.nbt.NbtUtils;
|
import com.nukkitx.nbt.NbtUtils;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -59,7 +58,7 @@ public class BiomeTranslator {
|
|||||||
biomesTag = (NbtMap) biomenbtInputStream.readTag();
|
biomesTag = (NbtMap) biomenbtInputStream.readTag();
|
||||||
BIOMES = biomesTag;
|
BIOMES = biomesTag;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.biome_read"));
|
GeyserConnector.getInstance().getLogger().warning("Failed to get biomes from biome definitions, is there something wrong with the file?");
|
||||||
throw new AssertionError(ex);
|
throw new AssertionError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ import com.nukkitx.nbt.NBTInputStream;
|
|||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtUtils;
|
import com.nukkitx.nbt.NbtUtils;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ public class EntityIdentifierRegistry {
|
|||||||
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
|
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
|
||||||
ENTITY_IDENTIFIERS = (NbtMap) nbtInputStream.readTag();
|
ENTITY_IDENTIFIERS = (NbtMap) nbtInputStream.readTag();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.entity"), e);
|
throw new AssertionError("Unable to get entities from entity identifiers", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ public class ItemRegistry {
|
|||||||
try {
|
try {
|
||||||
itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType);
|
itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_bedrock"), e);
|
throw new AssertionError("Unable to load Bedrock runtime item IDs", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lodestoneCompassId = 0;
|
int lodestoneCompassId = 0;
|
||||||
@ -172,7 +172,7 @@ public class ItemRegistry {
|
|||||||
try {
|
try {
|
||||||
creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items");
|
creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e);
|
throw new AssertionError("Unable to load creative items", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int netId = 1;
|
int netId = 1;
|
||||||
@ -247,7 +247,7 @@ public class ItemRegistry {
|
|||||||
try {
|
try {
|
||||||
items = GeyserConnector.JSON_MAPPER.readTree(stream);
|
items = GeyserConnector.JSON_MAPPER.readTree(stream);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
|
throw new AssertionError("Unable to load Java runtime item IDs", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockTranslator blockTranslator = BlockTranslator1_17_0.INSTANCE;
|
BlockTranslator blockTranslator = BlockTranslator1_17_0.INSTANCE;
|
||||||
|
@ -41,7 +41,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -144,7 +143,7 @@ public class RecipeRegistry {
|
|||||||
try {
|
try {
|
||||||
items = GeyserConnector.JSON_MAPPER.readTree(stream);
|
items = GeyserConnector.JSON_MAPPER.readTree(stream);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
|
throw new AssertionError("Unable to load Java runtime item IDs", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JsonNode entry : items.get("leather_armor")) {
|
for (JsonNode entry : items.get("leather_armor")) {
|
||||||
|
@ -39,6 +39,7 @@ import org.geysermc.connector.entity.player.PlayerEntity;
|
|||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
import org.geysermc.connector.utils.ChunkUtils;
|
||||||
import org.geysermc.connector.utils.DimensionUtils;
|
import org.geysermc.connector.utils.DimensionUtils;
|
||||||
import org.geysermc.connector.utils.PluginMessageUtils;
|
import org.geysermc.connector.utils.PluginMessageUtils;
|
||||||
|
|
||||||
@ -53,6 +54,9 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
|
|||||||
public void translate(ServerJoinGamePacket packet, GeyserSession session) {
|
public void translate(ServerJoinGamePacket packet, GeyserSession session) {
|
||||||
PlayerEntity entity = session.getPlayerEntity();
|
PlayerEntity entity = session.getPlayerEntity();
|
||||||
entity.setEntityId(packet.getEntityId());
|
entity.setEntityId(packet.getEntityId());
|
||||||
|
|
||||||
|
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
|
||||||
|
|
||||||
// If the player is already initialized and a join game packet is sent, they
|
// If the player is already initialized and a join game packet is sent, they
|
||||||
// are swapping servers
|
// are swapping servers
|
||||||
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
||||||
|
@ -36,6 +36,7 @@ import org.geysermc.connector.network.session.GeyserSession;
|
|||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
import org.geysermc.connector.utils.ChunkUtils;
|
||||||
import org.geysermc.connector.utils.DimensionUtils;
|
import org.geysermc.connector.utils.DimensionUtils;
|
||||||
|
|
||||||
@Translator(packet = ServerRespawnPacket.class)
|
@Translator(packet = ServerRespawnPacket.class)
|
||||||
@ -78,6 +79,8 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
|
|||||||
session.setThunder(false);
|
session.setThunder(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
|
||||||
|
|
||||||
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
||||||
if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
|
if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
|
||||||
if (!packet.getWorldName().equals(session.getWorldName()) && session.getDimension().equals(newDimension)) {
|
if (!packet.getWorldName().equals(session.getWorldName()) && session.getDimension().equals(newDimension)) {
|
||||||
|
@ -32,6 +32,7 @@ import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette;
|
|||||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette;
|
import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||||
import com.nukkitx.math.vector.Vector2i;
|
import com.nukkitx.math.vector.Vector2i;
|
||||||
@ -67,6 +68,14 @@ import static org.geysermc.connector.network.translators.world.block.BlockTransl
|
|||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class ChunkUtils {
|
public class ChunkUtils {
|
||||||
|
/**
|
||||||
|
* The minimum height Bedrock Edition will accept.
|
||||||
|
*/
|
||||||
|
private static final int MINIMUM_ACCEPTED_HEIGHT = 0;
|
||||||
|
/**
|
||||||
|
* The maximum height Bedrock Edition will accept.
|
||||||
|
*/
|
||||||
|
private static final int MAXIMUM_ACCEPTED_HEIGHT = 256;
|
||||||
|
|
||||||
private static int indexYZXtoXZY(int yzx) {
|
private static int indexYZXtoXZY(int yzx) {
|
||||||
return (yzx >> 8) | (yzx & 0x0F0) | ((yzx & 0x00F) << 8);
|
return (yzx >> 8) | (yzx & 0x0F0) | ((yzx & 0x00F) << 8);
|
||||||
@ -74,7 +83,9 @@ public class ChunkUtils {
|
|||||||
|
|
||||||
public static ChunkData translateToBedrock(GeyserSession session, Column column) {
|
public static ChunkData translateToBedrock(GeyserSession session, Column column) {
|
||||||
Chunk[] javaSections = column.getChunks();
|
Chunk[] javaSections = column.getChunks();
|
||||||
ChunkSection[] sections = new ChunkSection[javaSections.length];
|
// Ensure that, if the player is using lower world heights, the position is not offset
|
||||||
|
int yOffset = session.getChunkCache().getChunkMinY();
|
||||||
|
ChunkSection[] sections = new ChunkSection[javaSections.length - yOffset];
|
||||||
|
|
||||||
// Temporarily stores compound tags of Bedrock-only block entities
|
// Temporarily stores compound tags of Bedrock-only block entities
|
||||||
List<NbtMap> bedrockOnlyBlockEntities = new ArrayList<>();
|
List<NbtMap> bedrockOnlyBlockEntities = new ArrayList<>();
|
||||||
@ -83,6 +94,11 @@ public class ChunkUtils {
|
|||||||
BitSet pistonOrFlowerPaletteIds = new BitSet();
|
BitSet pistonOrFlowerPaletteIds = new BitSet();
|
||||||
|
|
||||||
for (int sectionY = 0; sectionY < javaSections.length; sectionY++) {
|
for (int sectionY = 0; sectionY < javaSections.length; sectionY++) {
|
||||||
|
if (yOffset < 0 && sectionY < -yOffset) {
|
||||||
|
// Ignore this chunk since it goes below the accepted height limit
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Chunk javaSection = javaSections[sectionY];
|
Chunk javaSection = javaSections[sectionY];
|
||||||
|
|
||||||
// No need to encode an empty section...
|
// No need to encode an empty section...
|
||||||
@ -114,7 +130,7 @@ public class ChunkUtils {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sections[sectionY] = section;
|
sections[sectionY + yOffset] = section;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +203,7 @@ public class ChunkUtils {
|
|||||||
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
|
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
|
||||||
}
|
}
|
||||||
|
|
||||||
sections[sectionY] = new ChunkSection(layers);
|
sections[sectionY + yOffset] = new ChunkSection(layers);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompoundTag[] blockEntities = column.getTileEntities();
|
CompoundTag[] blockEntities = column.getTileEntities();
|
||||||
@ -220,7 +236,7 @@ public class ChunkUtils {
|
|||||||
|
|
||||||
// Get Java blockstate ID from block entity position
|
// Get Java blockstate ID from block entity position
|
||||||
int blockState = 0;
|
int blockState = 0;
|
||||||
Chunk section = column.getChunks()[pos.getY() >> 4];
|
Chunk section = column.getChunks()[(pos.getY() >> 4) - yOffset];
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
blockState = section.get(pos.getX() & 0xF, pos.getY() & 0xF, pos.getZ() & 0xF);
|
blockState = section.get(pos.getX() & 0xF, pos.getY() & 0xF, pos.getZ() & 0xF);
|
||||||
}
|
}
|
||||||
@ -385,6 +401,28 @@ public class ChunkUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the minimum and maximum heights for this dimension
|
||||||
|
*/
|
||||||
|
public static void applyDimensionHeight(GeyserSession session, CompoundTag dimensionTag) {
|
||||||
|
int minY = ((IntTag) dimensionTag.get("min_y")).getValue();
|
||||||
|
int maxY = ((IntTag) dimensionTag.get("height")).getValue();
|
||||||
|
// Logical height can be ignored probably - seems to be for artificial limits like the Nether.
|
||||||
|
|
||||||
|
if (minY % 16 != 0) {
|
||||||
|
throw new RuntimeException("Minimum Y must be a multiple of 16!");
|
||||||
|
}
|
||||||
|
if (maxY % 16 != 0) {
|
||||||
|
throw new RuntimeException("Maximum Y must be a multiple of 16!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minY < MINIMUM_ACCEPTED_HEIGHT || maxY > MAXIMUM_ACCEPTED_HEIGHT) {
|
||||||
|
session.getConnector().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds"));
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getChunkCache().setMinY(minY);
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static final class ChunkData {
|
public static final class ChunkData {
|
||||||
private final ChunkSection[] sections;
|
private final ChunkSection[] sections;
|
||||||
|
@ -152,7 +152,7 @@ public class FileUtils {
|
|||||||
public static InputStream getResource(String resource) {
|
public static InputStream getResource(String resource) {
|
||||||
InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource);
|
InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource);
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.resource", resource));
|
throw new AssertionError("Unable to find resource: " + resource);
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b66aef5db3633468f1e6ece408ecd7a3d4a4faeb
|
Subproject commit fcc8f01e25e481c9c82f2ee9bff23111ec781dd7
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren