diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
new file mode 100644
index 000000000..598cab46a
--- /dev/null
+++ b/.github/workflows/sonarcloud.yml
@@ -0,0 +1,36 @@
+name: SonarCloud
+on:
+ push:
+ branches:
+ - master
+jobs:
+ build:
+ name: SonarCloud
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+ submodules: true
+ - name: Set up JDK 17
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: 17
+ - name: Cache SonarCloud packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.sonar/cache
+ key: ${{ runner.os }}-sonar
+ restore-keys: ${{ runner.os }}-sonar
+ - name: Cache Maven packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
+ - name: Build and analyze
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=GeyserMC_Geyser
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 85f8a6e9e..401002e1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -239,8 +239,9 @@ nbdist/
run/
config.yml
logs/
-public-key.pem
+key.pem
locales/
/cache/
/packs/
-/dump.json
\ No newline at end of file
+/dump.json
+/saved-refresh-tokens.json
\ No newline at end of file
diff --git a/README.md b/README.md
index 593514e52..885ec920b 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
-### Currently supporting Minecraft Bedrock 1.17.41 + 1.18.0 - 1.18.10 and Minecraft Java 1.18/1.18.1.
+### Currently supporting Minecraft Bedrock 1.17.41 + 1.18.0 - 1.18.10 and Minecraft Java 1.18.2.
## Setting Up
Take a look [here](https://github.com/GeyserMC/Geyser/wiki/Setup) for how to set up Geyser.
diff --git a/ap/pom.xml b/ap/pom.xml
index dce28a7d7..75f98275c 100644
--- a/ap/pom.xml
+++ b/ap/pom.xml
@@ -6,9 +6,9 @@
org.geysermc
geyser-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
ap
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
\ No newline at end of file
diff --git a/api/base/pom.xml b/api/base/pom.xml
index 17edb1a85..37e97ef7e 100644
--- a/api/base/pom.xml
+++ b/api/base/pom.xml
@@ -5,7 +5,7 @@
org.geysermc
api-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
4.0.0
diff --git a/api/geyser/pom.xml b/api/geyser/pom.xml
index de9c63e83..084b4e745 100644
--- a/api/geyser/pom.xml
+++ b/api/geyser/pom.xml
@@ -5,7 +5,7 @@
org.geysermc
api-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
../pom.xml
4.0.0
@@ -35,7 +35,7 @@
org.geysermc
base-api
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
diff --git a/api/pom.xml b/api/pom.xml
index b6d865cb4..6abbb4479 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
../pom.xml
diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml
index 45a08c7db..f06a219bb 100644
--- a/bootstrap/bungeecord/pom.xml
+++ b/bootstrap/bungeecord/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-bungeecord
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index 58c651455..381f68bc2 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-parent
pom
@@ -34,7 +34,7 @@
org.geysermc
ap
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
provided
diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml
index 6eda527f3..da8b184e9 100644
--- a/bootstrap/spigot/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-spigot
@@ -25,7 +25,7 @@
org.geysermc
core
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
@@ -43,7 +43,7 @@
org.geysermc.geyser.adapters
spigot-all
- 1.3-SNAPSHOT
+ 1.4-SNAPSHOT
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
index e0ad866c8..7f1c4aa06 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
@@ -32,27 +32,26 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.common.PlatformType;
-import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserBootstrap;
+import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.command.GeyserCommandManager;
-import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
-import org.geysermc.geyser.network.MinecraftProtocol;
import org.geysermc.geyser.level.WorldManager;
+import org.geysermc.geyser.network.MinecraftProtocol;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
-import org.geysermc.geyser.Constants;
-import org.geysermc.geyser.util.FileUtils;
-import org.geysermc.geyser.text.GeyserLocale;
-import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor;
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager;
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSource;
import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener;
-import org.geysermc.geyser.platform.spigot.world.GeyserSpigot1_11CraftingListener;
import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener;
import org.geysermc.geyser.platform.spigot.world.manager.*;
+import org.geysermc.geyser.session.auth.AuthType;
+import org.geysermc.geyser.text.GeyserLocale;
+import org.geysermc.geyser.util.FileUtils;
import java.io.File;
import java.io.IOException;
@@ -236,11 +235,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
- if (isPre1_12) {
- // Register events needed to send all recipes to the client
- Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigot1_11CraftingListener(geyser), this);
- }
-
this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(geyser));
// Check to ensure the current setup can support the protocol version Geyser uses
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigot1_11CraftingListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigot1_11CraftingListener.java
deleted file mode 100644
index 78a64e47b..000000000
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigot1_11CraftingListener.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2019-2022 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.geyser.platform.spigot.world;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
-import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
-import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
-import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
-import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
-import com.viaversion.viaversion.api.Via;
-import com.viaversion.viaversion.api.data.MappingData;
-import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
-import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
-import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
-import com.viaversion.viaversion.util.Pair;
-import org.bukkit.Bukkit;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.inventory.Recipe;
-import org.bukkit.inventory.ShapedRecipe;
-import org.bukkit.inventory.ShapelessRecipe;
-import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.network.MinecraftProtocol;
-import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
-import org.geysermc.geyser.util.InventoryUtils;
-
-import java.util.*;
-
-/**
- * Used to send all available recipes from the server to the client, as a valid recipe book packet won't be sent by the server.
- * Requires ViaVersion.
- */
-public class GeyserSpigot1_11CraftingListener implements Listener {
-
- private final GeyserImpl geyser;
- /**
- * Specific mapping data for 1.12 to 1.13. Used to convert the 1.12 item into 1.13.
- */
- private final MappingData mappingData1_12to1_13;
- /**
- * The list of all protocols from the client's version to 1.13.
- */
- private final List protocolList;
-
- public GeyserSpigot1_11CraftingListener(GeyserImpl geyser) {
- this.geyser = geyser;
- this.mappingData1_12to1_13 = Via.getManager().getProtocolManager().getProtocol(Protocol1_13To1_12_2.class).getMappingData();
- this.protocolList = Via.getManager().getProtocolManager().getProtocolPath(MinecraftProtocol.getJavaProtocolVersion(),
- ProtocolVersion.v1_13.getVersion());
- }
-
- @EventHandler
- public void onPlayerJoin(PlayerJoinEvent event) {
- GeyserSession session = null;
- for (GeyserSession otherSession : geyser.getSessionManager().getSessions().values()) {
- if (otherSession.name().equals(event.getPlayer().getName())) {
- session = otherSession;
- break;
- }
- }
- if (session == null) {
- return;
- }
-
- sendServerRecipes(session);
- }
-
- public void sendServerRecipes(GeyserSession session) {
- int netId = InventoryUtils.LAST_RECIPE_NET_ID;
-
- CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
- craftingDataPacket.setCleanRecipes(true);
-
- Iterator recipeIterator = Bukkit.getServer().recipeIterator();
- while (recipeIterator.hasNext()) {
- Recipe recipe = recipeIterator.next();
-
- Pair outputs = translateToBedrock(session, recipe.getResult());
- ItemStack javaOutput = outputs.getKey();
- ItemData output = outputs.getValue();
- if (output == null || output.getId() == 0) continue; // If items make air we don't want that
-
- boolean isNotAllAir = false; // Check for all-air recipes
- if (recipe instanceof ShapedRecipe shapedRecipe) {
- int size = shapedRecipe.getShape().length * shapedRecipe.getShape()[0].length();
- Ingredient[] ingredients = new Ingredient[size];
- ItemData[] input = new ItemData[size];
- for (int i = 0; i < input.length; i++) {
- // Index is converting char to integer, adding i then converting back to char based on ASCII code
- Pair result = translateToBedrock(session, shapedRecipe.getIngredientMap().get((char) ('a' + i)));
- ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
- input[i] = result.getValue();
- isNotAllAir |= input[i].getId() != 0;
- }
-
- if (!isNotAllAir) continue;
- UUID uuid = UUID.randomUUID();
- // Add recipe to our internal cache
- ShapedRecipeData data = new ShapedRecipeData(shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length,
- "", ingredients, javaOutput);
- session.getCraftingRecipes().put(netId,
- new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPED, uuid.toString(), data));
-
- // Add recipe for Bedrock
- craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
- shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length, Arrays.asList(input),
- Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
- } else if (recipe instanceof ShapelessRecipe shapelessRecipe) {
- Ingredient[] ingredients = new Ingredient[shapelessRecipe.getIngredientList().size()];
- ItemData[] input = new ItemData[shapelessRecipe.getIngredientList().size()];
-
- for (int i = 0; i < input.length; i++) {
- Pair result = translateToBedrock(session, shapelessRecipe.getIngredientList().get(i));
- ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
- input[i] = result.getValue();
- isNotAllAir |= input[i].getId() != 0;
- }
-
- if (!isNotAllAir) continue;
- UUID uuid = UUID.randomUUID();
- // Add recipe to our internal cache
- ShapelessRecipeData data = new ShapelessRecipeData("", ingredients, javaOutput);
- session.getCraftingRecipes().put(netId,
- new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPELESS, uuid.toString(), data));
-
- // Add recipe for Bedrock
- craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
- Arrays.asList(input), Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
- }
- }
-
- session.sendUpstreamPacket(craftingDataPacket);
- }
-
- @SuppressWarnings("deprecation")
- private Pair translateToBedrock(GeyserSession session, org.bukkit.inventory.ItemStack itemStack) {
- if (itemStack != null && itemStack.getData() != null) {
- if (itemStack.getType().getId() == 0) {
- return new Pair<>(null, ItemData.AIR);
- }
-
- int legacyId = (itemStack.getType().getId() << 4) | (itemStack.getData().getData() & 0xFFFF);
-
- if (itemStack.getType().getId() == 355 && itemStack.getData().getData() == (byte) 0) { // Handle bed color since the server will always be pre-1.12
- legacyId = (itemStack.getType().getId() << 4) | ((byte) 14 & 0xFFFF);
- }
-
- // old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 and so on
- int itemId;
- if (mappingData1_12to1_13.getItemMappings().containsKey(legacyId)) {
- itemId = mappingData1_12to1_13.getNewItemId(legacyId);
- } else if (mappingData1_12to1_13.getItemMappings().containsKey((itemStack.getType().getId() << 4) | (0))) {
- itemId = mappingData1_12to1_13.getNewItemId((itemStack.getType().getId() << 4) | (0));
- } else {
- // No ID found, just send back air
- return new Pair<>(null, ItemData.AIR);
- }
-
- for (int i = protocolList.size() - 1; i >= 0; i--) {
- MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
- if (mappingData != null) {
- itemId = mappingData.getNewItemId(itemId);
- }
- }
-
- ItemStack mcItemStack = new ItemStack(itemId, itemStack.getAmount());
- ItemData finalData = ItemTranslator.translateToBedrock(session, mcItemStack);
- return new Pair<>(mcItemStack, finalData);
- }
-
- // Empty slot, most likely
- return new Pair<>(null, ItemData.AIR);
- }
-
-}
diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml
index ab3b7d970..6285c6dbf 100644
--- a/bootstrap/sponge/pom.xml
+++ b/bootstrap/sponge/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-sponge
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml
index 881c87e6c..6babc6933 100644
--- a/bootstrap/standalone/pom.xml
+++ b/bootstrap/standalone/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-standalone
@@ -18,7 +18,7 @@
org.geysermc
core
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
@@ -47,17 +47,17 @@
org.jline
jline-terminal
- 3.20.0
+ 3.21.0
org.jline
jline-terminal-jna
- 3.20.0
+ 3.21.0
org.jline
jline-reader
- 3.20.0
+ 3.21.0
org.apache.logging.log4j
@@ -132,7 +132,6 @@
implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer">
- ${project.build.directory}/dependency-reduced-pom.xml
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
index ca41d3c1d..3c69b4749 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
@@ -276,6 +276,12 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
return Paths.get(System.getProperty("user.dir"));
}
+ @Override
+ public Path getSavedUserLoginsFolder() {
+ // Return the location of the config
+ return new File(configFilename).getAbsoluteFile().getParentFile().toPath();
+ }
+
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserStandaloneDumpInfo(this);
diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml
index ff052471d..1621d6ee6 100644
--- a/bootstrap/velocity/pom.xml
+++ b/bootstrap/velocity/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
bootstrap-velocity
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
diff --git a/common/pom.xml b/common/pom.xml
index fde2605bc..a563b7aff 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
common
diff --git a/core/pom.xml b/core/pom.xml
index 31f9a075f..b606c3ef7 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
core
@@ -20,19 +20,19 @@
org.geysermc
ap
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
provided
org.geysermc
geyser-api
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
org.geysermc
common
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
compile
@@ -146,23 +146,23 @@
- com.github.RednedEpic
+ com.github.GeyserMC
MCAuthLib
- 6c99331
+ d9d773e
compile
com.github.GeyserMC
MCProtocolLib
- 6a23a780
+ 0771504
compile
- com.github.steveice10
+ com.github.GeyserMC
packetlib
- com.github.steveice10
+ com.github.GeyserMC
mcauthlib
diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java
index 49f8fa676..23fb76d16 100644
--- a/core/src/main/java/org/geysermc/geyser/Constants.java
+++ b/core/src/main/java/org/geysermc/geyser/Constants.java
@@ -37,6 +37,8 @@ public final class Constants {
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/";
+ static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
+
static {
URI wsUri = null;
try {
diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java
index bc6a07ae3..261c7416b 100644
--- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java
+++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java
@@ -97,6 +97,13 @@ public interface GeyserBootstrap {
*/
Path getConfigFolder();
+ /**
+ * @return the folder where user tokens are saved. This should always point to the location of the config.
+ */
+ default Path getSavedUserLoginsFolder() {
+ return getConfigFolder();
+ }
+
/**
* Information used for the bootstrap section of the debug dump
*
diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
index 68bb69b46..3977bfde4 100644
--- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser;
import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.steveice10.packetlib.tcp.TcpSession;
@@ -37,6 +38,7 @@ import io.netty.channel.kqueue.KQueue;
import io.netty.util.NettyRuntime;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.internal.SystemPropertyUtil;
+import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -65,6 +67,7 @@ import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.SessionManager;
import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
@@ -77,6 +80,9 @@ import org.geysermc.geyser.util.*;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -84,6 +90,7 @@ import java.net.UnknownHostException;
import java.security.Key;
import java.text.DecimalFormat;
import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.regex.Matcher;
@@ -134,6 +141,10 @@ public class GeyserImpl implements GeyserApi {
private Metrics metrics;
+ private PendingMicrosoftAuthentication pendingMicrosoftAuthentication;
+ @Getter(AccessLevel.NONE)
+ private Map savedRefreshTokens;
+
private static GeyserImpl instance;
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) {
@@ -286,6 +297,8 @@ public class GeyserImpl implements GeyserApi {
logger.debug("Not getting git properties for the news handler as we are in a development environment.");
}
+ pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.getPendingAuthenticationTimeout());
+
this.newsHandler = new NewsHandler(branch, buildNumber);
CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
@@ -338,7 +351,7 @@ public class GeyserImpl implements GeyserApi {
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size));
// Prevent unwanted words best we can
- metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase()));
+ metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase(Locale.ROOT)));
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName));
metrics.addCustomChart(new Metrics.SimplePie("defaultLocale", GeyserLocale::getDefaultLocale));
metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserImpl.VERSION));
@@ -422,6 +435,47 @@ public class GeyserImpl implements GeyserApi {
metrics = null;
}
+ if (config.getRemote().getAuthType() == AuthType.ONLINE) {
+ if (config.getUserAuths() != null && !config.getUserAuths().isEmpty()) {
+ getLogger().warning("The 'userAuths' config section is now deprecated, and will be removed in the near future! " +
+ "Please migrate to the new 'saved-user-logins' config option: " +
+ "https://wiki.geysermc.org/geyser/understanding-the-config/");
+ }
+
+ // May be written/read to on multiple threads from each GeyserSession as well as writing the config
+ savedRefreshTokens = new ConcurrentHashMap<>();
+
+ File tokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
+ if (tokensFile.exists()) {
+ TypeReference