diff options
| author | Pugmatt <pugmatt@gmail.com> | 2019-06-18 23:22:41 -0400 |
|---|---|---|
| committer | Pugmatt <pugmatt@gmail.com> | 2019-06-18 23:22:41 -0400 |
| commit | a98d6164e8f03c19ed568fbe05b69b2a1d4eccf2 (patch) | |
| tree | f7fb1e3057cc942e5ba78be233339e15c6dea788 /serverlist-server/src/main/com | |
| parent | 9be6579e87cc4db8dab08f007482317f5bd980a3 (diff) | |
| download | BedrockConnect-a98d6164e8f03c19ed568fbe05b69b2a1d4eccf2.tar.gz BedrockConnect-a98d6164e8f03c19ed568fbe05b69b2a1d4eccf2.tar.bz2 BedrockConnect-a98d6164e8f03c19ed568fbe05b69b2a1d4eccf2.zip | |
Added serverlist bedrock server
Diffstat (limited to 'serverlist-server/src/main/com')
19 files changed, 3886 insertions, 0 deletions
diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/AuthData.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/AuthData.java new file mode 100644 index 0000000..46955e8 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/AuthData.java @@ -0,0 +1,30 @@ +package main.com.pyratron.pugmatt.bedrockconnect; + +import java.util.UUID; + +public class AuthData { + private final String displayName; + private final UUID identity; + + public String getDisplayName() { + return displayName; + } + + public UUID getIdentity() { + return identity; + } + + public String getXuid() { + return xuid; + } + + private final String xuid; + + public AuthData(String displayName, UUID identity, String xuid) { + this.displayName = displayName; + this.identity = identity; + this.xuid = xuid; + } + + +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/BedrockConnect.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/BedrockConnect.java new file mode 100644 index 0000000..bda3b38 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/BedrockConnect.java @@ -0,0 +1,16 @@ +package main.com.pyratron.pugmatt.bedrockconnect; + +import main.com.pyratron.pugmatt.bedrockconnect.utils.PaletteManager; + +public class BedrockConnect { + + + public static PaletteManager paletteManager; + + public static void main(String[] args) { + paletteManager = new PaletteManager(); + + Server server = new Server(); + } + +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Chunk.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Chunk.java new file mode 100644 index 0000000..3f9ec0f --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Chunk.java @@ -0,0 +1,107 @@ +package main.com.pyratron.pugmatt.bedrockconnect; + +// References to this: https://github.com/NukkitX/Nukkit/blob/4ce13f2afb9a1a330df63a482bee9995ce1f96d5/src/main/java/cn/nukkit/level/format/anvil/ChunkRequestTask.java +// https://github.com/Nukkit/Nukkit/blob/master/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java +// https://github.com/Nukkit/Nukkit/blob/master/src/main/java/cn/nukkit/level/format/leveldb/Chunk.java +// https://github.com/NukkitX/Nukkit/blob/4ce13f2afb9a1a330df63a482bee9995ce1f96d5/src/main/java/cn/nukkit/level/format/mcregion/McRegion.java + +import java.nio.ByteBuffer; + +public class Chunk{ + + byte[] ids; + byte[] meta; + byte[] heightMap; + byte[] skyLight; + byte[] blockLight; + byte[] biomes; + byte[] blockEntities; + + public Chunk(int x, int z) { + ids = getBlockIdArray(); + meta = getBlockDataArray(); + heightMap = getHeightMapArray(x, z); + skyLight = getBlockSkyLightArray(); + blockLight = getBlockLightArray(); + biomes = getBiomeIdArray(); + blockEntities = getBlockEntitiesArray(); + } + + public byte[] encode() { + return ByteBuffer.allocate( + 16 * 16 * 128 + + 16 * 16 * 64 + + heightMap.length + + biomes.length + + this.blockEntities.length) + .put(ids) + .put(meta) + .put(heightMap) + .put(biomes) + .put(blockEntities) + .array(); + } + + public byte[] getBlockIdArray() { + byte[] blocks = new byte[16*128*16]; + for (int i = 0; i < 16*128*16; i++) { + int d = 1; + blocks[i] = (byte) d; + } + return blocks; + } + + public byte[] getBlockDataArray() { + byte[] blocks = new byte[16384]; + for (int i = 0; i < 16384; i++) { + int d = 0; + blocks[i] = (byte) d; + } + return blocks; + } + + public byte[] getBlockSkyLightArray() { + byte[] lights = new byte[16384]; + for (int i = 0; i < 16384; i++) { + int d = 0; + lights[i] = (byte) d; + } + return lights; + } + + public byte[] getBlockLightArray() { + byte[] lights = new byte[16384]; + for (int i = 0; i < 16384; i++) { + int d = 0; + lights[i] = (byte) d; + } + return lights; + } + + public byte[] getHeightMapArray(int x, int z) { + byte[] heights = new byte[256]; + for (int i = 0; i < 256; i++) { + int d = 1; + heights[i] = (byte) ((z << 4) | x & 0xFF); + } + return heights; + } + + public byte[] getBiomeIdArray() { + byte[] ids = new byte[1024]; + for (int i = 0; i < 1024; i++) { + int d = i; + ids[i] = (byte) (d >> 24); + } + return ids; + } + + public byte[] getBlockEntitiesArray() { + byte[] ids = new byte[32]; + for (int i = 0; i < 32; i++) { + int d = i; + ids[i] = (byte) d; + } + return ids; + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/PipePlayer.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/PipePlayer.java new file mode 100644 index 0000000..110a53d --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/PipePlayer.java @@ -0,0 +1,206 @@ +package main.com.pyratron.pugmatt.bedrockconnect; + +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.BedrockServerSession; +import com.nukkitx.protocol.bedrock.data.Attribute; +import com.nukkitx.protocol.bedrock.data.GamePublishSetting; +import com.nukkitx.protocol.bedrock.data.GameRule; +import com.nukkitx.protocol.bedrock.packet.*; +import main.com.pyratron.pugmatt.bedrockconnect.chunk.ChunkData; + +import java.util.ArrayList; + +public class PipePlayer { + + private BedrockServerSession session; + + public PipePlayer(AuthData data, BedrockServerSession session) { + this.session = session; + } + + public BedrockServerSession getSession() { + return session; + } + + public void joinGame() { + + /** + StartGamePacket pkStartGame = new StartGamePacket(); + pkStartGame.setUniqueEntityId(packet.getEntityId()); + pkStartGame.setRuntimeEntityId(packet.getEntityId()); + pkStartGame.setDimensionId(0); + pkStartGame.setSeed(0); + pkStartGame.setGeneratorId(1); + pkStartGame.setDifficulty(0); + pkStartGame.setDefaultSpawn(new Vector3i(0, 72, 0)); + pkStartGame.setPlayerPosition(new Vector3f(0f, 72f + 5, 0f)); + pkStartGame.setLevelId(""); + pkStartGame.setWorldName("World"); + pkStartGame.setDefaultPlayerPermission(2); + pkStartGame.setCommandsEnabled(true); + pkStartGame.setPremiumWorldTemplateId(""); **/ + + MovePlayerPacket mp = new MovePlayerPacket(); + mp.setRuntimeEntityId(-1); + mp.setOnGround(false); + mp.setMode(MovePlayerPacket.Mode.NORMAL); + mp.setRotation(new Vector3f(0,0,0)); + mp.setPosition(new Vector3f(0,0,0)); + session.sendPacketImmediately(mp); + + StartGamePacket startGamePacket = new StartGamePacket(); + startGamePacket.setUniqueEntityId(0); + startGamePacket.setRuntimeEntityId(0); + startGamePacket.setPlayerGamemode(0); + startGamePacket.setPlayerPosition(new Vector3f(-249, 67, -275)); + startGamePacket.setRotation(new Vector2f(1, 1)); + + startGamePacket.setSeed(1111); + startGamePacket.setDimensionId(0); + startGamePacket.setGeneratorId(0); + startGamePacket.setLevelGamemode(0); + startGamePacket.setDifficulty(0); + startGamePacket.setDefaultSpawn(new Vector3i(-249, 67, -275)); + startGamePacket.setAcheivementsDisabled(true); + startGamePacket.setTime(1300); + startGamePacket.setEduLevel(false); + startGamePacket.setEduFeaturesEnabled(false); + startGamePacket.setRainLevel(0); + startGamePacket.setLightningLevel(0); + startGamePacket.setPlatformLockedContentConfirmed(false); + startGamePacket.setMultiplayerGame(false); + startGamePacket.setBroadcastingToLan(false); + startGamePacket.getGamerules().add((new GameRule("showcoordinates", true))); + startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC); + startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC); + startGamePacket.setCommandsEnabled(true); + startGamePacket.setTexturePacksRequired(false); + startGamePacket.setBonusChestEnabled(false); + startGamePacket.setStartingWithMap(false); + startGamePacket.setTrustingPlayers(true); + startGamePacket.setDefaultPlayerPermission(1); + startGamePacket.setServerChunkTickRange(4); + startGamePacket.setBehaviorPackLocked(false); + startGamePacket.setResourcePackLocked(false); + startGamePacket.setFromLockedWorldTemplate(false); + startGamePacket.setUsingMsaGamertagsOnly(false); + startGamePacket.setFromWorldTemplate(false); + startGamePacket.setWorldTemplateOptionLocked(false); + + startGamePacket.setLevelId("oerjhii"); + startGamePacket.setWorldName("world"); + startGamePacket.setPremiumWorldTemplateId("00000000-0000-0000-0000-000000000000"); + startGamePacket.setCurrentTick(1); + startGamePacket.setEnchantmentSeed(1); + startGamePacket.setMultiplayerCorrelationId(""); + + startGamePacket.setCachedPalette(BedrockConnect.paletteManager.getCachedPalette()); + + session.sendPacketImmediately(startGamePacket); + + spawn(); + + + } + + public void sendAttributes() { + UpdateAttributesPacket pk = new UpdateAttributesPacket(); + pk.setRuntimeEntityId(0); + pk.setAttributes(new ArrayList<Attribute>() { + { + add(new Attribute("minecraft:health", 0.00f, 20.00f, 20.00f, 20.00f)); + add(new Attribute("minecraft:player.hunger", 0.00f, 20.00f, 20.00f, 20.00f)); + add(new Attribute("minecraft:movement", 0.00f, 340282346638528859811704183484516925440.00f, 0.10f, 0.10f)); + add(new Attribute("minecraft:player.level", 0.00f, 24791.00f, 0.00f, 0.00f)); + add(new Attribute("minecraft:player.experience", 0.00f, 1.00f, 0.00f, 0.00f)); + } + }); + session.sendPacketImmediately(pk); + + RespawnPacket rp = new RespawnPacket(); + rp.setPosition(new Vector3f(0, 0 ,0)); + session.sendPacketImmediately(rp); + + spawn(); + } + + public void spawn() { + + ChunkData data = new ChunkData(true); + data.encode(); + + Vector3f pos = new Vector3f(-249, 67, -275); + int chunkX = pos.getFloorX() >> 4; + int chunkZ = pos.getFloorX() >> 4; + + for (int x = -3; x < 3; x++) { + for (int z = -3; z < 3; z++) { + FullChunkDataPacket data2 = new FullChunkDataPacket(); + data2.setChunkX(chunkX + x); + data2.setChunkZ(chunkZ + z); + data2.setData(new byte[0]); + session.sendPacketImmediately(data2); + } + } + + PlayStatusPacket playStatus = new PlayStatusPacket(); + playStatus.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); + session.sendPacketImmediately(playStatus); + + /** SetSpawnPositionPacket pkSpawn = new SetSpawnPositionPacket(); + pkSpawn.setSpawnType(SetSpawnPositionPacket.Type.PLAYER_SPAWN); + pkSpawn.setSpawnForced(false); + pkSpawn.setBlockPosition(new Vector3i(-249, 67, -275)); + session.sendPacketImmediately(pkSpawn); + + MovePlayerPacket mp = new MovePlayerPacket(); + mp.setRuntimeEntityId(-1); + mp.setOnGround(false); + mp.setMode(MovePlayerPacket.Mode.NORMAL); + mp.setRotation(new Vector3f(0,0,0)); + mp.setPosition(new Vector3f(0,0,0)); + session.sendPacketImmediately(mp); + + SetTimePacket st = new SetTimePacket(); + st.setTime(0); + session.sendPacketImmediately(st); + + AdventureSettingsPacket as = new AdventureSettingsPacket(); + as.setCommandPermission(0); + as.setCustomFlags(0); + as.setPlayerFlags(0); + as.setPlayerPermission(0); + as.setUniqueEntityId(0); + as.setWorldFlags(0); + as.setWorldFlags(0); + session.sendPacketImmediately(as); + + RespawnPacket rp = new RespawnPacket(); + rp.setPosition(new Vector3f(0,0,0)); + session.sendPacketImmediately(rp); + + + /** FullChunkDataPacket fullChunk = new FullChunkDataPacket(); + fullChunk.setChunkX(0); + fullChunk.setChunkZ(0); + fullChunk.setData(data.getBuffer()); + session.sendPacketImmediately(fullChunk); + fullChunk.setChunkX(0); + fullChunk.setChunkZ(-1); + session.sendPacketImmediately(fullChunk); + fullChunk.setChunkX(-1); + fullChunk.setChunkZ(0); + session.sendPacketImmediately(fullChunk); + fullChunk.setChunkX(-1); + fullChunk.setChunkZ(-1); + session.sendPacketImmediately(fullChunk); **/ + + //SetSpawnPositionPacket ss = new SetSpawnPositionPacket(); + //ss.setSpawnType(SetSpawnPositionPacket.Type.PLAYER_SPAWN); + //session.sendPacketImmediately(ss); + + + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Server.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Server.java new file mode 100644 index 0000000..f2570ae --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/Server.java @@ -0,0 +1,88 @@ +package main.com.pyratron.pugmatt.bedrockconnect; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import com.nukkitx.protocol.bedrock.*; +import com.nukkitx.protocol.bedrock.v354.Bedrock_v354; +import main.com.pyratron.pugmatt.bedrockconnect.listeners.PacketHandler; + + +import javax.annotation.Nonnull; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; + +public class Server { + + public BedrockServer server; + public BedrockPong pong; + + private BedrockPacketCodec codec; + + public int getProtocol() { + return codec.getProtocolVersion(); + } + + public BedrockPacketCodec getCodec() { + return codec; + } + + public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + public static final YAMLMapper YAML_MAPPER = (YAMLMapper) new YAMLMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + private List<PipePlayer> players = new ArrayList<>(); + + public List<PipePlayer> getPlayers() { + return players; + } + + public void addPlayer(PipePlayer player) { + this.players.add(player); + } + + public PipePlayer addPlayer(AuthData data, BedrockServerSession session) { + PipePlayer player = new PipePlayer(data, session); + this.players.add(player); + return player; + } + + public void removePlayer(PipePlayer player) { + this.players.remove(player); + } + + + public Server() { + Server current = this; + InetSocketAddress bindAddress = new InetSocketAddress("localhost", 19132); + codec = Bedrock_v354.V354_CODEC; + server = new BedrockServer(bindAddress); + pong = new BedrockPong(); + pong.setEdition("MCPE"); + pong.setMotd("BedrockConnect Connection Successful"); + pong.setSubMotd("Test"); + pong.setPlayerCount(0); + pong.setMaximumPlayerCount(20); + pong.setGameType("Survival"); + pong.setProtocolVersion(Bedrock_v354.V354_CODEC.getProtocolVersion()); + server.setHandler(new BedrockServerEventHandler() { + @Override + public boolean onConnectionRequest(InetSocketAddress address) { + return true; // Connection will be accepted + } + @Nonnull + public BedrockPong onQuery(InetSocketAddress address) { + return pong; + } + @Override + public void onSessionCreation(BedrockServerSession session) { + session.setPacketHandler(new PacketHandler(session, current)); + } + }); + // Start server up + server.bind().join(); + System.out.println("Bedrock Connection Started: localhost:19132"); + + while(true) { } + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ChunkData.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ChunkData.java new file mode 100644 index 0000000..a7460d3 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ChunkData.java @@ -0,0 +1,80 @@ +package main.com.pyratron.pugmatt.bedrockconnect.chunk; + +import main.com.pyratron.pugmatt.bedrockconnect.utils.BinaryStream; + +import java.util.Arrays; + +// reference: https://github.com/DragonetMC/DragonProxy/blob/master/protocol/src/main/java/org/dragonet/protocol/type/chunk/ChunkData.java +// Original Author: HoverEpic + +public class ChunkData extends BinaryStream { + + /** + * 16x16x16 section of the chunk. The array's keys also indicate the + * section's height (the 3rd element of the array will be the 3rd section + * from bottom, starting at `y=24`). The amount of sections should be in a + * range from 0 (empty chunk) to 16. + */ + public Section[] sections = new Section[0]; + public short[] heights = new short[256]; + /** + * Biomes in order `xz`. + */ + public byte[] biomes = new byte[256]; + /** + * Colums where there are world borders (in format `xz`). This feature + * hasn't been implemented in the game yet and crashes the client. + */ + public byte[] borders = new byte[0]; + public ExtraData[] extraData = new ExtraData[0]; + /** + * Additional data for the chunk's block entities (tiles), encoded in the + * same way as BlockEntityData.nbt is. The position is given by the `Int` + * tags `x`, `y`, `z` which are added to the block's compound tag together + * with the `String` tag `id` that contains the name of the tile in pascal + * case. Wrong encoding or missing tags may result in the block becoming + * invisible. + */ + public byte[] blockEntities = new byte[0]; + + public ChunkData(boolean empty) { + if(empty) { + sections = new Section[16]; + for (int cy = 0; cy < 16; cy++) { + sections[cy] = new Section(); + if (cy < 6) + Arrays.fill(sections[cy].blockIds, (byte) 1); + } + } + } + + public ChunkData(Section[] sections, short[] heights, byte[] biomes, byte[] borders, ExtraData[] extraData, + byte[] blockEntities) { + this.sections = sections; + this.heights = heights; + this.biomes = biomes; + this.borders = borders; + this.extraData = extraData; + this.blockEntities = blockEntities; + } + + public void encode() { + reset(); + putByte((byte) (sections.length & 0xff)); + for (Section s : sections) { + s.encode(this); + } + for (short h : heights) { + this.putLShort(h); + } + this.put(biomes); + this.putByte((byte) (borders.length & 0xFF)); + this.put(borders); + this.putVarInt(extraData.length); + for (ExtraData extra : extraData) { + extra.encode(this); + } + this.put(blockEntities); + } + +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ExtraData.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ExtraData.java new file mode 100644 index 0000000..351b2ad --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/ExtraData.java @@ -0,0 +1,40 @@ +package main.com.pyratron.pugmatt.bedrockconnect.chunk; + +// reference: https://github.com/DragonetMC/DragonProxy/blob/master/protocol/src/main/java/org/dragonet/protocol/type/chunk/ExtraData.java +// Original Author: HoverEpic + +import main.com.pyratron.pugmatt.bedrockconnect.utils.BinaryStream; + +public class ExtraData { + + private int key; + private short value; + + public int getKey() { + return key; + } + + public short getValue() { + return value; + } + + public ExtraData() { + + } + + public ExtraData(int key, short value) { + this.key = key; + this.value = value; + } + + public void encode(BinaryStream out) { + out.putVarInt(key); + out.putLShort(value); + } + + public void decode(BinaryStream in) { + key = (int) in.getUnsignedVarInt(); + value = (short) in.getLShort(); + } + +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/Section.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/Section.java new file mode 100644 index 0000000..f771f06 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/chunk/Section.java @@ -0,0 +1,35 @@ +package main.com.pyratron.pugmatt.bedrockconnect.chunk; + +// reference: https://github.com/DragonetMC/DragonProxy/blob/master/protocol/src/main/java/org/dragonet/protocol/type/chunk/Section.java +// Original Author: HoverEpic + +import main.com.pyratron.pugmatt.bedrockconnect.utils.BinaryStream; + +public class Section { + + public byte storageVers = 0; + public byte[] blockIds = new byte[4096]; + public byte[] blockMetas = new byte[2048]; + + public Section(byte storageVers, byte[] blockIds, byte[] blockMetas) { + this.storageVers = storageVers; + this.blockIds = blockIds; + this.blockMetas = blockMetas; + } + + public Section() { + + } + + public void encode(BinaryStream out) { + out.putByte(storageVers); + out.put(blockIds); + out.put(blockMetas); + } + + public void decode(BinaryStream in) { + storageVers = (byte) (in.getByte() & 0xFF); + blockIds = in.get(4096); + blockMetas = in.get(2048); + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIComponents.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIComponents.java new file mode 100644 index 0000000..85c656b --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIComponents.java @@ -0,0 +1,83 @@ +package main.com.pyratron.pugmatt.bedrockconnect.gui; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.util.ArrayList; + +public class UIComponents { + + public static JsonObject createLabel(String text) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "label"); + obj.addProperty("text", text); + return obj; + } + + public static JsonObject createInput(String text, String placeholder) { + JsonObject input = new JsonObject(); + input.addProperty("type", "input"); + input.addProperty("placeholder", placeholder); + input.addProperty("text", text); + return input; + } + + public static JsonObject createButton(String text, String image, String imageType) { + JsonObject button = new JsonObject(); + button.addProperty("text", text); + if(image != null && imageType != null) { + JsonObject buttonImage = new JsonObject(); + buttonImage.addProperty("type", imageType); + buttonImage.addProperty("data", image); + button.add("image", buttonImage); + } + return button; + } + + public static JsonObject createButton(String text) { + JsonObject button = new JsonObject(); + button.addProperty("text", text); + return button; + } + + public static JsonObject createForm(String type, String title) { + JsonObject form = new JsonObject(); + form.addProperty("type", type); + form.addProperty("title", title); + return form; + } + + public static ModalFormRequestPacket createError(String error) { + ModalFormRequestPacket mf = new ModalFormRequestPacket(); + mf.setFormId(UIForms.ERROR); + JsonObject form = new JsonObject(); + form.addProperty("type", "custom_form"); + form.addProperty("title", "Error"); + JsonArray content = new JsonArray(); + content.add(createLabel(error)); + form.add("content", content); + mf.setFormData(form.toString()); + return mf; + } + + public static ArrayList<String> getFormData(String data) { + JSONParser parser = new JSONParser(); + try { + JSONArray obj = (JSONArray) parser.parse(data); + ArrayList<String> strings = new ArrayList<>(); + for(int i=0;i<obj.size();i++) { + System.out.println(obj.get(i).toString()); + strings.add(obj.get(i).toString()); + } + return strings; + } catch(ParseException e) { + System.out.println(e.toString()); + } + + return null; + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIForms.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIForms.java new file mode 100644 index 0000000..90d93e7 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/gui/UIForms.java @@ -0,0 +1,50 @@ +package main.com.pyratron.pugmatt.bedrockconnect.gui; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket; + +public class UIForms { + public static final int ERROR = 2, MAIN = 0, DIRECT_CONNECT = 1; + + public static int currentForm = 0; + + public static ModalFormRequestPacket createMain() { + currentForm = MAIN; + ModalFormRequestPacket mf = new ModalFormRequestPacket(); + mf.setFormId(UIForms.MAIN); + + JsonObject out = UIComponents.createForm("form", "ServerList"); + out.addProperty("content", ""); + + JsonArray buttons = new JsonArray(); + + buttons.add(UIComponents.createButton("Direct Connect")); + buttons.add(UIComponents.createButton("Play.SkyBlockpe.com:19132", "https://i.imgur.com/3BmFZRE.png", "url")); + buttons.add(UIComponents.createButton("Add Server")); + buttons.add(UIComponents.createButton("Remove Server")); + + out.add("buttons", buttons); + + mf.setFormData(out.toString()); + + return mf; + } + + public static ModalFormRequestPacket createDirectConnect() { + currentForm = DIRECT_CONNECT; + ModalFormRequestPacket mf = new ModalFormRequestPacket(); + mf.setFormId(UIForms.DIRECT_CONNECT); + JsonObject out = UIComponents.createForm("custom_form", "Add Server"); + + JsonArray inputs = new JsonArray(); + + inputs.add(UIComponents.createInput("Server Address", "Please enter IP or Address")); + inputs.add(UIComponents.createInput("Server Port", "Please enter Port (E.g. 19132)")); + + out.add("content", inputs); + mf.setFormData(out.toString()); + + return mf; + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/ClientPacketHandler.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/ClientPacketHandler.java new file mode 100644 index 0000000..2595a33 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/ClientPacketHandler.java @@ -0,0 +1,828 @@ +package main.com.pyratron.pugmatt.bedrockconnect.listeners; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.nukkitx.protocol.bedrock.BedrockClientSession; +import com.nukkitx.protocol.bedrock.packet.*; + +import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; +import com.nukkitx.protocol.bedrock.packet.LoginPacket; +import main.com.pyratron.pugmatt.bedrockconnect.AuthData; +import main.com.pyratron.pugmatt.bedrockconnect.PipePlayer; +import net.minidev.json.JSONObject; + +// Heavily referenced from https://github.com/NukkitX/ProxyPass/blob/master/src/main/java/com/nukkitx/proxypass/network/bedrock/session/UpstreamPacketHandler.java + +public class ClientPacketHandler implements BedrockPacketHandler { + + private static final int PIXEL_SIZE = 4; + + public static final int SINGLE_SKIN_SIZE = 64 * 32 * PIXEL_SIZE; + public static final int DOUBLE_SKIN_SIZE = 64 * 64 * PIXEL_SIZE; + public static final int SKIN_128_64_SIZE = 128 * 64 * PIXEL_SIZE; + public static final int SKIN_128_128_SIZE = 128 * 128 * PIXEL_SIZE; + + private BedrockClientSession session; + private PipePlayer player; + + private JSONObject skinData; + private JSONObject extraData; + private ArrayNode chainData; + private AuthData authData; + + @Override + public boolean handle(AdventureSettingsPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AnimatePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BlockEntityDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BlockPickRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BookEditPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ClientToServerHandshakePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CommandBlockUpdatePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CommandRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ContainerClosePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CraftingEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(EntityEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(EntityFallPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(EntityPickRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(EventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(InteractPacket packet) { + System.out.println(packet.toString()); + session.sendPacketImmediately(packet); + return false; + } + + @Override + public boolean handle(InventoryContentPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(InventorySlotPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(InventoryTransactionPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ItemFrameDropItemPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LabTablePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LecternUpdatePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LevelSoundEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LevelSoundEvent3Packet packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MapInfoRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MobArmorEquipmentPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MobEquipmentPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ModalFormResponsePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MoveEntityAbsolutePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MovePlayerPacket packet) { + System.out.println(packet.toString()); + session.sendPacketImmediately(packet); + return false; + } + + @Override + public boolean handle(NetworkStackLatencyPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PhotoTransferPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayerActionPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayerHotbarPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayerInputPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayerSkinPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PurchaseReceiptPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(RequestChunkRadiusPacket packet) { + System.out.println(packet.toString()); + ChunkRadiusUpdatedPacket chunk = new ChunkRadiusUpdatedPacket(); + chunk.setRadius(Math.max(3, Math.min(packet.getRadius(), 5))); + //PacketHeader ph = new PacketHeader(); + // ph.set + //chunk.setHeader(); + session.sendPacketImmediately(chunk); + + int chunkPositionX = 0; + int chunkPositionZ = 0; + int chunkRadius = 5; + for (int x = -chunkRadius; x < chunkRadius; x++) { + for (int z = -chunkRadius; z < chunkRadius; z++) { + FullChunkDataPacket fullChunk = new FullChunkDataPacket(); + fullChunk.setChunkX(chunkPositionX + x); + fullChunk.setChunkZ(chunkPositionZ + z); + fullChunk.setData(new byte[0]); + session.sendPacket(fullChunk); + } + } + + PlayStatusPacket play = new PlayStatusPacket(); + play.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); + session.sendPacketImmediately(play); + + SetTimePacket st = new SetTimePacket(); + st.setTime(0); + session.sendPacketImmediately(st); + return false; + } + + @Override + public boolean handle(RiderJumpPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ServerSettingsRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetDefaultGameTypePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetLocalPlayerAsInitializedPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetPlayerGameTypePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SubClientLoginPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(TextPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddBehaviorTreePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddEntityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddHangingEntityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddItemEntityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddPaintingPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AddPlayerPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AvailableCommandsPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BlockEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BossEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CameraPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ChangeDimensionPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ChunkRadiusUpdatedPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ClientboundMapItemDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CommandOutputPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ContainerOpenPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ContainerSetDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(CraftingDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ExplodePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(FullChunkDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(GameRulesChangedPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(GuiDataPickItemPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(HurtArmorPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AutomationClientConnectPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LevelEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MapCreateLockedCopyPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MobEffectPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ModalFormRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(MoveEntityDeltaPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(NpcRequestPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(OnScreenTextureAnimationPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayerListPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlaySoundPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(PlayStatusPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(RemoveEntityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(RemoveObjectivePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ResourcePackChunkDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ResourcePackDataInfoPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ResourcePacksInfoPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ResourcePackStackPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(RespawnPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ScriptCustomEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ServerSettingsResponsePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ServerToClientHandshakePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetCommandsEnabledPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetDifficultyPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetDisplayObjectivePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetEntityDataPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetEntityLinkPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetEntityMotionPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetHealthPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetLastHurtByPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetScoreboardIdentityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetScorePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetSpawnPositionPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetTimePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SetTitlePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ShowCreditsPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ShowProfilePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(ShowStoreOfferPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SimpleEventPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SpawnExperienceOrbPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(StartGamePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(StopSoundPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(StructureBlockUpdatePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(TakeItemEntityPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(TransferPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateAttributesPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateBlockPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateBlockSyncedPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateEquipPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateSoftEnumPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(UpdateTradePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(AvailableEntityIdentifiersPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(BiomeDefinitionListPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(LevelSoundEvent2Packet packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(NetworkChunkPublisherUpdatePacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(SpawnParticleEffectPacket packet) { + System.out.println(packet.toString()); + return false; + } + + @Override + public boolean handle(VideoStreamConnectPacket packet) { + System.out.println(packet.toString()); + return false; + } + + public ClientPacketHandler(BedrockClientSession session) { + this.session = session; + + session.addDisconnectHandler((Reason) -> disconnect()); + } + + public void disconnect() { + //player.getClient().getSession().disconnect("Left Game"); + //server.removePlayer(player); + } + + @Override + public boolean handle(DisconnectPacket packet) { + System.out.println(packet.toString()); + return true; + } + + @Override + public boolean handle(ResourcePackChunkRequestPacket packet) { + System.out.println(packet.toString()); + return true; + } + + @Override + public boolean handle(ResourcePackClientResponsePacket packet) { + System.out.println(packet.toString()); + return true; + } + + @Override + public boolean handle(LoginPacket packet) { + System.out.println(packet.toString()); + return true; + } + +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/PacketHandler.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/PacketHandler.java new file mode 100644 index 0000000..64b680e --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/listeners/PacketHandler.java @@ -0,0 +1,1016 @@ +package main.com.pyratron.pugmatt.bedrockconnect.listeners; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.nukkitx.network.util.Preconditions; +import com.nukkitx.protocol.bedrock.packet.*; + +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jose.crypto.factories.DefaultJWSVerifierFactory; +import com.nukkitx.protocol.bedrock.BedrockServerSession; +import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; +import com.nukkitx.protocol.bedrock.packet.LoginPacket; +import com.nukkitx.protocol.bedrock.util.EncryptionUtils; +import main.com.pyratron.pugmatt.bedrockconnect.AuthData; +import main.com.pyratron.pugmatt.bedrockconnect.PipePlayer; +import main.com.pyratron.pugmatt.bedrockconnect.Server; +import main.com.pyratron.pugmatt.bedrockconnect.gui.UIComponents; +import main.com.pyratron.pugmatt.bedrockconnect.gui.UIForms; +import net.minidev.json.JSONObject; + +import java.io.IOException; +import java.security.interfaces.ECPublicKey; +import java.util.ArrayList; +import java.util.UUID; + +// Heavily referenced from https://github.com/NukkitX/ProxyPass/blob/master/src/main/java/com/nukkitx/proxypass/network/bedrock/session/UpstreamPacketHandler.java + +public class PacketHandler implements BedrockPacketHandler { + + private static final int PIXEL_SIZE = 4; + + public static final int SINGLE_SKIN_SIZE = 64 * 32 * PIXEL_SIZE; + public static final int DOUBLE_SKIN_SIZE = 64 * 64 * PIXEL_SIZE; + public static final int SKIN_128_64_SIZE = 128 * 64 * PIXEL_SIZE; + public static final int SKIN_128_128_SIZE = 128 * 128 * PIXEL_SIZE; + + private Server server; + private BedrockServerSession session; + private PipePlayer player; + + private JSONObject skinData; + private JSONObject extraData; + private ArrayNode chainData; + private AuthData authData; + + @Override + public boolean handle(AdventureSettingsPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AnimatePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BlockEntityDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BlockPickRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BookEditPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ClientToServerHandshakePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CommandBlockUpdatePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CommandRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ContainerClosePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CraftingEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(EntityEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(EntityFallPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(EntityPickRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(EventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(InteractPacket packet) { + System.out.println(packet.getClass().getName()); + session.sendPacketImmediately(packet); + return false; + } + + @Override + public boolean handle(InventoryContentPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(InventorySlotPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(InventoryTransactionPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ItemFrameDropItemPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LabTablePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LecternUpdatePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LevelSoundEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LevelSoundEvent3Packet packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MapInfoRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MobArmorEquipmentPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MobEquipmentPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + + @Override + public boolean handle(ModalFormResponsePacket packet) { + System.out.println(packet.getClass().getName()); + System.out.println("\"" + packet.getFormData().replaceAll("\\s+","") + "\""); + + switch (packet.getFormId()) { + case 0: + if(UIForms.currentForm == UIForms.MAIN) { + if (packet.getFormData().replaceAll("\\s+","").contains("0")) { + session.sendPacketImmediately(UIForms.createDirectConnect()); + } else if (packet.getFormData().contains("null")) { + session.disconnect("Exiting Server List"); + } + } + break; + case 1: + try { + ArrayList<String> data = UIComponents.getFormData(packet.getFormData()); + TransferPacket tp = new TransferPacket(); + tp.setAddress(data.get(0).replace(" ", "")); + tp.setPort(Integer.parseInt(data.get(1))); + session.sendPacketImmediately(tp); + } catch(Exception e) { + session.sendPacketImmediately(UIComponents.createError("Please enter a port that contains only numbers.")); + } + break; + case 2: + session.sendPacketImmediately(UIForms.createMain()); + break; + } + return false; + } + + @Override + public boolean handle(MoveEntityAbsolutePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MovePlayerPacket packet) { + System.out.println(packet.getClass().getName()); + session.sendPacketImmediately(packet); + return false; + } + + @Override + public boolean handle(NetworkStackLatencyPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PhotoTransferPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayerActionPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayerHotbarPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayerInputPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayerSkinPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PurchaseReceiptPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(RequestChunkRadiusPacket packet) { + System.out.println(packet.getClass().getName()); + /** chunk = new ChunkRadiusUpdatedPacket(); + chunk.setRadius(Math.max(3, Math.min(packet.getRadius(), 5))); + //PacketHeader ph = new PacketHeader(); + // ph.set + //chunk.setHeader(); + session.sendPacketImmediately(chunk); + + int chunkPositionX = 0; + int chunkPositionZ = 0; + int chunkRadius = 5; + for (int x = -chunkRadius; x < chunkRadius; x++) { + for (int z = -chunkRadius; z < chunkRadius; z++) { + FullChunkDataPacket fullChunk = new FullChunkDataPacket(); + fullChunk.setChunkX(chunkPositionX + x); + fullChunk.setChunkZ(chunkPositionZ + z); + fullChunk.setData(new byte[0]); + session.sendPacketImmediately(fullChunk); + } + } + + PlayStatusPacket play = new PlayStatusPacket(); + play.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); + session.sendPacketImmediately(play); + + SetTimePacket st = new SetTimePacket(); + st.setTime(0); + session.sendPacketImmediately(st); + return false; **/ + return false; + } + + @Override + public boolean handle(RiderJumpPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ServerSettingsRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetDefaultGameTypePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetLocalPlayerAsInitializedPacket packet) { + System.out.println(packet.getClass().getName()); + + session.sendPacketImmediately(UIForms.createMain()); + return false; + } + + @Override + public boolean handle(SetPlayerGameTypePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SubClientLoginPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(TextPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddBehaviorTreePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddEntityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddHangingEntityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddItemEntityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddPaintingPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AddPlayerPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AvailableCommandsPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BlockEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BossEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CameraPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ChangeDimensionPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ChunkRadiusUpdatedPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ClientboundMapItemDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CommandOutputPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ContainerOpenPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ContainerSetDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(CraftingDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ExplodePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(FullChunkDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(GameRulesChangedPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(GuiDataPickItemPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(HurtArmorPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AutomationClientConnectPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LevelEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MapCreateLockedCopyPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MobEffectPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ModalFormRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(MoveEntityDeltaPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(NpcRequestPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(OnScreenTextureAnimationPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayerListPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlaySoundPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(PlayStatusPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(RemoveEntityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(RemoveObjectivePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ResourcePackChunkDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ResourcePackDataInfoPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ResourcePacksInfoPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ResourcePackStackPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(RespawnPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ScriptCustomEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ServerSettingsResponsePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ServerToClientHandshakePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetCommandsEnabledPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetDifficultyPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetDisplayObjectivePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetEntityDataPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetEntityLinkPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetEntityMotionPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetHealthPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetLastHurtByPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetScoreboardIdentityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetScorePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetSpawnPositionPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetTimePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SetTitlePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ShowCreditsPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ShowProfilePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(ShowStoreOfferPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SimpleEventPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SpawnExperienceOrbPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(StartGamePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(StopSoundPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(StructureBlockUpdatePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(TakeItemEntityPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(TransferPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateAttributesPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateBlockPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateBlockSyncedPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateEquipPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateSoftEnumPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(UpdateTradePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(AvailableEntityIdentifiersPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(BiomeDefinitionListPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(LevelSoundEvent2Packet packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(NetworkChunkPublisherUpdatePacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(SpawnParticleEffectPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + @Override + public boolean handle(VideoStreamConnectPacket packet) { + System.out.println(packet.getClass().getName()); + return false; + } + + public PacketHandler(BedrockServerSession session, Server server) { + this.session = session; + this.server = server; + + session.addDisconnectHandler((Reason) -> disconnect()); + } + + public void disconnect() { + server.removePlayer(player); + } + + private static boolean validateChainData(JsonNode data) throws Exception { + ECPublicKey lastKey = null; + boolean validChain = false; + for (JsonNode node : data) { + JWSObject jwt = JWSObject.parse(node.asText()); + + if (!validChain) { + validChain = verifyJwt(jwt, EncryptionUtils.getMojangPublicKey()); + } + + if (lastKey != null) { + verifyJwt(jwt, lastKey); + } + + JsonNode payloadNode = Server.JSON_MAPPER.readTree(jwt.getPayload().toString()); + JsonNode ipkNode = payloadNode.get("identityPublicKey"); + Preconditions.checkState(ipkNode != null && ipkNode.getNodeType() == JsonNodeType.STRING, "identityPublicKey node is missing in chain"); + lastKey = EncryptionUtils.generateKey(ipkNode.asText()); + } + return validChain; + } + + + private static boolean verifyJwt(JWSObject jwt, ECPublicKey key) throws JOSEException { + return jwt.verify(new DefaultJWSVerifierFactory().createJWSVerifier(jwt.getHeader(), key)); + } + + @Override + public boolean handle(DisconnectPacket packet) { + return false; + } + + @Override + public boolean handle(ResourcePackChunkRequestPacket packet) { + System.out.println("Received Chunk Radius request"); + return false; + } + + @Override + public boolean handle(ResourcePackClientResponsePacket packet) { + switch (packet.getStatus()) { + case COMPLETED: + this.player = this.server.addPlayer(authData, session); + this.player.joinGame(); + break; + case HAVE_ALL_PACKS: + ResourcePackStackPacket rs = new ResourcePackStackPacket(); + rs.setExperimental(false); + rs.setForcedToAccept(false); + session.sendPacketImmediately(rs); + break; + default: + session.disconnect("disconnectionScreen.resourcePack"); + break; + } + + return true; + } + + @Override + public boolean handle(LoginPacket packet) { + int protocolVersion = packet.getProtocolVersion(); + + if (protocolVersion != server.getProtocol()) { + PlayStatusPacket status = new PlayStatusPacket(); + if (protocolVersion > server.getProtocol()) { + status.setStatus(PlayStatusPacket.Status.FAILED_SERVER); + } else { + status.setStatus(PlayStatusPacket.Status.FAILED_CLIENT); + } + session.sendPacket(status); + } + session.setPacketCodec(server.getCodec()); + + JsonNode certData; + try { + certData = Server.JSON_MAPPER.readTree(packet.getChainData().toByteArray()); + } catch (IOException e) { + throw new RuntimeException("Certificate JSON can not be read."); + } + + JsonNode certChainData = certData.get("chain"); + if (certChainData.getNodeType() != JsonNodeType.ARRAY) { + throw new RuntimeException("Certificate data is not valid"); + } + chainData = (ArrayNode) certChainData; + + boolean validChain; + try { + validChain = validateChainData(certChainData); + + JWSObject jwt = JWSObject.parse(certChainData.get(certChainData.size() - 1).asText()); + JsonNode payload = Server.JSON_MAPPER.readTree(jwt.getPayload().toBytes()); + + if (payload.get("extraData").getNodeType() != JsonNodeType.OBJECT) { + throw new RuntimeException("AuthData was not found!"); + } + + extraData = (JSONObject) jwt.getPayload().toJSONObject().get("extraData"); + + this.authData = new AuthData(extraData.getAsString("displayName"), + UUID.fromString(extraData.getAsString("identity")), extraData.getAsString("XUID")); + + if (payload.get("identityPublicKey").getNodeType() != JsonNodeType.STRING) { + throw new RuntimeException("Identity Public Key was not found!"); + } + ECPublicKey identityPublicKey = EncryptionUtils.generateKey(payload.get("identityPublicKey").textValue()); + + JWSObject clientJwt = JWSObject.parse(packet.getSkinData().toString()); + verifyJwt(clientJwt, identityPublicKey); + skinData = clientJwt.getPayload().toJSONObject(); + + System.out.println("Made it through login - " + "User: " + extraData.getAsString("displayName") + " (" + extraData.getAsString("identity") + ")"); + + PlayStatusPacket status = new PlayStatusPacket(); + status.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS); + session.sendPacketImmediately(status); + + ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket(); + resourcePacksInfo.setForcedToAccept(false); + session.sendPacketImmediately(resourcePacksInfo); + + //this.player = this.server.addPlayer(authData, session); + //System.out.println(this.player.getProtocol().getProfile().getId()); + + /** MovePlayerPacket mp = new MovePlayerPacket(); + mp.setRuntimeEntityId(-1); + session.sendPacket(mp); + + SetSpawnPositionPacket ss = new SetSpawnPositionPacket(); + ss.setBlockPosition(new Vector3i(0, 0 ,0)); + ss.setSpawnForced(true); + ss.setSpawnType(SetSpawnPositionPacket.Type.PLAYER_SPAWN); + session.sendPacket(ss); + + session.sendPacket(mp); + + SetTimePacket st = new SetTimePacket(); + st.setTime(0); + session.sendPacket(st); + + RespawnPacket rp = new RespawnPacket(); + rp.setPosition(new Vector3f(0, 0 ,0)); + session.sendPacket(rp); **/ + + //MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + //PlayerList playerList = server.getPlayerList(); + + // GameProfile gameProfile = new GameProfile(UUID.fromString(extraData.getAsString("identity")), extraData.getAsString("displayName")); + + // PipePlayer pl = new PipePlayer(session); + // pl.addEvent(new LoginEvent(gameProfile)); + // this.server.addPlayer(pl); + + + + + //saveSkin(); + } catch (Exception e) { + session.disconnect("disconnectionScreen.internalError.cantConnect"); + throw new RuntimeException("Unable to complete login", e); + } + return true; + } + +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/Binary.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/Binary.java new file mode 100644 index 0000000..f27a3ff --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/Binary.java @@ -0,0 +1,322 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils; + +import main.com.pyratron.pugmatt.bedrockconnect.utils.math.NukkitMath; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.UUID; + +/** + * author: MagicDroidX Nukkit Project + */ +public class Binary { + + public Binary() { + + } + + public static int signByte(int value) { + return value << 56 >> 56; + } + + public static int unsignByte(int value) { + return value & 0xff; + } + + public static int signShort(int value) { + return value << 48 >> 48; + } + + public int unsignShort(int value) { + return value & 0xffff; + } + + public static int signInt(int value) { + return value << 32 >> 32; + } + + public static int unsignInt(int value) { + return value; + } + + // Triad: {0x00,0x00,0x01}<=>1 + public static int readTriad(byte[] bytes) { + return readInt(new byte[]{(byte) 0x00, bytes[0], bytes[1], bytes[2]}); + } + + public static byte[] writeTriad(int value) { + return new byte[]{(byte) ((value >>> 16) & 0xFF), (byte) ((value >>> 8) & 0xFF), (byte) (value & 0xFF)}; + } + + // LTriad: {0x01,0x00,0x00}<=>1 + public static int readLTriad(byte[] bytes) { + return readLInt(new byte[]{bytes[0], bytes[1], bytes[2], (byte) 0x00}); + } + + public static byte[] writeLTriad(int value) { + return new byte[]{(byte) (value & 0xFF), (byte) ((value >>> 8) & 0xFF), (byte) ((value >>> 16) & 0xFF)}; + } + + public static UUID readUUID(byte[] bytes) { + return new UUID(readLLong(bytes), readLLong( + new byte[]{bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]})); + } + + public static byte[] writeUUID(UUID uuid) { + return appendBytes(writeLLong(uuid.getMostSignificantBits()), writeLLong(uuid.getLeastSignificantBits())); + } + + public static boolean readBool(byte b) { + return b == 0; + } + + public static byte writeBool(boolean b) { + return (byte) (b ? 0x01 : 0x00); + } + + public static int readSignedByte(byte b) { + return b & 0xFF; + } + + public static byte writeByte(byte b) { + return b; + } + + public static int readShort(byte[] bytes) { + return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); + } + + public static short readSignedShort(byte[] bytes) { + return (short) readShort(bytes); + } + + public static byte[] writeShort(int s) { + return new byte[]{(byte) ((s >>> 8) & 0xFF), (byte) (s & 0xFF)}; + } + + public static int readLShort(byte[] bytes) { + return (bytes[1] & 0xFF << 8) + (bytes[0] & 0xFF); + } + + public static short readSignedLShort(byte[] bytes) { + return (short) readLShort(bytes); + } + + public static byte[] writeLShort(int s) { + s &= 0xffff; + return new byte[]{(byte) (s & 0xFF), (byte) ((s >>> 8) & 0xFF)}; + } + + public static int readInt(byte[] bytes) { + return ((bytes[0] & 0xff) << 24) + ((bytes[1] & 0xff) << 16) + ((bytes[2] & 0xff) << 8) + (bytes[3] & 0xff); + } + + public static byte[] writeInt(int i) { + return new byte[]{(byte) ((i >>> 24) & 0xFF), (byte) ((i >>> 16) & 0xFF), (byte) ((i >>> 8) & 0xFF), + (byte) (i & 0xFF)}; + } + + public static int readLInt(byte[] bytes) { + return ((bytes[3] & 0xff) << 24) + ((bytes[2] & 0xff) << 16) + ((bytes[1] & 0xff) << 8) + (bytes[0] & 0xff); + } + + public static byte[] writeLInt(int i) { + return new byte[]{(byte) (i & 0xFF), (byte) ((i >>> 8) & 0xFF), (byte) ((i >>> 16) & 0xFF), + (byte) ((i >>> 24) & 0xFF)}; + } + + public static float readFloat(byte[] bytes) { + return readFloat(bytes, -1); + } + + public static float readFloat(byte[] bytes, int accuracy) { + float val = Float.intBitsToFloat(readInt(bytes)); + if (accuracy > -1) { + return (float) NukkitMath.round(val, accuracy); + } else { + return val; + } + } + + public static byte[] writeFloat(float f) { + return writeInt(Float.floatToIntBits(f)); + } + + public static float readLFloat(byte[] bytes) { + return readLFloat(bytes, -1); + } + + public static float readLFloat(byte[] bytes, int accuracy) { + float val = Float.intBitsToFloat(readLInt(bytes)); + if (accuracy > -1) { + return (float) NukkitMath.round(val, accuracy); + } else { + return val; + } + } + + public static byte[] writeLFloat(float f) { + return writeLInt(Float.floatToIntBits(f)); + } + + public static double readDouble(byte[] bytes) { + return Double.longBitsToDouble(readLong(bytes)); + } + + public static byte[] writeDouble(double d) { + return writeLong(Double.doubleToLongBits(d)); + } + + public static double readLDouble(byte[] bytes) { + return Double.longBitsToDouble(readLLong(bytes)); + } + + public static byte[] writeLDouble(double d) { + return writeLLong(Double.doubleToLongBits(d)); + } + + public static long readLong(byte[] bytes) { + return (((long) bytes[0] << 56) + ((long) (bytes[1] & 0xFF) << 48) + ((long) (bytes[2] & 0xFF) << 40) + + ((long) (bytes[3] & 0xFF) << 32) + ((long) (bytes[4] & 0xFF) << 24) + ((bytes[5] & 0xFF) << 16) + + ((bytes[6] & 0xFF) << 8) + ((bytes[7] & 0xFF))); + } + + public static byte[] writeLong(long l) { + return new byte[]{(byte) (l >>> 56), (byte) (l >>> 48), (byte) (l >>> 40), (byte) (l >>> 32), + (byte) (l >>> 24), (byte) (l >>> 16), (byte) (l >>> 8), (byte) (l)}; + } + + public static long readLLong(byte[] bytes) { + return (((long) bytes[7] << 56) + ((long) (bytes[6] & 0xFF) << 48) + ((long) (bytes[5] & 0xFF) << 40) + + ((long) (bytes[4] & 0xFF) << 32) + ((long) (bytes[3] & 0xFF) << 24) + ((bytes[2] & 0xFF) << 16) + + ((bytes[1] & 0xFF) << 8) + ((bytes[0] & 0xFF))); + } + + public static byte[] writeLLong(long l) { + return new byte[]{(byte) (l), (byte) (l >>> 8), (byte) (l >>> 16), (byte) (l >>> 24), (byte) (l >>> 32), + (byte) (l >>> 40), (byte) (l >>> 48), (byte) (l >>> 56),}; + } + + public static byte[] writeVarInt(int v) { + BinaryStream stream = new BinaryStream(); + stream.putVarInt(v); + return stream.getBuffer(); + } + + public static byte[] writeUnsignedVarInt(long v) { + BinaryStream stream = new BinaryStream(); + stream.putUnsignedVarInt(v); + return stream.getBuffer(); + } + + public static byte[] reserveBytes(byte[] bytes) { + byte[] newBytes = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + newBytes[bytes.length - 1 - i] = bytes[i]; + } + return newBytes; + } + + public static String bytesToHexString(byte[] src) { + return bytesToHexString(src, false); + } + + public static String bytesToHexString(byte[] src, boolean blank) { + StringBuilder stringBuilder = new StringBuilder(""); + if (src == null || src.length <= 0) { + return null; + } + + for (byte b : src) { + if (!(stringBuilder.length() == 0) && blank) { + stringBuilder.append(" "); + } + int v = b & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString().toUpperCase(); + } + + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + String str = "0123456789ABCDEF"; + hexString = hexString.toUpperCase().replace(" ", ""); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (((byte) str.indexOf(hexChars[pos]) << 4) | ((byte) str.indexOf(hexChars[pos + 1]))); + } + return d; + } + + public static byte[] subBytes(byte[] bytes, int start, int length) { + int len = Math.min(bytes.length, start + length); + return Arrays.copyOfRange(bytes, start, len); + } + + public static byte[] subBytes(byte[] bytes, int start) { + return subBytes(bytes, start, bytes.length - start); + } + + public static byte[][] splitBytes(byte[] bytes, int chunkSize) { + byte[][] splits = new byte[(bytes.length + chunkSize - 1) / chunkSize][chunkSize]; + int chunks = 0; + + for (int i = 0; i < bytes.length; i += chunkSize) { + if ((bytes.length - i) > chunkSize) { + splits[chunks] = Arrays.copyOfRange(bytes, i, i + chunkSize); + } else { + splits[chunks] = Arrays.copyOfRange(bytes, i, bytes.length); + } + chunks++; + } + + return splits; + } + + public static byte[] appendBytes(byte[][] bytes) { + int length = 0; + for (byte[] b : bytes) { + length += b.length; + } + ByteBuffer buffer = ByteBuffer.allocate(length); + for (byte[] b : bytes) { + buffer.put(b); + } + return buffer.array(); + } + + public static byte[] appendBytes(byte byte1, byte[]... bytes2) { + int length = 1; + for (byte[] bytes : bytes2) { + length += bytes.length; + } + ByteBuffer buffer = ByteBuffer.allocate(length); + buffer.put(byte1); + for (byte[] bytes : bytes2) { + buffer.put(bytes); + } + return buffer.array(); + } + + public static byte[] appendBytes(byte[] bytes1, byte[]... bytes2) { + int length = bytes1.length; + for (byte[] bytes : bytes2) { + length += bytes.length; + } + ByteBuffer buffer = ByteBuffer.allocate(length); + buffer.put(bytes1); + for (byte[] bytes : bytes2) { + buffer.put(bytes); + } + return buffer.array(); + } +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/BinaryStream.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/BinaryStream.java new file mode 100644 index 0000000..a52301e --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/BinaryStream.java @@ -0,0 +1,528 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +/** + * author: MagicDroidX Nukkit Project + */ +public class BinaryStream { + + public int offset; + private byte[] buffer = new byte[32]; + private int count; + + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + public BinaryStream() { + this.buffer = new byte[32]; + this.offset = 0; + this.count = 0; + } + + public BinaryStream(byte[] buffer) { + this(buffer, 0); + } + + public BinaryStream(byte[] buffer, int offset) { + this.buffer = buffer; + this.offset = offset; + this.count = buffer.length; + } + + public void reset() { + this.buffer = new byte[32]; + this.offset = 0; + this.count = 0; + } + + public byte[] getBuffer() { + return Arrays.copyOf(buffer, count); + } + + public void setBuffer(byte[] buffer) { + this.buffer = buffer; + this.count = buffer == null ? -1 : buffer.length; + } + + public void setBuffer(byte[] buffer, int offset) { + this.setBuffer(buffer); + this.setOffset(offset); + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public int getCount() { + return count; + } + + public byte[] get() { + return this.get(this.count - this.offset); + } + + public byte[] get(int len) { + if (len < 0) { + this.offset = this.count - 1; + return new byte[0]; + } + len = Math.min(len, this.getCount() - this.offset); + this.offset += len; + return Arrays.copyOfRange(this.buffer, this.offset - len, this.offset); + } + + public void put(byte[] bytes) { + if (bytes == null) { + return; + } + + this.ensureCapacity(this.count + bytes.length); + + System.arraycopy(bytes, 0, this.buffer, this.count, bytes.length); + this.count += bytes.length; + } + + public long getLong() { + return Binary.readLong(this.get(8)); + } + + public void putLong(long l) { + this.put(Binary.writeLong(l)); + } + + public int getInt() { + return Binary.readInt(this.get(4)); + } + + public void putInt(int i) { + this.put(Binary.writeInt(i)); + } + + public long getLLong() { + return Binary.readLLong(this.get(8)); + } + + public void putLLong(long l) { + this.put(Binary.writeLLong(l)); + } + + public int getLInt() { + return Binary.readLInt(this.get(4)); + } + + public void putLInt(int i) { + this.put(Binary.writeLInt(i)); + } + + public int getShort() { + return Binary.readShort(this.get(2)); + } + + public void putShort(int s) { + this.put(Binary.writeShort(s)); + } + + public int getLShort() { + return Binary.readLShort(this.get(2)); + } + + public void putLShort(int s) { + this.put(Binary.writeLShort(s)); + } + + public float getFloat() { + return getFloat(-1); + } + + public float getFloat(int accuracy) { + return Binary.readFloat(this.get(4), accuracy); + } + + public void putFloat(float v) { + this.put(Binary.writeFloat(v)); + } + + public float getLFloat() { + return getLFloat(-1); + } + + public float getLFloat(int accuracy) { + return Binary.readLFloat(this.get(4), accuracy); + } + + public void putLFloat(float v) { + this.put(Binary.writeLFloat(v)); + } + + public int getTriad() { + return Binary.readTriad(this.get(3)); + } + + public void putTriad(int triad) { + this.put(Binary.writeTriad(triad)); + } + + public int getLTriad() { + return Binary.readLTriad(this.get(3)); + } + + public void putLTriad(int triad) { + this.put(Binary.writeLTriad(triad)); + } + + public boolean getBoolean() { + return this.getByte() == 0x01; + } + + public void putBoolean(boolean bool) { + this.putByte((byte) (bool ? 1 : 0)); + } + + public int getByte() { + return this.buffer[this.offset++] & 0xff; + } + + public void putByte(byte b) { + this.put(new byte[]{b}); + } + + /** public void putEntityLink(PEEntityLink link) { + putVarLong(link.riding); + putVarLong(link.rider); + putByte(link.type); + putByte(link.unknownByte); + } + +// public PEEntityLink getEntityLink() { +// return new PEEntityLink( +// getVarLong(), +// getVarLong(), +// getByte(), +// getByte()); +// } + + public Map<String, GameRule> getGameRules() { + int count = (int) getUnsignedVarInt(); + Map<String, GameRule> rules = new HashMap<>(); + for (int i = 0; i < count; i++) { + GameRule rule = GameRule.read(this); + rules.put(rule.name, rule); + } + return rules; + } + + public void putGameRules(Map<String, GameRule> rules) { + if (rules == null) { + putUnsignedVarInt(0); + return; + } + putUnsignedVarInt(rules.size()); + for (GameRule rule : rules.values()) { + rule.write(this); + } + } + + public float getByteRotation() { + return (((float) (getByte() & 0xFF)) * (360 / 256)); + } + + public void putByteRotation(float rotation) { + putByte((byte) (((int) (rotation / (360 / 256))) & 0xFF)); + } + + /** + * Reads a list of Attributes from the stream. + * + * @return Attribute[] + */ + /** + public PEEntityAttribute[] getAttributeList() throws Exception { + List<PEEntityAttribute> list = new ArrayList<>(); + long count = this.getUnsignedVarInt(); + + for (int i = 0; i < count; ++i) { + String name = this.getString(); + PEEntityAttribute attr = PEEntityAttribute.findAttribute(name); + if (attr != null) { + attr.min = getLFloat(); + attr.currentValue = getLFloat(); + attr.max = this.getLFloat(); + list.add(attr); + } else { + throw new Exception("Unknown attribute type \"" + name + "\""); + } + } + + return list.stream().toArray(PEEntityAttribute[]::new); + } + /** + + /** + * Writes a list of Attributes to the packet buffer using the standard + * format. + */ + /** + public void putAttributeList(PEEntityAttribute[] attributes) { + this.putUnsignedVarInt(attributes.length); + for (PEEntityAttribute attribute : attributes) { + this.putString(attribute.name); + this.putLFloat(attribute.min); + this.putLFloat(attribute.currentValue); + this.putLFloat(attribute.max); + } + } + + public void putUUID(UUID uuid) { + this.put(Binary.writeUUID(uuid)); + } + + public UUID getUUID() { + return Binary.readUUID(this.get(16)); + } + + public void putSkin(Skin skin) { + this.putString(skin.getModel()); + this.putByteArray(skin.getData()); + this.putByteArray(skin.getCape().getData()); + } + + public Skin getSkin() { + String modelId = this.getString(); + byte[] skinData = this.getByteArray(); + return new Skin(skinData, modelId); + } + + public Slot getSlot() { + int id = this.getVarInt(); + + if (id <= 0) { + return Slot.AIR; + } + int auxValue = this.getVarInt(); + int data = auxValue >> 8; + if (data == Short.MAX_VALUE) { + data = -1; + } + int cnt = auxValue & 0xff; + + int nbtLen = this.getLShort(); + byte[] nbt; + CompoundTag tag = null; + if (nbtLen > 0) { + nbt = this.get(nbtLen); + try { + tag = NBTIO.read(nbt, ByteOrder.LITTLE_ENDIAN, false); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // TODO + int canPlaceOn = this.getVarInt(); + if (canPlaceOn > 0) { + for (int i = 0; i < canPlaceOn; ++i) { + this.getString(); + } + } + + // TODO + int canDestroy = this.getVarInt(); + if (canDestroy > 0) { + for (int i = 0; i < canDestroy; ++i) { + this.getString(); + } + } + + return new Slot(id, data, cnt, tag); + } + + public void putSlot(Slot item) { + if (item == null || item.id == 0) { + this.putVarInt(0); + return; + } + + this.putVarInt(item.id); + int auxValue = ((item.damage & 0x7fff) << 8) | item.count; + this.putVarInt(auxValue); + byte[] nbt; + if (item.tag != null) { + try { + nbt = NBTIO.write(item.tag, ByteOrder.LITTLE_ENDIAN, false); + } catch (IOException e) { + e.printStackTrace(); + nbt = new byte[0]; + } + } else { + nbt = new byte[0]; + } + this.putLShort(nbt.length); + this.put(nbt); + this.putVarInt(0); // TODO CanPlaceOn entry count + this.putVarInt(0); // TODO CanDestroy entry count + } + + **/ + + + public byte[] getByteArray() { + return this.get((int) this.getUnsignedVarInt()); + } + + public void putByteArray(byte[] b) { + this.putUnsignedVarInt(b.length); + this.put(b); + } + + public String getString() { + return new String(this.getByteArray(), StandardCharsets.UTF_8); + } + + public void putString(String string) { + byte[] b = string.getBytes(StandardCharsets.UTF_8); + this.putByteArray(b); + } + + public long getUnsignedVarInt() { + return VarInt.readUnsignedVarInt(this); + } + + public void putUnsignedVarInt(long v) { + VarInt.writeUnsignedVarInt(this, v); + } + + public int getVarInt() { + return VarInt.readVarInt(this); + } + + public void putVarInt(int v) { + VarInt.writeVarInt(this, v); + } + + public long getVarLong() { + return VarInt.readVarLong(this); + } + + public void putVarLong(long v) { + VarInt.writeVarLong(this, v); + } + + public long getUnsignedVarLong() { + return VarInt.readUnsignedVarLong(this); + } + + public void putUnsignedVarLong(long v) { + VarInt.writeUnsignedVarLong(this, v); + } + + /** + public BlockPosition getBlockPosition() { + return new BlockPosition(this.getVarInt(), (int) this.getUnsignedVarInt(), this.getVarInt()); + } + + public BlockPosition getSignedBlockPosition() { + return new BlockPosition(getVarInt(), getVarInt(), getVarInt()); + } + + public void putSignedBlockPosition(BlockPosition v) { + putVarInt(v.x); + putVarInt(v.y); + putVarInt(v.z); + } + + public void putBlockPosition(BlockPosition v) { + this.putBlockPosition(v.x, v.y, v.z); + } + + public void putBlockPosition(int x, int y, int z) { + this.putVarInt(x); + this.putUnsignedVarInt(y); + this.putVarInt(z); + } + + public Vector3F getVector3F() { + return new Vector3F(this.getLFloat(4), this.getLFloat(4), this.getLFloat(4)); + } + + public void putVector3F(Vector3F v) { + if (v == null) { + this.putVector3F(0f, 0f, 0f); + } else { + this.putVector3F(v.x, v.y, v.z); + } + } + + public void putVector3F(float x, float y, float z) { + this.putLFloat(Math.round(x * 10000f) / 10000f); + this.putLFloat(Math.round(y * 10000f) / 10000f); + this.putLFloat(Math.round(z * 10000f) / 10000f); + } + + /** + * Reads and returns an EntityUniqueID + * + * @return int + */ + public long getEntityUniqueId() { + return this.getVarLong(); + } + + /** + * Writes an EntityUniqueID + */ + public void putEntityUniqueId(long eid) { + this.putVarLong(eid); + } + + /** + * Reads and returns an EntityRuntimeID + */ + public long getEntityRuntimeId() { + return this.getUnsignedVarLong(); + } + + /** + * Writes an EntityUniqueID + */ + public void putEntityRuntimeId(long eid) { + this.putUnsignedVarLong(eid); + } + + public boolean feof() { + return this.offset < 0 || this.offset >= this.buffer.length; + } + + private void ensureCapacity(int minCapacity) { + // overflow-conscious code + if (minCapacity - buffer.length > 0) { + grow(minCapacity); + } + } + + private void grow(int minCapacity) { + // overflow-conscious code + int oldCapacity = buffer.length; + int newCapacity = oldCapacity << 1; + + if (newCapacity - minCapacity < 0) { + newCapacity = minCapacity; + } + + if (newCapacity - MAX_ARRAY_SIZE > 0) { + newCapacity = hugeCapacity(minCapacity); + } + this.buffer = Arrays.copyOf(buffer, newCapacity); + } + + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) { // overflow + throw new OutOfMemoryError(); + } + return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/FixedPlayerListPacket.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/FixedPlayerListPacket.java new file mode 100644 index 0000000..8313681 --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/FixedPlayerListPacket.java @@ -0,0 +1,7 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils; + +import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; + +public class FixedPlayerListPacket extends PlayerListPacket { + +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/PaletteManager.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/PaletteManager.java new file mode 100644 index 0000000..6c033fc --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/PaletteManager.java @@ -0,0 +1,69 @@ +package main.com.pyratron.pugmatt.bedrockconnect.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.v354.BedrockUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import main.com.pyratron.pugmatt.bedrockconnect.BedrockConnect; + +import java.io.InputStream; +import java.util.ArrayList; + +// https://github.com/DragonetMC/DragonProxy/blob/rewrite/proxy/src/main/java/org/dragonet/proxy/util/PaletteManager.java +// Author: lukeeey + +public class PaletteManager { + + private ByteBuf cachedPalette; + + public ByteBuf getCachedPalette() { + return cachedPalette; + } + + public PaletteManager() { + InputStream stream = BedrockConnect.class.getClassLoader().getResourceAsStream("tables/runtimeid_table.json"); + if (stream == null) { + throw new AssertionError("Static Runtime ID table not found"); + } + + ObjectMapper mapper = new ObjectMapper(); + CollectionType type = mapper.getTypeFactory().constructCollectionType(ArrayList.class, RuntimeEntry.class); + + ArrayList<RuntimeEntry> entries = new ArrayList<>(); + try { + entries = mapper.readValue(stream, type); + } catch (Exception e) { + e.printStackTrace(); + } + + cachedPalette = Unpooled.buffer(); + + VarInts.writeInt(cachedPalette, entries.size()); + + for (RuntimeEntry entry : entries) { + BedrockUtils.writeString(cachedPalette, entry.name); + cachedPalette.writeShortLE(entry.data); + } + + } + + private static class RuntimeEntry { + @JsonProperty("name") + private String name; + @JsonProperty("id") + private int id; + @JsonProperty("data") + private int data; + + public RuntimeEntry() {} + + public RuntimeEntry(String name, int id, int data) { + this.id = id; + this.name = name; + this.data = data; + } + } +} diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/VarInt.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/VarInt.java new file mode 100644 index 0000000..ad5ec7e --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/VarInt.java @@ -0,0 +1,235 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Tool class for VarInt or VarLong operations. + * <p> + * Some code from http://wiki.vg/Protocol. + * + * @author MagicDroidX + * @author lmlstarqaq + */ +public final class VarInt { + + private VarInt() { + // no instance + } + + /** + * @param v Signed int + * @return Unsigned encoded int + */ + public static long encodeZigZag32(int v) { + // Note: the right-shift must be arithmetic + return (long) ((v << 1) ^ (v >> 31)); + } + + /** + * @param v Unsigned encoded int + * @return Signed decoded int + */ + public static int decodeZigZag32(long v) { + return (int) (v >> 1) ^ -(int) (v & 1); + } + + /** + * @param v Signed long + * @return Unsigned encoded long + */ + public static long encodeZigZag64(long v) { + return (v << 1) ^ (v >> 63); + } + + /** + * @param v Signed encoded long + * @return Unsigned decoded long + */ + public static long decodeZigZag64(long v) { + return (v >>> 1) ^ -(v & 1); + } + + /** + * @param stream BinaryStream + * @return Signed int + */ + public static int readVarInt(BinaryStream stream) { + return decodeZigZag32(readUnsignedVarInt(stream)); + } + + /** + * @param stream InputStream + * @return Signed int + */ + public static int readVarInt(InputStream stream) throws IOException { + return decodeZigZag32(readUnsignedVarInt(stream)); + } + + /** + * @param stream BinaryStream + * @return Unsigned int + */ + public static long readUnsignedVarInt(BinaryStream stream) { + return read(stream, 5); + } + + /** + * @param stream InputStream + * @return Unsigned int + */ + public static long readUnsignedVarInt(InputStream stream) throws IOException { + return read(stream, 5); + } + + /** + * @param stream BinaryStream + * @return Signed long + */ + public static long readVarLong(BinaryStream stream) { + return decodeZigZag64(readUnsignedVarLong(stream)); + } + + /** + * @param stream InputStream + * @return Signed long + */ + public static long readVarLong(InputStream stream) throws IOException { + return decodeZigZag64(readUnsignedVarLong(stream)); + } + + /** + * @param stream BinaryStream + * @return Unsigned long + */ + public static long readUnsignedVarLong(BinaryStream stream) { + return read(stream, 10); + } + + /** + * @param stream InputStream + * @return Unsigned long + */ + public static long readUnsignedVarLong(InputStream stream) throws IOException { + return read(stream, 10); + } + + /** + * @param stream BinaryStream + * @param value Signed int + */ + public static void writeVarInt(BinaryStream stream, int value) { + writeUnsignedVarInt(stream, encodeZigZag32(value)); + } + + /** + * @param stream OutputStream + * @param value Signed int + */ + public static void writeVarInt(OutputStream stream, int value) throws IOException { + writeUnsignedVarInt(stream, encodeZigZag32(value)); + } + + /** + * @param stream BinaryStream + * @param value Unsigned int + */ + public static void writeUnsignedVarInt(BinaryStream stream, long value) { + write(stream, value); + } + + /** + * @param stream OutputStream + * @param value Unsigned int + */ + public static void writeUnsignedVarInt(OutputStream stream, long value) throws IOException { + write(stream, value); + } + + /** + * @param stream BinaryStream + * @param value Signed long + */ + public static void writeVarLong(BinaryStream stream, long value) { + writeUnsignedVarLong(stream, encodeZigZag64(value)); + } + + /** + * @param stream OutputStream + * @param value Signed long + */ + public static void writeVarLong(OutputStream stream, long value) throws IOException { + writeUnsignedVarLong(stream, encodeZigZag64(value)); + } + + /** + * @param stream BinaryStream + * @param value Unsigned long + */ + public static void writeUnsignedVarLong(BinaryStream stream, long value) { + write(stream, value); + } + + /** + * @param stream OutputStream + * @param value Unsigned long + */ + public static void writeUnsignedVarLong(OutputStream stream, long value) throws IOException { + write(stream, value); + } + + private static long read(BinaryStream stream, int maxSize) { + long value = 0; + int size = 0; + int b; + while (((b = stream.getByte()) & 0x80) == 0x80) { + value |= (long) (b & 0x7F) << (size++ * 7); + if (size >= maxSize) { + throw new IllegalArgumentException("VarLong too big"); + } + } + + return value | ((long) (b & 0x7F) << (size * 7)); + } + + private static long read(InputStream stream, int maxSize) throws IOException { + long value = 0; + int size = 0; + int b; + while (((b = stream.read()) & 0x80) == 0x80) { + value |= (long) (b & 0x7F) << (size++ * 7); + if (size >= maxSize) { + throw new IllegalArgumentException("VarLong too big"); + } + } + + return value | ((long) (b & 0x7F) << (size * 7)); + } + + private static void write(BinaryStream stream, long value) { + do { + byte temp = (byte) (value & 0b01111111); + // Note: >>> means that the sign bit is shifted with the rest of the number + // rather than being left alone + value >>>= 7; + if (value != 0) { + temp |= 0b10000000; + } + stream.putByte(temp); + } while (value != 0); + } + + private static void write(OutputStream stream, long value) throws IOException { + do { + byte temp = (byte) (value & 0b01111111); + // Note: >>> means that the sign bit is shifted with the rest of the number + // rather than being left alone + value >>>= 7; + if (value != 0) { + temp |= 0b10000000; + } + stream.write(temp); + } while (value != 0); + } +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitMath.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitMath.java new file mode 100644 index 0000000..a7445df --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitMath.java @@ -0,0 +1,67 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils.math; + +/** + * author: MagicDroidX Nukkit Project + */ +public class NukkitMath { + + public NukkitMath() { + + } + + public static int floorDouble(double n) { + int i = (int) n; + return n >= i ? i : i - 1; + } + + public static int ceilDouble(double n) { + int i = (int) (n + 1); + return n >= i ? i : i - 1; + } + + public static int floorFloat(float n) { + int i = (int) n; + return n >= i ? i : i - 1; + } + + public static int ceilFloat(float n) { + int i = (int) (n + 1); + return n >= i ? i : i - 1; + } + + public static int randomRange(NukkitRandom random) { + return randomRange(random, 0); + } + + public static int randomRange(NukkitRandom random, int start) { + return randomRange(random, 0, 0x7fffffff); + } + + public static int randomRange(NukkitRandom random, int start, int end) { + return start + (random.nextInt() % (end + 1 - start)); + } + + public static double round(double d) { + return round(d, 0); + } + + public static double round(double d, int precision) { + return ((double) Math.round(d * Math.pow(10, precision))) / Math.pow(10, precision); + } + + public static double clamp(double check, double min, double max) { + return check > max ? max : (check < min ? min : check); + } + + public static double getDirection(double d0, double d1) { + if (d0 < 0.0D) { + d0 = -d0; + } + + if (d1 < 0.0D) { + d1 = -d1; + } + + return d0 > d1 ? d0 : d1; + } +}
\ No newline at end of file diff --git a/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitRandom.java b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitRandom.java new file mode 100644 index 0000000..013eb1f --- /dev/null +++ b/serverlist-server/src/main/com/pyratron/pugmatt/bedrockconnect/utils/math/NukkitRandom.java @@ -0,0 +1,79 @@ +package main.com.pyratron.pugmatt.bedrockconnect.utils.math; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.zip.CRC32; + +/** + * author: Angelic47 Nukkit Project + */ +public class NukkitRandom { + + protected long seed; + + // constructor + public NukkitRandom() { + this(-1); + } + + public NukkitRandom(long seeds) { + if (seeds == -1) { + seeds = System.currentTimeMillis() / 1000L; + } + this.setSeed(seeds); + } + + public void setSeed(long seeds) { + CRC32 crc32 = new CRC32(); + ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); + buffer.putInt((int) seeds); + crc32.update(buffer.array()); + this.seed = crc32.getValue(); + } + + public int nextSignedInt() { + int t = (((int) ((this.seed * 65535) + 31337) >> 8) + 1337); + this.seed ^= t; + return t; + } + + public int nextInt() { + return this.nextSignedInt() & 0x7fffffff; + } + + public double nextDouble() { + return (double) this.nextInt() / 0x7fffffff; + } + + public float nextFloat() { + return (float) this.nextInt() / 0x7fffffff; + } + + public float nextSignedFloat() { + return (float) this.nextInt() / 0x7fffffff; + } + + public double nextSignedDouble() { + return (double) this.nextSignedInt() / 0x7fffffff; + } + + public boolean nextBoolean() { + return (this.nextSignedInt() & 0x01) == 0; + } + + public int nextRange() { + return nextRange(0, 0x7fffffff); + } + + public int nextRange(int start) { + return nextRange(start, 0x7fffffff); + } + + public int nextRange(int start, int end) { + return start + (this.nextInt() % (end + 1 - start)); + } + + public int nextBoundedInt(int bound) { + return this.nextInt() % bound; + } +}
\ No newline at end of file |
