diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml
index 4a570df56..9cb0726ca 100644
--- a/.github/workflows/pullrequest.yml
+++ b/.github/workflows/pullrequest.yml
@@ -29,12 +29,12 @@ jobs:
with:
name: Geyser Standalone
path: bootstrap/standalone/target/Geyser.jar
- - name: Archive artifacts (Geyser Bukkit)
+ - name: Archive artifacts (Geyser Spigot)
uses: actions/upload-artifact@v2
if: success()
with:
- name: Geyser Bukkit
- path: bootstrap/bukkit/target/Geyser-Bukkit.jar
+ name: Geyser Spigot
+ path: bootstrap/spigot/target/Geyser-Spigot.jar
- name: Archive artifacts (Geyser BungeeCord)
uses: actions/upload-artifact@v2
if: success()
diff --git a/.gitmodules b/.gitmodules
index 0090e64ab..35887822e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,7 @@
[submodule "connector/src/main/resources/mappings"]
path = connector/src/main/resources/mappings
url = https://github.com/GeyserMC/mappings.git
+ branch = feature/1.16
+[submodule "connector/src/main/resources/languages"]
+ path = connector/src/main/resources/languages
+ url = https://github.com/GeyserMC/languages.git
diff --git a/README.md b/README.md
index b8f8749b8..a22a7a8d0 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 now joined us here!
-### Currently supporting Minecraft Bedrock v1.14.6(0) and Minecraft Java v1.15.2.
+### Currently supporting Minecraft Bedrock v1.16.0/1 and Minecraft Java v1.16.1.
## Setting Up
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml
index dd66db322..565264f0f 100644
--- a/bootstrap/bungeecord/pom.xml
+++ b/bootstrap/bungeecord/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
../
bootstrap-bungeecord
@@ -14,7 +14,7 @@
org.geysermc
connector
- 1.0-SNAPSHOT
+ 1.0.0
compile
@@ -65,6 +65,10 @@
io.netty
org.geysermc.platform.bungeecord.shaded.netty
+
+ org.reflections.reflections
+ org.geysermc.platform.bungeecord.shaded.reflections
+
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java
new file mode 100644
index 000000000..547011162
--- /dev/null
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.bungeecord;
+
+import lombok.Getter;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.plugin.Plugin;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Getter
+public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
+
+ private String platformName;
+ private String platformVersion;
+ private boolean onlineMode;
+ private List listeners;
+ private List plugins;
+
+ GeyserBungeeDumpInfo(ProxyServer proxy) {
+ super();
+ this.platformName = proxy.getName();
+ this.platformVersion = proxy.getVersion();
+ this.onlineMode = proxy.getConfig().isOnlineMode();
+ this.listeners = new ArrayList<>();
+ this.plugins = new ArrayList<>();
+
+ for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
+ this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort()));
+ }
+
+ for (Plugin plugin : proxy.getPluginManager().getPlugins()) {
+ this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Arrays.asList(plugin.getDescription().getAuthor())));
+ }
+ }
+}
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java
index eabbcc698..999b29eaf 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java
@@ -26,7 +26,7 @@
package org.geysermc.platform.bungeecord;
-import org.geysermc.common.main.IGeyserMain;
+import org.geysermc.connector.common.main.IGeyserMain;
public class GeyserBungeeMain extends IGeyserMain {
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java
index c7f8f2762..f2166aad7 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java
@@ -35,7 +35,7 @@ import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.protocol.ProtocolConstants;
-import org.geysermc.common.ping.GeyserPingInfo;
+import org.geysermc.connector.common.ping.GeyserPingInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import java.net.Inet4Address;
@@ -60,14 +60,15 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
else future.complete(event);
}));
ProxyPingEvent event = future.join();
+ ServerPing response = event.getResponse();
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
- event.getResponse().getDescription(),
- event.getResponse().getPlayers().getOnline(),
- event.getResponse().getPlayers().getMax()
+ response.getDescriptionComponent().toLegacyText(),
+ new GeyserPingInfo.Players(response.getPlayers().getMax(), response.getPlayers().getOnline()),
+ new GeyserPingInfo.Version(response.getVersion().getName(), response.getVersion().getProtocol())
);
if (event.getResponse().getPlayers().getSample() != null) {
Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer -> {
- geyserPingInfo.addPlayer(proxiedPlayer.getName());
+ geyserPingInfo.getPlayerList().add(proxiedPlayer.getName());
});
}
return geyserPingInfo;
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
index 1cf519c0e..38d319e15 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
@@ -30,14 +30,16 @@ import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.configuration.GeyserConfiguration;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor;
import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager;
@@ -70,7 +72,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(getDataFolder(), "config.yml"));
} catch (IOException ex) {
- getLogger().log(Level.WARNING, "Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex);
+ getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
}
@@ -92,7 +94,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && getProxy().getPluginManager().getPlugin("floodgate-bungee") == null) {
- geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling...");
+ geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
return;
}
@@ -140,4 +142,9 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
public Path getConfigFolder() {
return getDataFolder().toPath();
}
+
+ @Override
+ public BootstrapDumpInfo getDumpInfo() {
+ return new GeyserBungeeDumpInfo(getProxy());
+ }
}
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java
index d1c8473bd..3b051c5c3 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java
@@ -33,6 +33,8 @@ import net.md_5.bungee.api.plugin.TabExecutor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -52,7 +54,14 @@ public class GeyserBungeeCommandExecutor extends Command implements TabExecutor
if (args.length > 0) {
if (getCommand(args[0]) != null) {
if (!sender.hasPermission(getCommand(args[0]).getPermission())) {
- sender.sendMessage(TextComponent.fromLegacyText(ChatColor.RED + "You do not have permission to execute this command!"));
+ String message = "";
+ if (sender instanceof GeyserSession) {
+ message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", ((GeyserSession) sender).getClientData().getLanguageCode());
+ } else {
+ message = LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail");
+ }
+
+ sender.sendMessage(TextComponent.fromLegacyText(ChatColor.RED + message));
return;
}
getCommand(args[0]).execute(new BungeeCommandSender(sender), args);
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index 6d12b6732..85ede3466 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -10,7 +10,7 @@
../
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
pom
@@ -35,8 +35,8 @@
- bukkit
bungeecord
+ spigot
sponge
standalone
velocity
diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/spigot/pom.xml
similarity index 82%
rename from bootstrap/bukkit/pom.xml
rename to bootstrap/spigot/pom.xml
index 95926854d..e05ad7f03 100644
--- a/bootstrap/bukkit/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -6,15 +6,15 @@
org.geysermc
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
../
- bootstrap-bukkit
+ bootstrap-spigot
org.geysermc
connector
- 1.0-SNAPSHOT
+ 1.0.0
compile
@@ -26,12 +26,12 @@
us.myles
viaversion
- 3.0.0-SNAPSHOT
+ 3.0.1
provided
- ${outputName}-Bukkit
+ ${outputName}-Spigot
src/main/resources/
@@ -46,7 +46,7 @@
- org.geysermc.platform.bukkit.GeyserBukkitMain
+ org.geysermc.platform.spigot.GeyserSpigotMain
@@ -65,15 +65,19 @@
io.netty
- org.geysermc.platform.bukkit.shaded.netty
+ org.geysermc.platform.spigot.shaded.netty
it.unimi.dsi.fastutil
- org.geysermc.platform.bukkit.shaded.fastutil
+ org.geysermc.platform.spigot.shaded.fastutil
com.fasterxml.jackson
- org.geysermc.platform.bukkit.shaded.jackson
+ org.geysermc.platform.spigot.shaded.jackson
+
+
+ org.reflections.reflections
+ org.geysermc.platform.spigot.shaded.reflections
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java
similarity index 93%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java
index 327c41dae..9a6811562 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java
@@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit;
+package org.geysermc.platform.spigot;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -38,14 +38,14 @@ import java.nio.file.Paths;
@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
-public class GeyserBukkitConfiguration extends GeyserJacksonConfiguration {
+public class GeyserSpigotConfiguration extends GeyserJacksonConfiguration {
@JsonProperty("floodgate-key-file")
private String floodgateKeyFile;
private Path floodgateKey;
- public void loadFloodgate(GeyserBukkitPlugin plugin) {
+ public void loadFloodgate(GeyserSpigotPlugin plugin) {
Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate-bukkit");
floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(plugin.getDataFolder().toString(), plugin.getConfig().getString("floodgate-key-file", "public-key.pem")), floodgate, floodgate != null ? floodgate.getDataFolder().toPath() : null);
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java
new file mode 100644
index 000000000..01d513fa8
--- /dev/null
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.spigot;
+
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
+
+ private String platformName;
+ private String platformVersion;
+ private String platformAPIVersion;
+ private boolean onlineMode;
+ private String serverIP;
+ private int serverPort;
+ private List plugins;
+
+ GeyserSpigotDumpInfo() {
+ super();
+ this.platformName = Bukkit.getName();
+ this.platformVersion = Bukkit.getVersion();
+ this.platformAPIVersion = Bukkit.getBukkitVersion();
+ this.onlineMode = Bukkit.getOnlineMode();
+ this.serverIP = Bukkit.getIp();
+ this.serverPort = Bukkit.getPort();
+ this.plugins = new ArrayList<>();
+
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ this.plugins.add(new PluginInfo(plugin.isEnabled(), plugin.getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), plugin.getDescription().getAuthors()));
+ }
+ }
+}
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java
similarity index 95%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java
index 08822568c..252d6bbed 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java
@@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit;
+package org.geysermc.platform.spigot;
import lombok.AllArgsConstructor;
@@ -33,7 +33,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
@AllArgsConstructor
-public class GeyserBukkitLogger implements GeyserLogger {
+public class GeyserSpigotLogger implements GeyserLogger {
private Logger logger;
private boolean debugMode;
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java
similarity index 88%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java
index b6da66c1b..15826d334 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java
@@ -24,14 +24,14 @@
*
*/
-package org.geysermc.platform.bukkit;
+package org.geysermc.platform.spigot;
-import org.geysermc.common.main.IGeyserMain;
+import org.geysermc.connector.common.main.IGeyserMain;
-public class GeyserBukkitMain extends IGeyserMain {
+public class GeyserSpigotMain extends IGeyserMain {
public static void main(String[] args) {
- new GeyserBukkitMain().displayMessage();
+ new GeyserSpigotMain().displayMessage();
}
public String getPluginType() {
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java
similarity index 79%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java
index 812467be7..9658a68da 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java
@@ -24,14 +24,15 @@
*
*/
-package org.geysermc.platform.bukkit;
+package org.geysermc.platform.spigot;
+import com.github.steveice10.mc.protocol.MinecraftConstants;
import lombok.AllArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.util.CachedServerIcon;
-import org.geysermc.common.ping.GeyserPingInfo;
+import org.geysermc.connector.common.ping.GeyserPingInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import java.net.InetAddress;
@@ -39,23 +40,24 @@ import java.util.Collections;
import java.util.Iterator;
@AllArgsConstructor
-public class GeyserBukkitPingPassthrough implements IGeyserPingPassthrough {
+public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
- private final GeyserBukkitLogger logger;
+ private final GeyserSpigotLogger logger;
@Override
public GeyserPingInfo getPingInformation() {
try {
ServerListPingEvent event = new GeyserPingEvent(InetAddress.getLocalHost(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers());
Bukkit.getPluginManager().callEvent(event);
- GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), event.getNumPlayers(), event.getMaxPlayers());
- Bukkit.getOnlinePlayers().forEach(player -> {
- geyserPingInfo.addPlayer(player.getName());
- });
+ GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(),
+ new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers()),
+ new GeyserPingInfo.Version(Bukkit.getVersion(), MinecraftConstants.PROTOCOL_VERSION) // thanks Spigot for not exposing this, just default to latest
+ );
+ Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add);
return geyserPingInfo;
} catch (Exception e) {
logger.debug("Error while getting Bukkit ping passthrough: " + e.toString());
- return new GeyserPingInfo(null, 0, 0);
+ return new GeyserPingInfo(null, null, null);
}
}
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
similarity index 68%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
index 3a13777b4..38141c520 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
@@ -23,39 +23,41 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit;
+package org.geysermc.platform.spigot;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.configuration.GeyserConfiguration;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.network.translators.world.WorldManager;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils;
-import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor;
-import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager;
-import org.geysermc.platform.bukkit.world.GeyserBukkitBlockPlaceListener;
-import org.geysermc.platform.bukkit.world.GeyserBukkitWorldManager;
-import us.myles.ViaVersion.api.Via;
+import org.geysermc.connector.utils.LanguageUtils;
+import org.geysermc.platform.spigot.command.GeyserSpigotCommandExecutor;
+import org.geysermc.platform.spigot.command.GeyserSpigotCommandManager;
+import org.geysermc.platform.spigot.world.GeyserSpigotBlockPlaceListener;
+import org.geysermc.platform.spigot.world.GeyserSpigotWorldManager;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.logging.Level;
-public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
+public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
- private GeyserBukkitCommandManager geyserCommandManager;
- private GeyserBukkitConfiguration geyserConfig;
- private GeyserBukkitLogger geyserLogger;
- private IGeyserPingPassthrough geyserBukkitPingPassthrough;
- private GeyserBukkitBlockPlaceListener blockPlaceListener;
- private GeyserBukkitWorldManager geyserWorldManager;
+ private GeyserSpigotCommandManager geyserCommandManager;
+ private GeyserSpigotConfiguration geyserConfig;
+ private GeyserSpigotLogger geyserLogger;
+ private IGeyserPingPassthrough geyserSpigotPingPassthrough;
+ private GeyserSpigotBlockPlaceListener blockPlaceListener;
+ private GeyserSpigotWorldManager geyserWorldManager;
private GeyserConnector connector;
@@ -63,12 +65,19 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
public void onEnable() {
// This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed
try {
- if (!getDataFolder().exists())
+ if (!getDataFolder().exists()) {
getDataFolder().mkdir();
+ File bukkitConfig = new File("plugins/Geyser-Bukkit/config.yml");
+ if (bukkitConfig.exists()) { // Copy over old configs
+ getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copy_bukkit_config"));
+ Files.copy(bukkitConfig.toPath(), new File(getDataFolder().toString() + "/config.yml").toPath());
+ getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copied_bukkit_config"));
+ }
+ }
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
- this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBukkitConfiguration.class);
+ this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
} catch (IOException ex) {
- getLogger().log(Level.WARNING, "Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex);
+ getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
}
@@ -80,48 +89,39 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
geyserConfig.getRemote().setPort(Bukkit.getPort());
- this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode());
+ this.geyserLogger = new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && Bukkit.getPluginManager().getPlugin("floodgate-bukkit") == null) {
- geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling...");
+ geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
this.getPluginLoader().disablePlugin(this);
return;
}
geyserConfig.loadFloodgate(this);
- this.connector = GeyserConnector.start(PlatformType.BUKKIT, this);
+ this.connector = GeyserConnector.start(PlatformType.SPIGOT, this);
if (geyserConfig.isLegacyPingPassthrough()) {
- this.geyserBukkitPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
+ this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
} else {
- this.geyserBukkitPingPassthrough = new GeyserBukkitPingPassthrough(geyserLogger);
+ this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
}
- this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector);
+ this.geyserCommandManager = new GeyserSpigotCommandManager(this, connector);
- boolean isViaVersion = false;
+ boolean isViaVersion = (Bukkit.getPluginManager().getPlugin("ViaVersion") != null);
// Used to determine if Block.getBlockData() is present.
boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0");
if (isLegacy)
geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected.");
- if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
- // TODO: Update when ViaVersion updates
- // API changes between 2.2.3 and 3.0.0-SNAPSHOT require this check
- if (!Via.getAPI().getVersion().equals("3.0.0-SNAPSHOT") && isLegacy) {
- geyserLogger.info("ViaVersion detected but not ViaVersion-ABSTRACTION. Please update your ViaVersion plugin for compatibility with Geyser.");
- } else {
- isViaVersion = true;
- }
- }
+ this.geyserWorldManager = new GeyserSpigotWorldManager(isLegacy, isViaVersion);
+ this.blockPlaceListener = new GeyserSpigotBlockPlaceListener(connector, isLegacy, isViaVersion);
- this.geyserWorldManager = new GeyserBukkitWorldManager(isLegacy, isViaVersion);
- this.blockPlaceListener = new GeyserBukkitBlockPlaceListener(connector, isLegacy, isViaVersion);
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);
- this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector));
+ this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(connector));
}
@Override
@@ -131,12 +131,12 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
}
@Override
- public GeyserBukkitConfiguration getGeyserConfig() {
+ public GeyserSpigotConfiguration getGeyserConfig() {
return geyserConfig;
}
@Override
- public GeyserBukkitLogger getGeyserLogger() {
+ public GeyserSpigotLogger getGeyserLogger() {
return geyserLogger;
}
@@ -147,7 +147,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
@Override
public IGeyserPingPassthrough getGeyserPingPassthrough() {
- return geyserBukkitPingPassthrough;
+ return geyserSpigotPingPassthrough;
}
@Override
@@ -194,4 +194,8 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap {
return temp;
}
+ @Override
+ public BootstrapDumpInfo getDumpInfo() {
+ return new GeyserSpigotDumpInfo();
+ }
}
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java
similarity index 74%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java
index d2603f7c5..381872752 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java
@@ -23,23 +23,24 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit.command;
+package org.geysermc.platform.spigot.command;
import lombok.AllArgsConstructor;
-
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@AllArgsConstructor
-public class GeyserBukkitCommandExecutor implements TabExecutor {
+public class GeyserSpigotCommandExecutor implements TabExecutor {
private GeyserConnector connector;
@@ -48,14 +49,21 @@ public class GeyserBukkitCommandExecutor implements TabExecutor {
if (args.length > 0) {
if (getCommand(args[0]) != null) {
if (!sender.hasPermission(getCommand(args[0]).getPermission())) {
- sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!");
+ String message = "";
+ if (sender instanceof GeyserSession) {
+ message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", ((GeyserSession) sender).getClientData().getLanguageCode());
+ } else {
+ message = LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail");
+ }
+
+ sender.sendMessage(ChatColor.RED + message);
return true;
}
- getCommand(args[0]).execute(new BukkitCommandSender(sender), args);
+ getCommand(args[0]).execute(new SpigotCommandSender(sender), args);
return true;
}
} else {
- getCommand("help").execute(new BukkitCommandSender(sender), args);
+ getCommand("help").execute(new SpigotCommandSender(sender), args);
return true;
}
return true;
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java
similarity index 88%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java
index b826ab1f5..2fbec1562 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java
@@ -23,18 +23,18 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit.command;
+package org.geysermc.platform.spigot.command;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.platform.bukkit.GeyserBukkitPlugin;
+import org.geysermc.platform.spigot.GeyserSpigotPlugin;
import java.lang.reflect.Field;
-public class GeyserBukkitCommandManager extends CommandManager {
+public class GeyserSpigotCommandManager extends CommandManager {
private static CommandMap COMMAND_MAP;
@@ -48,9 +48,9 @@ public class GeyserBukkitCommandManager extends CommandManager {
}
}
- private GeyserBukkitPlugin plugin;
+ private GeyserSpigotPlugin plugin;
- public GeyserBukkitCommandManager(GeyserBukkitPlugin plugin, GeyserConnector connector) {
+ public GeyserSpigotCommandManager(GeyserSpigotPlugin plugin, GeyserConnector connector) {
super(connector);
this.plugin = plugin;
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java
similarity index 94%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java
index 05e371e5a..55475a303 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java
@@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.platform.bukkit.command;
+package org.geysermc.platform.spigot.command;
import lombok.AllArgsConstructor;
@@ -31,7 +31,7 @@ import org.bukkit.command.ConsoleCommandSender;
import org.geysermc.connector.command.CommandSender;
@AllArgsConstructor
-public class BukkitCommandSender implements CommandSender {
+public class SpigotCommandSender implements CommandSender {
private org.bukkit.command.CommandSender handle;
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
similarity index 93%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
index 76d1564ea..4fe93d459 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
@@ -24,7 +24,7 @@
*
*/
-package org.geysermc.platform.bukkit.world;
+package org.geysermc.platform.spigot.world;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
@@ -39,7 +39,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
@AllArgsConstructor
-public class GeyserBukkitBlockPlaceListener implements Listener {
+public class GeyserSpigotBlockPlaceListener implements Listener {
private final GeyserConnector connector;
private final boolean isLegacy;
@@ -47,7 +47,7 @@ public class GeyserBukkitBlockPlaceListener implements Listener {
@EventHandler
public void place(final BlockPlaceEvent event) {
- for (GeyserSession session : connector.getPlayers().values()) {
+ for (GeyserSession session : connector.getPlayers()) {
if (event.getPlayer() == Bukkit.getPlayer(session.getPlayerEntity().getUsername())) {
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
@@ -55,7 +55,7 @@ public class GeyserBukkitBlockPlaceListener implements Listener {
placeBlockSoundPacket.setBabySound(false);
String javaBlockId;
if (isLegacy) {
- javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserBukkitWorldManager.getLegacyBlock(session,
+ javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserSpigotWorldManager.getLegacyBlock(session,
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ(), isViaVersion));
} else {
javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
similarity index 83%
rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java
rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
index fbdf2a47b..d785fabca 100644
--- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
@@ -24,23 +24,19 @@
*
*/
-package org.geysermc.platform.bukkit.world;
-
-import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
+package org.geysermc.platform.spigot.world;
import lombok.AllArgsConstructor;
-import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.WorldManager;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.platform.bukkit.GeyserBukkitPlugin;
import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13;
-import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData;
+import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData;
@AllArgsConstructor
-public class GeyserBukkitWorldManager extends WorldManager {
+public class GeyserSpigotWorldManager extends WorldManager {
private final boolean isLegacy;
// You need ViaVersion to connect to an older server with Geyser.
@@ -48,7 +44,7 @@ public class GeyserBukkitWorldManager extends WorldManager {
private final boolean isViaVersion;
@Override
- public BlockState getBlockAt(GeyserSession session, int x, int y, int z) {
+ public int getBlockAt(GeyserSession session, int x, int y, int z) {
if (session.getPlayerEntity() == null) {
return BlockTranslator.AIR;
}
@@ -59,16 +55,17 @@ public class GeyserBukkitWorldManager extends WorldManager {
}
@SuppressWarnings("deprecation")
- public static BlockState getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) {
+ public static int getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) {
if (isViaVersion) {
Block block = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z);
// Black magic that gets the old block state ID
int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
- // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15
+ // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16
int thirteenBlockId = us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.blockMappings.getNewId(oldBlockId);
int thirteenPointOneBlockId = Protocol1_13_1To1_13.getNewBlockStateId(thirteenBlockId);
int fourteenBlockId = us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.blockStateMappings.getNewId(thirteenPointOneBlockId);
- return new BlockState(MappingData.blockStateMappings.getNewId(fourteenBlockId));
+ int fifteenBlockId = us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData.blockStateMappings.getNewId(fourteenBlockId);
+ return MappingData.blockStateMappings.getNewId(fifteenBlockId);
} else {
return BlockTranslator.AIR;
}
diff --git a/bootstrap/bukkit/src/main/resources/plugin.yml b/bootstrap/spigot/src/main/resources/plugin.yml
similarity index 74%
rename from bootstrap/bukkit/src/main/resources/plugin.yml
rename to bootstrap/spigot/src/main/resources/plugin.yml
index 89c90789e..fee71ab1f 100644
--- a/bootstrap/bukkit/src/main/resources/plugin.yml
+++ b/bootstrap/spigot/src/main/resources/plugin.yml
@@ -1,5 +1,5 @@
-main: org.geysermc.platform.bukkit.GeyserBukkitPlugin
-name: ${outputName}-Bukkit
+main: org.geysermc.platform.spigot.GeyserSpigotPlugin
+name: ${outputName}-Spigot
author: ${project.organization.name}
website: ${project.organization.url}
version: ${project.version}
diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml
index c9abbe3ed..cca3fcaae 100644
--- a/bootstrap/sponge/pom.xml
+++ b/bootstrap/sponge/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
../
bootstrap-sponge
@@ -14,7 +14,7 @@
org.geysermc
connector
- 1.0-SNAPSHOT
+ 1.0.0
compile
@@ -69,6 +69,10 @@
it.unimi.dsi.fastutil
org.geysermc.platform.sponge.shaded.fastutil
+
+ org.reflections.reflections
+ org.geysermc.platform.sponge.shaded.reflections
+
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java
new file mode 100644
index 000000000..e8f0feaef
--- /dev/null
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.sponge;
+
+import lombok.Getter;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
+import org.spongepowered.api.Platform;
+import org.spongepowered.api.Sponge;
+import org.spongepowered.api.plugin.PluginContainer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
+
+ private String platformName;
+ private String platformVersion;
+ private boolean onlineMode;
+ private String serverIP;
+ private int serverPort;
+ private List plugins;
+
+ GeyserSpongeDumpInfo() {
+ super();
+ PluginContainer container = Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION);
+ this.platformName = container.getName();
+ this.platformVersion = container.getVersion().get();
+ this.onlineMode = Sponge.getServer().getOnlineMode();
+ this.serverIP = Sponge.getServer().getBoundAddress().get().getHostString();
+ this.serverPort = Sponge.getServer().getBoundAddress().get().getPort();
+ this.plugins = new ArrayList<>();
+
+ for (PluginContainer plugin : Sponge.getPluginManager().getPlugins()) {
+ String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown");
+ this.plugins.add(new PluginInfo(true, plugin.getName(), plugin.getVersion().get(), pluginClass, plugin.getAuthors()));
+ }
+ }
+}
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java
index 11b9583f9..1c9605d0a 100644
--- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java
@@ -26,7 +26,7 @@
package org.geysermc.platform.sponge;
-import org.geysermc.common.main.IGeyserMain;
+import org.geysermc.connector.common.main.IGeyserMain;
public class GeyserSpongeMain extends IGeyserMain {
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java
index 31b6dc7fb..862c744bb 100644
--- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java
@@ -26,7 +26,8 @@
package org.geysermc.platform.sponge;
-import org.geysermc.common.ping.GeyserPingInfo;
+import com.github.steveice10.mc.protocol.MinecraftConstants;
+import org.geysermc.connector.common.ping.GeyserPingInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.spongepowered.api.MinecraftVersion;
import org.spongepowered.api.Sponge;
@@ -35,6 +36,7 @@ import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.event.cause.EventContext;
import org.spongepowered.api.event.server.ClientPingServerEvent;
import org.spongepowered.api.network.status.StatusClient;
+import org.spongepowered.api.profile.GameProfile;
import java.lang.reflect.Method;
import java.net.Inet4Address;
@@ -68,11 +70,18 @@ public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
Sponge.getEventManager().post(event);
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
event.getResponse().getDescription().toPlain(),
- event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline(),
- event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax());
- event.getResponse().getPlayers().get().getProfiles().forEach(player -> {
- geyserPingInfo.addPlayer(player.getName().orElseThrow(IllegalStateException::new));
- });
+ new GeyserPingInfo.Players(
+ event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax(),
+ event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline()
+ ),
+ new GeyserPingInfo.Version(
+ event.getResponse().getVersion().getName(),
+ MinecraftConstants.PROTOCOL_VERSION) // thanks for also not exposing this sponge
+ );
+ event.getResponse().getPlayers().get().getProfiles().stream()
+ .map(GameProfile::getName)
+ .map(op -> op.orElseThrow(IllegalStateException::new))
+ .forEach(geyserPingInfo.getPlayerList()::add);
return geyserPingInfo;
}
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
index c5f13b581..3151e973c 100644
--- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
@@ -29,14 +29,16 @@ import com.google.inject.Inject;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader;
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor;
import org.geysermc.platform.sponge.command.GeyserSpongeCommandManager;
import org.slf4j.Logger;
@@ -79,7 +81,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
try {
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()));
} catch (IOException ex) {
- logger.warn("Failed to copy config.yml from jar path!");
+ logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"));
ex.printStackTrace();
}
@@ -89,7 +91,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
config = loader.load();
this.geyserConfig = new GeyserSpongeConfiguration(configDir, config);
} catch (IOException ex) {
- logger.warn("Failed to load config.yml!");
+ logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"));
ex.printStackTrace();
return;
}
@@ -162,4 +164,9 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
public void onServerStop(GameStoppedEvent event) {
onDisable();
}
+
+ @Override
+ public BootstrapDumpInfo getDumpInfo() {
+ return new GeyserSpongeDumpInfo();
+ }
}
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java
index 91cb59b0f..d37321ffe 100644
--- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java
@@ -26,10 +26,10 @@
package org.geysermc.platform.sponge.command;
import lombok.AllArgsConstructor;
-
-import org.geysermc.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
+import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.utils.LanguageUtils;
import org.spongepowered.api.command.CommandCallable;
import org.spongepowered.api.command.CommandException;
import org.spongepowered.api.command.CommandResult;
@@ -55,7 +55,8 @@ public class GeyserSpongeCommandExecutor implements CommandCallable {
if (args.length > 0) {
if (getCommand(args[0]) != null) {
if (!source.hasPermission(getCommand(args[0]).getPermission())) {
- source.sendMessage(Text.of(ChatColor.RED + "You do not have permission to execute this command!"));
+ // Not ideal to use log here but we dont get a session
+ source.sendMessage(Text.of(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail")));
return CommandResult.success();
}
getCommand(args[0]).execute(new SpongeCommandSender(source), args);
diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml
index df75f7533..468042b8f 100644
--- a/bootstrap/standalone/pom.xml
+++ b/bootstrap/standalone/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
../
bootstrap-standalone
@@ -14,13 +14,13 @@
org.geysermc
connector
- 1.0-SNAPSHOT
+ 1.0.0
compile
net.minecrell
terminalconsoleappender
- 1.1.1
+ 1.2.0
org.apache.logging.log4j
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
index 0fca35038..5da4c37d9 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
@@ -25,15 +25,24 @@
package org.geysermc.platform.standalone;
-import org.geysermc.common.PlatformType;
+import lombok.Getter;
+import net.minecrell.terminalconsole.TerminalConsoleAppender;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
-import org.geysermc.connector.configuration.GeyserConfiguration;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.connector.ping.IGeyserPingPassthrough;
+import org.geysermc.connector.configuration.GeyserConfiguration;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
+import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.platform.standalone.command.GeyserCommandManager;
+import org.geysermc.platform.standalone.gui.GeyserStandaloneGUI;
import java.io.File;
import java.io.IOException;
@@ -48,14 +57,49 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserStandaloneLogger geyserLogger;
private IGeyserPingPassthrough geyserPingPassthrough;
+ private GeyserStandaloneGUI gui;
+
+ @Getter
+ private boolean useGui = System.console() == null;
+
private GeyserConnector connector;
public static void main(String[] args) {
+ for (String arg : args) {
+ // By default, standalone Geyser will check if it should open the GUI based on if the GUI is null
+ // Optionally, you can force the use of a GUI or no GUI by specifying args
+ if (arg.equals("gui")) {
+ new GeyserStandaloneBootstrap().onEnable(true);
+ return;
+ } else if (arg.equals("nogui")) {
+ new GeyserStandaloneBootstrap().onEnable(false);
+ return;
+ }
+ }
new GeyserStandaloneBootstrap().onEnable();
}
+ public void onEnable(boolean useGui) {
+ this.useGui = useGui;
+ this.onEnable();
+ }
+
@Override
public void onEnable() {
+ Logger logger = (Logger) LogManager.getRootLogger();
+ for (Appender appender : logger.getAppenders().values()) {
+ // Remove the appender that is not in use
+ // Prevents multiple appenders/double logging and removes harmless errors
+ if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) {
+ logger.removeAppender(appender);
+ }
+ }
+ if (useGui && gui == null) {
+ gui = new GeyserStandaloneGUI();
+ gui.redirectSystemStreams();
+ gui.startUpdateThread();
+ }
+
geyserLogger = new GeyserStandaloneLogger();
LoopbackUtil.checkLoopback(geyserLogger);
@@ -64,7 +108,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
File configFile = FileUtils.fileOrCopiedFromResource("config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
} catch (IOException ex) {
- geyserLogger.severe("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex);
+ geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
System.exit(0);
}
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
@@ -72,9 +116,15 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
connector = GeyserConnector.start(PlatformType.STANDALONE, this);
geyserCommandManager = new GeyserCommandManager(connector);
+ if (gui != null) {
+ gui.setupInterface(geyserLogger, geyserCommandManager);
+ }
+
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
- geyserLogger.start();
+ if (!useGui) {
+ geyserLogger.start(); // Throws an error otherwise
+ }
}
@Override
@@ -108,4 +158,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
// Return the current working directory
return Paths.get(System.getProperty("user.dir"));
}
+
+ @Override
+ public BootstrapDumpInfo getDumpInfo() {
+ return new BootstrapDumpInfo();
+ }
}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java
index 7102d206e..ffc322dd5 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java
@@ -30,8 +30,9 @@ import lombok.extern.log4j.Log4j2;
import net.minecrell.terminalconsole.SimpleTerminalConsole;
+import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
-import org.geysermc.common.ChatColor;
+import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
@@ -96,7 +97,15 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements org
@Override
public void setDebug(boolean debug) {
- Configurator.setLevel(log.getName(), debug ? org.apache.logging.log4j.Level.DEBUG : log.getLevel());
+ Configurator.setLevel(log.getName(), debug ? Level.DEBUG : Level.INFO);
+ }
+
+ /**
+ * Used for setting debug mode in GUI mode
+ * @return if debug is enabled
+ */
+ public boolean isDebug() {
+ return log.isDebugEnabled();
}
@Override
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java
index 03c49705d..8c54d141b 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java
@@ -1,12 +1,13 @@
package org.geysermc.platform.standalone;
+import org.geysermc.connector.common.ChatColor;
+import org.geysermc.connector.utils.LanguageUtils;
+
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Paths;
-import org.geysermc.common.ChatColor;
-
public class LoopbackUtil {
private static final String checkExemption = "powershell -Command \"CheckNetIsolation LoopbackExempt -s\""; // Java's Exec feature runs as CMD, NetIsolation is only accessible from PowerShell.
private static final String loopbackCommand = "powershell -Command \"CheckNetIsolation LoopbackExempt -a -n='Microsoft.MinecraftUWP_8wekyb3d8bbwe'\"";
@@ -31,12 +32,12 @@ public class LoopbackUtil {
Files.write(Paths.get(System.getenv("temp") + "/loopback_minecraft.bat"), loopbackCommand.getBytes(), new OpenOption[0]);
process = Runtime.getRuntime().exec(startScript);
- geyserLogger.info(ChatColor.AQUA + "Added loopback exemption to Windows!");
+ geyserLogger.info(ChatColor.AQUA + LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.added"));
}
} catch (Exception e) {
e.printStackTrace();
- geyserLogger.error("Couldn't auto add loopback exemption to Windows!");
+ geyserLogger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.failed"));
}
}
}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java
new file mode 100644
index 000000000..1f4ff998a
--- /dev/null
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.standalone.gui;
+
+import lombok.Getter;
+
+import java.awt.*;
+import java.util.regex.Pattern;
+
+public enum ANSIColor {
+ // Normal colors
+ BLACK("(0;)?30(0;)?m", Color.getHSBColor(0.000f, 0.000f, 0.000f)),
+ RED("(0;)?31(0;)?m", Color.getHSBColor(0.000f, 1.000f, 0.502f)),
+ GREEN("(0;)?32(0;)?m", Color.getHSBColor(0.333f, 1.000f, 0.502f)),
+ YELLOW("(0;)?33(0;)?m", Color.getHSBColor(0.167f, 1.000f, 0.502f)),
+ BLUE("(0;)?34(0;)?m", Color.getHSBColor(0.667f, 1.000f, 0.502f)),
+ MAGENTA("(0;)?35(0;)?m", Color.getHSBColor(0.833f, 1.000f, 0.502f)),
+ CYAN("(0;)?36(0;)?m", Color.getHSBColor(0.500f, 1.000f, 0.502f)),
+ WHITE("(0;)?37(0;)?m", Color.getHSBColor(0.000f, 0.000f, 0.753f)),
+
+ // Bold colors
+ B_BLACK("(1;30|30;1)m", Color.getHSBColor(0.000f, 0.000f, 0.502f)),
+ B_RED("(1;31|31;1)m", Color.getHSBColor(0.000f, 1.000f, 1.000f)),
+ B_GREEN("(1;32|32;1)m", Color.getHSBColor(0.333f, 1.000f, 1.000f)),
+ B_YELLOW("(1;33|33;1)m", Color.getHSBColor(0.167f, 1.000f, 1.000f)),
+ B_BLUE("(1;34|34;1)m", Color.getHSBColor(0.667f, 1.000f, 1.000f)),
+ B_MAGENTA("(1;35|35;1)m", Color.getHSBColor(0.833f, 1.000f, 1.000f)),
+ B_CYAN("(1;36|36;1)m", Color.getHSBColor(0.500f, 1.000f, 1.000f)),
+ B_WHITE("(1;37|37;1)m", Color.getHSBColor(0.000f, 0.000f, 1.000f)),
+
+ RESET("0m", Color.getHSBColor(0.000f, 0.000f, 1.000f));
+
+ private static final ANSIColor[] VALUES = values();
+ private static final String PREFIX = Pattern.quote("\u001B[");
+
+ private final String ANSICode;
+
+ @Getter
+ private final Color color;
+
+ ANSIColor(String ANSICode, Color color) {
+ this.ANSICode = ANSICode;
+ this.color = color;
+ }
+
+ public static ANSIColor fromANSI(String code) {
+ for (ANSIColor value : VALUES) {
+ if (code.matches(PREFIX + value.ANSICode)) {
+ return value;
+ }
+ }
+
+ return B_WHITE;
+ }
+}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java
new file mode 100644
index 000000000..f4586bbb1
--- /dev/null
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.standalone.gui;
+
+import javax.swing.*;
+import javax.swing.text.*;
+import java.awt.*;
+
+/**
+ * This class was based on this code: https://stackoverflow.com/a/6899478/5299903
+ */
+public class ColorPane extends JTextPane {
+ private static Color colorCurrent = ANSIColor.RESET.getColor();
+ private String remaining = "";
+
+ /**
+ * Append the given string in the given color to the text pane
+ * @param c The color
+ * @param s The text
+ */
+ private void append(Color c, String s) {
+ StyleContext sc = StyleContext.getDefaultStyleContext();
+ AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
+ int len = getDocument().getLength();
+
+ try {
+ getDocument().insertString(len, s, aset);
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Extract the ANSI color codes from the string and add each part to the text pane
+ *
+ * @param s The text to parse
+ */
+ public void appendANSI(String s) { // convert ANSI color codes first
+ int aPos = 0; // current char position in addString
+ int aIndex = 0; // index of next Escape sequence
+ int mIndex = 0; // index of "m" terminating Escape sequence
+ String tmpString = "";
+ boolean stillSearching = true; // true until no more Escape sequences
+ String addString = remaining + s;
+ remaining = "";
+
+ if (addString.length() > 0) {
+ aIndex = addString.indexOf("\u001B"); // find first escape
+ if (aIndex == -1) { // no escape/color change in this string, so just send it with current color
+ append(colorCurrent, addString);
+ return;
+ }
+ // otherwise There is an escape character in the string, so we must process it
+
+ if (aIndex > 0) { // Escape is not first char, so send text up to first escape
+ tmpString = addString.substring(0, aIndex);
+ append(colorCurrent, tmpString);
+ aPos = aIndex; // aPos is now at the beginning of the first escape sequence
+ }
+
+
+ // while there's text in the input buffer
+ stillSearching = true;
+ while (stillSearching) {
+ mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence
+ if (mIndex < 0) { // the buffer ends halfway through the ansi string!
+ remaining = addString.substring(aPos, addString.length());
+ stillSearching = false;
+ continue;
+ } else {
+ tmpString = addString.substring(aPos, mIndex+1);
+ colorCurrent = ANSIColor.fromANSI(tmpString).getColor();
+ }
+ aPos = mIndex + 1;
+ // now we have the color, send text that is in that color (up to next escape)
+
+ aIndex = addString.indexOf("\u001B", aPos);
+
+ if (aIndex == -1) { // if that was the last sequence of the input, send remaining text
+ tmpString = addString.substring(aPos, addString.length());
+ append(colorCurrent, tmpString);
+ stillSearching = false;
+ continue; // jump out of loop early, as the whole string has been sent now
+ }
+
+ // there is another escape sequence, so send part of the string and prepare for the next
+ tmpString = addString.substring(aPos, aIndex);
+ aPos = aIndex;
+ append(colorCurrent, tmpString);
+
+ }
+ }
+ }
+}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java
new file mode 100644
index 000000000..0c0ec1127
--- /dev/null
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.standalone.gui;
+
+import org.geysermc.connector.GeyserConnector;
+import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
+import org.geysermc.platform.standalone.GeyserStandaloneLogger;
+import org.geysermc.platform.standalone.command.GeyserCommandManager;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.text.Document;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class GeyserStandaloneGUI {
+
+ private static final DefaultTableModel playerTableModel = new DefaultTableModel();
+ private static final List ramValues = new ArrayList<>();
+
+ private static final ColorPane consolePane = new ColorPane();
+ private static final GraphPanel ramGraph = new GraphPanel();
+ private static final JTable playerTable = new JTable(playerTableModel);
+ private static final int originalFontSize = consolePane.getFont().getSize();
+
+ private static final long MEGABYTE = 1024L * 1024L;
+
+ private final JMenu commandsMenu;
+ private final JMenu optionsMenu;
+
+ public GeyserStandaloneGUI() {
+ // Create the frame and setup basic settings
+ JFrame frame = new JFrame(LanguageUtils.getLocaleStringLog("geyser.gui.title"));
+ frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ frame.setSize(800, 400);
+ frame.setMinimumSize(frame.getSize());
+
+ // Remove Java UI look
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception ignored) { }
+
+ // Show a confirm dialog on close
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent we)
+ {
+ String[] buttons = {LanguageUtils.getLocaleStringLog("geyser.gui.exit.confirm"), LanguageUtils.getLocaleStringLog("geyser.gui.exit.deny")};
+ int result = JOptionPane.showOptionDialog(frame, LanguageUtils.getLocaleStringLog("geyser.gui.exit.message"), frame.getTitle(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, buttons, buttons[1]);
+ if (result == JOptionPane.YES_OPTION) {
+ System.exit(0);
+ }
+ }
+ });
+
+ Container cp = frame.getContentPane();
+
+ // Fetch and set the icon for the frame
+ URL image = getClass().getClassLoader().getResource("icon.png");
+ if (image != null) {
+ ImageIcon icon = new ImageIcon(image);
+ frame.setIconImage(icon.getImage());
+ }
+
+ // Setup the split pane and event listeners
+ JSplitPane splitPane = new JSplitPane();
+ splitPane.setDividerLocation(600);
+ splitPane.addPropertyChangeListener("dividerLocation", e -> splitPaneLimit((JSplitPane)e.getSource()));
+ splitPane.addComponentListener(new ComponentAdapter() {
+ public void componentResized(ComponentEvent e) {
+ splitPaneLimit((JSplitPane)e.getSource());
+ }
+ });
+
+ cp.add(splitPane, BorderLayout.CENTER);
+
+ // Set the background and disable input for the text pane
+ consolePane.setBackground(Color.BLACK);
+ consolePane.setEditable(false);
+
+ // Wrap the text pane in a scroll pane and add it to the form
+ JScrollPane consoleScrollPane = new JScrollPane(consolePane);
+ //cp.add(consoleScrollPane, BorderLayout.CENTER);
+ splitPane.setLeftComponent(consoleScrollPane);
+
+ // Create a new menu bar for the top of the frame
+ JMenuBar menuBar = new JMenuBar();
+
+ // Create 'File'
+ JMenu fileMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file"));
+ fileMenu.setMnemonic(KeyEvent.VK_F);
+ menuBar.add(fileMenu);
+
+ // 'Open Geyser folder' button
+ JMenuItem openButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O);
+ openButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
+ openButton.addActionListener(e -> {
+ try {
+ Desktop.getDesktop().open(new File("./"));
+ } catch (IOException ignored) { }
+ });
+ fileMenu.add(openButton);
+
+ fileMenu.addSeparator();
+
+ // 'Exit' button
+ JMenuItem exitButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X);
+ exitButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK));
+ exitButton.addActionListener(e -> System.exit(0));
+ fileMenu.add(exitButton);
+
+ // Create 'Commands'
+ commandsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.commands"));
+ commandsMenu.setMnemonic(KeyEvent.VK_C);
+ menuBar.add(commandsMenu);
+
+ // Create 'View'
+ JMenu viewMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view"));
+ viewMenu.setMnemonic(KeyEvent.VK_V);
+ menuBar.add(viewMenu);
+
+ // 'Zoom in' button
+ JMenuItem zoomInButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_in"));
+ zoomInButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK));
+ zoomInButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() + 1)));
+ viewMenu.add(zoomInButton);
+
+ // 'Zoom in' button
+ JMenuItem zoomOutButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_out"));
+ zoomOutButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK));
+ zoomOutButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() - 1)));
+ viewMenu.add(zoomOutButton);
+
+ // 'Reset Zoom' button
+ JMenuItem resetZoomButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.reset_zoom"));
+ resetZoomButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), originalFontSize)));
+ viewMenu.add(resetZoomButton);
+
+ // create 'Options'
+ optionsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options"));
+ viewMenu.setMnemonic(KeyEvent.VK_O);
+ menuBar.add(optionsMenu);
+
+ // Set the frames menu bar
+ frame.setJMenuBar(menuBar);
+
+ JPanel rightPane = new JPanel();
+ rightPane.setLayout(new CardLayout(5, 5));
+ //cp.add(rightPane, BorderLayout.EAST);
+ splitPane.setRightComponent(rightPane);
+
+ JPanel rightContentPane = new JPanel();
+ rightContentPane.setLayout(new GridLayout(2, 1, 5, 5));
+ rightPane.add(rightContentPane);
+
+ // Set the ram graph to 0
+ for (int i = 0; i < 10; i++) {
+ ramValues.add(0);
+ }
+ ramGraph.setValues(ramValues);
+ ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.loading"));
+ rightContentPane.add(ramGraph);
+
+ playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.ip"));
+ playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.username"));
+
+ JScrollPane playerScrollPane = new JScrollPane(playerTable);
+ rightContentPane.add(playerScrollPane);
+
+ // This has to be done last
+ frame.setVisible(true);
+ }
+
+ /**
+ * Queue up an update to the text pane so we don't block the main thread
+ *
+ * @param text The text to append
+ */
+ private void updateTextPane(final String text) {
+ SwingUtilities.invokeLater(() -> {
+ consolePane.appendANSI(text);
+ Document doc = consolePane.getDocument();
+ consolePane.setCaretPosition(doc.getLength());
+ });
+ }
+
+ /**
+ * Redirect the default io streams to the text pane
+ */
+ public void redirectSystemStreams() {
+ // Setup a new output stream to forward it to the text pane
+ OutputStream out = new OutputStream() {
+ @Override
+ public void write(final int b) {
+ updateTextPane(String.valueOf((char) b));
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ updateTextPane(new String(b, off, len));
+ }
+
+ @Override
+ public void write(byte[] b) {
+ write(b, 0, b.length);
+ }
+ };
+
+ // Override the system output streams
+ System.setOut(new PrintStream(out, true));
+ System.setErr(new PrintStream(out, true));
+
+ }
+
+ /**
+ * Add all the Geyser commands to the commands menu, and setup the debug mode toggle
+ *
+ * @param geyserStandaloneLogger The current logger
+ * @param geyserCommandManager The commands manager
+ */
+ public void setupInterface(GeyserStandaloneLogger geyserStandaloneLogger, GeyserCommandManager geyserCommandManager) {
+ commandsMenu.removeAll();
+ optionsMenu.removeAll();
+
+ for (Map.Entry command : geyserCommandManager.getCommands().entrySet()) {
+ // Remove the offhand command and any alias commands to prevent duplicates in the list
+ if ("offhand".equals(command.getValue().getName()) || command.getValue().getAliases().contains(command.getKey())) {
+ continue;
+ }
+
+ // Create the button that runs the command
+ JMenuItem commandButton = new JMenuItem(command.getValue().getName());
+ commandButton.getAccessibleContext().setAccessibleDescription(command.getValue().getDescription());
+ commandButton.addActionListener(e -> command.getValue().execute(geyserStandaloneLogger, new String[]{ }));
+ commandsMenu.add(commandButton);
+ }
+
+ // 'Debug Mode' toggle
+ JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode"));
+ debugMode.setSelected(geyserStandaloneLogger.isDebug());
+ debugMode.addActionListener(e -> geyserStandaloneLogger.setDebug(!geyserStandaloneLogger.isDebug()));
+ optionsMenu.add(debugMode);
+ }
+
+ /**
+ * Start the thread to update the form information every 1s
+ */
+ public void startUpdateThread() {
+ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+
+ Runnable periodicTask = () -> {
+ if (GeyserConnector.getInstance() != null) {
+ // Update player table
+ playerTableModel.getDataVector().removeAllElements();
+
+ for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
+ Vector row = new Vector();
+ row.add(player.getSocketAddress().getHostName());
+ row.add(player.getPlayerEntity().getUsername());
+
+ playerTableModel.addRow(row);
+ }
+
+ playerTableModel.fireTableDataChanged();
+ }
+
+ // Update ram graph
+ final long freeMemory = Runtime.getRuntime().freeMemory();
+ final long totalMemory = Runtime.getRuntime().totalMemory();
+ final int freePercent = (int)(freeMemory * 100.0 / totalMemory + 0.5);
+ ramValues.add(100 - freePercent);
+
+ ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.usage", String.format("%,d", (totalMemory - freeMemory) / MEGABYTE), freePercent));
+
+ // Trim the list
+ int k = ramValues.size();
+ if ( k > 10 )
+ ramValues.subList(0, k - 10).clear();
+
+ // Update the graph
+ ramGraph.setValues(ramValues);
+ };
+
+ // SwingUtilities.invokeLater is called so we don't run into threading issues with the GUI
+ executor.scheduleAtFixedRate(() -> SwingUtilities.invokeLater(periodicTask), 0, 1, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Make sure the JSplitPane divider is within a set of bounds
+ *
+ * @param splitPane The JSplitPane to check
+ */
+ private void splitPaneLimit(JSplitPane splitPane) {
+ JRootPane frame = splitPane.getRootPane();
+ int location = splitPane.getDividerLocation();
+ if (location < frame.getWidth() - frame.getWidth() * 0.4f) {
+ splitPane.setDividerLocation(Math.round(frame.getWidth() - frame.getWidth() * 0.4f));
+ } else if (location > frame.getWidth() - 200) {
+ splitPane.setDividerLocation(frame.getWidth() - 200);
+ }
+ }
+}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java
new file mode 100644
index 000000000..0e3361327
--- /dev/null
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.standalone.gui;
+
+import lombok.Setter;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This has been modified to fit Geyser more but is based on
+ * https://gist.github.com/roooodcastro/6325153#gistcomment-3107524
+ */
+public final class GraphPanel extends JPanel {
+ private final static int padding = 10;
+ private final static int labelPadding = 25;
+ private final static int pointWidth = 4;
+ private final static int numberYDivisions = 10;
+ private final static Color lineColor = new Color(44, 102, 230, 255);
+ private final static Color pointColor = new Color(100, 100, 100, 255);
+ private final static Color gridColor = new Color(200, 200, 200, 255);
+ private static final Stroke graphStroke = new BasicStroke(2f);
+ private List values = new ArrayList<>(10);
+
+ @Setter
+ private String xLabel = "";
+
+ public GraphPanel() {
+ setPreferredSize(new Dimension(200 - (padding * 2), 150 - (padding * 2)));
+ }
+
+ public void setValues(Collection newValues) {
+ values.clear();
+ addValues(newValues);
+ }
+
+ public void addValues(Collection newValues) {
+ values.addAll(newValues);
+ updateUI();
+ }
+
+ @Override
+ protected void paintComponent(Graphics graphics) {
+ super.paintComponent(graphics);
+ if (!(graphics instanceof Graphics2D)) {
+ graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0);
+ return;
+ }
+ final Graphics2D g = (Graphics2D) graphics;
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ final int length = values.size();
+ final int width = getWidth();
+ final int height = getHeight();
+ final int maxScore = getMaxScore();
+ final int minScore = getMinScore();
+ final int scoreRange = maxScore - minScore;
+
+ // draw white background
+ g.setColor(Color.WHITE);
+ g.fillRect(
+ padding + labelPadding,
+ padding,
+ width - (2 * padding) - labelPadding,
+ height - 2 * padding - labelPadding);
+ g.setColor(Color.BLACK);
+
+ final FontMetrics fontMetrics = g.getFontMetrics();
+ final int fontHeight = fontMetrics.getHeight();
+
+ // create hatch marks and grid lines for y axis.
+ for (int i = 0; i < numberYDivisions + 1; i++) {
+ final int x1 = padding + labelPadding;
+ final int x2 = pointWidth + padding + labelPadding;
+ final int y = height - ((i * (height - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);
+ if (length > 0) {
+ g.setColor(gridColor);
+ g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y);
+
+ g.setColor(Color.BLACK);
+ final int tickValue = (int) (minScore + ((scoreRange * i) / numberYDivisions));
+ final String yLabel = tickValue + "";
+ final int labelWidth = fontMetrics.stringWidth(yLabel);
+ g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3);
+ }
+ g.drawLine(x1, y, x2, y);
+ }
+
+ // and for x axis
+ if (length > 1) {
+ for (int i = 0; i < length; i++) {
+ final int x = i * (width - padding * 2 - labelPadding) / (length - 1) + padding + labelPadding;
+ final int y1 = height - padding - labelPadding;
+ final int y2 = y1 - pointWidth;
+ if ((i % ((int) ((length / 20.0)) + 1)) == 0) {
+ g.setColor(gridColor);
+ g.drawLine(x, height - padding - labelPadding - 1 - pointWidth, x, padding);
+
+ g.setColor(Color.BLACK);
+
+ /*g.setColor(Color.BLACK);
+ final String xLabel = i + "";
+ final int labelWidth = fontMetrics.stringWidth(xLabel);
+ g.drawString(xLabel, x - labelWidth / 2, y1 + fontHeight + 3);*/
+ }
+ g.drawLine(x, y1, x, y2);
+ }
+ }
+
+ // create x and y axes
+ g.drawLine(padding + labelPadding, height - padding - labelPadding, padding + labelPadding, padding);
+ g.drawLine(padding + labelPadding, height - padding - labelPadding, width - padding, height - padding - labelPadding);
+
+ g.setColor(Color.BLACK);
+ final int labelWidth = fontMetrics.stringWidth(xLabel);
+ final int labelX = ((padding + labelPadding) + (width - padding)) / 2;
+ final int labelY = height - padding - labelPadding;
+ g.drawString(xLabel, labelX - labelWidth / 2, labelY + fontHeight + 3);
+
+ final Stroke oldStroke = g.getStroke();
+ g.setColor(lineColor);
+ g.setStroke(graphStroke);
+
+ final double xScale = ((double) width - (2 * padding) - labelPadding) / (length - 1);
+ final double yScale = ((double) height - 2 * padding - labelPadding) / scoreRange;
+
+ final List graphPoints = new ArrayList<>(length);
+ for (int i = 0; i < length; i++) {
+ final int x1 = (int) (i * xScale + padding + labelPadding);
+ final int y1 = (int) ((maxScore - values.get(i)) * yScale + padding);
+ graphPoints.add(new Point(x1, y1));
+ }
+
+ for (int i = 0; i < graphPoints.size() - 1; i++) {
+ final int x1 = graphPoints.get(i).x;
+ final int y1 = graphPoints.get(i).y;
+ final int x2 = graphPoints.get(i + 1).x;
+ final int y2 = graphPoints.get(i + 1).y;
+ g.drawLine(x1, y1, x2, y2);
+ }
+
+ boolean drawDots = width > (length * pointWidth);
+ if (drawDots) {
+ g.setStroke(oldStroke);
+ g.setColor(pointColor);
+ for (Point graphPoint : graphPoints) {
+ final int x = graphPoint.x - pointWidth / 2;
+ final int y = graphPoint.y - pointWidth / 2;
+ g.fillOval(x, y, pointWidth, pointWidth);
+ }
+ }
+ }
+
+ private int getMinScore() {
+ return 0;
+ }
+
+ private int getMaxScore() {
+ return 100;
+ }
+}
diff --git a/bootstrap/standalone/src/main/resources/icon.png b/bootstrap/standalone/src/main/resources/icon.png
new file mode 100644
index 000000000..4e6a38a78
Binary files /dev/null and b/bootstrap/standalone/src/main/resources/icon.png differ
diff --git a/bootstrap/standalone/src/main/resources/log4j2.xml b/bootstrap/standalone/src/main/resources/log4j2.xml
index 957415405..238a27da5 100644
--- a/bootstrap/standalone/src/main/resources/log4j2.xml
+++ b/bootstrap/standalone/src/main/resources/log4j2.xml
@@ -1,9 +1,12 @@
-
+
+
+
+
@@ -14,6 +17,7 @@
+
diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml
index fb06767e0..7c42ba336 100644
--- a/bootstrap/velocity/pom.xml
+++ b/bootstrap/velocity/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 1.0-SNAPSHOT
+ 1.0.0
../
bootstrap-velocity
@@ -14,7 +14,7 @@
org.geysermc
connector
- 1.0-SNAPSHOT
+ 1.0.0
compile
@@ -61,6 +61,10 @@
it.unimi.dsi.fastutil
org.geysermc.platform.velocity.shaded.fastutil
+
+ org.reflections.reflections
+ org.geysermc.platform.velocity.shaded.reflections
+
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java
new file mode 100644
index 000000000..906a04142
--- /dev/null
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019-2020 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.platform.velocity;
+
+import com.velocitypowered.api.plugin.PluginContainer;
+import com.velocitypowered.api.proxy.ProxyServer;
+import lombok.Getter;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
+
+ private String platformName;
+ private String platformVersion;
+ private String platformVendor;
+ private boolean onlineMode;
+ private String serverIP;
+ private int serverPort;
+ private List plugins;
+
+ GeyserVelocityDumpInfo(ProxyServer proxy) {
+ super();
+ this.platformName = proxy.getVersion().getName();
+ this.platformVersion = proxy.getVersion().getVersion();
+ this.platformVendor = proxy.getVersion().getVendor();
+ this.onlineMode = proxy.getConfiguration().isOnlineMode();
+ this.serverIP = proxy.getBoundAddress().getHostString();
+ this.serverPort = proxy.getBoundAddress().getPort();
+ this.plugins = new ArrayList<>();
+
+ for (PluginContainer plugin : proxy.getPluginManager().getPlugins()) {
+ String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown");
+ this.plugins.add(new PluginInfo(true, plugin.getDescription().getName().get(), plugin.getDescription().getVersion().get(), pluginClass, plugin.getDescription().getAuthors()));
+ }
+ }
+}
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java
index 73eaddf09..b5c79cc2b 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java
@@ -26,7 +26,7 @@
package org.geysermc.platform.velocity;
-import org.geysermc.common.main.IGeyserMain;
+import org.geysermc.connector.common.main.IGeyserMain;
public class GeyserVelocityMain extends IGeyserMain {
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java
index 01be949b8..980c5b3ee 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java
@@ -32,9 +32,8 @@ import com.velocitypowered.api.proxy.InboundConnection;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.ServerPing;
import lombok.AllArgsConstructor;
-import net.kyori.text.TextComponent;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
-import org.geysermc.common.ping.GeyserPingInfo;
+import org.geysermc.connector.common.ping.GeyserPingInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import java.net.Inet4Address;
@@ -60,13 +59,17 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough {
throw new RuntimeException(e);
}
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
- LegacyComponentSerializer.INSTANCE.serialize(event.getPing().getDescription(), '§'),
- event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline(),
- event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax()
+ LegacyComponentSerializer.legacy().serialize(event.getPing().getDescription(), '§'),
+ new GeyserPingInfo.Players(
+ event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax(),
+ event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline()
+ ),
+ new GeyserPingInfo.Version(
+ event.getPing().getVersion().getName(),
+ event.getPing().getVersion().getProtocol()
+ )
);
- event.getPing().getPlayers().get().getSample().forEach(player -> {
- geyserPingInfo.addPlayer(player.getName());
- });
+ event.getPing().getPlayers().get().getSample().stream().map(ServerPing.SamplePlayer::getName).forEach(geyserPingInfo.getPlayerList()::add);
return geyserPingInfo;
}
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
index 5abf3c230..425aba183 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
@@ -35,13 +35,15 @@ import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import lombok.Getter;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor;
import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager;
import org.slf4j.Logger;
@@ -84,7 +86,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
} catch (IOException ex) {
- logger.warn("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex);
+ logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
}
@@ -102,7 +104,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
if (geyserConfig.getRemote().getAuthType().equals("floodgate") && !proxyServer.getPluginManager().getPlugin("floodgate").isPresent()) {
- geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling...");
+ geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
return;
}
@@ -153,4 +155,9 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
public void onShutdown(ProxyShutdownEvent event) {
onDisable();
}
+
+ @Override
+ public BootstrapDumpInfo getDumpInfo() {
+ return new GeyserVelocityDumpInfo(proxyServer);
+ }
}
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java
index 940c52244..fa3aaa3c3 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java
@@ -32,9 +32,10 @@ import lombok.AllArgsConstructor;
import net.kyori.text.TextComponent;
-import org.geysermc.common.ChatColor;
+import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.utils.LanguageUtils;
@AllArgsConstructor
public class GeyserVelocityCommandExecutor implements Command {
@@ -46,7 +47,8 @@ public class GeyserVelocityCommandExecutor implements Command {
if (args.length > 0) {
if (getCommand(args[0]) != null) {
if (!source.hasPermission(getCommand(args[0]).getPermission())) {
- source.sendMessage(TextComponent.of(ChatColor.RED + "You do not have permission to execute this command!"));
+ // Not ideal to use log here but we dont get a session
+ source.sendMessage(TextComponent.of(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail")));
return;
}
getCommand(args[0]).execute(new VelocityCommandSender(source), args);
diff --git a/common/pom.xml b/common/pom.xml
index 0a47fbcaa..0df8ef4bf 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -10,7 +10,7 @@
../
common
- 1.0-SNAPSHOT
+ 1.0.0
com.google.code.gson
diff --git a/common/src/main/java/org/geysermc/common/AuthType.java b/common/src/main/java/org/geysermc/common/AuthType.java
deleted file mode 100644
index 8edbc4d55..000000000
--- a/common/src/main/java/org/geysermc/common/AuthType.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.geysermc.common;
-
-import lombok.Getter;
-
-@Getter
-public enum AuthType {
- OFFLINE,
- ONLINE,
- FLOODGATE;
-
- public static final AuthType[] VALUES = values();
-
- public static AuthType getById(int id) {
- return id < VALUES.length ? VALUES[id] : OFFLINE;
- }
-
- /**
- * Convert the AuthType string (from config) to the enum, OFFLINE on fail
- *
- * @param name AuthType string
- *
- * @return The converted AuthType
- */
- public static AuthType getByName(String name) {
- String upperCase = name.toUpperCase();
- for (AuthType type : VALUES) {
- if (type.name().equals(upperCase)) {
- return type;
- }
- }
- return OFFLINE;
- }
-}
\ No newline at end of file
diff --git a/common/src/main/java/org/geysermc/common/PlatformType.java b/common/src/main/java/org/geysermc/common/PlatformType.java
deleted file mode 100644
index fa6f57fda..000000000
--- a/common/src/main/java/org/geysermc/common/PlatformType.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.geysermc.common;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public enum PlatformType {
-
- BUKKIT("Bukkit"),
- BUNGEECORD("BungeeCord"),
- SPONGE("Sponge"),
- STANDALONE("Standalone"),
- VELOCITY("Velocity");
-
- private String platformName;
-}
diff --git a/common/src/main/resources/help.txt b/common/src/main/resources/help.txt
deleted file mode 100644
index 3512ed839..000000000
--- a/common/src/main/resources/help.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
---------------------------------------------------------------------------------
-
- Oops! You attempted to run a plugin version of Geyser directly!
-
- This jar file is a plugin for ${plugin_type}. You can run this file as a
- plugin by dropping the jar file into the "${plugin_folder}" directory.
-
- There is also a standalone version available that doesn't need to
- be installed as a plugin, you can find it on our build server:
-
- http://ci.geysermc.org/
-
- If you need more help, you should check out our discord:
-
- http://discord.geysermc.org/
-
---------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/connector/pom.xml b/connector/pom.xml
index 91cf6f3db..3fdd5f37a 100644
--- a/connector/pom.xml
+++ b/connector/pom.xml
@@ -10,12 +10,12 @@
../
connector
- 1.0-SNAPSHOT
+ 1.0.0
org.geysermc
common
- 1.0-SNAPSHOT
+ 1.0.0
compile
@@ -32,8 +32,8 @@
com.nukkitx.protocol
- bedrock-v390
- 2.5.6-SNAPSHOT
+ bedrock-v407
+ 2.6.0-SNAPSHOT
compile
@@ -66,6 +66,12 @@
8.3.1
compile
+
+ com.nukkitx.fastutil
+ fastutil-int-byte-maps
+ 8.3.1
+ compile
+
com.nukkitx.fastutil
fastutil-int-double-maps
@@ -99,7 +105,7 @@
com.github.steveice10
mcprotocollib
- 4c315aa206
+ 7545884a2d
compile
@@ -121,20 +127,20 @@
net.kyori
- text-api
- 3.0.3
+ adventure-api
+ 4.0.0-SNAPSHOT
compile
net.kyori
- text-serializer-gson
- 3.0.3
+ adventure-text-serializer-gson
+ 4.0.0-SNAPSHOT
compile
net.kyori
- text-serializer-legacy
- 3.0.3
+ adventure-text-serializer-legacy
+ 4.0.0-SNAPSHOT
compile
@@ -164,6 +170,11 @@
false
git.user.*
+ git.*.user.*
+ git.closest.*
+ git.commit.id.describe
+ git.commit.id.describe-short
+ git.commit.message.short
flat
diff --git a/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java b/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java
index 617ac83eb..d4413d68b 100644
--- a/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java
+++ b/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java
@@ -26,6 +26,7 @@
package org.geysermc.connector;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.connector.configuration.GeyserConfiguration;
import java.nio.file.Files;
@@ -37,13 +38,13 @@ public class FloodgateKeyLoader {
if (floodgate != null) {
Path autoKey = floodgateFolder.resolve("public-key.pem");
if (Files.exists(autoKey)) {
- logger.info("Auto-loaded floodgate key");
+ logger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded"));
floodgateKey = autoKey;
} else {
- logger.error("Auth-type set to floodgate and the public key is missing!");
+ logger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.missing_key"));
}
} else {
- logger.error("Auth-type set to floodgate but floodgate is not installed!");
+ logger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed"));
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
index d201656ad..675c2b9a2 100644
--- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
+++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
@@ -29,11 +29,11 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.BedrockServer;
-import com.nukkitx.protocol.bedrock.v390.Bedrock_v390;
+import com.nukkitx.protocol.bedrock.v407.Bedrock_v407;
import lombok.Getter;
import lombok.Setter;
-import org.geysermc.common.AuthType;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.AuthType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.configuration.GeyserConfiguration;
@@ -44,22 +44,23 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.BiomeTranslator;
import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
+import org.geysermc.connector.network.translators.effect.EffectRegistry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.sound.SoundHandlerRegistry;
+import org.geysermc.connector.network.translators.sound.SoundRegistry;
import org.geysermc.connector.network.translators.world.WorldManager;
+import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.connector.network.translators.effect.EffectRegistry;
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
import org.geysermc.connector.utils.DimensionUtils;
import org.geysermc.connector.utils.DockerCheck;
import org.geysermc.connector.utils.LocaleUtils;
-import org.geysermc.connector.network.translators.sound.SoundRegistry;
import java.net.InetSocketAddress;
import java.text.DecimalFormat;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -70,12 +71,12 @@ public class GeyserConnector {
public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
- public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v390.V390_CODEC;
+ public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v407.V407_CODEC;
public static final String NAME = "Geyser";
public static final String VERSION = "DEV"; // A fallback for running in IDEs
- private final Map players = new HashMap<>();
+ private final List players = new ArrayList<>();
private static GeyserConnector instance;
@@ -107,7 +108,7 @@ public class GeyserConnector {
logger.info("******************************************");
logger.info("");
- logger.info("Loading " + NAME + " version " + VERSION);
+ logger.info(LanguageUtils.getLocaleStringLog("geyser.core.load", NAME, VERSION));
logger.info("");
logger.info("******************************************");
@@ -143,9 +144,9 @@ public class GeyserConnector {
bedrockServer.setHandler(new ConnectorServerEventHandler(this));
bedrockServer.bind().whenComplete((avoid, throwable) -> {
if (throwable == null) {
- logger.info("Started Geyser on " + config.getBedrock().getAddress() + ":" + config.getBedrock().getPort());
+ logger.info(LanguageUtils.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort())));
} else {
- logger.severe("Failed to start Geyser on " + config.getBedrock().getAddress() + ":" + config.getBedrock().getPort());
+ logger.severe(LanguageUtils.getLocaleStringLog("geyser.core.fail", config.getBedrock().getAddress(), config.getBedrock().getPort()));
throwable.printStackTrace();
}
}).join();
@@ -158,19 +159,34 @@ public class GeyserConnector {
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName));
}
+ boolean isGui = false;
+ // This will check if we are in standalone and get the 'useGui' variable from there
+ if (platformType == PlatformType.STANDALONE) {
+ try {
+ Class> cls = Class.forName("org.geysermc.platform.standalone.GeyserStandaloneBootstrap");
+ isGui = (boolean) cls.getMethod("isUseGui").invoke(cls.cast(bootstrap));
+ } catch (Exception e) { e.printStackTrace(); }
+ }
+
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
- logger.info(String.format("Done (%ss)! Run /geyser help for help!", new DecimalFormat("#.###").format(completeTime)));
+ String message = LanguageUtils.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)) + " ";
+ if (isGui) {
+ message += LanguageUtils.getLocaleStringLog("geyser.core.finish.gui");
+ } else {
+ message += LanguageUtils.getLocaleStringLog("geyser.core.finish.console");
+ }
+ logger.info(message);
}
public void shutdown() {
- bootstrap.getGeyserLogger().info("Shutting down Geyser.");
+ bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown"));
shuttingDown = true;
if (players.size() >= 1) {
- bootstrap.getGeyserLogger().info("Kicking " + players.size() + " player(s)");
+ bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.log", players.size()));
- for (GeyserSession playerSession : players.values()) {
- playerSession.disconnect("Geyser Proxy shutting down.");
+ for (GeyserSession playerSession : players) {
+ playerSession.disconnect(LanguageUtils.getPlayerLocaleString("geyser.core.shutdown.kick.message", playerSession.getClientData().getLanguageCode()));
}
CompletableFuture future = CompletableFuture.runAsync(new Runnable() {
@@ -194,7 +210,7 @@ public class GeyserConnector {
// Block and wait for the future to complete
try {
future.get();
- bootstrap.getGeyserLogger().info("Kicked all players");
+ bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.done"));
} catch (Exception e) {
// Quietly fail
}
@@ -207,15 +223,15 @@ public class GeyserConnector {
authType = null;
this.getCommandManager().getCommands().clear();
- bootstrap.getGeyserLogger().info("Geyser shutdown successfully.");
+ bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done"));
}
public void addPlayer(GeyserSession player) {
- players.put(player.getSocketAddress(), player);
+ players.add(player);
}
public void removePlayer(GeyserSession player) {
- players.remove(player.getSocketAddress());
+ players.remove(player);
}
public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) {
diff --git a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java
index 8683f80cd..f089350fb 100644
--- a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java
+++ b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java
@@ -26,6 +26,7 @@
package org.geysermc.connector.bootstrap;
+import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserLogger;
@@ -92,4 +93,11 @@ public interface GeyserBootstrap {
* @return Path location of data folder
*/
Path getConfigFolder();
+
+ /**
+ * Information used for the bootstrap section of the debug dump
+ *
+ * @return The info about the bootstrap
+ */
+ BootstrapDumpInfo getDumpInfo();
}
diff --git a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java
index 8b1d0bc78..afa75503e 100644
--- a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java
+++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java
@@ -29,6 +29,7 @@ import lombok.Getter;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.defaults.*;
+import org.geysermc.connector.utils.LanguageUtils;
import java.util.Collections;
import java.util.HashMap;
@@ -44,16 +45,18 @@ public abstract class CommandManager {
public CommandManager(GeyserConnector connector) {
this.connector = connector;
- registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.", "geyser.command.help"));
- registerCommand(new ListCommand(connector, "list", "List all players connected through Geyser.", "geyser.command.list"));
- registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload"));
- registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop"));
- registerCommand(new OffhandCommand(connector, "offhand", "Puts an items in your offhand.", "geyser.command.offhand"));
+ registerCommand(new HelpCommand(connector, "help", LanguageUtils.getLocaleStringLog("geyser.commands.help.desc"), "geyser.command.help"));
+ registerCommand(new ListCommand(connector, "list", LanguageUtils.getLocaleStringLog("geyser.commands.list.desc"), "geyser.command.list"));
+ registerCommand(new ReloadCommand(connector, "reload", LanguageUtils.getLocaleStringLog("geyser.commands.reload.desc"), "geyser.command.reload"));
+ registerCommand(new StopCommand(connector, "stop", LanguageUtils.getLocaleStringLog("geyser.commands.stop.desc"), "geyser.command.stop"));
+ registerCommand(new OffhandCommand(connector, "offhand", LanguageUtils.getLocaleStringLog("geyser.commands.offhand.desc"), "geyser.command.offhand"));
+ registerCommand(new DumpCommand(connector, "dump", LanguageUtils.getLocaleStringLog("geyser.commands.dump.desc"), "geyser.command.dump"));
+ registerCommand(new VersionCommand(connector, "version", LanguageUtils.getLocaleStringLog("geyser.commands.version.desc"), "geyser.command.version"));
}
public void registerCommand(GeyserCommand command) {
commands.put(command.getName(), command);
- connector.getLogger().debug("Registered command " + command.getName());
+ connector.getLogger().debug(LanguageUtils.getLocaleStringLog("geyser.commands.registered", command.getName()));
if (command.getAliases().isEmpty())
return;
@@ -81,7 +84,7 @@ public abstract class CommandManager {
GeyserCommand cmd = commands.get(label);
if (cmd == null) {
- connector.getLogger().error("Invalid Command! Try /geyser help for a list of commands.");
+ connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.invalid"));
return;
}
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java
new file mode 100644
index 000000000..6566ecc1c
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019-2020 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.command.defaults;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
+import org.geysermc.connector.common.ChatColor;
+import org.geysermc.connector.GeyserConnector;
+import org.geysermc.connector.command.CommandSender;
+import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.dump.DumpInfo;
+import org.geysermc.connector.utils.LanguageUtils;
+import org.geysermc.connector.utils.WebUtils;
+
+import java.io.IOException;
+
+public class DumpCommand extends GeyserCommand {
+
+ private final GeyserConnector connector;
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+ private static final String DUMP_URL = "https://dump.geysermc.org/";
+
+ public DumpCommand(GeyserConnector connector, String name, String description, String permission) {
+ super(name, description, permission);
+
+ this.connector = connector;
+
+ final SimpleFilterProvider filter = new SimpleFilterProvider();
+ filter.addFilter("dump_user_auth", SimpleBeanPropertyFilter.serializeAllExcept(new String[] {"password"}));
+
+ MAPPER.setFilterProvider(filter);
+ }
+
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collecting"));
+ String dumpData = "";
+ try {
+ dumpData = MAPPER.writeValueAsString(new DumpInfo());
+ } catch (IOException e) {
+ sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error"));
+ connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e);
+ return;
+ }
+
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.uploading"));
+ String response;
+ JsonNode responseNode;
+ try {
+ response = WebUtils.post(DUMP_URL + "documents", dumpData);
+ responseNode = MAPPER.readTree(response);
+ } catch (IOException e) {
+ sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error"));
+ connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error_short"), e);
+ return;
+ }
+
+ if (!responseNode.has("key")) {
+ sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error_short") + ": " + (responseNode.has("message") ? responseNode.get("message").asText() : response));
+ return;
+ }
+
+ String uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText();
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.message") + " " + ChatColor.DARK_AQUA + uploadedDumpUrl);
+ if (!sender.isConsole()) {
+ connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.commands.dump.created", sender.getName(), uploadedDumpUrl));
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java
index 6acb7822b..0407cf6ef 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java
@@ -25,10 +25,12 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.common.ChatColor;
+import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
import java.util.Collections;
import java.util.List;
@@ -48,7 +50,17 @@ public class HelpCommand extends GeyserCommand {
@Override
public void execute(CommandSender sender, String[] args) {
- sender.sendMessage("---- Showing Help For: Geyser (Page 1/1) ----");
+ int page = 1;
+ int maxPage = 1;
+ String header = "";
+
+ if (sender instanceof GeyserSession) {
+ header = LanguageUtils.getPlayerLocaleString("geyser.commands.help.header", ((GeyserSession) sender).getClientData().getLanguageCode(), page, maxPage);
+ } else {
+ header = LanguageUtils.getLocaleStringLog("geyser.commands.help.header", page, maxPage);
+ }
+
+ sender.sendMessage(header);
Map cmds = connector.getCommandManager().getCommands();
List commands = connector.getCommandManager().getCommands().keySet().stream().sorted().collect(Collectors.toList());
commands.forEach(cmd -> sender.sendMessage(ChatColor.YELLOW + "/geyser " + cmd + ChatColor.WHITE + ": " + cmds.get(cmd).getDescription()));
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java
index 21fa42535..3c78c5540 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java
@@ -25,11 +25,11 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
import java.util.stream.Collectors;
@@ -45,6 +45,13 @@ public class ListCommand extends GeyserCommand {
@Override
public void execute(CommandSender sender, String[] args) {
- sender.sendMessage(ChatColor.YELLOW + "Online Players (" + connector.getPlayers().size() + "): " + ChatColor.WHITE + connector.getPlayers().values().stream().map(GeyserSession::getName).collect(Collectors.joining(" ")));
+ String message = "";
+ if (sender instanceof GeyserSession) {
+ message = LanguageUtils.getPlayerLocaleString("geyser.commands.list.message", ((GeyserSession) sender).getClientData().getLanguageCode(), connector.getPlayers().size(), connector.getPlayers().stream().map(GeyserSession::getName).collect(Collectors.joining(" ")));
+ } else {
+ message = LanguageUtils.getLocaleStringLog("geyser.commands.list.message", connector.getPlayers().size(), connector.getPlayers().stream().map(GeyserSession::getName).collect(Collectors.joining(" ")));
+ }
+
+ sender.sendMessage(message);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java
index a49506b0f..b1b601328 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java
@@ -59,7 +59,7 @@ public class OffhandCommand extends GeyserCommand {
return;
}
// Needed for Bukkit - sender is not an instance of GeyserSession
- for (GeyserSession session : connector.getPlayers().values()) {
+ for (GeyserSession session : connector.getPlayers()) {
if (sender.getName().equals(session.getPlayerEntity().getUsername())) {
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0),
BlockFace.DOWN);
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
index c38a0c23d..9c24fa2be 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
@@ -25,12 +25,12 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.common.ChatColor;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
public class ReloadCommand extends GeyserCommand {
@@ -46,9 +46,18 @@ public class ReloadCommand extends GeyserCommand {
if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) {
return;
}
- sender.sendMessage(ChatColor.YELLOW + "Reloading Geyser configurations... all connected bedrock clients will be kicked.");
- for (GeyserSession session : connector.getPlayers().values()) {
- session.disconnect("Geyser has been reloaded... sorry for the inconvenience!");
+
+ String message = "";
+ if (sender instanceof GeyserSession) {
+ message = LanguageUtils.getPlayerLocaleString("geyser.commands.reload.message", ((GeyserSession) sender).getClientData().getLanguageCode());
+ } else {
+ message = LanguageUtils.getLocaleStringLog("geyser.commands.reload.message");
+ }
+
+ sender.sendMessage(message);
+
+ for (GeyserSession session : connector.getPlayers()) {
+ session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.commands.reload.kick", session.getClientData().getLanguageCode()));
}
connector.reload();
}
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
index 2222cdef5..636058a02 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
@@ -25,7 +25,7 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.common.PlatformType;
+import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java
new file mode 100644
index 000000000..7dd59712a
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019-2020 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.command.defaults;
+
+import com.github.steveice10.mc.protocol.MinecraftConstants;
+import org.geysermc.connector.GeyserConnector;
+import org.geysermc.connector.command.CommandSender;
+import org.geysermc.connector.command.GeyserCommand;
+import org.geysermc.connector.utils.FileUtils;
+import org.geysermc.connector.utils.LanguageUtils;
+import org.geysermc.connector.utils.WebUtils;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+public class VersionCommand extends GeyserCommand {
+
+ public GeyserConnector connector;
+
+ public VersionCommand(GeyserConnector connector, String name, String description, String permission) {
+ super(name, description, permission);
+ this.connector = connector;
+ }
+
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.version", GeyserConnector.NAME, GeyserConnector.VERSION, MinecraftConstants.GAME_VERSION, GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()));
+
+ // Disable update checking in dev mode
+ //noinspection ConstantConditions - changes in production
+ if (!GeyserConnector.VERSION.equals("DEV")) {
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.checking"));
+ try {
+ Properties gitProp = new Properties();
+ gitProp.load(FileUtils.getResource("git.properties"));
+
+ String buildXML = WebUtils.getBody("https://ci.nukkitx.com/job/GeyserMC/job/Geyser/job/" + URLEncoder.encode(gitProp.getProperty("git.branch"), StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
+ if (buildXML.startsWith("")) {
+ int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim());
+ int buildNum = Integer.parseInt(gitProp.getProperty("git.build.number"));
+ if (latestBuildNum != buildNum) {
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.no_updates"));
+ } else {
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.outdated", (latestBuildNum - buildNum), "http://ci.geysermc.org/"));
+ }
+ } else {
+ throw new AssertionError("buildNumber missing");
+ }
+ } catch (IOException | AssertionError | NumberFormatException e) {
+ GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.version.failed"), e);
+ sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.failed"));
+ }
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/common/AuthType.java b/connector/src/main/java/org/geysermc/connector/common/AuthType.java
new file mode 100644
index 000000000..f15e3ff58
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/common/AuthType.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019-2020 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.common;
+
+import lombok.Getter;
+
+@Getter
+public enum AuthType {
+ OFFLINE,
+ ONLINE,
+ FLOODGATE;
+
+ public static final AuthType[] VALUES = values();
+
+ public static AuthType getById(int id) {
+ return id < VALUES.length ? VALUES[id] : OFFLINE;
+ }
+
+ /**
+ * Convert the AuthType string (from config) to the enum, OFFLINE on fail
+ *
+ * @param name AuthType string
+ *
+ * @return The converted AuthType
+ */
+ public static AuthType getByName(String name) {
+ String upperCase = name.toUpperCase();
+ for (AuthType type : VALUES) {
+ if (type.name().equals(upperCase)) {
+ return type;
+ }
+ }
+ return OFFLINE;
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/org/geysermc/common/ChatColor.java b/connector/src/main/java/org/geysermc/connector/common/ChatColor.java
similarity index 75%
rename from common/src/main/java/org/geysermc/common/ChatColor.java
rename to connector/src/main/java/org/geysermc/connector/common/ChatColor.java
index 8868b063c..1397f88cf 100644
--- a/common/src/main/java/org/geysermc/common/ChatColor.java
+++ b/connector/src/main/java/org/geysermc/connector/common/ChatColor.java
@@ -1,29 +1,30 @@
/*
* Copyright (c) 2019-2020 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:
+ * 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 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.
+ * 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
*
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.common;
+package org.geysermc.connector.common;
public class ChatColor {
diff --git a/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java b/connector/src/main/java/org/geysermc/connector/common/PlatformType.java
similarity index 75%
rename from common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java
rename to connector/src/main/java/org/geysermc/connector/common/PlatformType.java
index 40ef6da62..ee68b6d7b 100644
--- a/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java
+++ b/connector/src/main/java/org/geysermc/connector/common/PlatformType.java
@@ -24,25 +24,20 @@
*
*/
-package org.geysermc.common.ping;
+package org.geysermc.connector.common;
-import lombok.Data;
+import lombok.AllArgsConstructor;
import lombok.Getter;
-import java.util.ArrayList;
-import java.util.Collection;
+@Getter
+@AllArgsConstructor
+public enum PlatformType {
-@Data
-public class GeyserPingInfo {
+ BUNGEECORD("BungeeCord"),
+ SPIGOT("Spigot"),
+ SPONGE("Sponge"),
+ STANDALONE("Standalone"),
+ VELOCITY("Velocity");
- public final String motd;
- public final int currentPlayerCount;
- public final int maxPlayerCount;
-
- @Getter
- private Collection players = new ArrayList<>();
-
- public void addPlayer(String username) {
- players.add(username);
- }
+ private String platformName;
}
diff --git a/common/src/main/java/org/geysermc/common/main/IGeyserMain.java b/connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java
similarity index 61%
rename from common/src/main/java/org/geysermc/common/main/IGeyserMain.java
rename to connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java
index 75da4e6b9..a3e99ccb3 100644
--- a/common/src/main/java/org/geysermc/common/main/IGeyserMain.java
+++ b/connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java
@@ -24,28 +24,43 @@
*
*/
-package org.geysermc.common.main;
+package org.geysermc.connector.common.main;
import javax.swing.*;
import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.Locale;
import java.util.Scanner;
public class IGeyserMain {
+ /**
+ * Displays the run help message in the console and a message box if running with a gui
+ */
public void displayMessage() {
String message = createMessage();
- if (System.console() == null) {
+ if (System.console() == null && !isHeadless()) {
JOptionPane.showMessageDialog(null, message, "GeyserMC Plugin: " + this.getPluginType(), JOptionPane.ERROR_MESSAGE);
}
printMessage(message);
}
+ /**
+ * Load and format the run help text
+ *
+ * @return The formatted message
+ */
private String createMessage() {
String message = "";
- InputStream helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("help.txt");
+ InputStream helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/" + Locale.getDefault().toString() + ".txt");
+
+ if (helpStream == null) {
+ helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/en_US.txt");
+ }
+
Scanner help = new Scanner(helpStream).useDelimiter("\\Z");
String line = "";
while (help.hasNext()) {
@@ -60,14 +75,44 @@ public class IGeyserMain {
return message;
}
+ /**
+ * Check if we are in a headless environment
+ *
+ * @return Are we in a headless environment?
+ */
+ private boolean isHeadless() {
+ try {
+ Class> graphicsEnvironment = Class.forName("java.awt.GraphicsEnvironment");
+ Method isHeadless = graphicsEnvironment.getDeclaredMethod("isHeadless");
+ return (Boolean)isHeadless.invoke(null);
+ } catch (Exception ex) { }
+
+ return true;
+ }
+
+ /**
+ * Simply print a message to console
+ *
+ * @param message The message to print
+ */
private void printMessage(String message) {
System.out.print(message);
}
+ /**
+ * Get the platform the plugin is for
+ *
+ * @return The string representation of the plugin platforms name
+ */
public String getPluginType() {
return "unknown";
}
+ /**
+ * Get the folder name the plugin should go into
+ *
+ * @return The string representation of the folder
+ */
public String getPluginFolder() {
return "unknown";
}
diff --git a/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java b/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java
new file mode 100644
index 000000000..246a3c6e3
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019-2020 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.common.ping;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class GeyserPingInfo {
+
+ private String description;
+
+ private Players players;
+ private Version version;
+
+ @JsonIgnore
+ private Collection playerList = new ArrayList<>();
+
+ public GeyserPingInfo() {
+ }
+
+ public GeyserPingInfo(String description, Players players, Version version) {
+ this.description = description;
+ this.players = players;
+ this.version = version;
+ }
+
+ @JsonSetter("description")
+ void setDescription(JsonNode description) {
+ this.description = description.toString();
+ }
+
+ @Data
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class Players {
+
+ private int max;
+ private int online;
+
+ public Players() {
+ }
+
+ public Players(int max, int online) {
+ this.max = max;
+ this.online = online;
+ }
+ }
+
+ @Data
+ public static class Version {
+
+ private String name;
+ private int protocol;
+
+ public Version() {
+ }
+
+ public Version(String name, int protocol) {
+ this.name = name;
+ this.protocol = protocol;
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java b/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java
new file mode 100644
index 000000000..3fac2e08a
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019-2020 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.common.serializer;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Optional;
+
+public class AsteriskSerializer extends StdSerializer