Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-27 08:30:12 +01:00
Merge pull request #3250 from Kas-tle/feature/extensions
Feature/extensions 1.19.21
Dieser Commit ist enthalten in:
Commit
70ebc670bd
@ -2,6 +2,8 @@ val bungeeVersion = "a7c6ede";
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(projects.core)
|
api(projects.core)
|
||||||
|
|
||||||
|
implementation("net.kyori", "adventure-text-serializer-bungeecord", Versions.adventurePlatformVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
platformRelocate("net.md_5.bungee.jni")
|
platformRelocate("net.md_5.bungee.jni")
|
||||||
|
@ -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.BungeeCommandSource;
|
||||||
|
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 BungeeCommandSource(player));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,11 +25,15 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.platform.bungeecord.command;
|
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.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class BungeeCommandSource implements GeyserCommandSource {
|
public class BungeeCommandSource implements GeyserCommandSource {
|
||||||
|
|
||||||
private final net.md_5.bungee.api.CommandSender handle;
|
private final net.md_5.bungee.api.CommandSender handle;
|
||||||
@ -50,6 +54,18 @@ public class BungeeCommandSource implements GeyserCommandSource {
|
|||||||
handle.sendMessage(TextComponent.fromLegacyText(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
|
@Override
|
||||||
public boolean isConsole() {
|
public boolean isConsole() {
|
||||||
return !(handle instanceof ProxiedPlayer);
|
return !(handle instanceof ProxiedPlayer);
|
||||||
@ -58,8 +74,11 @@ public class BungeeCommandSource implements GeyserCommandSource {
|
|||||||
@Override
|
@Override
|
||||||
public String locale() {
|
public String locale() {
|
||||||
if (handle instanceof ProxiedPlayer player) {
|
if (handle instanceof ProxiedPlayer player) {
|
||||||
String locale = player.getLocale().getLanguage() + "_" + player.getLocale().getCountry();
|
Locale locale = player.getLocale();
|
||||||
return GeyserLocale.formatLocale(locale);
|
if (locale != null) {
|
||||||
|
// Locale can be null early on in the conneciton
|
||||||
|
return GeyserLocale.formatLocale(locale.getLanguage() + "_" + locale.getCountry());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return GeyserLocale.getDefaultLocale();
|
return GeyserLocale.getDefaultLocale();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
val paperVersion = "1.19-R0.1-SNAPSHOT"
|
val paperVersion = "1.19-R0.1-SNAPSHOT"
|
||||||
val viaVersion = "4.0.0"
|
val viaVersion = "4.0.0"
|
||||||
val adaptersVersion = "1.5-SNAPSHOT"
|
val adaptersVersion = "1.5-SNAPSHOT"
|
||||||
val commodoreVersion = "1.13"
|
val commodoreVersion = "2.2"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(projects.core)
|
api(projects.core)
|
||||||
@ -10,6 +10,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation("me.lucko", "commodore", commodoreVersion)
|
implementation("me.lucko", "commodore", commodoreVersion)
|
||||||
|
|
||||||
|
implementation("net.kyori", "adventure-text-serializer-bungeecord", Versions.adventurePlatformVersion)
|
||||||
|
|
||||||
// Both paper-api and paper-mojangapi only provide Java 17 versions for 1.19
|
// Both paper-api and paper-mojangapi only provide Java 17 versions for 1.19
|
||||||
compileOnly("io.papermc.paper", "paper-api", paperVersion) {
|
compileOnly("io.papermc.paper", "paper-api", paperVersion) {
|
||||||
attributes {
|
attributes {
|
||||||
@ -25,7 +27,8 @@ dependencies {
|
|||||||
|
|
||||||
platformRelocate("it.unimi.dsi.fastutil")
|
platformRelocate("it.unimi.dsi.fastutil")
|
||||||
platformRelocate("com.fasterxml.jackson")
|
platformRelocate("com.fasterxml.jackson")
|
||||||
platformRelocate("net.kyori")
|
// Relocate net.kyori but exclude the component logger
|
||||||
|
platformRelocate("net.kyori", "net.kyori.adventure.text.logger.slf4j.ComponentLogger")
|
||||||
platformRelocate("org.objectweb.asm")
|
platformRelocate("org.objectweb.asm")
|
||||||
platformRelocate("me.lucko.commodore")
|
platformRelocate("me.lucko.commodore")
|
||||||
platformRelocate("io.netty.channel.kqueue")
|
platformRelocate("io.netty.channel.kqueue")
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -123,6 +123,22 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
return;
|
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
|
// By default this should be localhost but may need to be changed in some circumstances
|
||||||
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
|
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
|
||||||
geyserConfig.setAutoconfiguredRemote(true);
|
geyserConfig.setAutoconfiguredRemote(true);
|
||||||
@ -137,7 +153,8 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
geyserConfig.getBedrock().setPort(Bukkit.getPort());
|
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);
|
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||||
|
|
||||||
// Remove this in like a year
|
// Remove this in like a year
|
||||||
@ -269,12 +286,16 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
GeyserLocale.getLocaleStringLog(command.description()),
|
GeyserLocale.getLocaleStringLog(command.description()),
|
||||||
command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE));
|
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
|
// Events cannot be unregistered - re-registering results in duplicate firings
|
||||||
GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager);
|
GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager);
|
||||||
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);
|
Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this);
|
||||||
|
|
||||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
|
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
|
||||||
|
|
||||||
|
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigotUpdateListener(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean brigadierSupported = CommodoreProvider.isSupported();
|
boolean brigadierSupported = CommodoreProvider.isSupported();
|
||||||
|
@ -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.SpigotCommandSource;
|
||||||
|
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 SpigotCommandSource(player));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.github.steveice10.mc.protocol.data.DefaultComponentSerializer;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for converting our shaded Adventure into the Adventure bundled in Paper.
|
||||||
|
*
|
||||||
|
* Code mostly taken from https://github.com/KyoriPowered/adventure-platform/blob/94d5821f2e755170f42bd8a5fe1d5bf6f66d04ad/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/PaperFacet.java#L46
|
||||||
|
* and the MinecraftReflection class.
|
||||||
|
*/
|
||||||
|
public final class PaperAdventure {
|
||||||
|
private static final MethodHandle NATIVE_GSON_COMPONENT_SERIALIZER_DESERIALIZE_METHOD_BOUND;
|
||||||
|
private static final Method SEND_MESSAGE_COMPONENT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||||
|
|
||||||
|
MethodHandle nativeGsonComponentSerializerDeserializeMethodBound = null;
|
||||||
|
|
||||||
|
// String.join because otherwise the class name will be relocated
|
||||||
|
final Class<?> nativeGsonComponentSerializerClass = findClass(String.join(".",
|
||||||
|
"net", "kyori", "adventure", "text", "serializer", "gson", "GsonComponentSerializer"));
|
||||||
|
final Class<?> nativeGsonComponentSerializerImplClass = findClass(String.join(".",
|
||||||
|
"net", "kyori", "adventure", "text", "serializer", "gson", "GsonComponentSerializerImpl"));
|
||||||
|
if (nativeGsonComponentSerializerClass != null && nativeGsonComponentSerializerImplClass != null) {
|
||||||
|
MethodHandle nativeGsonComponentSerializerGsonGetter = null;
|
||||||
|
try {
|
||||||
|
nativeGsonComponentSerializerGsonGetter = lookup.findStatic(nativeGsonComponentSerializerClass,
|
||||||
|
"gson", MethodType.methodType(nativeGsonComponentSerializerClass));
|
||||||
|
} catch (final NoSuchMethodException | IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandle nativeGsonComponentSerializerDeserializeMethod = null;
|
||||||
|
try {
|
||||||
|
final Method method = nativeGsonComponentSerializerImplClass.getDeclaredMethod("deserialize", String.class);
|
||||||
|
method.setAccessible(true);
|
||||||
|
nativeGsonComponentSerializerDeserializeMethod = lookup.unreflect(method);
|
||||||
|
} catch (final NoSuchMethodException | IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeGsonComponentSerializerGsonGetter != null) {
|
||||||
|
if (nativeGsonComponentSerializerDeserializeMethod != null) {
|
||||||
|
try {
|
||||||
|
nativeGsonComponentSerializerDeserializeMethodBound = nativeGsonComponentSerializerDeserializeMethod
|
||||||
|
.bindTo(nativeGsonComponentSerializerGsonGetter.invoke());
|
||||||
|
} catch (final Throwable throwable) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Failed to access native GsonComponentSerializer", throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NATIVE_GSON_COMPONENT_SERIALIZER_DESERIALIZE_METHOD_BOUND = nativeGsonComponentSerializerDeserializeMethodBound;
|
||||||
|
|
||||||
|
Method playerComponentSendMessage = null;
|
||||||
|
final Class<?> nativeComponentClass = findClass(String.join(".",
|
||||||
|
"net", "kyori", "adventure", "text", "Component"));
|
||||||
|
if (nativeComponentClass != null) {
|
||||||
|
try {
|
||||||
|
playerComponentSendMessage = CommandSender.class.getMethod("sendMessage", nativeComponentClass);
|
||||||
|
} catch (final NoSuchMethodException e) {
|
||||||
|
if (GeyserImpl.getInstance().getLogger().isDebug()) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SEND_MESSAGE_COMPONENT = playerComponentSendMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object toNativeComponent(final Component component) {
|
||||||
|
if (NATIVE_GSON_COMPONENT_SERIALIZER_DESERIALIZE_METHOD_BOUND == null) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Illegal state where Component serialization was called when it wasn't available!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return NATIVE_GSON_COMPONENT_SERIALIZER_DESERIALIZE_METHOD_BOUND.invoke(DefaultComponentSerializer.get().serialize(component));
|
||||||
|
} catch (final Throwable throwable) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Failed to create native Component message", throwable);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendMessage(final CommandSender sender, final Component component) {
|
||||||
|
if (SEND_MESSAGE_COMPONENT == null) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Illegal state where Component sendMessage was called when it wasn't available!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object nativeComponent = toNativeComponent(component);
|
||||||
|
if (nativeComponent != null) {
|
||||||
|
try {
|
||||||
|
SEND_MESSAGE_COMPONENT.invoke(sender, nativeComponent);
|
||||||
|
} catch (final InvocationTargetException | IllegalAccessException e) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Failed to send native Component message", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canSendMessageUsingComponent() {
|
||||||
|
return SEND_MESSAGE_COMPONENT != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a class by the first name available.
|
||||||
|
*
|
||||||
|
* @return a class or {@code null} if not found
|
||||||
|
*/
|
||||||
|
private static @Nullable Class<?> findClass(final String className) {
|
||||||
|
try {
|
||||||
|
return Class.forName(className);
|
||||||
|
} catch (final ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PaperAdventure() {
|
||||||
|
}
|
||||||
|
}
|
@ -25,10 +25,13 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.platform.spigot.command;
|
package org.geysermc.geyser.platform.spigot.command;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
|
import org.geysermc.geyser.platform.spigot.PaperAdventure;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -63,6 +66,16 @@ public class SpigotCommandSource implements GeyserCommandSource {
|
|||||||
handle.sendMessage(message);
|
handle.sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Component message) {
|
||||||
|
if (PaperAdventure.canSendMessageUsingComponent()) {
|
||||||
|
PaperAdventure.sendMessage(handle, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.sendMessage(BungeeComponentSerializer.get().serialize(message));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConsole() {
|
public boolean isConsole() {
|
||||||
return handle instanceof ConsoleCommandSender;
|
return handle instanceof ConsoleCommandSender;
|
||||||
|
@ -95,24 +95,4 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
|
|||||||
public boolean isDebug() {
|
public boolean isDebug() {
|
||||||
return log.isDebugEnabled();
|
return log.isDebugEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return "CONSOLE";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(String message) {
|
|
||||||
info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConsole() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(String permission) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,8 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||||||
} else {
|
} else {
|
||||||
this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer);
|
this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
|
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import org.geysermc.geyser.Constants;
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.platform.velocity.command.VelocityCommandSource;
|
||||||
|
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||||
|
|
||||||
|
public final class GeyserVelocityUpdateListener {
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onPlayerJoin(PostLoginEvent event) {
|
||||||
|
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
|
||||||
|
final Player player = event.getPlayer();
|
||||||
|
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
||||||
|
VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.platform.velocity.command;
|
|||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.proxy.ConsoleCommandSource;
|
import com.velocitypowered.api.proxy.ConsoleCommandSource;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
@ -59,6 +60,12 @@ public class VelocityCommandSource implements GeyserCommandSource {
|
|||||||
handle.sendMessage(LegacyComponentSerializer.legacy('§').deserialize(message));
|
handle.sendMessage(LegacyComponentSerializer.legacy('§').deserialize(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Component message) {
|
||||||
|
// Be careful that we don't shade in Adventure!!
|
||||||
|
handle.sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConsole() {
|
public boolean isConsole() {
|
||||||
return handle instanceof ConsoleCommandSource;
|
return handle instanceof ConsoleCommandSource;
|
||||||
|
@ -39,6 +39,7 @@ object Versions {
|
|||||||
const val mcprotocollibversion = "9f78bd5"
|
const val mcprotocollibversion = "9f78bd5"
|
||||||
const val packetlibVersion = "3.0"
|
const val packetlibVersion = "3.0"
|
||||||
const val adventureVersion = "4.9.3"
|
const val adventureVersion = "4.9.3"
|
||||||
|
const val adventurePlatformVersion = "4.1.2"
|
||||||
const val junitVersion = "4.13.1"
|
const val junitVersion = "4.13.1"
|
||||||
const val checkerQualVersion = "3.19.0"
|
const val checkerQualVersion = "3.19.0"
|
||||||
const val cumulusVersion = "1.1.1"
|
const val cumulusVersion = "1.1.1"
|
||||||
|
@ -43,9 +43,11 @@ fun Project.exclude(group: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Project.platformRelocate(pattern: String) {
|
fun Project.platformRelocate(pattern: String, exclusion: String = "") {
|
||||||
tasks.named<ShadowJar>("shadowJar") {
|
tasks.named<ShadowJar>("shadowJar") {
|
||||||
relocate(pattern, "org.geysermc.geyser.platform.${project.name}.shaded.$pattern")
|
relocate(pattern, "org.geysermc.geyser.platform.${project.name}.shaded.$pattern") {
|
||||||
|
exclude(exclusion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,9 @@ public final class Constants {
|
|||||||
|
|
||||||
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/";
|
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/";
|
||||||
|
|
||||||
|
public static final String GEYSER_DOWNLOAD_LOCATION = "https://ci.geysermc.org";
|
||||||
|
public static final String UPDATE_PERMISSION = "geyser.update";
|
||||||
|
|
||||||
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
|
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -41,6 +41,8 @@ import io.netty.util.internal.SystemPropertyUtil;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -77,7 +79,6 @@ import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
|
|||||||
import org.geysermc.geyser.session.SessionManager;
|
import org.geysermc.geyser.session.SessionManager;
|
||||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||||
import org.geysermc.geyser.skin.SkinProvider;
|
import org.geysermc.geyser.skin.SkinProvider;
|
||||||
import org.geysermc.geyser.text.ChatColor;
|
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.text.MinecraftLocale;
|
import org.geysermc.geyser.text.MinecraftLocale;
|
||||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||||
@ -312,8 +313,8 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
int port = config.getBedrock().port();
|
int port = config.getBedrock().port();
|
||||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
|
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
|
||||||
if (!"0.0.0.0".equals(address)) {
|
if (!"0.0.0.0".equals(address)) {
|
||||||
logger.info(ChatColor.GREEN + "Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0");
|
logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN));
|
||||||
logger.info(ChatColor.GREEN + "Then, restart this server.");
|
logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).join();
|
}).join();
|
||||||
@ -465,6 +466,9 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED);
|
newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED);
|
||||||
|
|
||||||
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
||||||
|
if (config.isNotifyOnNewBedrockUpdate()) {
|
||||||
|
VersionCheckUtils.checkForGeyserUpdate(this::getLogger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,9 +25,12 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser;
|
package org.geysermc.geyser;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public interface GeyserLogger {
|
public interface GeyserLogger extends GeyserCommandSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a severe message to console
|
* Logs a severe message to console
|
||||||
@ -73,6 +76,15 @@ public interface GeyserLogger {
|
|||||||
*/
|
*/
|
||||||
void info(String message);
|
void info(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an info component to console
|
||||||
|
*
|
||||||
|
* @param message the message to log
|
||||||
|
*/
|
||||||
|
default void info(Component message) {
|
||||||
|
sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a debug message to console
|
* Logs a debug message to console
|
||||||
*
|
*
|
||||||
@ -100,4 +112,24 @@ public interface GeyserLogger {
|
|||||||
* If debug is enabled for this logger
|
* If debug is enabled for this logger
|
||||||
*/
|
*/
|
||||||
boolean isDebug();
|
boolean isDebug();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default String name() {
|
||||||
|
return "CONSOLE";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void sendMessage(String message) {
|
||||||
|
info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isConsole() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean hasPermission(String permission) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ package org.geysermc.geyser.command;
|
|||||||
|
|
||||||
import org.geysermc.geyser.api.command.CommandSource;
|
import org.geysermc.geyser.api.command.CommandSource;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implemented on top of any class that can send a command.
|
* Implemented on top of any class that can send a command.
|
||||||
@ -40,4 +42,8 @@ public interface GeyserCommandSource extends CommandSource {
|
|||||||
default String locale() {
|
default String locale() {
|
||||||
return GeyserLocale.getDefaultLocale();
|
return GeyserLocale.getDefaultLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void sendMessage(Component message) {
|
||||||
|
sendMessage(LegacyComponentSerializer.legacySection().serialize(message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,8 @@ public interface GeyserConfiguration {
|
|||||||
|
|
||||||
int getCustomSkullRenderDistance();
|
int getCustomSkullRenderDistance();
|
||||||
|
|
||||||
|
boolean isNotifyOnNewBedrockUpdate();
|
||||||
|
|
||||||
IMetricsInfo getMetrics();
|
IMetricsInfo getMetrics();
|
||||||
|
|
||||||
int getPendingAuthenticationTimeout();
|
int getPendingAuthenticationTimeout();
|
||||||
|
@ -148,6 +148,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||||||
@JsonProperty("xbox-achievements-enabled")
|
@JsonProperty("xbox-achievements-enabled")
|
||||||
private boolean xboxAchievementsEnabled = false;
|
private boolean xboxAchievementsEnabled = false;
|
||||||
|
|
||||||
|
@JsonProperty("notify-on-new-bedrock-update")
|
||||||
|
private boolean notifyOnNewBedrockUpdate = true;
|
||||||
|
|
||||||
private MetricsInfo metrics = new MetricsInfo();
|
private MetricsInfo metrics = new MetricsInfo();
|
||||||
|
|
||||||
@JsonProperty("pending-authentication-timeout")
|
@JsonProperty("pending-authentication-timeout")
|
||||||
|
@ -106,6 +106,9 @@ public class LivingEntity extends Entity {
|
|||||||
|
|
||||||
// Riptide spin attack
|
// Riptide spin attack
|
||||||
setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
|
setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
|
||||||
|
|
||||||
|
// OptionalPack usage
|
||||||
|
setFlag(EntityFlag.EMERGING, isUsingItem && isUsingOffhand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHealth(FloatEntityMetadata entityMetadata) {
|
public void setHealth(FloatEntityMetadata entityMetadata) {
|
||||||
|
@ -45,7 +45,10 @@ public final class GameProtocol {
|
|||||||
* Default Bedrock codec that should act as a fallback. Should represent the latest available
|
* Default Bedrock codec that should act as a fallback. Should represent the latest available
|
||||||
* release of the game that Geyser supports.
|
* release of the game that Geyser supports.
|
||||||
*/
|
*/
|
||||||
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v544.V544_CODEC;
|
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v544.V544_CODEC.toBuilder()
|
||||||
|
.minecraftVersion("1.19.21")
|
||||||
|
.protocolVersion(545)
|
||||||
|
.build();
|
||||||
/**
|
/**
|
||||||
* A list of all supported Bedrock versions that can join Geyser
|
* A list of all supported Bedrock versions that can join Geyser
|
||||||
*/
|
*/
|
||||||
@ -64,6 +67,7 @@ public final class GameProtocol {
|
|||||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v534.V534_CODEC.toBuilder()
|
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v534.V534_CODEC.toBuilder()
|
||||||
.minecraftVersion("1.19.10/1.19.11")
|
.minecraftVersion("1.19.10/1.19.11")
|
||||||
.build());
|
.build());
|
||||||
|
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v544.V544_CODEC);
|
||||||
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
|
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
import org.geysermc.geyser.scoreboard.Scoreboard;
|
import org.geysermc.geyser.scoreboard.Scoreboard;
|
||||||
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
|
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
@ -54,6 +54,7 @@ import org.geysermc.geyser.inventory.Inventory;
|
|||||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||||
import org.geysermc.geyser.inventory.click.Click;
|
import org.geysermc.geyser.inventory.click.Click;
|
||||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||||
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||||
@ -62,10 +63,7 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
|||||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
import org.geysermc.geyser.util.BlockUtils;
|
import org.geysermc.geyser.util.*;
|
||||||
import org.geysermc.geyser.util.EntityUtils;
|
|
||||||
import org.geysermc.geyser.util.InteractionResult;
|
|
||||||
import org.geysermc.geyser.util.InventoryUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -468,6 +466,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||||||
ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entityId,
|
ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(entityId,
|
||||||
InteractAction.ATTACK, session.isSneaking());
|
InteractAction.ATTACK, session.isSneaking());
|
||||||
session.sendDownstreamPacket(attackPacket);
|
session.sendDownstreamPacket(attackPacket);
|
||||||
|
|
||||||
|
if (GameProtocol.supports1_19_10(session)) {
|
||||||
|
// Since 1.19.10, LevelSoundEventPackets are no longer sent by the client when attacking entities
|
||||||
|
CooldownUtils.sendCooldown(session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -31,7 +31,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server
|
|||||||
import com.github.steveice10.packetlib.packet.Packet;
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
import com.nukkitx.math.vector.Vector3d;
|
import com.nukkitx.math.vector.Vector3d;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
|
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
|
||||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||||
@ -49,17 +48,6 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
|
|||||||
SessionPlayerEntity entity = session.getPlayerEntity();
|
SessionPlayerEntity entity = session.getPlayerEntity();
|
||||||
if (!session.isSpawned()) return;
|
if (!session.isSpawned()) return;
|
||||||
|
|
||||||
if (!session.getUpstream().isInitialized()) {
|
|
||||||
MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket();
|
|
||||||
moveEntityBack.setRuntimeEntityId(entity.getGeyserId());
|
|
||||||
moveEntityBack.setPosition(entity.getPosition());
|
|
||||||
moveEntityBack.setRotation(entity.getBedrockRotation());
|
|
||||||
moveEntityBack.setTeleported(true);
|
|
||||||
moveEntityBack.setOnGround(true);
|
|
||||||
session.sendUpstreamPacketImmediately(moveEntityBack);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
session.setLastMovementTimestamp(System.currentTimeMillis());
|
session.setLastMovementTimestamp(System.currentTimeMillis());
|
||||||
|
|
||||||
// Send book update before the player moves
|
// Send book update before the player moves
|
||||||
|
@ -25,10 +25,22 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.util;
|
package org.geysermc.geyser.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TextReplacementConfig;
|
||||||
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import org.geysermc.geyser.Constants;
|
import org.geysermc.geyser.Constants;
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.GeyserLogger;
|
import org.geysermc.geyser.GeyserLogger;
|
||||||
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public final class VersionCheckUtils {
|
public final class VersionCheckUtils {
|
||||||
|
|
||||||
public static void checkForOutdatedFloodgate(GeyserLogger logger) {
|
public static void checkForOutdatedFloodgate(GeyserLogger logger) {
|
||||||
@ -42,6 +54,41 @@ public final class VersionCheckUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void checkForGeyserUpdate(Supplier<GeyserCommandSource> recipient) {
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
JsonNode json = WebUtils.getJson("https://api.geysermc.org/v2/versions/geyser");
|
||||||
|
JsonNode bedrock = json.get("bedrock").get("protocol");
|
||||||
|
int protocolVersion = bedrock.get("id").asInt();
|
||||||
|
if (GameProtocol.getBedrockCodec(protocolVersion) != null) {
|
||||||
|
// We support the latest version! No need to print a message.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String newBedrockVersion = bedrock.get("name").asText();
|
||||||
|
|
||||||
|
// Delayed for two reasons: save unnecessary processing, and wait to load locale if this is on join.
|
||||||
|
GeyserCommandSource sender = recipient.get();
|
||||||
|
|
||||||
|
// Overarching component is green - geyser.version.new component cannot be green or else the link blue is overshadowed
|
||||||
|
Component message = Component.text().color(NamedTextColor.GREEN)
|
||||||
|
.append(Component.text(GeyserLocale.getPlayerLocaleString("geyser.version.new", sender.locale(), newBedrockVersion))
|
||||||
|
.replaceText(TextReplacementConfig.builder()
|
||||||
|
.match("\\{1\\}") // Replace "Download here: {1}" so we can use fancy text component yesyes
|
||||||
|
.replacement(Component.text()
|
||||||
|
.content(Constants.GEYSER_DOWNLOAD_LOCATION)
|
||||||
|
.color(NamedTextColor.BLUE)
|
||||||
|
.decoration(TextDecoration.UNDERLINED, TextDecoration.State.TRUE)
|
||||||
|
.clickEvent(ClickEvent.openUrl(Constants.GEYSER_DOWNLOAD_LOCATION)))
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
sender.sendMessage(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Error whilst checking for Geyser update!", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private VersionCheckUtils() {
|
private VersionCheckUtils() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,8 @@ public class WebUtils {
|
|||||||
public static JsonNode getJson(String reqURL) throws IOException {
|
public static JsonNode getJson(String reqURL) throws IOException {
|
||||||
HttpURLConnection con = (HttpURLConnection) new URL(reqURL).openConnection();
|
HttpURLConnection con = (HttpURLConnection) new URL(reqURL).openConnection();
|
||||||
con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION);
|
con.setRequestProperty("User-Agent", "Geyser-" + GeyserImpl.getInstance().getPlatformType().toString() + "/" + GeyserImpl.VERSION);
|
||||||
|
con.setConnectTimeout(10000);
|
||||||
|
con.setReadTimeout(10000);
|
||||||
return GeyserImpl.JSON_MAPPER.readTree(con.getInputStream());
|
return GeyserImpl.JSON_MAPPER.readTree(con.getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +175,11 @@ force-resource-packs: true
|
|||||||
# THIS DISABLES ALL COMMANDS FROM SUCCESSFULLY RUNNING FOR BEDROCK IN-GAME, as otherwise Bedrock thinks you are cheating.
|
# THIS DISABLES ALL COMMANDS FROM SUCCESSFULLY RUNNING FOR BEDROCK IN-GAME, as otherwise Bedrock thinks you are cheating.
|
||||||
xbox-achievements-enabled: false
|
xbox-achievements-enabled: false
|
||||||
|
|
||||||
|
# Whether to alert the console and operators that a new Geyser version is available that supports a Bedrock version
|
||||||
|
# that this Geyser version does not support. It's recommended to keep this option enabled, as many Bedrock platforms
|
||||||
|
# auto-update.
|
||||||
|
notify-on-new-bedrock-update: true
|
||||||
|
|
||||||
# bStats is a stat tracker that is entirely anonymous and tracks only basic information
|
# bStats is a stat tracker that is entirely anonymous and tracks only basic information
|
||||||
# about Geyser, such as how many people are online, how many servers are using Geyser,
|
# about Geyser, such as how many people are online, how many servers are using Geyser,
|
||||||
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
|
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren