This commit is contained in:
Camotoy 2022-10-03 13:33:32 -04:00
commit 04883a166a
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
24 changed files with 336 additions and 182 deletions

View file

@ -52,10 +52,8 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
this.plugins = new ArrayList<>();
for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
String hostname;
if (AsteriskSerializer.showSensitive || (listener.getHost().getHostString().equals("") || listener.getHost().getHostString().equals("0.0.0.0"))) {
hostname = listener.getHost().getHostString();
} else {
String hostname = listener.getHost().getHostString();
if (!AsteriskSerializer.showSensitive && !(hostname.equals("") || hostname.equals("0.0.0.0"))) {
hostname = "***";
}
this.listeners.add(new ListenerInfo(hostname, listener.getHost().getPort()));

View file

@ -69,6 +69,9 @@ public class GeyserBungeeCommandExecutor extends Command implements TabExecutor
return;
}
command.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
} else {
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale());
commandSender.sendMessage(ChatColor.RED + message);
}
} else {
this.commandExecutor.getCommand("help").execute(session, commandSender, new String[0]);

View file

@ -51,8 +51,9 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
this.platformVersion = Bukkit.getVersion();
this.platformAPIVersion = Bukkit.getBukkitVersion();
this.onlineMode = Bukkit.getOnlineMode();
if (AsteriskSerializer.showSensitive || (Bukkit.getIp().equals("") || Bukkit.getIp().equals("0.0.0.0"))) {
this.serverIP = Bukkit.getIp();
String ip = Bukkit.getIp();
if (AsteriskSerializer.showSensitive || (ip.equals("") || ip.equals("0.0.0.0"))) {
this.serverIP = ip;
} else {
this.serverIP = "***";
}

View file

@ -66,6 +66,9 @@ public class GeyserSpigotCommandExecutor extends GeyserCommandExecutor implement
}
geyserCommand.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
return true;
} else {
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale());
commandSender.sendMessage(ChatColor.RED + message);
}
} else {
getCommand("help").execute(session, commandSender, new String[0]);

View file

@ -7,13 +7,8 @@ platformRelocate("io.netty")
platformRelocate("it.unimi.dsi.fastutil")
platformRelocate("com.google.common")
platformRelocate("com.google.guava")
platformRelocate("net.kyori")
// Exclude these dependencies
exclude("com.google.code.gson:*")
exclude("org.yaml:*")
exclude("org.slf4j:*")
exclude("org.ow2.asm:*")
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
platformRelocate("net.kyori.adventure.nbt")
// These dependencies are already present on the platform
provided(libs.sponge.api)
@ -30,5 +25,14 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
exclude(dependency("org.yaml:.*"))
exclude(dependency("org.slf4j:.*"))
exclude(dependency("org.ow2.asm:.*"))
// Exclude all Kyori dependencies except the legacy NBT serializer and NBT
exclude(dependency("net.kyori:adventure-api:.*"))
exclude(dependency("net.kyori:examination-api:.*"))
exclude(dependency("net.kyori:examination-string:.*"))
exclude(dependency("net.kyori:adventure-text-serializer-gson:.*"))
exclude(dependency("net.kyori:adventure-text-serializer-legacy:.*"))
exclude(dependency("net.kyori:adventure-text-serializer-plain:.*"))
exclude(dependency("net.kyori:adventure-key:.*"))
}
}

View file

