mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge branch 'crash-fix' of https://github.com/GeyserMC/Geyser into crash-fix
# Conflicts: # connector/pom.xml # connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java # connector/src/main/java/org/geysermc/connector/network/translators/Registry.java # connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
This commit is contained in:
commit
5725ff4c41
20 changed files with 10997 additions and 10365 deletions
17
README.md
17
README.md
|
|
@ -10,9 +10,26 @@ The ultimate goal for this project is to allow those to join Minecraft: Java Edi
|
|||
If you're interested in development, please join our Discord server:
|
||||
https://discord.gg/mRjbCsS
|
||||
|
||||
## What's Completed
|
||||
- [x] Server recognized in server list
|
||||
- [x] Join detection from remote
|
||||
- [ ] Online mode/auth support
|
||||
- [ ] Chat/command support
|
||||
- [ ] Inventory support
|
||||
- [ ] Movement support
|
||||
- [ ] Entity support
|
||||
- [ ] Chunks
|
||||
- [ ] Block break/place support
|
||||
|
||||
## Compiling
|
||||
Clone the repo to your computer, and run `mvn clean install`.
|
||||
|
||||
## Contributing
|
||||
As a project that is still nowhere near completion, any contributions are appreciated. Please feel free to reach out to us on Discord if
|
||||
you're interested in helping this project come along.
|
||||
|
||||
## Libraries Used:
|
||||
- [NukkitX Bedrock Protocol Library](https://github.com/NukkitX/Protocol)
|
||||
- [Steveice10's Java Protocol Library](https://github.com/Steveice10/MCProtocolLib)
|
||||
- [TerminalConsoleAppender](https://github.com/Minecrell/TerminalConsoleAppender)
|
||||
- [Simple Logging Facade for Java (slf4j)](https://github.com/qos-ch/slf4j)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>api</artifactId>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
package org.geysermc.api;
|
||||
|
||||
public class GeyserAPI {
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>common</artifactId>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -6,20 +6,20 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>connector</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
@ -59,6 +59,12 @@
|
|||
<version>1.18.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.nukkitx.protocol</groupId>
|
||||
<artifactId>bedrock-v361</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
|
|
@ -71,12 +77,6 @@
|
|||
<version>2.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.nukkitx.protocol</groupId>
|
||||
<artifactId>bedrock-v361</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.nukkitx.protocol</groupId>
|
||||
<artifactId>bedrock-v340</artifactId>
|
||||
|
|
|
|||
|
|
@ -27,20 +27,12 @@ package org.geysermc.connector;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.nukkitx.network.raknet.RakNetServer;
|
||||
import com.nukkitx.network.raknet.RakNetServerListener;
|
||||
import com.nukkitx.network.raknet.RakNetServerSession;
|
||||
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
|
||||
import com.nukkitx.protocol.bedrock.BedrockServer;
|
||||
import com.nukkitx.protocol.bedrock.v361.Bedrock_v361;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import lombok.Getter;
|
||||
import org.apache.logging.log4j.core.filter.Filterable;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.geysermc.api.ChatColor;
|
||||
import org.geysermc.api.Connector;
|
||||
import org.geysermc.api.ConsoleColors;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.command.CommandMap;
|
||||
import org.geysermc.api.logger.Logger;
|
||||
|
|
|
|||
|
|
@ -92,29 +92,38 @@ public class GeyserLogger implements org.geysermc.api.logger.Logger {
|
|||
|
||||
@Override
|
||||
public void severe(String message) {
|
||||
waitFor();
|
||||
System.out.println(printConsole(ChatColor.DARK_RED + message, colored));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
waitFor();
|
||||
System.out.println(printConsole(ChatColor.RED + message, colored));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String message) {
|
||||
waitFor();
|
||||
System.out.println(printConsole(ChatColor.YELLOW + message, colored));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
waitFor();
|
||||
System.out.println(printConsole(ChatColor.WHITE + message, colored));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
waitFor();
|
||||
System.out.println(printConsole(ChatColor.GRAY + message, colored));
|
||||
}
|
||||
|
||||
private synchronized void waitFor() {
|
||||
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,10 @@ import com.nukkitx.protocol.bedrock.BedrockPong;
|
|||
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
|
||||
import com.nukkitx.protocol.bedrock.BedrockServerSession;
|
||||
import com.nukkitx.protocol.bedrock.v361.Bedrock_v361;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.console.GeyserLogger;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
|
@ -45,13 +47,13 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
|||
|
||||
@Override
|
||||
public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
|
||||
System.out.println(inetSocketAddress + " tried to connect!");
|
||||
GeyserLogger.DEFAULT.info(inetSocketAddress + " tried to connect!");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
|
||||
connector.getLogger().info(inetSocketAddress + " has pinged you!");
|
||||
GeyserLogger.DEFAULT.info(inetSocketAddress + " has pinged you!");
|
||||
GeyserConfiguration config = connector.getConfig();
|
||||
BedrockPong pong = new BedrockPong();
|
||||
pong.setEdition("MCPE");
|
||||
|
|
@ -71,8 +73,11 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
|||
@Override
|
||||
public void onSessionCreation(BedrockServerSession bedrockServerSession) {
|
||||
bedrockServerSession.setLogging(true);
|
||||
bedrockServerSession.setPacketCodec(Bedrock_v361.V361_CODEC);
|
||||
bedrockServerSession.addDisconnectHandler((x) -> connector.getLogger().warning("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconnected for reason " + x));
|
||||
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession)));
|
||||
bedrockServerSession.addDisconnectHandler((x) -> GeyserLogger.DEFAULT.warning("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconnected for reason " + x));
|
||||
bedrockServerSession.setPacketCodec(Bedrock_v361.V361_CODEC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators;
|
||||
|
||||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.connector.console.GeyserLogger;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Registry<T> {
|
||||
|
||||
private final Map<Class<? extends T>, BiConsumer<? extends T, GeyserSession>> MAP = new HashMap<>();
|
||||
|
||||
public static final Registry<Packet> JAVA = new Registry<>();
|
||||
|
|
@ -21,7 +48,7 @@ public class Registry<T> {
|
|||
try {
|
||||
((BiConsumer<P, GeyserSession>) JAVA.MAP.get(clazz)).accept(p, s);
|
||||
} catch (NullPointerException e) {
|
||||
System.err.println("could not translate packet" + p.getClass().getSimpleName());
|
||||
GeyserLogger.DEFAULT.warning("could not translate packet " + p.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2f;
|
||||
|
|
@ -5,18 +30,41 @@ import com.flowpowered.math.vector.Vector2i;
|
|||
import com.flowpowered.math.vector.Vector3f;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
|
||||
import com.nukkitx.nbt.CompoundTagBuilder;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import com.nukkitx.nbt.stream.NBTOutputStream;
|
||||
import com.nukkitx.nbt.tag.CompoundTag;
|
||||
import com.nukkitx.network.VarInts;
|
||||
import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
|
||||
import com.nukkitx.protocol.bedrock.data.GameRule;
|
||||
import com.nukkitx.protocol.bedrock.packet.*;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.geysermc.connector.utils.PSPEStuff;
|
||||
import org.geysermc.connector.utils.PositionSerializer;
|
||||
import org.geysermc.connector.utils.GeyserUtils;
|
||||
import org.geysermc.connector.utils.Toolbox;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TranslatorsInit {
|
||||
private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag();
|
||||
private static final byte[] EMPTY_LEVEL_CHUNK_DATA;
|
||||
|
||||
static {
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
outputStream.write(new byte[258]); // Biomes + Border Size + Extra Data Size
|
||||
|
||||
try (NBTOutputStream stream = NbtUtils.createNetworkWriter(outputStream)) {
|
||||
stream.write(EMPTY_TAG);
|
||||
}
|
||||
|
||||
EMPTY_LEVEL_CHUNK_DATA = outputStream.toByteArray();
|
||||
}catch (IOException e) {
|
||||
throw new AssertionError("Unable to generate empty level chunk data");
|
||||
}
|
||||
}
|
||||
|
||||
public static void start() {
|
||||
addLoginPackets();
|
||||
|
|
@ -24,12 +72,10 @@ public class TranslatorsInit {
|
|||
|
||||
private static void addLoginPackets() {
|
||||
Registry.add(ServerJoinGamePacket.class, (packet, session) -> {
|
||||
//for(byte b : Toolbox.EMPTY_CHUNK) {
|
||||
// GeyserLogger.DEFAULT.warning("" + b);
|
||||
//}
|
||||
|
||||
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
|
||||
|
||||
bedrockPacket.setUniqueEntityId(packet.getEntityId());
|
||||
|
||||
session.getUpstream().sendPacketImmediately(bedrockPacket);
|
||||
|
||||
StartGamePacket startGamePacket = new StartGamePacket();
|
||||
|
|
@ -46,16 +92,16 @@ public class TranslatorsInit {
|
|||
startGamePacket.setDifficulty(1);
|
||||
startGamePacket.setDefaultSpawn(new Vector3i(0, 0, 0));
|
||||
startGamePacket.setAcheivementsDisabled(true);
|
||||
startGamePacket.setTime(1300);
|
||||
startGamePacket.setTime(0);
|
||||
startGamePacket.setEduLevel(false);
|
||||
startGamePacket.setEduFeaturesEnabled(false);
|
||||
startGamePacket.setRainLevel(0);
|
||||
startGamePacket.setLightningLevel(0);
|
||||
startGamePacket.setMultiplayerGame(false);
|
||||
startGamePacket.setMultiplayerGame(true);
|
||||
startGamePacket.setBroadcastingToLan(true);
|
||||
startGamePacket.getGamerules().add((new GameRule("showcoordinates", true)));
|
||||
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.FRIENDS_OF_FRIENDS);
|
||||
startGamePacket.setXblBroadcastMode(GamePublishSetting.FRIENDS_OF_FRIENDS);
|
||||
startGamePacket.getGamerules().add(new GameRule<>("showcoordinates", true));
|
||||
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
|
||||
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
|
||||
startGamePacket.setCommandsEnabled(true);
|
||||
startGamePacket.setTexturePacksRequired(false);
|
||||
startGamePacket.setBonusChestEnabled(false);
|
||||
|
|
@ -73,34 +119,41 @@ public class TranslatorsInit {
|
|||
startGamePacket.setLevelId("oerjhii");
|
||||
startGamePacket.setWorldName("world");
|
||||
startGamePacket.setPremiumWorldTemplateId("00000000-0000-0000-0000-000000000000");
|
||||
startGamePacket.setCurrentTick(1);
|
||||
startGamePacket.setEnchantmentSeed(1);
|
||||
startGamePacket.setCurrentTick(0);
|
||||
startGamePacket.setEnchantmentSeed(0);
|
||||
startGamePacket.setMultiplayerCorrelationId("");
|
||||
startGamePacket.setCachedPalette(Toolbox.CACHED_PALLETE);
|
||||
startGamePacket.setItemEntries(Toolbox.ITEMS);
|
||||
|
||||
session.getUpstream().sendPacketImmediately(startGamePacket);
|
||||
session.getUpstream().sendPacket(startGamePacket);
|
||||
|
||||
Vector3f pos = new Vector3f(0, 0, 0);
|
||||
|
||||
int chunkX = pos.getFloorX() >> 4;
|
||||
|
||||
int chunkZ = pos.getFloorZ() >> 4;
|
||||
|
||||
for (int x = -3; x < 3; x++) {
|
||||
|
||||
for (int z = -3; z < 3; z++) {
|
||||
|
||||
LevelChunkPacket data = new LevelChunkPacket();
|
||||
data.setChunkX(chunkX + x);
|
||||
data.setChunkZ(chunkZ + z);
|
||||
data.setSubChunksLength(0);
|
||||
|
||||
data.setData(EMPTY_LEVEL_CHUNK_DATA);
|
||||
|
||||
data.setData(Toolbox.EMPTY_CHUNK);
|
||||
session.getUpstream().sendPacketImmediately(data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PlayStatusPacket packet1 = new PlayStatusPacket();
|
||||
|
||||
packet1.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
|
||||
|
||||
session.getUpstream().sendPacket(packet1);
|
||||
});
|
||||
}
|
||||
|
|
@ -108,7 +161,7 @@ public class TranslatorsInit {
|
|||
private static byte[] empty(byte[] b, Vector2i pos) {
|
||||
ByteBuf by = Unpooled.buffer();
|
||||
|
||||
PositionSerializer.writePEChunkCoord(by, pos);
|
||||
GeyserUtils.writePEChunkCoord(by, pos);
|
||||
|
||||
return by.array();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,272 +0,0 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
|
||||
|
||||
public class ArraySerializer {
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) {
|
||||
|
||||
int length = from.readShort();
|
||||
|
||||
MiscSerializer.checkLimit(length, limit);
|
||||
|
||||
return from.readSlice(length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
|
||||
|
||||
T[] array = (T[]) Array.newInstance(tclass, from.readShort());
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = elementReader.apply(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] readVarIntByteArray(ByteBuf from) {
|
||||
|
||||
return MiscSerializer.readBytes(from, VarNumberSerializer.readVarInt(from));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) {
|
||||
|
||||
int length = VarNumberSerializer.readVarInt(from);
|
||||
|
||||
MiscSerializer.checkLimit(length, limit);
|
||||
|
||||
return from.readSlice(length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readVarIntByteArraySlice(ByteBuf from) {
|
||||
|
||||
return from.readSlice(VarNumberSerializer.readVarInt(from));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
|
||||
|
||||
T[] array = (T[]) Array.newInstance(tclass, VarNumberSerializer.readVarInt(from));
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = elementReader.apply(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int[] readVarIntVarIntArray(ByteBuf from) {
|
||||
|
||||
int[] array = new int[VarNumberSerializer.readVarInt(from)];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = VarNumberSerializer.readVarInt(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, ByteBuf data) {
|
||||
|
||||
to.writeShort(data.readableBytes());
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, byte[] data) {
|
||||
|
||||
to.writeShort(data.length);
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
MiscSerializer.writeLengthPrefixedBytes(to, (lTo, length) -> lTo.writeShort(length), dataWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
to.writeShort(array.length);
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, data.readableBytes());
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, byte[] data) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, data.length);
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
MiscSerializer.writeLengthPrefixedBytes(to, VarNumberSerializer::writeFixedSizeVarInt, dataWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) {
|
||||
|
||||
MiscSerializer.writeSizePrefixedData(to, VarNumberSerializer::writeFixedSizeVarInt, arrayWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, array.length);
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, array.size());
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntVarIntArray(ByteBuf to, int[] array) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, array.length);
|
||||
|
||||
for (int element : array) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSVarIntSVarIntArray(ByteBuf to, int[] array) {
|
||||
|
||||
VarNumberSerializer.writeSVarInt(to, array.length);
|
||||
|
||||
for (int element : array) {
|
||||
|
||||
VarNumberSerializer.writeSVarInt(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntLongArray(ByteBuf to, long[] array) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, array.length);
|
||||
|
||||
for (long element : array) {
|
||||
|
||||
to.writeLong(element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,653 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3d;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.*;
|
||||
|
||||
public class GeyserUtils {
|
||||
|
||||
public static final int FLAG_RUNTIME = 1;
|
||||
|
||||
public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14;
|
||||
|
||||
public static final int SECTION_COUNT_BLOCKS = 16;
|
||||
|
||||
public static final int SECTION_COUNT_LIGHT = 18;
|
||||
|
||||
public static final int BLOCKS_IN_SECTION = 16 * 16 * 16;
|
||||
|
||||
public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2;
|
||||
|
||||
public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8;
|
||||
|
||||
public static final int SUBCHUNK_VERSION = 8;
|
||||
|
||||
public static void writeEmpty(ByteBuf to) {
|
||||
|
||||
to.writeByte(storageHeader(1));
|
||||
|
||||
to.writeZero(EMPTY_SUBCHUNK_BYTES);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static final int storageHeader(int bitsPerBlock) {
|
||||
|
||||
return (bitsPerBlock << 1) | FLAG_RUNTIME;
|
||||
|
||||
}
|
||||
|
||||
public static void writeEmptySubChunk(ByteBuf out) {
|
||||
|
||||
out.writeBytes(new byte[4096 + 4096]);
|
||||
|
||||
}
|
||||
|
||||
public static void skipPosition(ByteBuf from) {
|
||||
from.skipBytes(Long.BYTES);
|
||||
}
|
||||
|
||||
public static Vector3d readPosition(ByteBuf from) {
|
||||
long l = from.readLong();
|
||||
return new Vector3d(
|
||||
(int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38)
|
||||
);
|
||||
}
|
||||
|
||||
public static void readPEPosition(ByteBuf from) {
|
||||
readSVarInt(from);
|
||||
readVarInt(from);
|
||||
readSVarInt(from);
|
||||
}
|
||||
|
||||
public static Vector3d readLegacyPositionI(ByteBuf from) {
|
||||
return new Vector3d(from.readInt(), from.readInt(), from.readInt());
|
||||
}
|
||||
|
||||
public static void writePosition(ByteBuf to, Vector3i position) {
|
||||
to.writeLong(((position.getX() & 0x3FFFFFFL) << 38) | ((position.getZ() & 0x3FFFFFFL) << 12) | (position.getY() & 0xFFFL));
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionL(ByteBuf to, Vector3d position) {
|
||||
to.writeLong((((int) position.getX() & 0x3FFFFFFL) << 38) | (((int) position.getY() & 0xFFFL) << 26) | ((int) position.getZ() & 0x3FFFFFFL));
|
||||
}
|
||||
|
||||
public static void writePEPosition(ByteBuf to, Vector3d position) {
|
||||
writeSVarInt(to, (int) position.getX());
|
||||
writeVarInt(to, (int) position.getY());
|
||||
writeSVarInt(to, (int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionB(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeByte((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionS(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeShort((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionI(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeInt((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static Vector2i readIntChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(from.readInt(), from.readInt());
|
||||
}
|
||||
|
||||
public static Vector2i readVarIntChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(readVarInt(from), readVarInt(from));
|
||||
}
|
||||
|
||||
public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
to.writeInt(chunk.getX());
|
||||
to.writeInt(chunk.getY());
|
||||
}
|
||||
|
||||
public static Vector2i readPEChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(readSVarInt(from), readSVarInt(from));
|
||||
}
|
||||
|
||||
public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
writeSVarInt(to, chunk.getX());
|
||||
writeSVarInt(to, chunk.getY());
|
||||
}
|
||||
|
||||
public static int readLocalCoord(ByteBuf from) {
|
||||
return from.readUnsignedShort();
|
||||
}
|
||||
|
||||
public static void writeLocalCoord(ByteBuf to, int coord) {
|
||||
to.writeShort(coord);
|
||||
}
|
||||
|
||||
public static void writeVarIntChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
writeVarInt(to, chunk.getX());
|
||||
writeVarInt(to, chunk.getY());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final int MAX_LENGTH = 5;
|
||||
|
||||
|
||||
|
||||
public static void writeFixedSizeVarInt(ByteBuf to, int i) {
|
||||
|
||||
int writerIndex = to.writerIndex();
|
||||
|
||||
while ((i & 0xFFFFFF80) != 0x0) {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
i >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
int paddingBytes = MAX_LENGTH - (to.writerIndex() - writerIndex) - 1;
|
||||
|
||||
if (paddingBytes == 0) {
|
||||
|
||||
to.writeByte(i);
|
||||
|
||||
} else {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
while (--paddingBytes > 0) {
|
||||
|
||||
to.writeByte(0x80);
|
||||
|
||||
}
|
||||
|
||||
to.writeByte(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int readVarInt(ByteBuf from) {
|
||||
|
||||
int value = 0;
|
||||
|
||||
int length = 0;
|
||||
|
||||
byte part;
|
||||
|
||||
do {
|
||||
|
||||
part = from.readByte();
|
||||
|
||||
value |= (part & 0x7F) << (length++ * 7);
|
||||
|
||||
if (length > MAX_LENGTH) {
|
||||
|
||||
throw new DecoderException("VarInt too big");
|
||||
|
||||
}
|
||||
|
||||
} while (part < 0);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarInt(ByteBuf to, int i) {
|
||||
|
||||
while ((i & 0xFFFFFF80) != 0x0) {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
i >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
to.writeByte(i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int readSVarInt(ByteBuf from) {
|
||||
|
||||
int varint = readVarInt(from);
|
||||
|
||||
return (varint >> 1) ^ -(varint & 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSVarInt(ByteBuf to, int varint) {
|
||||
|
||||
writeVarInt(to, (varint << 1) ^ (varint >> 31));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static long readVarLong(ByteBuf from) {
|
||||
|
||||
long varlong = 0L;
|
||||
|
||||
int length = 0;
|
||||
|
||||
byte part;
|
||||
|
||||
do {
|
||||
|
||||
part = from.readByte();
|
||||
|
||||
varlong |= (part & 0x7F) << (length++ * 7);
|
||||
|
||||
if (length > 10) {
|
||||
|
||||
throw new RuntimeException("VarLong too big");
|
||||
|
||||
}
|
||||
|
||||
} while ((part & 0x80) == 0x80);
|
||||
|
||||
return varlong;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarLong(ByteBuf to, long varlong) {
|
||||
|
||||
while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) {
|
||||
|
||||
to.writeByte((int) (varlong & 0x7FL) | 0x80);
|
||||
|
||||
varlong >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
to.writeByte((int) varlong);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static long readSVarLong(ByteBuf from) {
|
||||
|
||||
long varlong = readVarLong(from);
|
||||
|
||||
return (varlong >> 1) ^ -(varlong & 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSVarLong(ByteBuf to, long varlong) {
|
||||
|
||||
writeVarLong(to, (varlong << 1) ^ (varlong >> 63));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) {
|
||||
|
||||
int length = from.readShort();
|
||||
|
||||
checkLimit(length, limit);
|
||||
|
||||
return from.readSlice(length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
|
||||
|
||||
T[] array = (T[]) Array.newInstance(tclass, from.readShort());
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = elementReader.apply(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] readVarIntByteArray(ByteBuf from) {
|
||||
|
||||
return readBytes(from, readVarInt(from));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) {
|
||||
|
||||
int length = readVarInt(from);
|
||||
|
||||
checkLimit(length, limit);
|
||||
|
||||
return from.readSlice(length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readVarIntByteArraySlice(ByteBuf from) {
|
||||
|
||||
return from.readSlice(readVarInt(from));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
|
||||
|
||||
T[] array = (T[]) Array.newInstance(tclass, readVarInt(from));
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = elementReader.apply(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int[] readVarIntVarIntArray(ByteBuf from) {
|
||||
|
||||
int[] array = new int[readVarInt(from)];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
array[i] = readVarInt(from);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, ByteBuf data) {
|
||||
|
||||
to.writeShort(data.readableBytes());
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, byte[] data) {
|
||||
|
||||
to.writeShort(data.length);
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
writeLengthPrefixedBytes(to, (lTo, length) -> lTo.writeShort(length), dataWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
to.writeShort(array.length);
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) {
|
||||
|
||||
writeVarInt(to, data.readableBytes());
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, byte[] data) {
|
||||
|
||||
writeVarInt(to, data.length);
|
||||
|
||||
to.writeBytes(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
writeLengthPrefixedBytes(to, GeyserUtils::writeFixedSizeVarInt, dataWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) {
|
||||
|
||||
writeSizePrefixedData(to, GeyserUtils::writeFixedSizeVarInt, arrayWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
writeVarInt(to, array.length);
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) {
|
||||
|
||||
writeVarInt(to, array.size());
|
||||
|
||||
for (T element : array) {
|
||||
|
||||
elementWriter.accept(to, element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void writeVarIntEnum(ByteBuf to, Enum<?> e) {
|
||||
|
||||
writeVarInt(to, e.ordinal());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeByteEnum(ByteBuf to, Enum<?> e) {
|
||||
|
||||
to.writeByte(e.ordinal());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static UUID readUUID(ByteBuf from) {
|
||||
|
||||
return new UUID(from.readLong(), from.readLong());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeUUID(ByteBuf to, UUID uuid) {
|
||||
|
||||
to.writeLong(uuid.getMostSignificantBits());
|
||||
|
||||
to.writeLong(uuid.getLeastSignificantBits());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writePEUUID(ByteBuf to, UUID uuid) {
|
||||
|
||||
to.writeLongLE(uuid.getMostSignificantBits());
|
||||
|
||||
to.writeLongLE(uuid.getLeastSignificantBits());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] readAllBytes(ByteBuf buf) {
|
||||
|
||||
return readBytes(buf, buf.readableBytes());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readAllBytesSlice(ByteBuf from) {
|
||||
|
||||
return from.readSlice(from.readableBytes());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) {
|
||||
|
||||
checkLimit(buf.readableBytes(), limit);
|
||||
|
||||
return readAllBytesSlice(buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] readBytes(ByteBuf buf, int length) {
|
||||
|
||||
byte[] result = new byte[length];
|
||||
|
||||
buf.readBytes(result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static void checkLimit(int length, int limit) {
|
||||
|
||||
if (length > limit) {
|
||||
|
||||
throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
int lengthWriterIndex = to.writerIndex();
|
||||
|
||||
lengthWriter.accept(to, 0);
|
||||
|
||||
int writerIndexDataStart = to.writerIndex();
|
||||
|
||||
dataWriter.accept(to);
|
||||
|
||||
int writerIndexDataEnd = to.writerIndex();
|
||||
|
||||
to.writerIndex(lengthWriterIndex);
|
||||
|
||||
lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart);
|
||||
|
||||
to.writerIndex(writerIndexDataEnd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) {
|
||||
|
||||
int sizeWriterIndex = to.writerIndex();
|
||||
|
||||
sizeWriter.accept(to, 0);
|
||||
|
||||
int size = dataWriter.applyAsInt(to);
|
||||
|
||||
int writerIndexDataEnd = to.writerIndex();
|
||||
|
||||
to.writerIndex(sizeWriterIndex);
|
||||
|
||||
sizeWriter.accept(to, size);
|
||||
|
||||
to.writerIndex(writerIndexDataEnd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static int getAnvilIndex(int x, int y, int z) {
|
||||
|
||||
return (y << 8) + (z << 4) + x;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import java.util.function.ObjIntConsumer;
|
||||
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
|
||||
|
||||
public class MiscSerializer {
|
||||
|
||||
|
||||
public static void writeVarIntEnum(ByteBuf to, Enum<?> e) {
|
||||
|
||||
VarNumberSerializer.writeVarInt(to, e.ordinal());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeByteEnum(ByteBuf to, Enum<?> e) {
|
||||
|
||||
to.writeByte(e.ordinal());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static UUID readUUID(ByteBuf from) {
|
||||
|
||||
return new UUID(from.readLong(), from.readLong());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeUUID(ByteBuf to, UUID uuid) {
|
||||
|
||||
to.writeLong(uuid.getMostSignificantBits());
|
||||
|
||||
to.writeLong(uuid.getLeastSignificantBits());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writePEUUID(ByteBuf to, UUID uuid) {
|
||||
|
||||
to.writeLongLE(uuid.getMostSignificantBits());
|
||||
|
||||
to.writeLongLE(uuid.getLeastSignificantBits());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] readAllBytes(ByteBuf buf) {
|
||||
|
||||
return MiscSerializer.readBytes(buf, buf.readableBytes());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readAllBytesSlice(ByteBuf from) {
|
||||
|
||||
return from.readSlice(from.readableBytes());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) {
|
||||
|
||||
checkLimit(buf.readableBytes(), limit);
|
||||
|
||||
return readAllBytesSlice(buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] readBytes(ByteBuf buf, int length) {
|
||||
|
||||
byte[] result = new byte[length];
|
||||
|
||||
buf.readBytes(result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static void checkLimit(int length, int limit) {
|
||||
|
||||
if (length > limit) {
|
||||
|
||||
throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) {
|
||||
|
||||
int lengthWriterIndex = to.writerIndex();
|
||||
|
||||
lengthWriter.accept(to, 0);
|
||||
|
||||
int writerIndexDataStart = to.writerIndex();
|
||||
|
||||
dataWriter.accept(to);
|
||||
|
||||
int writerIndexDataEnd = to.writerIndex();
|
||||
|
||||
to.writerIndex(lengthWriterIndex);
|
||||
|
||||
lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart);
|
||||
|
||||
to.writerIndex(writerIndexDataEnd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) {
|
||||
|
||||
int sizeWriterIndex = to.writerIndex();
|
||||
|
||||
sizeWriter.accept(to, 0);
|
||||
|
||||
int size = dataWriter.applyAsInt(to);
|
||||
|
||||
int writerIndexDataEnd = to.writerIndex();
|
||||
|
||||
to.writerIndex(sizeWriterIndex);
|
||||
|
||||
sizeWriter.accept(to, size);
|
||||
|
||||
to.writerIndex(writerIndexDataEnd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class PSPEStuff {
|
||||
|
||||
public static final int FLAG_RUNTIME = 1;
|
||||
|
||||
public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14;
|
||||
|
||||
public static final int SECTION_COUNT_BLOCKS = 16;
|
||||
|
||||
public static final int SECTION_COUNT_LIGHT = 18;
|
||||
|
||||
public static final int BLOCKS_IN_SECTION = 16 * 16 * 16;
|
||||
|
||||
public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2;
|
||||
|
||||
public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8;
|
||||
|
||||
public static final int SUBCHUNK_VERSION = 8;
|
||||
|
||||
public static void writeEmpty(ByteBuf to) {
|
||||
|
||||
to.writeByte(storageHeader(1));
|
||||
|
||||
to.writeZero(EMPTY_SUBCHUNK_BYTES);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static final int storageHeader(int bitsPerBlock) {
|
||||
|
||||
return (bitsPerBlock << 1) | FLAG_RUNTIME;
|
||||
|
||||
}
|
||||
|
||||
public static void writeEmptySubChunk(ByteBuf out) {
|
||||
|
||||
out.writeByte(SUBCHUNK_VERSION);
|
||||
|
||||
out.writeByte(1); //only blockstate storage
|
||||
|
||||
writeEmpty(out);
|
||||
|
||||
VarNumberSerializer.writeSVarInt(out, 1); //Palette size
|
||||
|
||||
VarNumberSerializer.writeSVarInt(out, 0); //Palette: Air
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3d;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class PositionSerializer {
|
||||
|
||||
public static void skipPosition(ByteBuf from) {
|
||||
from.skipBytes(Long.BYTES);
|
||||
}
|
||||
|
||||
public static Vector3d readPosition(ByteBuf from) {
|
||||
long l = from.readLong();
|
||||
return new Vector3d(
|
||||
(int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38)
|
||||
);
|
||||
}
|
||||
|
||||
public static void readPEPosition(ByteBuf from) {
|
||||
VarNumberSerializer.readSVarInt(from);
|
||||
VarNumberSerializer.readVarInt(from);
|
||||
VarNumberSerializer.readSVarInt(from);
|
||||
}
|
||||
|
||||
public static Vector3d readLegacyPositionI(ByteBuf from) {
|
||||
return new Vector3d(from.readInt(), from.readInt(), from.readInt());
|
||||
}
|
||||
|
||||
public static void writePosition(ByteBuf to, Vector3i position) {
|
||||
to.writeLong(((position.getX() & 0x3FFFFFFL) << 38) | ((position.getZ() & 0x3FFFFFFL) << 12) | (position.getY() & 0xFFFL));
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionL(ByteBuf to, Vector3d position) {
|
||||
to.writeLong((((int) position.getX() & 0x3FFFFFFL) << 38) | (((int) position.getY() & 0xFFFL) << 26) | ((int) position.getZ() & 0x3FFFFFFL));
|
||||
}
|
||||
|
||||
public static void writePEPosition(ByteBuf to, Vector3d position) {
|
||||
VarNumberSerializer.writeSVarInt(to, (int) position.getX());
|
||||
VarNumberSerializer.writeVarInt(to, (int) position.getY());
|
||||
VarNumberSerializer.writeSVarInt(to, (int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionB(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeByte((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionS(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeShort((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static void writeLegacyPositionI(ByteBuf to, Vector3d position) {
|
||||
to.writeInt((int) position.getX());
|
||||
to.writeInt((int) position.getY());
|
||||
to.writeInt((int) position.getZ());
|
||||
}
|
||||
|
||||
public static Vector2i readIntChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(from.readInt(), from.readInt());
|
||||
}
|
||||
|
||||
public static Vector2i readVarIntChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(VarNumberSerializer.readVarInt(from), VarNumberSerializer.readVarInt(from));
|
||||
}
|
||||
|
||||
public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
to.writeInt(chunk.getX());
|
||||
to.writeInt(chunk.getY());
|
||||
}
|
||||
|
||||
public static Vector2i readPEChunkCoord(ByteBuf from) {
|
||||
return new Vector2i(VarNumberSerializer.readSVarInt(from), VarNumberSerializer.readSVarInt(from));
|
||||
}
|
||||
|
||||
public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
VarNumberSerializer.writeSVarInt(to, chunk.getX());
|
||||
VarNumberSerializer.writeSVarInt(to, chunk.getY());
|
||||
}
|
||||
|
||||
public static int readLocalCoord(ByteBuf from) {
|
||||
return from.readUnsignedShort();
|
||||
}
|
||||
|
||||
public static void writeLocalCoord(ByteBuf to, int coord) {
|
||||
to.writeShort(coord);
|
||||
}
|
||||
|
||||
public static void writeVarIntChunkCoord(ByteBuf to, Vector2i chunk) {
|
||||
VarNumberSerializer.writeVarInt(to, chunk.getX());
|
||||
VarNumberSerializer.writeVarInt(to, chunk.getY());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.CollectionType;
|
||||
import com.nukkitx.network.VarInts;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import com.nukkitx.protocol.bedrock.v361.BedrockUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
|
|
@ -30,11 +27,12 @@ public class Toolbox {
|
|||
|
||||
ByteBuf b = Unpooled.buffer();
|
||||
|
||||
VarInts.writeInt(b, entries.size());
|
||||
VarInts.writeUnsignedInt(b, entries.size());
|
||||
|
||||
for (Map<String, Object> e : entries) {
|
||||
BedrockUtils.writeString(b, (String) e.get("name"));
|
||||
b.writeShortLE((Integer) e.get("data"));
|
||||
b.writeShortLE((int) e.get("data"));
|
||||
b.writeShortLE((int) e.get("id"));
|
||||
}
|
||||
|
||||
CACHED_PALLETE = b;
|
||||
|
|
@ -59,23 +57,23 @@ public class Toolbox {
|
|||
ArrayList<StartGamePacket.ItemEntry> l = new ArrayList<>();
|
||||
|
||||
for(HashMap e : s) {
|
||||
l.add(new StartGamePacket.ItemEntry((String) e.get("name"), ((Integer) e.get("id")).shortValue()));
|
||||
l.add(new StartGamePacket.ItemEntry((String) e.get("name"), (short) ((int) e.get("id"))));
|
||||
}
|
||||
|
||||
ITEMS = l;
|
||||
|
||||
ByteBuf serializer;
|
||||
/*ByteBuf serializer;
|
||||
|
||||
serializer = Unpooled.buffer();
|
||||
serializer.writeShortLE(1);
|
||||
ArraySerializer.writeVarIntByteArray(serializer, (chunkdata) -> {
|
||||
PSPEStuff.writeEmptySubChunk(chunkdata);
|
||||
GeyserUtils.writeVarIntByteArray(serializer, (chunkdata) -> {
|
||||
GeyserUtils.writeEmptySubChunk(chunkdata);
|
||||
chunkdata.writeZero(512);
|
||||
chunkdata.writeZero(256);
|
||||
chunkdata.writeByte(0);
|
||||
});
|
||||
|
||||
EMPTY_CHUNK = MiscSerializer.readAllBytes(serializer);
|
||||
EMPTY_CHUNK = GeyserUtils.readAllBytes(serializer);*/
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +81,6 @@ public class Toolbox {
|
|||
|
||||
public static final ByteBuf CACHED_PALLETE;
|
||||
|
||||
public static final byte[] EMPTY_CHUNK;
|
||||
//public static final byte[] EMPTY_CHUNK;
|
||||
|
||||
}
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
|
||||
|
||||
|
||||
public class VarNumberSerializer {
|
||||
|
||||
|
||||
|
||||
public static final int MAX_LENGTH = 5;
|
||||
|
||||
|
||||
|
||||
public static void writeFixedSizeVarInt(ByteBuf to, int i) {
|
||||
|
||||
int writerIndex = to.writerIndex();
|
||||
|
||||
while ((i & 0xFFFFFF80) != 0x0) {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
i >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
int paddingBytes = MAX_LENGTH - (to.writerIndex() - writerIndex) - 1;
|
||||
|
||||
if (paddingBytes == 0) {
|
||||
|
||||
to.writeByte(i);
|
||||
|
||||
} else {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
while (--paddingBytes > 0) {
|
||||
|
||||
to.writeByte(0x80);
|
||||
|
||||
}
|
||||
|
||||
to.writeByte(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int readVarInt(ByteBuf from) {
|
||||
|
||||
int value = 0;
|
||||
|
||||
int length = 0;
|
||||
|
||||
byte part;
|
||||
|
||||
do {
|
||||
|
||||
part = from.readByte();
|
||||
|
||||
value |= (part & 0x7F) << (length++ * 7);
|
||||
|
||||
if (length > MAX_LENGTH) {
|
||||
|
||||
throw new DecoderException("VarInt too big");
|
||||
|
||||
}
|
||||
|
||||
} while (part < 0);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarInt(ByteBuf to, int i) {
|
||||
|
||||
while ((i & 0xFFFFFF80) != 0x0) {
|
||||
|
||||
to.writeByte(i | 0x80);
|
||||
|
||||
i >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
to.writeByte(i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int readSVarInt(ByteBuf from) {
|
||||
|
||||
int varint = readVarInt(from);
|
||||
|
||||
return (varint >> 1) ^ -(varint & 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSVarInt(ByteBuf to, int varint) {
|
||||
|
||||
writeVarInt(to, (varint << 1) ^ (varint >> 31));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static long readVarLong(ByteBuf from) {
|
||||
|
||||
long varlong = 0L;
|
||||
|
||||
int length = 0;
|
||||
|
||||
byte part;
|
||||
|
||||
do {
|
||||
|
||||
part = from.readByte();
|
||||
|
||||
varlong |= (part & 0x7F) << (length++ * 7);
|
||||
|
||||
if (length > 10) {
|
||||
|
||||
throw new RuntimeException("VarLong too big");
|
||||
|
||||
}
|
||||
|
||||
} while ((part & 0x80) == 0x80);
|
||||
|
||||
return varlong;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeVarLong(ByteBuf to, long varlong) {
|
||||
|
||||
while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) {
|
||||
|
||||
to.writeByte((int) (varlong & 0x7FL) | 0x80);
|
||||
|
||||
varlong >>>= 7;
|
||||
|
||||
}
|
||||
|
||||
to.writeByte((int) varlong);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static long readSVarLong(ByteBuf from) {
|
||||
|
||||
long varlong = readVarLong(from);
|
||||
|
||||
return (varlong >> 1) ^ -(varlong & 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void writeSVarLong(ByteBuf to, long varlong) {
|
||||
|
||||
writeVarLong(to, (varlong << 1) ^ (varlong >> 63));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>plugin</artifactId>
|
||||
</project>
|
||||
3
pom.xml
3
pom.xml
|
|
@ -5,7 +5,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>GeyserMC</name>
|
||||
<description>Allows for players from Minecraft Bedrock Edition to join Minecraft Java Edition servers.</description>
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<revision>1.0-SNAPSHOT</revision>
|
||||
</properties>
|
||||
<organization>
|
||||
<name>GeyserMC</name>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue