diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..3055316c7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,52 @@ +pipeline { + agent any + tools { + maven 'Maven 3' + jdk 'Java 8' + } + options { + buildDiscarder(logRotator(artifactNumToKeepStr: '5')) + } + stages { + stage ('Build') { + steps { + sh 'mvn clean package' + } + post { + success { + archiveArtifacts artifacts: 'target/Geyser.jar', fingerprint: true + } + } + } + + stage ('Deploy') { + when { + branch "master" + } + steps { + sh 'mvn javadoc:jar source:jar deploy -DskipTests' + } + } + + stage ('Javadoc') { + when { + branch "master" + } + steps { + sh 'mvn javadoc:javadoc -DskipTests -pl api' + step([$class: 'JavadocArchiver', + javadocDir: 'api/target/site/apidocs', + keepAll: false]) + } + } + } + + post { + always { + deleteDir() + withCredentials([string(credentialsId: 'geyser-discord-webhook', variable: 'DISCORD_WEBHOOK')]) { + discordSend description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n\n[**Artifacts on Jenkins**](https://ci.nukkitx.com/job/Geyser)", footer: 'NukkitX Jenkins', link: env.BUILD_URL, successful: currentBuild.resultIsBetterOrEqualTo('SUCCESS'), title: "${env.JOB_NAME} #${currentBuild.id}", webhookURL: DISCORD_WEBHOOK + } + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index a23afe99e..1f6b56ab8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # Geyser + +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Build Status](https://ci.nukkitx.com/job/Geyser/job/master/badge/icon)](https://ci.nukkitx.com/job/Geyser/job/master/) +[![Discord](https://img.shields.io/discord/597838753859633172.svg?color=%237289da&label=discord)](https://discord.gg/mRjbCsS) + A bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition, closing the gap from those wanting to play together. ## What is Geyser? diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java index 5d125dff4..66db7e426 100644 --- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java @@ -103,6 +103,6 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { bedrockServerSession.setLogging(true); bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession))); bedrockServerSession.addDisconnectHandler((x) -> GeyserLogger.DEFAULT.warning("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconnected for reason " + x)); - bedrockServerSession.setPacketCodec(Bedrock_v361.V361_CODEC); + bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 09b737bcb..f144154e3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -25,15 +25,13 @@ package org.geysermc.connector.network; -import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; -import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerSwingArmPacket; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; import com.nimbusds.jose.JWSObject; import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; import com.nukkitx.protocol.bedrock.packet.*; -import net.minidev.json.JSONArray; +import com.nukkitx.protocol.bedrock.util.EncryptionUtils; import net.minidev.json.JSONObject; -import net.minidev.json.JSONValue; import org.geysermc.api.events.player.PlayerFormResponseEvent; import org.geysermc.api.window.CustomFormBuilder; import org.geysermc.api.window.CustomFormWindow; @@ -45,7 +43,16 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.auth.BedrockAuthData; import org.geysermc.connector.network.session.cache.WindowCache; +import org.geysermc.connector.network.translators.Registry; +import org.geysermc.connector.utils.LoginEncryptionUtils; +import javax.crypto.SecretKey; +import java.io.IOException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; import java.util.UUID; public class UpstreamPacketHandler implements BedrockPacketHandler { @@ -67,22 +74,48 @@ public class UpstreamPacketHandler implements BedrockPacketHandler { return true; } - session.getUpstream().setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); - + JsonNode certData; try { - JSONObject chainData = (JSONObject) JSONValue.parse(loginPacket.getChainData().array()); - JSONArray chainArray = (JSONArray) chainData.get("chain"); + certData = LoginEncryptionUtils.JSON_MAPPER.readTree(loginPacket.getChainData().toByteArray()); + } catch (IOException ex) { + throw new RuntimeException("Certificate JSON can not be read."); + } - Object identityObject = chainArray.get(chainArray.size() - 1); + JsonNode certChainData = certData.get("chain"); + if (certChainData.getNodeType() != JsonNodeType.ARRAY) { + throw new RuntimeException("Certificate data is not valid"); + } - JWSObject identity = JWSObject.parse((String) identityObject); - JSONObject extraData = (JSONObject) identity.getPayload().toJSONObject().get("extraData"); + boolean validChain; + try { + validChain = LoginEncryptionUtils.validateChainData(certChainData); + connector.getLogger().debug(String.format("Is player data valid? %s", validChain)); + + JWSObject jwt = JWSObject.parse(certChainData.get(certChainData.size() - 1).asText()); + JsonNode payload = LoginEncryptionUtils.JSON_MAPPER.readTree(jwt.getPayload().toBytes()); + + if (payload.get("extraData").getNodeType() != JsonNodeType.OBJECT) { + throw new RuntimeException("AuthData was not found!"); + } + + JSONObject extraData = (JSONObject) jwt.getPayload().toJSONObject().get("extraData"); session.setAuthenticationData(new BedrockAuthData(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(loginPacket.getSkinData().toString()); + EncryptionUtils.verifyJwt(clientJwt, identityPublicKey); + + if (EncryptionUtils.canUseEncryption()) { + startEncryptionHandshake(identityPublicKey); + } } catch (Exception ex) { - session.getUpstream().disconnect("An internal error occurred when connecting to this server."); - ex.printStackTrace(); - return true; + session.disconnect("disconnectionScreen.internalError.cantConnect"); + throw new RuntimeException("Unable to complete login", ex); } PlayStatusPacket playStatus = new PlayStatusPacket(); @@ -125,11 +158,7 @@ public class UpstreamPacketHandler implements BedrockPacketHandler { @Override public boolean handle(AnimatePacket packet) { connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName()); - switch (packet.getAction()) { - case SWING_ARM: - ClientPlayerSwingArmPacket swingArmPacket = new ClientPlayerSwingArmPacket(Hand.MAIN_HAND); - session.getDownstream().getSession().send(swingArmPacket); - } + Registry.BEDROCK.translate(packet.getClass(), packet, session); return true; } @@ -184,15 +213,7 @@ public class UpstreamPacketHandler implements BedrockPacketHandler { @Override public boolean handle(CommandRequestPacket packet) { connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName()); - - String command = packet.getCommand().replace("/", ""); - if (connector.getCommandMap().getCommands().containsKey(command)) { - connector.getCommandMap().runCommand(session, command); - } else { - ClientChatPacket chatPacket = new ClientChatPacket(packet.getCommand()); - session.getDownstream().getSession().send(chatPacket); - } - + Registry.BEDROCK.translate(packet.getClass(), packet, session); return true; } @@ -455,16 +476,7 @@ public class UpstreamPacketHandler implements BedrockPacketHandler { @Override public boolean handle(TextPacket packet) { connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName()); - - if (packet.getMessage().charAt(0) == '.') { - ClientChatPacket chatPacket = new ClientChatPacket(packet.getMessage().replace(".", "/")); - session.getDownstream().getSession().send(chatPacket); - return true; - } - - ClientChatPacket chatPacket = new ClientChatPacket(packet.getMessage()); - session.getDownstream().getSession().send(chatPacket); - + Registry.BEDROCK.translate(packet.getClass(), packet, session); return true; } @@ -959,4 +971,18 @@ public class UpstreamPacketHandler implements BedrockPacketHandler { connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName()); return false; } + + private void startEncryptionHandshake(PublicKey key) throws Exception { + KeyPairGenerator generator = KeyPairGenerator.getInstance("EC"); + generator.initialize(new ECGenParameterSpec("secp384r1")); + KeyPair serverKeyPair = generator.generateKeyPair(); + + byte[] token = EncryptionUtils.generateRandomToken(); + SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token); + session.getUpstream().enableEncryption(encryptionKey); + + ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket(); + packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize()); + session.getUpstream().sendPacketImmediately(packet); + } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 8cf5ced5d..c21252efa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -67,8 +67,6 @@ public class GeyserSession implements PlayerSession, Player { @Getter private Client downstream; - private final GeyserSession THIS = this; - @Getter private AuthData authenticationData; @@ -136,7 +134,7 @@ public class GeyserSession implements PlayerSession, Player { @Override public void packetReceived(PacketReceivedEvent event) { - Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), THIS); + Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } }); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslator.java new file mode 100644 index 000000000..412af6e7c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslator.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators; + +import org.geysermc.connector.network.session.GeyserSession; + +public abstract class PacketTranslator { + + public abstract void translate(T packet, GeyserSession session); + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java index ad0e8c21a..987fc4f27 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java @@ -26,28 +26,33 @@ package org.geysermc.connector.network.translators; import com.github.steveice10.packetlib.packet.Packet; +import com.nukkitx.protocol.bedrock.BedrockPacket; import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.network.session.GeyserSession; import java.util.HashMap; import java.util.Map; -import java.util.function.BiConsumer; public class Registry { - private final Map, BiConsumer> MAP = new HashMap<>(); + private final Map, PacketTranslator> MAP = new HashMap<>(); public static final Registry JAVA = new Registry<>(); + public static final Registry BEDROCK = new Registry<>(); - public static void add(Class clazz, BiConsumer translator) { + public static void registerJava(Class clazz, PacketTranslator translator) { JAVA.MAP.put(clazz, translator); } - public

void translate(Class

clazz, P p, GeyserSession s) { + public static void registerBedrock(Class clazz, PacketTranslator translator) { + BEDROCK.MAP.put(clazz, translator); + } + + public

void translate(Class clazz, P packet, GeyserSession session) { try { - ((BiConsumer) JAVA.MAP.get(clazz)).accept(p, s); - } catch (NullPointerException e) { - GeyserLogger.DEFAULT.debug("could not translate packet " + p.getClass().getSimpleName()); + ((PacketTranslator

) MAP.get(clazz)).translate(packet, session); + } catch (NullPointerException ex) { + GeyserLogger.DEFAULT.debug("Could not translate packet " + packet.getClass().getSimpleName()); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 2794d2bf4..0e882df1c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -25,32 +25,42 @@ package org.geysermc.connector.network.translators; -import com.flowpowered.math.vector.Vector3f; -import com.github.steveice10.mc.protocol.data.message.TranslationMessage; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerTitlePacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPositionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPositionRotationPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityVelocityPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.*; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnExpOrbPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTOutputStream; import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.packet.*; -import org.geysermc.connector.utils.MessageUtils; +import com.nukkitx.protocol.bedrock.packet.AnimatePacket; +import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket; +import com.nukkitx.protocol.bedrock.packet.TextPacket; +import org.geysermc.connector.network.translators.bedrock.BedrockAnimateTranslator; +import org.geysermc.connector.network.translators.bedrock.BedrockCommandRequestTranslator; +import org.geysermc.connector.network.translators.bedrock.BedrockTextTranslator; +import org.geysermc.connector.network.translators.java.JavaChatTranslator; +import org.geysermc.connector.network.translators.java.JavaJoinGameTranslator; +import org.geysermc.connector.network.translators.java.entity.JavaEntityDestroyTranslator; +import org.geysermc.connector.network.translators.java.entity.JavaEntityPositionRotationTranslator; +import org.geysermc.connector.network.translators.java.entity.JavaEntityPositionTranslator; +import org.geysermc.connector.network.translators.java.entity.JavaEntityTeleportTranslator; +import org.geysermc.connector.network.translators.java.entity.JavaEntityVelocityTranslator; +import org.geysermc.connector.network.translators.java.entity.spawn.JavaSpawnExpOrbTranslator; +import org.geysermc.connector.network.translators.java.world.JavaNotifyClientTranslator; +import org.geysermc.connector.network.translators.java.JavaTitleTranslator; +import org.geysermc.connector.network.translators.java.world.JavaUpdateTimeTranslator; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.concurrent.ThreadLocalRandom; public class TranslatorsInit { private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); - private static final byte[] EMPTY_LEVEL_CHUNK_DATA; + public static final byte[] EMPTY_LEVEL_CHUNK_DATA; static { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { @@ -67,182 +77,20 @@ public class TranslatorsInit { } public static void start() { - addLoginPackets(); - addChatPackets(); - addTitlePackets(); - addTimePackets(); - addEntityPackets(); - addNotifyPackets(); - } + Registry.registerJava(ServerJoinGamePacket.class, new JavaJoinGameTranslator()); + Registry.registerJava(ServerChatPacket.class, new JavaChatTranslator()); + Registry.registerJava(ServerTitlePacket.class, new JavaTitleTranslator()); + Registry.registerJava(ServerUpdateTimePacket.class, new JavaUpdateTimeTranslator()); + Registry.registerJava(ServerEntityPositionPacket.class, new JavaEntityPositionTranslator()); + Registry.registerJava(ServerEntityPositionRotationPacket.class, new JavaEntityPositionRotationTranslator()); + Registry.registerJava(ServerEntityTeleportPacket.class, new JavaEntityTeleportTranslator()); + Registry.registerJava(ServerEntityVelocityPacket.class, new JavaEntityVelocityTranslator()); + Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator()); + Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator()); + Registry.registerJava(ServerSpawnExpOrbPacket.class, new JavaSpawnExpOrbTranslator()); - private static void addLoginPackets() { - Registry.add(ServerJoinGamePacket.class, (packet, session) -> { - AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); - bedrockPacket.setUniqueEntityId(packet.getEntityId()); - session.getUpstream().sendPacketImmediately(bedrockPacket); - - Vector3f pos = new Vector3f(0, 0, 0); - int chunkX = pos.getFloorX() >> 4; - int chunkZ = pos.getFloorZ() >> 4; - for (int x = -3; x < 3; x++) { - for (int z = -3; z < 3; z++) { - LevelChunkPacket data = new LevelChunkPacket(); - data.setChunkX(chunkX + x); - data.setChunkZ(chunkZ + z); - data.setSubChunksLength(0); - - data.setData(EMPTY_LEVEL_CHUNK_DATA); - - session.getUpstream().sendPacketImmediately(data); - - } - } - }); - } - - private static void addChatPackets() { - Registry.add(ServerChatPacket.class, (packet, session) -> { - TextPacket textPacket = new TextPacket(); - textPacket.setPlatformChatId(""); - textPacket.setSourceName(""); - textPacket.setXuid(session.getAuthenticationData().getXboxUUID()); - switch (packet.getType()) { - case CHAT: - textPacket.setType(TextPacket.Type.CHAT); - case SYSTEM: - textPacket.setType(TextPacket.Type.SYSTEM); - case NOTIFICATION: - textPacket.setType(TextPacket.Type.TIP); - default: - textPacket.setType(TextPacket.Type.RAW); - } - - if (packet.getMessage() instanceof TranslationMessage) { - textPacket.setType(TextPacket.Type.TRANSLATION); - textPacket.setNeedsTranslation(true); - textPacket.setParameters(MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getTranslationParams())); - textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage())); - } else { - textPacket.setNeedsTranslation(false); - textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage())); - } - - session.getUpstream().sendPacket(textPacket); - }); - } - - public static void addTitlePackets() { - Registry.add(ServerTitlePacket.class, (packet, session) -> { - SetTitlePacket titlePacket = new SetTitlePacket(); - - switch (packet.getAction()) { - case TITLE: - titlePacket.setType(SetTitlePacket.Type.SET_TITLE); - titlePacket.setText(packet.getTitle().getFullText()); - break; - case SUBTITLE: - titlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); - titlePacket.setText(packet.getSubtitle().getFullText()); - break; - case CLEAR: - case RESET: - titlePacket.setType(SetTitlePacket.Type.RESET_TITLE); - titlePacket.setText(""); - break; - case ACTION_BAR: - titlePacket.setType(SetTitlePacket.Type.SET_ACTIONBAR_MESSAGE); - titlePacket.setText(packet.getActionBar().getFullText()); - break; - } - - titlePacket.setFadeInTime(packet.getFadeIn()); - titlePacket.setFadeOutTime(packet.getFadeOut()); - titlePacket.setStayTime(packet.getStay()); - - session.getUpstream().sendPacket(titlePacket); - }); - } - - public static void addTimePackets() { - Registry.add(ServerUpdateTimePacket.class, (packet, session) -> { - SetTimePacket setTimePacket = new SetTimePacket(); - setTimePacket.setTime((int) Math.abs(packet.getTime())); - - session.getUpstream().sendPacket(setTimePacket); - }); - } - - public static void addEntityPackets() { - Registry.add(ServerEntityPositionPacket.class, (packet, session) -> { - MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); - moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); - moveEntityPacket.setPosition(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); - moveEntityPacket.setRotation(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); - moveEntityPacket.setOnGround(packet.isOnGround()); - moveEntityPacket.setTeleported(false); - - session.getUpstream().sendPacket(moveEntityPacket); - }); - - Registry.add(ServerEntityPositionRotationPacket.class, (packet, session) -> { - MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); - moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); - moveEntityPacket.setPosition(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); - moveEntityPacket.setRotation(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); - moveEntityPacket.setOnGround(true); - moveEntityPacket.setTeleported(false); - - session.getUpstream().sendPacket(moveEntityPacket); - }); - - Registry.add(ServerEntityTeleportPacket.class, (packet, session) -> { - MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); - moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); - moveEntityPacket.setPosition(new Vector3f(packet.getX(), packet.getY(), packet.getZ())); - moveEntityPacket.setRotation(new Vector3f(packet.getX(), packet.getY(), packet.getZ())); - moveEntityPacket.setOnGround(packet.isOnGround()); - moveEntityPacket.setTeleported(true); - - session.getUpstream().sendPacket(moveEntityPacket); - }); - - Registry.add(ServerEntityVelocityPacket.class, (packet, session) -> { - SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); - entityMotionPacket.setRuntimeEntityId(packet.getEntityId()); - entityMotionPacket.setMotion(new Vector3f(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ())); - - session.getUpstream().sendPacket(entityMotionPacket); - }); - } - - public static void addNotifyPackets() { - Registry.add(ServerNotifyClientPacket.class, (packet, session) -> { - switch (packet.getNotification()) { - case START_RAIN: - LevelEventPacket startRainPacket = new LevelEventPacket(); - startRainPacket.setEvent(LevelEventPacket.Event.START_RAIN); - startRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); - startRainPacket.setPosition(new Vector3f(0, 0, 0)); - - session.getUpstream().sendPacket(startRainPacket); - break; - case STOP_RAIN: - LevelEventPacket stopRainPacket = new LevelEventPacket(); - stopRainPacket.setEvent(LevelEventPacket.Event.STOP_RAIN); - stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); - stopRainPacket.setPosition(new Vector3f(0, 0, 0)); - - session.getUpstream().sendPacket(stopRainPacket); - break; - case ENTER_CREDITS: - // ShowCreditsPacket showCreditsPacket = new ShowCreditsPacket(); - // showCreditsPacket.setStatus(ShowCreditsPacket.Status.START_CREDITS); - // showCreditsPacket.setRuntimeEntityId(runtimeEntityId); - // session.getUpstream().sendPacket(showCreditsPacket); - break; - default: - break; - } - }); + Registry.registerBedrock(AnimatePacket.class, new BedrockAnimateTranslator()); + Registry.registerBedrock(CommandRequestPacket.class, new BedrockCommandRequestTranslator()); + Registry.registerBedrock(TextPacket.class, new BedrockTextTranslator()); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java new file mode 100644 index 000000000..6056c54c9 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerSwingArmPacket; +import com.nukkitx.protocol.bedrock.packet.AnimatePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class BedrockAnimateTranslator extends PacketTranslator { + + @Override + public void translate(AnimatePacket packet, GeyserSession session) { + switch (packet.getAction()) { + case SWING_ARM: + ClientPlayerSwingArmPacket swingArmPacket = new ClientPlayerSwingArmPacket(Hand.MAIN_HAND); + session.getDownstream().getSession().send(swingArmPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java new file mode 100644 index 000000000..c453c31a3 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket; +import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket; +import org.geysermc.api.Geyser; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class BedrockCommandRequestTranslator extends PacketTranslator { + + @Override + public void translate(CommandRequestPacket packet, GeyserSession session) { + String command = packet.getCommand().replace("/", ""); + if (Geyser.getConnector().getCommandMap().getCommands().containsKey(command)) { + Geyser.getConnector().getCommandMap().runCommand(session, command); + } else { + ClientChatPacket chatPacket = new ClientChatPacket(packet.getCommand()); + session.getDownstream().getSession().send(chatPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java new file mode 100644 index 000000000..59d28eba0 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket; +import com.nukkitx.protocol.bedrock.packet.TextPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class BedrockTextTranslator extends PacketTranslator { + + @Override + public void translate(TextPacket packet, GeyserSession session) { + if (packet.getMessage().charAt(0) == '.') { + ClientChatPacket chatPacket = new ClientChatPacket(packet.getMessage().replace(".", "/")); + session.getDownstream().getSession().send(chatPacket); + return; + } + + ClientChatPacket chatPacket = new ClientChatPacket(packet.getMessage()); + session.getDownstream().getSession().send(chatPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java new file mode 100644 index 000000000..cc5838c90 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java; + +import com.github.steveice10.mc.protocol.data.message.TranslationMessage; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket; +import com.nukkitx.protocol.bedrock.packet.TextPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.utils.MessageUtils; + +public class JavaChatTranslator extends PacketTranslator { + + @Override + public void translate(ServerChatPacket packet, GeyserSession session) { + TextPacket textPacket = new TextPacket(); + textPacket.setPlatformChatId(""); + textPacket.setSourceName(""); + textPacket.setXuid(session.getAuthenticationData().getXboxUUID()); + switch (packet.getType()) { + case CHAT: + textPacket.setType(TextPacket.Type.CHAT); + case SYSTEM: + textPacket.setType(TextPacket.Type.SYSTEM); + case NOTIFICATION: + textPacket.setType(TextPacket.Type.TIP); + default: + textPacket.setType(TextPacket.Type.RAW); + } + + if (packet.getMessage() instanceof TranslationMessage) { + textPacket.setType(TextPacket.Type.TRANSLATION); + textPacket.setNeedsTranslation(true); + textPacket.setParameters(MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getTranslationParams())); + textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage())); + } else { + textPacket.setNeedsTranslation(false); + textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage())); + } + + session.getUpstream().sendPacket(textPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java new file mode 100644 index 000000000..a43fd4a43 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; +import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket; +import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; + +public class JavaJoinGameTranslator extends PacketTranslator { + + @Override + public void translate(ServerJoinGamePacket packet, GeyserSession session) { + AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); + bedrockPacket.setUniqueEntityId(packet.getEntityId()); + session.getUpstream().sendPacketImmediately(bedrockPacket); + + Vector3f pos = new Vector3f(0, 0, 0); + int chunkX = pos.getFloorX() >> 4; + int chunkZ = pos.getFloorZ() >> 4; + for (int x = -3; x < 3; x++) { + for (int z = -3; z < 3; z++) { + LevelChunkPacket data = new LevelChunkPacket(); + data.setChunkX(chunkX + x); + data.setChunkZ(chunkZ + z); + data.setSubChunksLength(0); + + data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); + + session.getUpstream().sendPacketImmediately(data); + + } + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java new file mode 100644 index 000000000..c9239fe29 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java; + +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerTitlePacket; +import com.nukkitx.protocol.bedrock.packet.SetTitlePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaTitleTranslator extends PacketTranslator { + + @Override + public void translate(ServerTitlePacket packet, GeyserSession session) { + SetTitlePacket titlePacket = new SetTitlePacket(); + + switch (packet.getAction()) { + case TITLE: + titlePacket.setType(SetTitlePacket.Type.SET_TITLE); + titlePacket.setText(packet.getTitle().getFullText()); + break; + case SUBTITLE: + titlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + titlePacket.setText(packet.getSubtitle().getFullText()); + break; + case CLEAR: + case RESET: + titlePacket.setType(SetTitlePacket.Type.RESET_TITLE); + titlePacket.setText(""); + break; + case ACTION_BAR: + titlePacket.setType(SetTitlePacket.Type.SET_ACTIONBAR_MESSAGE); + titlePacket.setText(packet.getActionBar().getFullText()); + break; + } + + titlePacket.setFadeInTime(packet.getFadeIn()); + titlePacket.setFadeOutTime(packet.getFadeOut()); + titlePacket.setStayTime(packet.getStay()); + + session.getUpstream().sendPacket(titlePacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityDestroyTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityDestroyTranslator.java new file mode 100644 index 000000000..a9885d330 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityDestroyTranslator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity; + +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityDestroyPacket; +import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaEntityDestroyTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityDestroyPacket packet, GeyserSession session) { + for (int entityId : packet.getEntityIds()) { + RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); + removeEntityPacket.setUniqueEntityId(entityId); + + session.getUpstream().sendPacket(removeEntityPacket); + } + } +} + diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java new file mode 100644 index 000000000..713a24323 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPositionRotationPacket; +import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaEntityPositionRotationTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityPositionRotationPacket packet, GeyserSession session) { + MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); + moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); + moveEntityPacket.setPosition(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); + moveEntityPacket.setRotation(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); + moveEntityPacket.setOnGround(true); + moveEntityPacket.setTeleported(false); + + session.getUpstream().sendPacket(moveEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionTranslator.java new file mode 100644 index 000000000..a79b9d720 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionTranslator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPositionPacket; +import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaEntityPositionTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityPositionPacket packet, GeyserSession session) { + MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); + moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); + moveEntityPacket.setPosition(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); + moveEntityPacket.setRotation(new Vector3f(packet.getMovementX(), packet.getMovementY(), packet.getMovementZ())); + moveEntityPacket.setOnGround(packet.isOnGround()); + moveEntityPacket.setTeleported(false); + + session.getUpstream().sendPacket(moveEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityTeleportTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityTeleportTranslator.java new file mode 100644 index 000000000..c5ec98fc0 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityTeleportTranslator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket; +import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaEntityTeleportTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityTeleportPacket packet, GeyserSession session) { + MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); + moveEntityPacket.setRuntimeEntityId(packet.getEntityId()); + moveEntityPacket.setPosition(new Vector3f(packet.getX(), packet.getY(), packet.getZ())); + moveEntityPacket.setRotation(new Vector3f(packet.getX(), packet.getY(), packet.getZ())); + moveEntityPacket.setOnGround(packet.isOnGround()); + moveEntityPacket.setTeleported(true); + + session.getUpstream().sendPacket(moveEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java new file mode 100644 index 000000000..ef96e2f50 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityVelocityTranslator.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityVelocityPacket; +import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaEntityVelocityTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityVelocityPacket packet, GeyserSession session) { + SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); + entityMotionPacket.setRuntimeEntityId(packet.getEntityId()); + entityMotionPacket.setMotion(new Vector3f(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ())); + + session.getUpstream().sendPacket(entityMotionPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnExpOrbTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnExpOrbTranslator.java new file mode 100644 index 000000000..c7f754dce --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnExpOrbTranslator.java @@ -0,0 +1,19 @@ +package org.geysermc.connector.network.translators.java.entity.spawn; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnExpOrbPacket; +import com.nukkitx.protocol.bedrock.packet.SpawnExperienceOrbPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaSpawnExpOrbTranslator extends PacketTranslator { + + @Override + public void translate(ServerSpawnExpOrbPacket packet, GeyserSession session) { + SpawnExperienceOrbPacket spawnExperienceOrbPacket = new SpawnExperienceOrbPacket(); + spawnExperienceOrbPacket.setPosition(new Vector3f(packet.getX(), packet.getY(), packet.getZ())); + spawnExperienceOrbPacket.setAmount(packet.getExp()); + + session.getUpstream().sendPacket(spawnExperienceOrbPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java new file mode 100644 index 000000000..65c25a1d3 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.flowpowered.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +import java.util.concurrent.ThreadLocalRandom; + +public class JavaNotifyClientTranslator extends PacketTranslator { + + @Override + public void translate(ServerNotifyClientPacket packet, GeyserSession session) { + switch (packet.getNotification()) { + case START_RAIN: + LevelEventPacket startRainPacket = new LevelEventPacket(); + startRainPacket.setEvent(LevelEventPacket.Event.START_RAIN); + startRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); + startRainPacket.setPosition(new Vector3f(0, 0, 0)); + + session.getUpstream().sendPacket(startRainPacket); + break; + case STOP_RAIN: + LevelEventPacket stopRainPacket = new LevelEventPacket(); + stopRainPacket.setEvent(LevelEventPacket.Event.STOP_RAIN); + stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); + stopRainPacket.setPosition(new Vector3f(0, 0, 0)); + + session.getUpstream().sendPacket(stopRainPacket); + break; + case ENTER_CREDITS: + // ShowCreditsPacket showCreditsPacket = new ShowCreditsPacket(); + // showCreditsPacket.setStatus(ShowCreditsPacket.Status.START_CREDITS); + // showCreditsPacket.setRuntimeEntityId(runtimeEntityId); + // session.getUpstream().sendPacket(showCreditsPacket); + break; + default: + break; + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java new file mode 100644 index 000000000..3e9cc40c8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTimeTranslator.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket; +import com.nukkitx.protocol.bedrock.packet.SetTimePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaUpdateTimeTranslator extends PacketTranslator { + + @Override + public void translate(ServerUpdateTimePacket packet, GeyserSession session) { + SetTimePacket setTimePacket = new SetTimePacket(); + setTimePacket.setTime((int) Math.abs(packet.getTime())); + + session.getUpstream().sendPacket(setTimePacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java new file mode 100644 index 000000000..47584fcc2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java @@ -0,0 +1,38 @@ +package org.geysermc.connector.utils; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.nimbusds.jose.JWSObject; +import com.nukkitx.network.util.Preconditions; +import com.nukkitx.protocol.bedrock.util.EncryptionUtils; + +import java.security.interfaces.ECPublicKey; + +public class LoginEncryptionUtils { + + public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + public 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 = EncryptionUtils.verifyJwt(jwt, EncryptionUtils.getMojangPublicKey()); + } + + if (lastKey != null) { + EncryptionUtils.verifyJwt(jwt, lastKey); + } + + JsonNode payloadNode = 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; + } +} diff --git a/pom.xml b/pom.xml index cd9dc69a5..973d270fb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,7 @@ GeyserMC Allows for players from Minecraft Bedrock Edition to join Minecraft Java Edition servers. https://geysermc.org + Geyser UTF-8 @@ -17,21 +18,25 @@ 1.8 1.8 + GeyserMC https://github.com/GeyserMC/Geyser/blob/master/pom.xml + scm:git:https://github.com/GeyserMC/Geyser.git scm:git:git@github.com:GeyserMC/Geyser.git https://github.com/GeyserMC/Geyser + api common connector plugin + CodeMC-repo @@ -44,10 +49,40 @@ - nukkitx-repo + nukkitx-release-repo https://repo.nukkitx.com/maven-releases/ + + true + + + false + + + + nukkitx-snapshot-repo + https://repo.nukkitx.com/maven-snapshots/ + + false + + + true + + + + + releases + nukkitx-releases + https://repo.nukkitx.com/maven-releases + + + snapshots + nukkitx-snapshots + https://repo.nukkitx.com/maven-snapshots + + + clean install