@ -27,12 +27,18 @@ package org.geysermc.geyser.platform.sponge;
import lombok.Getter;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.metadata.PluginMetadata;
import org.spongepowered.plugin.metadata.model.PluginContributor;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Getter
public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
@ -44,18 +50,25 @@ public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
private final List<PluginInfo> 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();
PluginContainer container = Sponge.platform().container(Platform.Component.IMPLEMENTATION);
PluginMetadata platformMeta = container.metadata();
this.platformName = platformMeta.name().orElse("unknown");
this.platformVersion = platformMeta.version().getQualifier();
this.onlineMode = Sponge.server().isOnlineModeEnabled();
Optional<InetSocketAddress> socketAddress = Sponge.server().boundAddress();
String hostString = socketAddress.map(InetSocketAddress::getHostString).orElse("unknown");
if (AsteriskSerializer.showSensitive || (hostString.equals("") || hostString.equals("0.0.0.0") || hostString.equals("unknown"))) {
this.serverIP = hostString;
} else {
this.serverIP = "***";
}
this.serverPort = socketAddress.map(InetSocketAddress::getPort).orElse(-1);
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()));
for (PluginContainer plugin : Sponge.pluginManager().plugins()) {
PluginMetadata meta = plugin.metadata();
List<String> contributors = meta.contributors().stream().map(PluginContributor::name).collect(Collectors.toList());
this.plugins.add(new PluginInfo(true, meta.name().orElse("unknown"), meta.version().toString(), meta.entrypoint(), contributors));
}
}
}

View file

@ -29,7 +29,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import org.slf4j.Logger;
import org.apache.logging.log4j.Logger;
@AllArgsConstructor
public class GeyserSpongeLogger implements GeyserLogger {

View file

@ -28,11 +28,12 @@ package org.geysermc.geyser.platform.sponge;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.ping.GeyserPingInfo;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.spongepowered.api.MinecraftVersion;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.event.EventContext;
import org.spongepowered.api.event.SpongeEventFactory;
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;
@ -43,7 +44,7 @@ import java.util.Optional;
public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.getServer());
private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.server());
private static Method SpongeStatusResponse_create;
@ -59,50 +60,46 @@ public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
SpongeStatusResponse_create = SpongeStatusResponse.getDeclaredMethod("create", MinecraftServer);
}
Object response = SpongeStatusResponse_create.invoke(null, Sponge.getServer());
Object response = SpongeStatusResponse_create.invoke(null, Sponge.server());
event = SpongeEventFactory.createClientPingServerEvent(CAUSE, new GeyserStatusClient(inetSocketAddress), (ClientPingServerEvent.Response) response);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
Sponge.getEventManager().post(event);
Sponge.eventManager().post(event);
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
event.getResponse().getDescription().toPlain(),
MessageTranslator.convertMessage(event.response().description()),
new GeyserPingInfo.Players(
event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax(),
event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline()
event.response().players().orElseThrow(IllegalStateException::new).max(),
event.response().players().orElseThrow(IllegalStateException::new).online()
),
new GeyserPingInfo.Version(
event.getResponse().getVersion().getName(),
event.response().version().name(),
GameProtocol.getJavaProtocolVersion()) // 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);
event.response().players().ifPresent(players -> players.profiles().stream()
.map(GameProfile::name)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(geyserPingInfo.getPlayerList()::add)
);
return geyserPingInfo;
}
@SuppressWarnings("NullableProblems")
private static class GeyserStatusClient implements StatusClient {
private final InetSocketAddress remote;
public GeyserStatusClient(InetSocketAddress remote) {
this.remote = remote;
}
private record GeyserStatusClient(InetSocketAddress remote) implements StatusClient {
@Override
public InetSocketAddress getAddress() {
public InetSocketAddress address() {
return this.remote;
}
@Override
public MinecraftVersion getVersion() {
return Sponge.getPlatform().getMinecraftVersion();
public MinecraftVersion version() {
return Sponge.platform().minecraftVersion();
}
@Override
public Optional<InetSocketAddress> getVirtualHost() {
public Optional<InetSocketAddress> virtualHost() {
return Optional.empty();
}
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.platform.sponge;
import com.google.inject.Inject;
import org.apache.logging.log4j.Logger;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
@ -36,18 +37,23 @@ import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor;
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.FileUtils;
import org.slf4j.Logger;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor;
import org.spongepowered.api.Server;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.game.state.GameStoppedEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.event.lifecycle.ConstructPluginEvent;
import org.spongepowered.api.event.lifecycle.RegisterCommandEvent;
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.builtin.jvm.Plugin;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
@ -55,54 +61,134 @@ import java.nio.file.Path;
import java.util.Map;
import java.util.UUID;
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Sponge", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
@Plugin(value = "geyser")
public class GeyserSpongePlugin implements GeyserBootstrap {
/**
* True if the plugin should be in a disabled state.
* This exists because you can't unregister or disable plugins in Sponge
*/
private boolean enabled = true;
@Inject
private PluginContainer pluginContainer;
@Inject
private Logger logger;
@Inject
@ConfigDir(sharedRoot = false)
private File configDir;
private Path configPath;
private GeyserSpongeCommandManager geyserCommandManager;
// Available after construction lifecycle
private GeyserSpongeConfiguration geyserConfig;
private GeyserSpongeLogger geyserLogger;
private GeyserImpl geyser;
private GeyserSpongeCommandManager geyserCommandManager; // Commands are only registered after command registration lifecycle
// Available after StartedEngine lifecycle
private IGeyserPingPassthrough geyserSpongePingPassthrough;
private GeyserImpl geyser;
public void onLoad() {
/**
* Only to be used for reloading
*/
@Override
public void onEnable() {
enabled = true;
onConstruction(null);
// new commands cannot be registered, and geyser's command manager does not need be reloaded
onStartedEngine(null);
}
@Override
public void onDisable() {
enabled = false;
if (geyser != null) {
geyser.shutdown();
geyser = null;
}
}
/**
* Construct the configuration, logger, and command manager. command manager will only be filled with commands once
* the connector is started, but it allows us to register events in sponge.
*
* @param event Not used.
*/
@Listener
public void onConstruction(@Nullable ConstructPluginEvent event) {
GeyserLocale.init(this);
if (!configDir.exists())
File configDir = configPath.toFile();
if (!configDir.exists()) {
configDir.mkdirs();
}
File configFile;
try {
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml",
(file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpongeConfiguration.class);
} catch (IOException ex) {
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
ex.printStackTrace();
onDisable();
return;
}
try {
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpongeConfiguration.class);
} catch (IOException ex) {
logger.warn(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
ex.printStackTrace();
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode());
this.geyser = GeyserImpl.load(PlatformType.SPONGE, this);
this.geyserCommandManager = new GeyserSpongeCommandManager(geyser);
this.geyserCommandManager.init();
}
/**
* Construct the {@link GeyserSpongeCommandManager} and register the commands
*
* @param event required to register the commands
*/
@Listener
public void onRegisterCommands(@Nonnull RegisterCommandEvent<org.spongepowered.api.command.Command.Raw> event) {
if (enabled) {
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
Map<String, Command> commands = entry.getValue();
if (commands.isEmpty()) {
continue;
}
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id());
}
}
}
/**
* Configure the config properly if remote address is auto. Start connector and ping passthrough, and register subcommands of /geyser
*
* @param event not required
*/
@Listener
public void onStartedEngine(@Nullable StartedEngineEvent<Server> event) {
if (!enabled) {
return;
}
if (Sponge.getServer().getBoundAddress().isPresent()) {
InetSocketAddress javaAddr = Sponge.getServer().getBoundAddress().get();
if (Sponge.server().boundAddress().isPresent()) {
InetSocketAddress javaAddr = Sponge.server().boundAddress().get();
// Don't change the ip if its listening on all interfaces
// By default this should be 127.0.0.1 but may need to be changed in some circumstances
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
this.geyserConfig.setAutoconfiguredRemote(true);
// Don't change the ip if its listening on all interfaces
if (!javaAddr.getHostString().equals("0.0.0.0") && !javaAddr.getHostString().equals("")) {
this.geyserConfig.getRemote().setAddress(javaAddr.getHostString());
}
geyserConfig.getRemote().setPort(javaAddr.getPort());
}
}
@ -111,14 +197,6 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
geyserConfig.getBedrock().setPort(geyserConfig.getRemote().port());
}
this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.SPONGE, this);
}
@Override
public void onEnable() {
GeyserImpl.start();
if (geyserConfig.isLegacyPingPassthrough()) {
@ -126,25 +204,11 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
} else {
this.geyserSpongePingPassthrough = new GeyserSpongePingPassthrough();
}
this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), geyser);
this.geyserCommandManager.init();
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
Map<String, Command> commands = entry.getValue();
if (commands.isEmpty()) {
continue;
}
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id());
}
}
@Override
public void onDisable() {
geyser.shutdown();
@Listener
public void onEngineStopping(StoppingEngineEvent<Server> event) {
onDisable();
}
@Override
@ -159,7 +223,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
@Override
public GeyserCommandManager getGeyserCommandManager() {
return this.geyserCommandManager;
return geyserCommandManager;
}
@Override
@ -169,22 +233,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
@Override
public Path getConfigFolder() {
return configDir.toPath();
}
@Listener
public void onServerStarting() {
onLoad();
}
@Listener
public void onServerStart(GameStartedServerEvent event) {
onEnable();
}
@Listener
public void onServerStop(GameStoppedEvent event) {
onDisable();
return configPath;
}
@Override
@ -194,6 +243,6 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
@Override
public String getMinecraftServerVersion() {
return Sponge.getPlatform().getMinecraftVersion().getName();
return Sponge.platform().minecraftVersion().name();
}
}

