diff --git a/src/main/java/de/bixilon/minosoft/Config.java b/src/main/java/de/bixilon/minosoft/Config.java index 54ce63ac0..18ff37d6a 100644 --- a/src/main/java/de/bixilon/minosoft/Config.java +++ b/src/main/java/de/bixilon/minosoft/Config.java @@ -15,4 +15,5 @@ package de.bixilon.minosoft; public class Config { public static String homeDir; + public static String configFileName = "game.yml"; } diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.java b/src/main/java/de/bixilon/minosoft/Minosoft.java index 746f2acef..a15a9b2a3 100644 --- a/src/main/java/de/bixilon/minosoft/Minosoft.java +++ b/src/main/java/de/bixilon/minosoft/Minosoft.java @@ -15,18 +15,21 @@ package de.bixilon.minosoft; import de.bixilon.minosoft.config.Configuration; import de.bixilon.minosoft.config.GameConfiguration; +import de.bixilon.minosoft.game.datatypes.Player; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.LogLevel; -import de.bixilon.minosoft.objects.Account; -import de.bixilon.minosoft.objects.Player; +import de.bixilon.minosoft.mojang.api.MojangAccount; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.util.OSUtil; import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.UUID; public class Minosoft { static Configuration config; + static List accountList; public static void main(String[] args) { // int log thread @@ -36,7 +39,7 @@ public class Minosoft { setConfigFolder(); Log.info("Reading config file..."); try { - config = new Configuration("game.yml"); + config = new Configuration(Config.configFileName); } catch (IOException e) { Log.fatal("Failed to load config file!"); e.printStackTrace(); @@ -46,8 +49,21 @@ public class Minosoft { // set log level from config Log.setLevel(LogLevel.byName(config.getString(GameConfiguration.GENERAL_LOG_LEVEL))); + checkClientToken(); + Connection c = new Connection(config.getString("debug.host"), config.getInteger("debug.port")); - c.setPlayer(new Player(new Account(config.getString("debug.username"), config.getString("debug.password")))); + accountList = config.getMojangAccounts(); + if (accountList.size() == 0) { + throw new RuntimeException("No accounts in config file!"); + //MojangAccount account = MojangAuthentication.login("email", "password"); + } + MojangAccount account = accountList.get(0); + if (!account.refreshToken()) { + // could not login + System.exit(1); + } + account.saveToConfig(); + c.setPlayer(new Player(account)); c.connect(); } @@ -79,4 +95,11 @@ public class Minosoft { public static Configuration getConfig() { return config; } + + public static void checkClientToken() { + if (config.getString(GameConfiguration.CLIENT_TOKEN) == null || config.getString(GameConfiguration.CLIENT_TOKEN).equals("randomGenerated")) { + config.putString(GameConfiguration.CLIENT_TOKEN, UUID.randomUUID().toString()); + config.saveToFile(Config.configFileName); + } + } } diff --git a/src/main/java/de/bixilon/minosoft/objects/ServerListPing.java b/src/main/java/de/bixilon/minosoft/ServerListPing.java similarity index 97% rename from src/main/java/de/bixilon/minosoft/objects/ServerListPing.java rename to src/main/java/de/bixilon/minosoft/ServerListPing.java index ca823ea65..cc0a3f148 100644 --- a/src/main/java/de/bixilon/minosoft/objects/ServerListPing.java +++ b/src/main/java/de/bixilon/minosoft/ServerListPing.java @@ -11,7 +11,7 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.objects; +package de.bixilon.minosoft; import de.bixilon.minosoft.game.datatypes.TextComponent; import org.json.JSONObject; diff --git a/src/main/java/de/bixilon/minosoft/config/Configuration.java b/src/main/java/de/bixilon/minosoft/config/Configuration.java index ec9622369..3d7411ddd 100644 --- a/src/main/java/de/bixilon/minosoft/config/Configuration.java +++ b/src/main/java/de/bixilon/minosoft/config/Configuration.java @@ -14,12 +14,13 @@ package de.bixilon.minosoft.config; import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.mojang.api.MojangAccount; import org.yaml.snakeyaml.Yaml; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.LinkedHashMap; +import java.util.*; public class Configuration { LinkedHashMap config; @@ -69,6 +70,38 @@ public class Configuration { } + public void putBoolean(ConfigEnum config, boolean value) { + putBoolean(config.getPath(), value); + } + + public void putBoolean(String path, boolean value) { + put(path, value); + } + + public void putInteger(ConfigEnum config, int value) { + putInteger(config.getPath(), value); + } + + public void putInteger(String path, int value) { + put(path, value); + } + + public void putString(ConfigEnum config, String value) { + putString(config.getPath(), value); + } + + public void putString(String path, String value) { + put(path, value); + } + + public void putMojangAccount(MojangAccount account) { + String basePath = String.format("account.accounts.%s.", account.getUserId()); + putString(basePath + "accessToken", account.getAccessToken()); + putString(basePath + "uuid", account.getUUID().toString()); + putString(basePath + "userName", account.getMojangUserName()); + putString(basePath + "playerName", account.getPlayerName()); + } + public Object get(String path) { if (path.contains(".")) { // split @@ -78,9 +111,54 @@ public class Configuration { //noinspection unchecked temp = (LinkedHashMap) temp.get(spilt[i]); } + if (temp == null) { + return null; + } return temp.get(spilt[spilt.length - 1]); } return config.get(path); } + + public void put(String path, Serializable value) { + if (path.contains(".")) { + // split + String[] spilt = path.split("\\."); + LinkedHashMap temp = config; + for (int i = 0; i < spilt.length - 1; i++) { + if (temp.get(spilt[i]) == null) { + // not yet existing, creating it + temp.put(spilt[i], new LinkedHashMap()); + } + temp = (LinkedHashMap) temp.get(spilt[i]); + + } + temp.put(spilt[spilt.length - 1], value); + return; + } + config.put(path, value); + } + + public void saveToFile(String filename) { + Yaml yaml = new Yaml(); + FileWriter writer = null; + try { + writer = new FileWriter(Config.homeDir + "config/" + filename); + } catch (IOException e) { + e.printStackTrace(); + return; + } + yaml.dump(config, writer); + } + + public List getMojangAccounts() { + List accounts = new ArrayList<>(); + LinkedHashMap objects = (LinkedHashMap) get("account.accounts"); + for (Map.Entry set : objects.entrySet()) { + LinkedHashMap entry = (LinkedHashMap) set.getValue(); + accounts.add(new MojangAccount((String) entry.get("accessToken"), set.getKey(), UUID.fromString((String) entry.get("uuid")), (String) entry.get("playerName"), (String) entry.get("mojangUserName"))); + } + return accounts; + + } } diff --git a/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java b/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java index 82a331e34..264410225 100644 --- a/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java +++ b/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java @@ -17,7 +17,8 @@ public enum GameConfiguration implements ConfigEnum { CONFIG_VERSION("version"), GAME_RENDER_DISTANCE("game.render-distance"), NETWORK_FAKE_CLIENT_BRAND("network.fake-client-brand"), - GENERAL_LOG_LEVEL("general.log-level"); + GENERAL_LOG_LEVEL("general.log-level"), + CLIENT_TOKEN("account.clientToken"); final String path; diff --git a/src/main/java/de/bixilon/minosoft/objects/Player.java b/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java similarity index 93% rename from src/main/java/de/bixilon/minosoft/objects/Player.java rename to src/main/java/de/bixilon/minosoft/game/datatypes/Player.java index 6703777be..fc2953788 100644 --- a/src/main/java/de/bixilon/minosoft/objects/Player.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java @@ -11,20 +11,18 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.objects; +package de.bixilon.minosoft.game.datatypes; -import de.bixilon.minosoft.game.datatypes.GameMode; -import de.bixilon.minosoft.game.datatypes.Slot; -import de.bixilon.minosoft.game.datatypes.Slots; import de.bixilon.minosoft.game.datatypes.entities.Location; import de.bixilon.minosoft.game.datatypes.entities.meta.HumanMetaData; import de.bixilon.minosoft.game.datatypes.world.World; +import de.bixilon.minosoft.mojang.api.MojangAccount; import java.util.HashMap; import java.util.UUID; public class Player { - final Account acc; + final MojangAccount acc; float health; short food; float saturation; @@ -39,9 +37,8 @@ public class Player { HashMap inventory = new HashMap<>(); boolean spawnConfirmed = false; - public Player(Account acc) { + public Player(MojangAccount acc) { this.acc = acc; - acc.login(); } public String getPlayerName() { @@ -52,7 +49,7 @@ public class Player { return acc.getUUID(); } - public Account getAccount() { + public MojangAccount getAccount() { return this.acc; } diff --git a/src/main/java/de/bixilon/minosoft/mojang/api/MojangAccount.java b/src/main/java/de/bixilon/minosoft/mojang/api/MojangAccount.java new file mode 100644 index 000000000..963241231 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/mojang/api/MojangAccount.java @@ -0,0 +1,89 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.mojang.api; + +import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.util.Util; +import org.json.JSONObject; + +import java.util.UUID; + +public class MojangAccount { + + String accessToken; + String userId; + + UUID uuid; + String playerName; + + String mojangUserName; + + public MojangAccount(JSONObject json) { + this.accessToken = json.getString("accessToken"); + JSONObject profile = json.getJSONObject("selectedProfile"); + this.uuid = Util.formatUUID(profile.getString("id")); + this.playerName = profile.getString("name"); + + JSONObject mojang = json.getJSONObject("user"); + this.userId = mojang.getString("id"); + this.mojangUserName = mojang.getString("username"); + } + + public MojangAccount(String accessToken, String userId, UUID uuid, String playerName, String mojangUserName) { + this.accessToken = accessToken; + this.userId = userId; + this.uuid = uuid; + this.playerName = playerName; + this.mojangUserName = mojangUserName; + } + + public void join(String serverId) { + MojangAuthentication.joinServer(this, serverId); + } + + public boolean refreshToken() { + String accessToken = MojangAuthentication.refresh(this.accessToken); + if (accessToken == null) { + return false; + } + this.accessToken = accessToken; + return true; + } + + public UUID getUUID() { + return this.uuid; + } + + public String getPlayerName() { + return this.playerName; + } + + public String getAccessToken() { + return accessToken; + } + + public String getMojangUserName() { + return mojangUserName; + } + + public String getUserId() { + return userId; + } + + public void saveToConfig() { + Minosoft.getConfig().putMojangAccount(this); + Minosoft.getConfig().saveToFile(Config.configFileName); + } +} diff --git a/src/main/java/de/bixilon/minosoft/mojang/api/MojangAuthentication.java b/src/main/java/de/bixilon/minosoft/mojang/api/MojangAuthentication.java new file mode 100644 index 000000000..d1e98a860 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/mojang/api/MojangAuthentication.java @@ -0,0 +1,97 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.mojang.api; + +import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.config.GameConfiguration; +import de.bixilon.minosoft.logging.Log; +import de.bixilon.minosoft.util.HTTP; +import org.json.JSONObject; + +import java.net.http.HttpResponse; + +public class MojangAuthentication { + + public static MojangAccount login(String clientToken, String username, String password) { + JSONObject payload = new JSONObject(); + payload.put("agent", new JSONObject().put("name", "Minecraft").put("version", 1)); + payload.put("username", username); + payload.put("password", password); + payload.put("clientToken", clientToken); + payload.put("requestUser", true); + + HttpResponse response = HTTP.postJson(MojangURLs.LOGIN.getUrl(), payload); + if (response == null) { + Log.mojang(String.format("Failed to login with username %s", username)); + return null; + } + JSONObject jsonResponse = new JSONObject(response.body()); + if (response.statusCode() != 200) { + Log.mojang(String.format("Failed to login with error code %d: %s", response.statusCode(), jsonResponse.getString("errorMessage"))); + return null; + } + // now it is okay + return new MojangAccount(jsonResponse); + } + + public static MojangAccount login(String username, String password) { + return login(Minosoft.getConfig().getString(GameConfiguration.CLIENT_TOKEN), username, password); + + } + + public static void joinServer(MojangAccount account, String serverId) { + + JSONObject payload = new JSONObject(); + payload.put("accessToken", account.getAccessToken()); + payload.put("selectedProfile", account.getUUID().toString().replace("-", "")); + payload.put("serverId", serverId); + + HttpResponse response = HTTP.postJson(MojangURLs.JOIN.toString(), payload); + + if (response == null) { + Log.mojang(String.format("Failed to join server: %s", serverId)); + return; + } + JSONObject jsonResponse = new JSONObject(response.body()); + if (response.statusCode() != 204) { + Log.mojang(String.format("Failed to join server with error code %d: %s", response.statusCode(), jsonResponse.getString("errorMessage"))); + return; + } + // joined + Log.mojang("Joined server successfully"); + } + + public static String refresh(String clientToken, String accessToken) { + JSONObject payload = new JSONObject(); + payload.put("accessToken", accessToken); + payload.put("clientToken", clientToken); + + HttpResponse response = HTTP.postJson(MojangURLs.REFRESH.getUrl(), payload); + if (response == null) { + Log.mojang("Failed to refresh session"); + return null; + } + JSONObject jsonResponse = new JSONObject(response.body()); + if (response.statusCode() != 200) { + Log.mojang(String.format("Failed to refresh session with error code %d: %s", response.statusCode(), jsonResponse.getString("errorMessage"))); + return null; + } + // now it is okay + return jsonResponse.getString("accessToken"); + } + + public static String refresh(String accessToken) { + return refresh(Minosoft.getConfig().getString(GameConfiguration.CLIENT_TOKEN), accessToken); + } +} diff --git a/src/main/java/de/bixilon/minosoft/mojang/api/MojangBlockedServers.java b/src/main/java/de/bixilon/minosoft/mojang/api/MojangBlockedServers.java new file mode 100644 index 000000000..687e49566 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/mojang/api/MojangBlockedServers.java @@ -0,0 +1,51 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.mojang.api; + +import de.bixilon.minosoft.logging.Log; +import de.bixilon.minosoft.util.HTTP; +import de.bixilon.minosoft.util.Util; + +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MojangBlockedServers { + + + public static List getBlockedServers() { + HttpResponse response = HTTP.get(MojangURLs.BLOCKED_SERVERS.getUrl()); + if (response == null) { + Log.mojang("Failed to fetch blocked servers"); + return null; + } + if (response.statusCode() != 200) { + Log.mojang(String.format("Failed to fetch blocked server error code %d", response.statusCode())); + return null; + } + // now it is hopefully okay + return new ArrayList<>(Arrays.asList(response.body().split("\n"))); + } + + public boolean isServerBlocked(List list, String hostname) { + for (String hash : list) { + if (hash.equals(Util.sha1(hostname))) { + return true; + } + // ToDo: check subdomains and ip addresses + } + return false; + } +} diff --git a/src/main/java/de/bixilon/minosoft/mojang/api/MojangStatus.java b/src/main/java/de/bixilon/minosoft/mojang/api/MojangStatus.java new file mode 100644 index 000000000..3fa87e4f6 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/mojang/api/MojangStatus.java @@ -0,0 +1,115 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.mojang.api; + +import de.bixilon.minosoft.logging.Log; +import de.bixilon.minosoft.util.HTTP; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Iterator; + +public class MojangStatus { + public static HashMap getStatus() { + HttpResponse response = HTTP.get(MojangURLs.STATUS.getUrl()); + if (response == null) { + Log.mojang("Failed to fetch Status"); + return getUnknownStatusMap(); + } + if (response.statusCode() != 200) { + Log.mojang(String.format("Failed to fetch Status with error code %d", response.statusCode())); + return getUnknownStatusMap(); + } + // now it is hopefully okay + HashMap ret = new HashMap<>(); + try { + JSONArray json = new JSONArray(response.body()); + for (int i = 0; i < json.length(); i++) { + JSONObject innerJson = json.getJSONObject(i); + Iterator keys = innerJson.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Services service = Services.byKey(key); + ret.put(service, ServiceStatus.byKey(innerJson.getString(key))); + } + } + if (ret.size() != Services.values().length) { + // new service or old one removed, technically an error + return ret; + } + return ret; + + } catch (NullPointerException | JSONException e) { + e.printStackTrace(); + return getUnknownStatusMap(); + } + } + + static HashMap getUnknownStatusMap() { + HashMap ret = new HashMap<>(); + for (Services service : Services.values()) { + ret.put(service, ServiceStatus.UNKNOWN); + } + return ret; + } + + enum Services { + MINECRAFT_NET("minecraft.net"), + ACCOUNT("account.mojang.com"), + AUTH("auth.mojang.com"), + AUTHENTICATION_SERVER("authserver.mojang.com"), + SESSION_SERVER("sessionserver.mojang.com"), + API("api.mojang.com"), + TEXTURES("textures.minecraft.net"), + MOJANG_COM("mojang.com"); + + final String key; + + Services(String key) { + this.key = key; + } + + public static Services byKey(String key) { + for (Services s : values()) { + if (s.getKey().equals(key)) { + return s; + } + } + return null; + } + + public String getKey() { + return key; + } + } + + enum ServiceStatus { + GREEN, + YELLOW, + RED, + UNKNOWN; + + public static ServiceStatus byKey(String key) { + for (ServiceStatus s : values()) { + if (s.name().equals(key)) { + return s; + } + } + return UNKNOWN; + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/mojang/api/MojangURLs.java b/src/main/java/de/bixilon/minosoft/mojang/api/MojangURLs.java new file mode 100644 index 000000000..08b5917bb --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/mojang/api/MojangURLs.java @@ -0,0 +1,46 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.mojang.api; + +public enum MojangURLs { + STATUS("https://status.mojang.com/check"), + BLOCKED_SERVERS("https://sessionserver.mojang.com/blockedservers"), + LOGIN("https://authserver.mojang.com/authenticate"), + JOIN("https://sessionserver.mojang.com/session/minecraft/join"), + REFRESH("https://authserver.mojang.com/refresh"); + + final String url; + + MojangURLs(String url) { + this.url = url; + } + + public static MojangURLs byUrl(String key) { + for (MojangURLs s : values()) { + if (s.getUrl().equals(key)) { + return s; + } + } + return null; + } + + public String getUrl() { + return url; + } + + @Override + public String toString() { + return url; + } +} diff --git a/src/main/java/de/bixilon/minosoft/objects/Account.java b/src/main/java/de/bixilon/minosoft/objects/Account.java deleted file mode 100644 index 9cf7b9b2b..000000000 --- a/src/main/java/de/bixilon/minosoft/objects/Account.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Codename Minosoft - * Copyright (C) 2020 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.objects; - -import de.bixilon.minosoft.logging.Log; -import de.bixilon.minosoft.util.HTTP; -import de.bixilon.minosoft.util.Util; -import org.json.JSONObject; - -import java.net.http.HttpResponse; -import java.util.UUID; - -public class Account { - - final String username; - final String password; - String playerName; - - String token; - UUID uuid; - - public Account(String username, String password) { - this.username = username; - this.password = password; - } - - public void login() { - JSONObject payload = new JSONObject(); - payload.put("agent", new JSONObject().put("name", "Minecraft").put("version", 1)); - payload.put("username", username); - payload.put("password", password); - // ToDo not in main thread - HttpResponse response = HTTP.postJson("https://authserver.mojang.com/authenticate", payload); - if (response == null || response.statusCode() != 200) { - assert response != null; - Log.info(String.format("[Mojang API] Login failed with username=%s (%s)", username, response.statusCode())); - return; - } - - - Log.info(String.format("[Mojang API] Login successful with username=%s", username)); - - // login good - JSONObject raw = new JSONObject(response.body()); - - token = raw.getString("accessToken"); - - uuid = Util.formatUUID(raw.getJSONObject("selectedProfile").getString("id")); - playerName = raw.getJSONObject("selectedProfile").getString("name"); - } - - public void join(String serverId) { - JSONObject payload = new JSONObject(); - payload.put("accessToken", token); - payload.put("selectedProfile", getUUID().toString().replace("-", "")); - payload.put("serverId", serverId); - // ToDo not in main thread - HttpResponse response = HTTP.postJson("https://sessionserver.mojang.com/session/minecraft/join", payload); - if (response == null || response.statusCode() != 204) { - assert response != null; - Log.info("[Mojang API] Login to join server!"); - return; - } - - Log.info("[Mojang API] Joined server successfully"); - } - - public UUID getUUID() { - return this.uuid; - } - - public String getPlayerName() { - return this.playerName; - } -} diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java index 44f481f3f..06448fe21 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java @@ -13,8 +13,8 @@ package de.bixilon.minosoft.protocol.network; +import de.bixilon.minosoft.game.datatypes.Player; import de.bixilon.minosoft.logging.Log; -import de.bixilon.minosoft.objects.Player; import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.packets.ServerboundPacket; import de.bixilon.minosoft.protocol.packets.serverbound.handshaking.PacketHandshake; diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/status/PacketStatusResponse.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/status/PacketStatusResponse.java index 55ace2573..6865a910f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/status/PacketStatusResponse.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/status/PacketStatusResponse.java @@ -13,8 +13,8 @@ package de.bixilon.minosoft.protocol.packets.clientbound.status; +import de.bixilon.minosoft.ServerListPing; import de.bixilon.minosoft.logging.Log; -import de.bixilon.minosoft.objects.ServerListPing; import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.protocol.InPacketBuffer; import de.bixilon.minosoft.protocol.protocol.PacketHandler; diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/serverbound/login/PacketLoginStart.java b/src/main/java/de/bixilon/minosoft/protocol/packets/serverbound/login/PacketLoginStart.java index f7a0944f3..549be8369 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/serverbound/login/PacketLoginStart.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/serverbound/login/PacketLoginStart.java @@ -13,8 +13,8 @@ package de.bixilon.minosoft.protocol.packets.serverbound.login; +import de.bixilon.minosoft.game.datatypes.Player; import de.bixilon.minosoft.logging.Log; -import de.bixilon.minosoft.objects.Player; import de.bixilon.minosoft.protocol.packets.ServerboundPacket; import de.bixilon.minosoft.protocol.protocol.OutPacketBuffer; import de.bixilon.minosoft.protocol.protocol.Packets; diff --git a/src/main/java/de/bixilon/minosoft/util/HTTP.java b/src/main/java/de/bixilon/minosoft/util/HTTP.java index 9399ef5a7..b9024ae50 100644 --- a/src/main/java/de/bixilon/minosoft/util/HTTP.java +++ b/src/main/java/de/bixilon/minosoft/util/HTTP.java @@ -31,8 +31,20 @@ public class HTTP { .header("Content-Type", "application/json") .build(); try { - return client.send(request, - HttpResponse.BodyHandlers.ofString()); + return client.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + return null; + } + + public static HttpResponse get(String url) { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .build(); + try { + return client.send(request, HttpResponse.BodyHandlers.ofString()); } catch (IOException | InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/java/de/bixilon/minosoft/util/Util.java b/src/main/java/de/bixilon/minosoft/util/Util.java index beb0f1503..6e6b81d2e 100644 --- a/src/main/java/de/bixilon/minosoft/util/Util.java +++ b/src/main/java/de/bixilon/minosoft/util/Util.java @@ -18,6 +18,9 @@ import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.UUID; import java.util.regex.Pattern; import java.util.zip.DataFormatException; @@ -77,4 +80,17 @@ public class Util { } return outputStream.toByteArray(); } + + public static String sha1(String string) { + try { + MessageDigest crypt = MessageDigest.getInstance("SHA-1"); + crypt.reset(); + crypt.update(string.getBytes(StandardCharsets.UTF_8)); + return new String(crypt.digest()); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } + } diff --git a/src/main/resources/config/game.yml b/src/main/resources/config/game.yml index 64abfb7ed..d0b80a778 100644 --- a/src/main/resources/config/game.yml +++ b/src/main/resources/config/game.yml @@ -11,9 +11,11 @@ game: network: fake-client-brand: false # if true, minosoft will tell the server that this is unmodified vanilla. if false, it will tell "minosoft". -# this will be removed soon +account: + clientToken: "randomGenerated" + accounts: + +# this will be removed soon, only for debugging (pre alpha stage): some features are not implemented yet -/- debug: host: "127.0.0.1" - port: 25565 - username: "Player" - password: "secret123" \ No newline at end of file + port: 25565 \ No newline at end of file