Skip to content

Commit

Permalink
Implement update notifications for Geyser
Browse files Browse the repository at this point in the history
Geyser installations will now get notified when a new Bedrock release is out and Geyser must be updated. The system works similarly to ViaVersion where OPs get a notification of an update when they join. The permission node for players to see update notifications is `geyser.update` and the backing JSON that controls this can be found at https://github.com/GeyserMC/GeyserSite/blob/gh-pages/versions.json. There is also a config option to disable update checking.

This update also fixes modern Paper installations not being able to see colored text logged from Geyser in the console.
  • Loading branch information
Camotoy committed Aug 22, 2022
1 parent a3b1cf6 commit 67a65c4
Show file tree
Hide file tree
Showing 26 changed files with 558 additions and 34 deletions.
6 changes: 6 additions & 0 deletions bootstrap/bungeecord/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
<version>a7c6ede</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-bungeecord</artifactId>
<version>${adventure-platform.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>${outputName}-BungeeCord</finalName>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public void onEnable() {
}

this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(geyser));

this.getProxy().getPluginManager().registerListener(this, new GeyserBungeeUpdateListener());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.platform.bungeecord;

import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSender;
import org.geysermc.geyser.util.VersionCheckUtils;

public final class GeyserBungeeUpdateListener implements Listener {

@EventHandler
public void onPlayerJoin(final PostLoginEvent event) {
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
final ProxiedPlayer player = event.getPlayer();
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSender(player));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@

package org.geysermc.geyser.platform.bungeecord.command;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.geysermc.geyser.command.CommandSender;
import org.geysermc.geyser.text.GeyserLocale;

import java.util.Locale;

public class BungeeCommandSender implements CommandSender {

private final net.md_5.bungee.api.CommandSender handle;
Expand All @@ -50,6 +54,18 @@ public void sendMessage(String message) {
handle.sendMessage(TextComponent.fromLegacyText(message));
}

private static final int PROTOCOL_HEX_COLOR = 713; // Added 20w17a

@Override
public void sendMessage(Component message) {
if (handle instanceof ProxiedPlayer player && player.getPendingConnection().getVersion() >= PROTOCOL_HEX_COLOR) {
// Include hex colors
handle.sendMessage(BungeeComponentSerializer.get().serialize(message));
return;
}
handle.sendMessage(BungeeComponentSerializer.legacy().serialize(message));
}

@Override
public boolean isConsole() {
return !(handle instanceof ProxiedPlayer);
Expand All @@ -58,8 +74,11 @@ public boolean isConsole() {
@Override
public String getLocale() {
if (handle instanceof ProxiedPlayer player) {
String locale = player.getLocale().getLanguage() + "_" + player.getLocale().getCountry();
return GeyserLocale.formatLocale(locale);
Locale locale = player.getLocale();
if (locale != null) {
// Locale can be null early on in the conneciton
return GeyserLocale.formatLocale(locale.getLanguage() + "_" + locale.getCountry());
}
}
return GeyserLocale.getDefaultLocale();
}
Expand Down
4 changes: 4 additions & 0 deletions bootstrap/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<artifactId>bootstrap-parent</artifactId>
<packaging>pom</packaging>

<properties>
<adventure-platform.version>4.1.2</adventure-platform.version>
</properties>

<repositories>
<repository>
<id>spigot-public</id>
Expand Down
11 changes: 10 additions & 1 deletion bootstrap/spigot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@
<dependency>
<groupId>me.lucko</groupId>
<artifactId>commodore</artifactId>
<version>1.13</version>
<version>2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-bungeecord</artifactId>
<version>${adventure-platform.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand Down Expand Up @@ -107,6 +113,9 @@
<relocation>
<pattern>net.kyori</pattern>
<shadedPattern>org.geysermc.geyser.platform.spigot.shaded.kyori</shadedPattern>
<excludes>
<exclude>net.kyori.adventure.text.logger.slf4j.ComponentLogger</exclude>
</excludes>
</relocation>
<relocation>
<pattern>org.objectweb.asm</pattern>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.platform.spigot;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.plugin.Plugin;

import java.util.logging.Logger;

public final class GeyserPaperLogger extends GeyserSpigotLogger {
private final ComponentLogger componentLogger;

public GeyserPaperLogger(Plugin plugin, Logger logger, boolean debug) {
super(logger, debug);
componentLogger = plugin.getComponentLogger();
}

/**
* Since 1.18.2 this is required so legacy format symbols don't show up in the console for colors
*/
@Override
public void sendMessage(Component message) {
// Done like this so the native component object field isn't relocated
componentLogger.info("{}", PaperAdventure.toNativeComponent(message));
}

static boolean supported() {
try {
Plugin.class.getMethod("getComponentLogger");
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ public void onEnable() {
return;
}

try {
Class.forName("net.md_5.bungee.chat.ComponentSerializer");
} catch (ClassNotFoundException e) {
if (!PaperAdventure.canSendMessageUsingComponent()) { // Prepare for Paper eventually removing Bungee chat
getLogger().severe("*********************************************");
getLogger().severe("");
getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName()));
getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper"));
getLogger().severe("");
getLogger().severe("*********************************************");

Bukkit.getPluginManager().disablePlugin(this);
return;
}
}

// By default this should be localhost but may need to be changed in some circumstances
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
geyserConfig.setAutoconfiguredRemote(true);
Expand All @@ -137,7 +153,8 @@ public void onEnable() {
geyserConfig.getBedrock().setPort(Bukkit.getPort());
}

this.geyserLogger = new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
this.geyserLogger = GeyserPaperLogger.supported() ? new GeyserPaperLogger(this, getLogger(), geyserConfig.isDebugMode())
: new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);

// Remove this in like a year
Expand Down Expand Up @@ -266,12 +283,16 @@ public void onEnable() {
GeyserLocale.getLocaleStringLog(command.getDescription()),
command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE));
}
Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION,
"Whether update notifications can be seen", PermissionDefault.OP));

// Events cannot be unregistered - re-registering results in duplicate firings
GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager);
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);

Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);

Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigotUpdateListener(), this);
}

boolean brigadierSupported = CommodoreProvider.isSupported();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.platform.spigot;

import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSender;
import org.geysermc.geyser.util.VersionCheckUtils;

public final class GeyserSpigotUpdateListener implements Listener {

@EventHandler
public void onPlayerJoin(final PlayerJoinEvent event) {
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
final Player player = event.getPlayer();
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new SpigotCommandSender(player));
}
}
}
}

0 comments on commit 67a65c4

Please sign in to comment.