View file

@ -25,81 +25,88 @@
package org.geysermc.geyser.platform.sponge.command;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandExecutor;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.spongepowered.api.command.CommandCallable;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.command.CommandCompletion;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import org.spongepowered.api.command.parameter.ArgumentReader;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public class GeyserSpongeCommandExecutor extends GeyserCommandExecutor implements CommandCallable {
public class GeyserSpongeCommandExecutor extends GeyserCommandExecutor implements org.spongepowered.api.command.Command.Raw {
public GeyserSpongeCommandExecutor(GeyserImpl geyser, Map<String, Command> commands) {
super(geyser, commands);
}
@Override
public CommandResult process(CommandSource source, String arguments) {
GeyserCommandSource commandSender = new SpongeCommandSource(source);
GeyserSession session = getGeyserSession(commandSender);
public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) {
GeyserCommandSource commandSource = new SpongeCommandSource(cause);
GeyserSession session = getGeyserSession(commandSource);
String[] args = arguments.split(" ");
if (args.length > 0) {
String[] args = arguments.input().split(" ");
// This split operation results in an array of length 1, containing a zero length string, if the input string is empty
if (args.length > 0 && !args[0].isEmpty()) {
GeyserCommand command = getCommand(args[0]);
if (command != null) {
if (!source.hasPermission(command.permission())) {
// Not ideal to use log here but we dont get a session
source.sendMessage(Text.of(ChatColor.RED + GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")));
if (!cause.hasPermission(command.permission())) {
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")).color(NamedTextColor.RED));
return CommandResult.success();
}
if (command.isBedrockOnly() && session == null) {
source.sendMessage(Text.of(ChatColor.RED + GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")));
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")).color(NamedTextColor.RED));
return CommandResult.success();
}
getCommand(args[0]).execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
command.execute(session, commandSource, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
} else {
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.not_found")).color(NamedTextColor.RED));
}
} else {
getCommand("help").execute(session, commandSender, new String[0]);
getCommand("help").execute(session, commandSource, new String[0]);
}
return CommandResult.success();
}
@Override
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) {
if (arguments.split(" ").length == 1) {
return tabComplete(new SpongeCommandSource(source));
public List<CommandCompletion> complete(CommandCause cause, ArgumentReader.Mutable arguments) {
if (arguments.input().split(" ").length == 1) {
return tabComplete(new SpongeCommandSource(cause)).stream().map(CommandCompletion::of).collect(Collectors.toList());
}
return Collections.emptyList();
}
@Override
public boolean testPermission(CommandSource source) {
public boolean canExecute(CommandCause cause) {
return true;
}
@Override
public Optional<Text> getShortDescription(CommandSource source) {
return Optional.of(Text.of("The main command for Geyser."));
public Optional<Component> shortDescription(CommandCause cause) {
return Optional.of(Component.text("The main command for Geyser."));
}
@Override
public Optional<Text> getHelp(CommandSource source) {
return Optional.of(Text.of("/geyser help"));
public Optional<Component> extendedDescription(CommandCause cause) {
return shortDescription(cause);
}
@Override
public Text getUsage(CommandSource source) {
return Text.of("/geyser help");
public Optional<Component> help(@NotNull CommandCause cause) {
return Optional.of(Component.text("/geyser help"));
}
@Override
public Component usage(CommandCause cause) {
return Component.text("/geyser help");
}
}

View file

@ -25,25 +25,37 @@
package org.geysermc.geyser.platform.sponge.command;
import net.kyori.adventure.text.Component;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandMapping;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.command.manager.CommandMapping;
import java.util.Optional;
public class GeyserSpongeCommandManager extends GeyserCommandManager {
private final org.spongepowered.api.command.CommandManager handle;
public GeyserSpongeCommandManager(org.spongepowered.api.command.CommandManager handle, GeyserImpl geyser) {
public GeyserSpongeCommandManager(GeyserImpl geyser) {
super(geyser);
this.handle = handle;
}
@Override
public String description(String command) {
return handle.get(command).map(CommandMapping::getCallable)
.map(callable -> callable.getShortDescription(Sponge.getServer().getConsole()).orElse(Text.EMPTY))
.orElse(Text.EMPTY).toPlain();
if (!Sponge.isServerAvailable()) {
return "";
}
// Note: The command manager may be replaced at any point during the game lifecycle
return Sponge.server().commandManager().commandMapping(command)
.map(this::description)
.map(Optional::get)
.map(MessageTranslator::convertMessage)
.orElse("");
}
public Optional<Component> description(CommandMapping mapping) {
return mapping.registrar().shortDescription(CommandCause.create(), mapping);
}
}

View file

@ -26,29 +26,30 @@
package org.geysermc.geyser.platform.sponge.command;
import lombok.AllArgsConstructor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.command.source.ConsoleSource;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
@AllArgsConstructor
public class SpongeCommandSource implements GeyserCommandSource {
private CommandSource handle;
private final CommandCause handle;
@Override
public String name() {
return handle.getName();
return handle.friendlyIdentifier().orElse(handle.identifier());
}
@Override
public void sendMessage(String message) {
handle.sendMessage(Text.of(message));
public void sendMessage(@NonNull String message) {
handle.audience().sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
}
@Override
public boolean isConsole() {
return handle instanceof ConsoleSource;
return !(handle.cause().root() instanceof ServerPlayer);
}
@Override

View file

@ -0,0 +1,30 @@
{
"loader": {
"name": "java_plain",
"version": "1.0"
},
"license": "MIT",
"plugins": [
{
"id": "${id}",
"name": "${name}-Sponge",
"version": "${version}",
"entrypoint": "org.geysermc.geyser.platform.sponge.GeyserSpongePlugin",
"description": "${description}",
"links": {
"homepage": "${url}"
},
"contributors": [
{
"name": "${author}"
}
],
"dependencies": [
{
"id": "spongeapi",
"version": "8.0.0"
}
]
}
]
}

View file

@ -0,0 +1,6 @@
{
"pack": {
"description": "Geyser for Sponge",
"pack_format": 6
}
}

View file

@ -51,8 +51,9 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
this.platformVersion = proxy.getVersion().getVersion();
this.platformVendor = proxy.getVersion().getVendor();
this.onlineMode = proxy.getConfiguration().isOnlineMode();
if (AsteriskSerializer.showSensitive || (proxy.getBoundAddress().getHostString().equals("") || proxy.getBoundAddress().getHostString().equals("0.0.0.0"))) {
this.serverIP = proxy.getBoundAddress().getHostString();
String hostString = proxy.getBoundAddress().getHostString();
if (AsteriskSerializer.showSensitive || (hostString.equals("") || hostString.equals("0.0.0.0"))) {
this.serverIP = hostString;
} else {
this.serverIP = "***";
}

View file

@ -63,6 +63,9 @@ public class GeyserVelocityCommandExecutor extends GeyserCommandExecutor impleme
return;
}
command.execute(session, sender, invocation.arguments().length > 1 ? Arrays.copyOfRange(invocation.arguments(), 1, invocation.arguments().length) : new String[0]);
} else {
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", sender.locale());
sender.sendMessage(ChatColor.RED + message);
}
} else {
getCommand("help").execute(session, sender, new String[0]);

View file

@ -9,9 +9,9 @@ dependencies {
tasks {
processResources {
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json")) {
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "META-INF/sponge_plugins.json")) {
expand(
"id" to "Geyser",
"id" to "geyser",
"name" to "Geyser",
"version" to project.version,
"description" to project.description,

View file

@ -11,8 +11,7 @@ publishing {
artifactId = project.name
version = project.version as String
artifact(tasks["shadowJar"])
artifact(tasks["sourcesJar"])
from(components["java"])
}
}
}

View file

@ -1,3 +1,7 @@
plugins {
id("geyser.publish-conventions")
}
dependencies {
api(libs.cumulus)
api(libs.gson)

View file

@ -216,19 +216,41 @@ public class Entity {
}
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
setOnGround(isOnGround);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
MoveEntityDeltaPacket moveEntityPacket = new MoveEntityDeltaPacket();
moveEntityPacket.setRuntimeEntityId(geyserId);
moveEntityPacket.setPosition(position);
moveEntityPacket.setRotation(getBedrockRotation());
moveEntityPacket.setOnGround(isOnGround);
moveEntityPacket.setTeleported(false);
if (relX != 0.0) {
moveEntityPacket.setX(position.getX());
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X);
}
if (relY != 0.0) {
moveEntityPacket.setY(position.getY());
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Y);
}
if (relZ != 0.0) {
moveEntityPacket.setZ(position.getZ());
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Z);
}
if (pitch != this.pitch) {
this.pitch = pitch;
moveEntityPacket.setPitch(pitch);
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH);
}
if (yaw != this.yaw) {
this.yaw = yaw;
moveEntityPacket.setYaw(yaw);
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
}
if (headYaw != this.headYaw) {
this.headYaw = headYaw;
moveEntityPacket.setHeadYaw(headYaw);
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
}
setOnGround(isOnGround);
if (isOnGround) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND);
}
session.sendUpstreamPacket(moveEntityPacket);
}

View file

@ -567,6 +567,7 @@ public class ItemRegistryPopulator {
.bedrockData(0)
.bedrockBlockId(-1)
.stackSize(1)
.customItemOptions(Object2IntMaps.emptyMap()) // TODO check for custom items with furnace minecart
.build());
creativeItems.add(ItemData.builder()

@ -1 +1 @@
Subproject commit 51d6f5ba7d85bfda318879dad34481d9ef4d488d
Subproject commit a9cf5999af605902b18dd5c77d3562481f8d7f3d

@ -1 +1 @@
Subproject commit 2c68dab9d751f78b2f5b0298da5e338ad6bc07ca
Subproject commit f1c9c2fbba0e102dc4f8c96dd9485f7ec9768174

View file

@ -25,7 +25,7 @@ adapters = "1.5-SNAPSHOT"
commodore = "2.2"
bungeecord = "a7c6ede"
velocity = "3.0.0"
sponge = "7.1.0"
sponge = "8.0.0"
[libraries]
jackson-annotations = { group = "com.fasterxml.jackson.core", name = "jackson-annotations", version.ref = "jackson" }