diff --git a/README.md b/README.md
index 619a0a78b..a23afe99e 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ https://discord.gg/mRjbCsS
## What's Completed
- [x] Server recognized in server list
- [x] Join detection from remote
-- [ ] Online mode/auth support
+- [x] Online mode/auth support
- [x] Chat/command support
- [ ] Inventory support
- [ ] Movement support
diff --git a/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java b/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java
index afc6d72c0..66efd850e 100644
--- a/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java
+++ b/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java
@@ -92,7 +92,7 @@ public class CustomFormWindow extends FormWindow {
}
public void setResponse(String data) {
- if (data == null || data.equalsIgnoreCase("null")) {
+ if (data == null || data.equalsIgnoreCase("null") || data.isEmpty()) {
closed = true;
return;
}
diff --git a/common/pom.xml b/common/pom.xml
index c88332601..6a0a6ff04 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -54,11 +54,5 @@
3.3.0
compile
-
- org.apache.commons
- commons-lang3
- 3.7
- compile
-
\ 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 886f86fa5..09b737bcb 100644
--- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
@@ -35,7 +35,12 @@ import net.minidev.json.JSONArray;
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;
import org.geysermc.api.window.FormWindow;
+import org.geysermc.api.window.component.InputComponent;
+import org.geysermc.api.window.component.LabelComponent;
+import org.geysermc.api.window.response.CustomFormResponse;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.session.auth.BedrockAuthData;
@@ -86,18 +91,6 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
session.getUpstream().sendPacketImmediately(resourcePacksInfo);
-
- // TODO: Implement this
- /**
- CustomFormWindow window = new CustomFormBuilder("Login")
- .addComponent(new LabelComponent("Minecraft: Java Edition account authentication."))
- .addComponent(new LabelComponent("Enter the credentials for your Minecraft: Java Edition account below."))
- .addComponent(new InputComponent("Email/Username", "account@geysermc.org", ""))
- .addComponent(new InputComponent("Password", "123456", ""))
- .build();
-
- session.sendForm(window, 1);
- */
return true;
}
@@ -107,7 +100,7 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
switch (textPacket.getStatus()) {
case COMPLETED:
session.connect(connector.getRemoteServer());
- connector.getLogger().info("Player connected with " + session.getAuthenticationData().getName());
+ connector.getLogger().info("Player connected with username " + session.getAuthenticationData().getName());
break;
case HAVE_ALL_PACKS:
ResourcePackStackPacket stack = new ResourcePackStackPacket();
@@ -327,8 +320,22 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
FormWindow window = windowCache.getWindows().remove(packet.getFormId());
window.setResponse(packet.getFormData().trim());
- PlayerFormResponseEvent event = new PlayerFormResponseEvent(session, packet.getFormId(), window);
- connector.getPluginManager().runEvent(event);
+ if (session.isLoggedIn()) {
+ PlayerFormResponseEvent event = new PlayerFormResponseEvent(session, packet.getFormId(), window);
+ connector.getPluginManager().runEvent(event);
+ } else {
+ if (window instanceof CustomFormWindow) {
+ CustomFormWindow customFormWindow = (CustomFormWindow) window;
+ if (!customFormWindow.getTitle().equals("Login"))
+ return false;
+
+ CustomFormResponse response = (CustomFormResponse) customFormWindow.getResponse();
+ session.authenticate(response.getInputResponses().get(2), response.getInputResponses().get(3));
+
+ // Clear windows so authentication data isn't accidentally cached
+ windowCache.getWindows().clear();
+ }
+ }
return true;
}
@@ -341,6 +348,17 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
@Override
public boolean handle(MovePlayerPacket packet) {
connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName());
+ if (!session.isLoggedIn()) {
+ CustomFormWindow window = new CustomFormBuilder("Login")
+ .addComponent(new LabelComponent("Minecraft: Java Edition account authentication."))
+ .addComponent(new LabelComponent("Enter the credentials for your Minecraft: Java Edition account below."))
+ .addComponent(new InputComponent("Email/Username", "account@geysermc.org", ""))
+ .addComponent(new InputComponent("Password", "123456", ""))
+ .build();
+
+ session.sendForm(window, 1);
+ return true;
+ }
return false;
}
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 2fa274765..8cf5ced5d 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
@@ -25,6 +25,10 @@
package org.geysermc.connector.network.session;
+import com.flowpowered.math.vector.Vector2f;
+import com.flowpowered.math.vector.Vector3f;
+import com.flowpowered.math.vector.Vector3i;
+import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.github.steveice10.packetlib.Client;
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
@@ -35,6 +39,10 @@ import com.github.steveice10.packetlib.tcp.TcpSessionFactory;
import com.nukkitx.network.util.DisconnectReason;
import com.nukkitx.protocol.PlayerSession;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
+import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
+import com.nukkitx.protocol.bedrock.data.GameRule;
+import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
+import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
import com.nukkitx.protocol.bedrock.packet.TextPacket;
import lombok.Getter;
import org.geysermc.api.Player;
@@ -44,6 +52,7 @@ import org.geysermc.api.window.FormWindow;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.cache.WindowCache;
import org.geysermc.connector.network.translators.Registry;
+import org.geysermc.connector.utils.Toolbox;
public class GeyserSession implements PlayerSession, Player {
@@ -66,6 +75,9 @@ public class GeyserSession implements PlayerSession, Player {
@Getter
private WindowCache windowCache;
+ @Getter
+ private boolean loggedIn;
+
private boolean closed;
public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
@@ -73,36 +85,70 @@ public class GeyserSession implements PlayerSession, Player {
this.upstream = bedrockServerSession;
this.windowCache = new WindowCache(this);
+
+ this.loggedIn = false;
}
public void connect(RemoteServer remoteServer) {
- MinecraftProtocol protocol = new MinecraftProtocol(authenticationData.getName());
- downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory());
- downstream.getSession().addListener(new SessionAdapter() {
+ // This has to be sent first so the player actually joins
+ startGame();
- @Override
- public void connected(ConnectedEvent event) {
- connector.getLogger().info(authenticationData.getName() + " has connected to remote java server on address " + remoteServer.getAddress());
- }
-
- @Override
- public void disconnected(DisconnectedEvent event) {
- connector.getLogger().info(authenticationData.getName() + " has disconnected from remote java server on address " + remoteServer.getAddress() + " because of " + event.getReason());
- upstream.disconnect(event.getReason());
- }
-
- @Override
- public void packetReceived(PacketReceivedEvent event) {
- Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), THIS);
- }
- });
-
- downstream.getSession().connect();
this.remoteServer = remoteServer;
+ if (!connector.getConfig().getRemote().isOnlineMode()) {
+ connector.getLogger().info("Attempting to login using offline mode... authentication is disabled.");
+ authenticate(authenticationData.getName());
+ }
+ }
+
+ public void authenticate(String username) {
+ authenticate(username, "");
+ }
+
+ public void authenticate(String username, String password) {
+ if (loggedIn) {
+ connector.getLogger().severe(username + " is already logged in!");
+ return;
+ }
+
+ try {
+ MinecraftProtocol protocol;
+ if (password != null && !password.isEmpty()) {
+ protocol = new MinecraftProtocol(username, password);
+ } else {
+ protocol = new MinecraftProtocol(username);
+ }
+
+ downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory());
+ downstream.getSession().addListener(new SessionAdapter() {
+
+ @Override
+ public void connected(ConnectedEvent event) {
+ loggedIn = true;
+ connector.getLogger().info(authenticationData.getName() + " (logged in as: " + protocol.getProfile().getName() + ")" + " has connected to remote java server on address " + remoteServer.getAddress());
+ }
+
+ @Override
+ public void disconnected(DisconnectedEvent event) {
+ loggedIn = false;
+ connector.getLogger().info(authenticationData.getName() + " has disconnected from remote java server on address " + remoteServer.getAddress() + " because of " + event.getReason());
+ upstream.disconnect(event.getReason());
+ }
+
+ @Override
+ public void packetReceived(PacketReceivedEvent event) {
+ Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), THIS);
+ }
+ });
+
+ downstream.getSession().connect();
+ } catch (RequestException ex) {
+ ex.printStackTrace();
+ }
}
public void disconnect(String reason) {
if (!closed) {
+ loggedIn = false;
downstream.getSession().disconnect(reason);
upstream.disconnect(reason);
}
@@ -164,4 +210,58 @@ public class GeyserSession implements PlayerSession, Player {
public void sendForm(FormWindow window) {
windowCache.showWindow(window);
}
+
+ private void startGame() {
+ StartGamePacket startGamePacket = new StartGamePacket();
+ startGamePacket.setUniqueEntityId(1); // TODO: Cache this value
+ startGamePacket.setRuntimeEntityId(1); // TODO: Cache this value
+ startGamePacket.setPlayerGamemode(0);
+ startGamePacket.setPlayerPosition(new Vector3f(0, 0, 0));
+ startGamePacket.setRotation(new Vector2f(1, 1));
+
+ startGamePacket.setSeed(1111);
+ startGamePacket.setDimensionId(0);
+ startGamePacket.setGeneratorId(0);
+ startGamePacket.setLevelGamemode(0);
+ startGamePacket.setDifficulty(1);
+ startGamePacket.setDefaultSpawn(new Vector3i(0, 0, 0));
+ startGamePacket.setAcheivementsDisabled(true);
+ startGamePacket.setTime(0);
+ startGamePacket.setEduLevel(false);
+ startGamePacket.setEduFeaturesEnabled(false);
+ startGamePacket.setRainLevel(0);
+ startGamePacket.setLightningLevel(0);
+ startGamePacket.setMultiplayerGame(true);
+ startGamePacket.setBroadcastingToLan(true);
+ 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(0);
+ startGamePacket.setEnchantmentSeed(0);
+ startGamePacket.setMultiplayerCorrelationId("");
+ startGamePacket.setCachedPalette(Toolbox.CACHED_PALLETE);
+ startGamePacket.setItemEntries(Toolbox.ITEMS);
+ upstream.sendPacket(startGamePacket);
+
+ PlayStatusPacket playStatusPacket = new PlayStatusPacket();
+ playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
+ upstream.sendPacket(playStatusPacket);
+ }
}
\ No newline at end of file
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 da8a344e6..2794d2bf4 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,9 +25,7 @@
package org.geysermc.connector.network.translators;
-import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector3f;
-import com.flowpowered.math.vector.Vector3i;
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;
@@ -42,11 +40,8 @@ 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.data.GamePublishSetting;
-import com.nukkitx.protocol.bedrock.data.GameRule;
import com.nukkitx.protocol.bedrock.packet.*;
import org.geysermc.connector.utils.MessageUtils;
-import org.geysermc.connector.utils.Toolbox;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -83,60 +78,9 @@ public class TranslatorsInit {
private static void addLoginPackets() {
Registry.add(ServerJoinGamePacket.class, (packet, session) -> {
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
-
bedrockPacket.setUniqueEntityId(packet.getEntityId());
-
session.getUpstream().sendPacketImmediately(bedrockPacket);
- StartGamePacket startGamePacket = new StartGamePacket();
- startGamePacket.setUniqueEntityId(packet.getEntityId());
- startGamePacket.setRuntimeEntityId(packet.getEntityId());
- startGamePacket.setPlayerGamemode(packet.getGameMode().ordinal());
- startGamePacket.setPlayerPosition(new Vector3f(0, 0, 0));
- startGamePacket.setRotation(new Vector2f(1, 1));
-
- startGamePacket.setSeed(1111);
- startGamePacket.setDimensionId(0);
- startGamePacket.setGeneratorId(0);
- startGamePacket.setLevelGamemode(packet.getGameMode().ordinal());
- startGamePacket.setDifficulty(1);
- startGamePacket.setDefaultSpawn(new Vector3i(0, 0, 0));
- startGamePacket.setAcheivementsDisabled(true);
- startGamePacket.setTime(0);
- startGamePacket.setEduLevel(false);
- startGamePacket.setEduFeaturesEnabled(false);
- startGamePacket.setRainLevel(0);
- startGamePacket.setLightningLevel(0);
- startGamePacket.setMultiplayerGame(true);
- startGamePacket.setBroadcastingToLan(true);
- 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(0);
- startGamePacket.setEnchantmentSeed(0);
- startGamePacket.setMultiplayerCorrelationId("");
- startGamePacket.setCachedPalette(Toolbox.CACHED_PALLETE);
- startGamePacket.setItemEntries(Toolbox.ITEMS);
-
- session.getUpstream().sendPacket(startGamePacket);
-
Vector3f pos = new Vector3f(0, 0, 0);
int chunkX = pos.getFloorX() >> 4;
int chunkZ = pos.getFloorZ() >> 4;
@@ -153,10 +97,6 @@ public class TranslatorsInit {
}
}
-
- PlayStatusPacket playStatusPacket = new PlayStatusPacket();
- playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
- session.getUpstream().sendPacket(playStatusPacket);
});
}