more fixes

This commit is contained in:
Alexander Medvedev 2026-07-26 10:47:39 +02:00
parent 1182c7e8fe
commit 5c00ff0b67
17 changed files with 531 additions and 117 deletions

View File

@ -20,8 +20,9 @@ java {
} }
tasks.withType<JavaCompile> { tasks.withType<JavaCompile> {
options.isWarnings = false
options.compilerArgs.addAll(listOf( options.compilerArgs.addAll(listOf(
"-Xlint:-removal", "-Xlint:none",
"-Xlint:-deprecation" "-nowarn"
)) ))
} }

View File

@ -60,8 +60,8 @@ public final class CommandSystemTests {
map.register("patchbukkittest", testCmd); map.register("patchbukkittest", testCmd);
CommandSender sender = Bukkit.getConsoleSender(); CommandSender sender = Bukkit.getConsoleSender();
boolean result = map.dispatch(sender, "pbtestexec"); boolean result = map.dispatch(sender, "/pbtestexec");
assertTrue(result, "dispatch() should return true"); assertTrue(result, "dispatch() with leading slash should return true");
assertTrue(executed[0], "command should have been executed"); assertTrue(executed[0], "command should have been executed");
} }

View File

@ -29,4 +29,18 @@ public final class EntityTests {
Bukkit.getServer().getEntity(UUID.randomUUID()); Bukkit.getServer().getEntity(UUID.randomUUID());
} }
@ConformanceTest(name = "Player flight state and speed getters run cleanly", category = TestCategory.ENTITY)
public void testPlayerFlightState() {
for (Player p : Bukkit.getOnlinePlayers()) {
boolean allow = p.getAllowFlight();
boolean flying = p.isFlying();
float flySpeed = p.getFlySpeed();
float walkSpeed = p.getWalkSpeed();
assertNotNull(allow, "Player.getAllowFlight()");
assertNotNull(flying, "Player.isFlying()");
assertTrue(flySpeed >= -1.0f && flySpeed <= 1.0f, "Fly speed in valid range");
assertTrue(walkSpeed >= -1.0f && walkSpeed <= 1.0f, "Walk speed in valid range");
}
}
} }

View File

@ -62,4 +62,20 @@ public final class PluginManagerTests {
assertNotNull(perms, "PluginManager.getPermissions()"); assertNotNull(perms, "PluginManager.getPermissions()");
} }
@ConformanceTest(name = "PluginManager.useTimings() returns boolean", category = TestCategory.PLUGIN_MANAGER)
public void testUseTimings() {
boolean timings = Bukkit.getPluginManager().useTimings();
assertTrue(!timings, "useTimings() should return false");
}
@ConformanceTest(name = "Server.getMessenger() returns non-null", category = TestCategory.PLUGIN_MANAGER)
public void testMessenger() {
var messenger = Bukkit.getMessenger();
assertNotNull(messenger, "Bukkit.getMessenger()");
messenger.registerOutgoingPluginChannel(plugin, "BungeeCord");
assertTrue(messenger.isOutgoingChannelRegistered(plugin, "BungeeCord"), "isOutgoingChannelRegistered() should be true");
messenger.unregisterOutgoingPluginChannel(plugin, "BungeeCord");
assertTrue(!messenger.isOutgoingChannelRegistered(plugin, "BungeeCord"), "isOutgoingChannelRegistered() should be false");
}
} }

View File

@ -64,9 +64,10 @@ java {
} }
tasks.withType<JavaCompile> { tasks.withType<JavaCompile> {
options.isWarnings = false
options.compilerArgs.addAll(listOf( options.compilerArgs.addAll(listOf(
"-Xlint:-removal", "-Xlint:none",
"-Xlint:-deprecation" "-nowarn"
)) ))
} }

View File

@ -1,6 +1,7 @@
package org.patchbukkit.loader; package org.patchbukkit.loader;
import java.io.File; import java.io.File;
import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -121,8 +122,56 @@ public class PatchBukkitPluginLoader implements PluginLoader {
Class<? extends Event>, Class<? extends Event>,
Set<RegisteredListener> Set<RegisteredListener>
> createRegisteredListeners(Listener listener, Plugin plugin) { > createRegisteredListeners(Listener listener, Plugin plugin) {
throw new UnsupportedOperationException( Map<Class<? extends Event>, Set<RegisteredListener>> ret = new java.util.HashMap<>();
"Unimplemented method 'createRegisteredListeners'" Set<java.lang.reflect.Method> methods;
); try {
Method[] publicMethods = listener.getClass().getMethods();
Method[] declaredMethods = listener.getClass().getDeclaredMethods();
methods = new java.util.HashSet<>(publicMethods.length + declaredMethods.length);
for (Method method : publicMethods) {
methods.add(method);
}
for (Method method : declaredMethods) {
methods.add(method);
}
} catch (NoClassDefFoundError e) {
plugin.getLogger().severe("Plugin " + plugin.getDescription().getFullName() + " has failed to register events for " + listener.getClass() + " because " + e.getMessage() + " does not exist.");
return ret;
}
for (final Method method : methods) {
final org.bukkit.event.EventHandler eh = method.getAnnotation(org.bukkit.event.EventHandler.class);
if (eh == null) continue;
if (method.isBridge() || method.isSynthetic()) {
continue;
}
final Class<?> checkClass;
if (method.getParameterTypes().length != 1 || !Event.class.isAssignableFrom(checkClass = method.getParameterTypes()[0])) {
plugin.getLogger().severe(plugin.getDescription().getFullName() + " attempted to register an invalid EventHandler method signature \"" + method.toGenericString() + "\" in " + listener.getClass());
continue;
}
final Class<? extends Event> eventClass = checkClass.asSubclass(Event.class);
method.setAccessible(true);
Set<RegisteredListener> eventSet = ret.computeIfAbsent(eventClass, k -> new java.util.HashSet<>());
EventExecutor executor = (l, event) -> {
try {
if (!eventClass.isAssignableFrom(event.getClass())) {
return;
}
method.invoke(l, event);
} catch (java.lang.reflect.InvocationTargetException ex) {
throw new org.bukkit.event.EventException(ex.getCause());
} catch (Throwable t) {
throw new org.bukkit.event.EventException(t);
}
};
eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
}
return ret;
} }
} }

View File

@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import org.patchbukkit.events.PatchBukkitEventManager; import org.patchbukkit.events.PatchBukkitEventManager;
import org.patchbukkit.loader.PatchBukkitPluginClassLoader;
import org.patchbukkit.permissions.PatchBukkitPermissionManager; import org.patchbukkit.permissions.PatchBukkitPermissionManager;
@SuppressWarnings("removal") @SuppressWarnings("removal")
@ -77,37 +78,77 @@ public class PatchBukkitPluginManager implements PluginManager {
@Override @Override
public @Nullable Plugin loadPlugin(@NotNull File file) public @Nullable Plugin loadPlugin(@NotNull File file)
throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
throw new UnsupportedOperationException( if (file == null || !file.exists()) {
"Unimplemented method 'loadPlugin'" throw new InvalidPluginException("File does not exist: " + file);
); }
PatchBukkitPluginClassLoader loader;
try {
loader = new PatchBukkitPluginClassLoader(
getClass().getClassLoader(),
file
);
} catch (Exception e) {
throw new InvalidPluginException("Failed to load plugin description or classloader: " + file.getName(), e);
}
PluginDescriptionFile description = loader.getDescription();
String mainClass = description.getMain();
try {
Class<?> jarClass = Class.forName(mainClass, true, loader);
Class<? extends Plugin> pluginClass = jarClass.asSubclass(Plugin.class);
Plugin plugin = pluginClass.getDeclaredConstructor().newInstance();
loader.init((org.bukkit.plugin.java.JavaPlugin) plugin);
registerPlugin(plugin);
return plugin;
} catch (Throwable e) {
throw new InvalidPluginException("Failed to instantiate main class " + mainClass + " for plugin " + description.getName(), e);
}
} }
@Override @Override
public @NotNull Plugin[] loadPlugins(@NotNull File directory) { public @NotNull Plugin[] loadPlugins(@NotNull File directory) {
throw new UnsupportedOperationException( if (directory == null || !directory.isDirectory()) {
"Unimplemented method 'loadPlugins'" return new Plugin[0];
); }
File[] files = directory.listFiles((dir, name) -> name.endsWith(".jar"));
if (files == null) {
return new Plugin[0];
}
return loadPlugins(files);
} }
@Override @Override
public @NotNull Plugin[] loadPlugins(@NonNull @NotNull File[] files) { public @NotNull Plugin[] loadPlugins(@NonNull @NotNull File[] files) {
throw new UnsupportedOperationException( java.util.List<Plugin> result = new java.util.ArrayList<>();
"Unimplemented method 'loadPlugins'" for (File file : files) {
); if (file != null && file.isFile() && file.getName().endsWith(".jar")) {
try {
Plugin plugin = loadPlugin(file);
if (plugin != null) {
result.add(plugin);
}
} catch (Exception e) {
server.getLogger().severe("Could not load plugin '" + file.getName() + "' in folder '" + file.getParent() + "': " + e.getMessage());
}
}
}
return result.toArray(new Plugin[0]);
} }
@Override @Override
public void disablePlugins() { public void disablePlugins() {
throw new UnsupportedOperationException( for (Plugin plugin : getPlugins()) {
"Unimplemented method 'disablePlugins'" disablePlugin(plugin);
); }
} }
@Override @Override
public void clearPlugins() { public void clearPlugins() {
throw new UnsupportedOperationException( disablePlugins();
"Unimplemented method 'clearPlugins'" plugins.clear();
);
} }
@Override @Override
@ -262,9 +303,7 @@ public class PatchBukkitPluginManager implements PluginManager {
@Override @Override
public boolean useTimings() { public boolean useTimings() {
throw new UnsupportedOperationException( return false;
"Unimplemented method 'useTimings'"
);
} }
@Override @Override
@ -272,8 +311,9 @@ public class PatchBukkitPluginManager implements PluginManager {
PluginMeta pluginMeta, PluginMeta pluginMeta,
PluginMeta dependencyConfig PluginMeta dependencyConfig
) { ) {
throw new UnsupportedOperationException( if (pluginMeta == null || dependencyConfig == null) {
"Unimplemented method 'isTransitiveDependency'" return false;
); }
return pluginMeta.getPluginDependencies().contains(dependencyConfig.getName());
} }
} }

View File

@ -101,6 +101,7 @@ import patchbukkit.bridge.NativeBridgeFfi;
import patchbukkit.log.LogLevel; import patchbukkit.log.LogLevel;
import patchbukkit.log.SendLogRequest; import patchbukkit.log.SendLogRequest;
@SuppressWarnings({ "deprecation", "removal", "unchecked" })
public class PatchBukkitServer implements Server { public class PatchBukkitServer implements Server {
private final String serverName = private final String serverName =
@ -181,40 +182,55 @@ public class PatchBukkitServer implements Server {
this.pluginManager.registerPlugin(plugin); this.pluginManager.registerPlugin(plugin);
} }
private final Messenger messenger = new org.patchbukkit.messaging.PatchBukkitMessenger();
private File pluginsFolder = new File("plugins");
private static void validateChannel(String channel) {
if (channel == null) throw new IllegalArgumentException("Channel cannot be null");
if (channel.length() > 64) {
throw new IllegalArgumentException("Channel '" + channel + "' is invalid");
}
}
@Override @Override
public void sendPluginMessage( public void sendPluginMessage(
@NotNull Plugin source, @NotNull Plugin source,
@NotNull String channel, @NotNull String channel,
byte@NotNull [] message byte@NotNull [] message
) { ) {
// TODO Auto-generated method stub if (source == null) throw new IllegalArgumentException("Plugin source cannot be null");
throw new UnsupportedOperationException( validateChannel(channel);
"Unimplemented method 'sendPluginMessage'" if (message == null) throw new IllegalArgumentException("Message cannot be null");
);
if (!messenger.isOutgoingChannelRegistered(source, channel)) {
throw new IllegalArgumentException("Plugin " + source.getDescription().getFullName() + " has not registered outgoing channel '" + channel + "'");
}
for (Player player : getOnlinePlayers()) {
player.sendPluginMessage(source, channel, message);
}
} }
@Override @Override
public @NotNull Set<String> getListeningPluginChannels() { public @NotNull Set<String> getListeningPluginChannels() {
// TODO Auto-generated method stub Set<String> channels = new java.util.HashSet<>();
throw new UnsupportedOperationException( for (Player player : getOnlinePlayers()) {
"Unimplemented method 'getListeningPluginChannels'" channels.addAll(player.getListeningPluginChannels());
); }
return java.util.Collections.unmodifiableSet(channels);
} }
@Override @Override
public @NotNull Iterable<? extends Audience> audiences() { public @NotNull Iterable<? extends Audience> audiences() {
// TODO Auto-generated method stub return (Collection<? extends Audience>) (Collection<?>) getOnlinePlayers();
throw new UnsupportedOperationException(
"Unimplemented method 'audiences'"
);
} }
@Override @Override
public @NotNull File getPluginsFolder() { public @NotNull File getPluginsFolder() {
// TODO Auto-generated method stub if (!pluginsFolder.exists()) {
throw new UnsupportedOperationException( pluginsFolder.mkdirs();
"Unimplemented method 'getPluginsFolder'" }
); return this.pluginsFolder;
} }
@Override @Override
@ -718,10 +734,10 @@ public class PatchBukkitServer implements Server {
@NotNull CommandSender sender, @NotNull CommandSender sender,
@NotNull String commandLine @NotNull String commandLine
) throws CommandException { ) throws CommandException {
// TODO Auto-generated method stub if (sender == null) throw new IllegalArgumentException("Sender cannot be null");
throw new UnsupportedOperationException( if (commandLine == null) throw new IllegalArgumentException("CommandLine cannot be null");
"Unimplemented method 'dispatchCommand'"
); return this.commandMap.dispatch(sender, commandLine);
} }
@Override @Override
@ -1098,10 +1114,7 @@ public class PatchBukkitServer implements Server {
@Override @Override
public @NotNull Messenger getMessenger() { public @NotNull Messenger getMessenger() {
// TODO Auto-generated method stub return this.messenger;
throw new UnsupportedOperationException(
"Unimplemented method 'getMessenger'"
);
} }
@Override @Override

View File

@ -61,7 +61,7 @@ public class PatchBukkitCommandMap implements CommandMap {
public boolean dispatch(@NotNull CommandSender sender, @NotNull String cmdLine) throws CommandException { public boolean dispatch(@NotNull CommandSender sender, @NotNull String cmdLine) throws CommandException {
if (cmdLine == null) return false; if (cmdLine == null) return false;
String cleanLine = cmdLine.trim(); String cleanLine = cmdLine.trim();
if (cleanLine.startsWith("/")) { while (cleanLine.startsWith("/")) {
cleanLine = cleanLine.substring(1).trim(); cleanLine = cleanLine.substring(1).trim();
} }
if (cleanLine.isEmpty()) return false; if (cleanLine.isEmpty()) return false;
@ -79,7 +79,6 @@ public class PatchBukkitCommandMap implements CommandMap {
try { try {
// Extract arguments (everything after the label) // Extract arguments (everything after the label)
String[] args = Arrays.copyOfRange(split, 1, split.length); String[] args = Arrays.copyOfRange(split, 1, split.length);
// This triggers the PluginCommand.execute() method you implemented earlier
return command.execute(sender, sentLabel, args); return command.execute(sender, sentLabel, args);
} catch (Exception ex) { } catch (Exception ex) {
throw new CommandException("Unhandled exception executing '" + cmdLine + "'", ex); throw new CommandException("Unhandled exception executing '" + cmdLine + "'", ex);
@ -108,7 +107,12 @@ public class PatchBukkitCommandMap implements CommandMap {
@Override @Override
public @Nullable List<String> tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) { public @Nullable List<String> tabComplete(@NotNull CommandSender sender, @NotNull String cmdLine, @Nullable Location location) {
String[] split = cmdLine.split(" ", -1); if (cmdLine == null) return new ArrayList<>();
String cleanLine = cmdLine.trim();
while (cleanLine.startsWith("/")) {
cleanLine = cleanLine.substring(1).trim();
}
String[] split = cleanLine.split(" ", -1);
if (split.length == 0) return new ArrayList<>(); if (split.length == 0) return new ArrayList<>();
String label = split[0].toLowerCase(); String label = split[0].toLowerCase();

View File

@ -76,7 +76,7 @@ import patchbukkit.abilities.SetAbilitiesRequest;
import patchbukkit.sound.PlayerEntityPlaySoundRequest; import patchbukkit.sound.PlayerEntityPlaySoundRequest;
import patchbukkit.sound.PlayerPlaySoundRequest; import patchbukkit.sound.PlayerPlaySoundRequest;
@SuppressWarnings({ "deprecation", "removal" }) @SuppressWarnings({ "deprecation", "removal", "unchecked" })
public class PatchBukkitPlayer public class PatchBukkitPlayer
extends PatchBukkitHumanEntity extends PatchBukkitHumanEntity
implements Player { implements Player {
@ -94,11 +94,7 @@ public class PatchBukkitPlayer
@Override @Override
public void sendRawMessage(UUID sender, String message) { public void sendRawMessage(UUID sender, String message) {
if (sender == null) { var request = SendMessageRequest.newBuilder().setMessage(message != null ? message : "").setUuid(BridgeUtils.convertUuid(this.getUniqueId())).build();
sender = this.getUniqueId();
}
var request = SendMessageRequest.newBuilder().setMessage(message).setUuid(BridgeUtils.convertUuid(sender)).build();
NativeBridgeFfi.sendMessage(request); NativeBridgeFfi.sendMessage(request);
} }
@ -1308,8 +1304,7 @@ public class PatchBukkitPlayer
@Override @Override
public boolean isFlying() { public boolean isFlying() {
// TODO Auto-generated method stub return NativeBridgeFfi.getAbilities(BridgeUtils.convertUuid(this.uuid)).getFlying();
throw new UnsupportedOperationException("Unimplemented method 'isFlying'");
} }
@Override @Override
@ -1321,26 +1316,32 @@ public class PatchBukkitPlayer
@Override @Override
public void setFlySpeed(float value) throws IllegalArgumentException { public void setFlySpeed(float value) throws IllegalArgumentException {
// TODO Auto-generated method stub if (value < -1.0f || value > 1.0f) {
throw new UnsupportedOperationException("Unimplemented method 'setFlySpeed'"); throw new IllegalArgumentException("Speed value " + value + " is not between -1.0 and 1.0");
}
var playerUuid = BridgeUtils.convertUuid(this.getUniqueId());
var abilities = NativeBridgeFfi.getAbilities(playerUuid).toBuilder().setFlySpeed(value).build();
NativeBridgeFfi.setAbilities(SetAbilitiesRequest.newBuilder().setAbilities(abilities).setUuid(playerUuid).build());
} }
@Override @Override
public void setWalkSpeed(float value) throws IllegalArgumentException { public void setWalkSpeed(float value) throws IllegalArgumentException {
// TODO Auto-generated method stub if (value < -1.0f || value > 1.0f) {
throw new UnsupportedOperationException("Unimplemented method 'setWalkSpeed'"); throw new IllegalArgumentException("Speed value " + value + " is not between -1.0 and 1.0");
}
var playerUuid = BridgeUtils.convertUuid(this.getUniqueId());
var abilities = NativeBridgeFfi.getAbilities(playerUuid).toBuilder().setWalkSpeed(value).build();
NativeBridgeFfi.setAbilities(SetAbilitiesRequest.newBuilder().setAbilities(abilities).setUuid(playerUuid).build());
} }
@Override @Override
public float getFlySpeed() { public float getFlySpeed() {
// TODO Auto-generated method stub return NativeBridgeFfi.getAbilities(BridgeUtils.convertUuid(this.uuid)).getFlySpeed();
throw new UnsupportedOperationException("Unimplemented method 'getFlySpeed'");
} }
@Override @Override
public float getWalkSpeed() { public float getWalkSpeed() {
// TODO Auto-generated method stub return NativeBridgeFfi.getAbilities(BridgeUtils.convertUuid(this.uuid)).getWalkSpeed();
throw new UnsupportedOperationException("Unimplemented method 'getWalkSpeed'");
} }
@Override @Override

View File

@ -0,0 +1,244 @@
package org.patchbukkit.messaging;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class PatchBukkitMessenger implements Messenger {
private final Map<String, Set<PluginMessageListenerRegistration>> incomingByChannel = new ConcurrentHashMap<>();
private final Map<Plugin, Set<PluginMessageListenerRegistration>> incomingByPlugin = new ConcurrentHashMap<>();
private final Map<String, Set<Plugin>> outgoingByChannel = new ConcurrentHashMap<>();
private final Map<Plugin, Set<String>> outgoingByPlugin = new ConcurrentHashMap<>();
private static void validateChannel(String channel) {
if (channel == null) {
throw new IllegalArgumentException("Channel cannot be null");
}
if (channel.length() > 64) {
throw new IllegalArgumentException("Channel cannot be longer than 64 characters");
}
}
@Override
public boolean isReservedChannel(String channel) {
validateChannel(channel);
return channel.equalsIgnoreCase("REGISTER") || channel.equalsIgnoreCase("UNREGISTER") || channel.equalsIgnoreCase("FML") || channel.equalsIgnoreCase("FML|HS") || channel.equalsIgnoreCase("FML|MP");
}
@Override
public void registerOutgoingPluginChannel(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
if (isReservedChannel(channel)) throw new ReservedChannelException(channel);
outgoingByChannel.computeIfAbsent(channel.toLowerCase(Locale.ENGLISH), k -> new CopyOnWriteArraySet<>()).add(plugin);
outgoingByPlugin.computeIfAbsent(plugin, k -> new CopyOnWriteArraySet<>()).add(channel.toLowerCase(Locale.ENGLISH));
}
@Override
public void unregisterOutgoingPluginChannel(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
Set<Plugin> plugins = outgoingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (plugins != null) {
plugins.remove(plugin);
}
Set<String> channels = outgoingByPlugin.get(plugin);
if (channels != null) {
channels.remove(channel.toLowerCase(Locale.ENGLISH));
}
}
@Override
public void unregisterOutgoingPluginChannel(Plugin plugin) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
Set<String> channels = outgoingByPlugin.remove(plugin);
if (channels != null) {
for (String channel : channels) {
Set<Plugin> plugins = outgoingByChannel.get(channel);
if (plugins != null) {
plugins.remove(plugin);
}
}
}
}
@Override
public PluginMessageListenerRegistration registerIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
if (isReservedChannel(channel)) throw new ReservedChannelException(channel);
PluginMessageListenerRegistration reg = new PluginMessageListenerRegistration(this, plugin, channel, listener);
incomingByChannel.computeIfAbsent(channel.toLowerCase(Locale.ENGLISH), k -> new CopyOnWriteArraySet<>()).add(reg);
incomingByPlugin.computeIfAbsent(plugin, k -> new CopyOnWriteArraySet<>()).add(reg);
return reg;
}
@Override
public void unregisterIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
PluginMessageListenerRegistration reg = new PluginMessageListenerRegistration(this, plugin, channel, listener);
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (regs != null) {
regs.remove(reg);
}
Set<PluginMessageListenerRegistration> pluginRegs = incomingByPlugin.get(plugin);
if (pluginRegs != null) {
pluginRegs.remove(reg);
}
}
@Override
public void unregisterIncomingPluginChannel(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (regs != null) {
regs.removeIf(reg -> reg.getPlugin().equals(plugin));
}
Set<PluginMessageListenerRegistration> pluginRegs = incomingByPlugin.get(plugin);
if (pluginRegs != null) {
pluginRegs.removeIf(reg -> reg.getChannel().equalsIgnoreCase(channel));
}
}
@Override
public void unregisterIncomingPluginChannel(Plugin plugin) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
Set<PluginMessageListenerRegistration> pluginRegs = incomingByPlugin.remove(plugin);
if (pluginRegs != null) {
for (PluginMessageListenerRegistration reg : pluginRegs) {
Set<PluginMessageListenerRegistration> channelRegs = incomingByChannel.get(reg.getChannel().toLowerCase(Locale.ENGLISH));
if (channelRegs != null) {
channelRegs.remove(reg);
}
}
}
}
@Override
public Set<String> getOutgoingChannels() {
return Collections.unmodifiableSet(outgoingByChannel.keySet());
}
@Override
public Set<String> getOutgoingChannels(Plugin plugin) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
Set<String> channels = outgoingByPlugin.get(plugin);
return channels != null ? Collections.unmodifiableSet(channels) : Collections.emptySet();
}
@Override
public Set<String> getIncomingChannels() {
return Collections.unmodifiableSet(incomingByChannel.keySet());
}
@Override
public Set<String> getIncomingChannels(Plugin plugin) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
Set<PluginMessageListenerRegistration> regs = incomingByPlugin.get(plugin);
if (regs == null || regs.isEmpty()) return Collections.emptySet();
Set<String> result = new HashSet<>();
for (PluginMessageListenerRegistration reg : regs) {
result.add(reg.getChannel());
}
return Collections.unmodifiableSet(result);
}
@Override
public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(Plugin plugin) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
Set<PluginMessageListenerRegistration> regs = incomingByPlugin.get(plugin);
return regs != null ? Collections.unmodifiableSet(regs) : Collections.emptySet();
}
@Override
public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(String channel) {
validateChannel(channel);
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
return regs != null ? Collections.unmodifiableSet(regs) : Collections.emptySet();
}
@Override
public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (regs == null || regs.isEmpty()) return Collections.emptySet();
Set<PluginMessageListenerRegistration> filtered = new HashSet<>();
for (PluginMessageListenerRegistration reg : regs) {
if (reg.getPlugin().equals(plugin)) {
filtered.add(reg);
}
}
return Collections.unmodifiableSet(filtered);
}
@Override
public boolean isRegistrationValid(PluginMessageListenerRegistration registration) {
if (registration == null) return false;
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(registration.getChannel().toLowerCase(Locale.ENGLISH));
return regs != null && regs.contains(registration);
}
@Override
public boolean isIncomingChannelRegistered(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (regs == null) return false;
for (PluginMessageListenerRegistration reg : regs) {
if (reg.getPlugin().equals(plugin)) return true;
}
return false;
}
@Override
public boolean isOutgoingChannelRegistered(Plugin plugin, String channel) {
if (plugin == null) throw new IllegalArgumentException("Plugin cannot be null");
validateChannel(channel);
Set<Plugin> plugins = outgoingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
return plugins != null && plugins.contains(plugin);
}
@Override
public void dispatchIncomingMessage(Player source, String channel, byte[] message) {
if (source == null) throw new IllegalArgumentException("Player source cannot be null");
validateChannel(channel);
if (message == null) throw new IllegalArgumentException("Message cannot be null");
Set<PluginMessageListenerRegistration> regs = incomingByChannel.get(channel.toLowerCase(Locale.ENGLISH));
if (regs != null) {
for (PluginMessageListenerRegistration reg : regs) {
try {
reg.getListener().onPluginMessageReceived(channel, source, message);
} catch (Throwable t) {
source.getServer().getLogger().severe("Error dispatching plugin message on " + channel + " to " + reg.getPlugin().getName() + ": " + t.getMessage());
}
}
}
}
@Override
public void dispatchIncomingMessage(io.papermc.paper.connection.PlayerConnection connection, String channel, byte[] message) {
if (connection == null) throw new IllegalArgumentException("Connection cannot be null");
// Non-player connection handling if applicable
}
}

72
rust/Cargo.lock generated
View File

@ -415,7 +415,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.19",
] ]
[[package]] [[package]]
@ -878,7 +878,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
dependencies = [ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.19",
] ]
[[package]] [[package]]
@ -1800,9 +1800,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]] [[package]]
name = "j4rs" name = "j4rs"
version = "0.25.0" version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbaca95c5c7799ed193fc8aa789568f9d31a9d01381460227ef0074fea1855f" checksum = "c26fb1429997a5d8f98777df359f0132f62905ecce1d3bc2836372045c67de89"
dependencies = [ dependencies = [
"cesu8", "cesu8",
"dunce", "dunce",
@ -1828,9 +1828,9 @@ dependencies = [
[[package]] [[package]]
name = "jiff" name = "jiff"
version = "0.2.34" version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16" checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc"
dependencies = [ dependencies = [
"defmt", "defmt",
"jiff-core", "jiff-core",
@ -1852,9 +1852,9 @@ dependencies = [
[[package]] [[package]]
name = "jiff-static" name = "jiff-static"
version = "0.2.34" version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de" checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204"
dependencies = [ dependencies = [
"jiff-core", "jiff-core",
"proc-macro2", "proc-macro2",
@ -2773,7 +2773,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin" name = "pumpkin"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"base64 0.23.0", "base64 0.23.0",
@ -2814,7 +2814,7 @@ dependencies = [
"sha1", "sha1",
"sha2 0.11.0", "sha2 0.11.0",
"sysinfo", "sysinfo",
"thiserror 2.0.18", "thiserror 2.0.19",
"time", "time",
"tokio", "tokio",
"tokio-util", "tokio-util",
@ -2831,7 +2831,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-api-macros" name = "pumpkin-api-macros"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
@ -2842,7 +2842,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-codecs" name = "pumpkin-codecs"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"serde_json", "serde_json",
"tracing", "tracing",
@ -2851,7 +2851,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-config" name = "pumpkin-config"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"pumpkin-util", "pumpkin-util",
"serde", "serde",
@ -2863,7 +2863,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-data" name = "pumpkin-data"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"crc-fast", "crc-fast",
"phf", "phf",
@ -2876,14 +2876,14 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-inventory" name = "pumpkin-inventory"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"pumpkin-data", "pumpkin-data",
"pumpkin-protocol", "pumpkin-protocol",
"pumpkin-util", "pumpkin-util",
"pumpkin-world", "pumpkin-world",
"rand 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 2.0.18", "thiserror 2.0.19",
"tokio", "tokio",
"tracing", "tracing",
] ]
@ -2891,7 +2891,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-macros" name = "pumpkin-macros"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error2", "proc-macro-error2",
@ -2903,14 +2903,14 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-nbt" name = "pumpkin-nbt"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"bytes", "bytes",
"cesu8", "cesu8",
"flate2", "flate2",
"pumpkin-codecs", "pumpkin-codecs",
"serde", "serde",
"thiserror 2.0.18", "thiserror 2.0.19",
"tracing", "tracing",
"uuid", "uuid",
] ]
@ -2918,7 +2918,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-protocol" name = "pumpkin-protocol"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"aes", "aes",
"async-compression", "async-compression",
@ -2935,7 +2935,7 @@ dependencies = [
"pumpkin-world", "pumpkin-world",
"serde", "serde",
"sha2 0.11.0", "sha2 0.11.0",
"thiserror 2.0.18", "thiserror 2.0.19",
"tokio", "tokio",
"uuid", "uuid",
] ]
@ -2943,7 +2943,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-util" name = "pumpkin-util"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"base64 0.23.0", "base64 0.23.0",
"bytes", "bytes",
@ -2961,7 +2961,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.11.0", "sha2 0.11.0",
"thiserror 2.0.18", "thiserror 2.0.19",
"tokio", "tokio",
"ureq", "ureq",
"uuid", "uuid",
@ -2970,7 +2970,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-world" name = "pumpkin-world"
version = "0.1.0-dev+26.2" version = "0.1.0-dev+26.2"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#faf8c50d806e6101be1e70ba2fee0d60bd1414cf" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#ac89bff1caea0a6c728e67212811a06914ea9dbe"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"bitflags 2.13.1", "bitflags 2.13.1",
@ -2995,7 +2995,7 @@ dependencies = [
"serde_json", "serde_json",
"sha2 0.11.0", "sha2 0.11.0",
"slotmap", "slotmap",
"thiserror 2.0.18", "thiserror 2.0.19",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tracing", "tracing",
@ -3105,7 +3105,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [ dependencies = [
"getrandom 0.2.17", "getrandom 0.2.17",
"libredox", "libredox",
"thiserror 2.0.18", "thiserror 2.0.19",
] ]
[[package]] [[package]]
@ -3125,9 +3125,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.12.4" version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -3732,11 +3732,11 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "2.0.18" version = "2.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
dependencies = [ dependencies = [
"thiserror-impl 2.0.18", "thiserror-impl 2.0.19",
] ]
[[package]] [[package]]
@ -3752,13 +3752,13 @@ dependencies = [
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "2.0.18" version = "2.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.119", "syn 3.0.3",
] ]
[[package]] [[package]]
@ -4384,7 +4384,7 @@ dependencies = [
"pulley-interpreter", "pulley-interpreter",
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
"thiserror 2.0.18", "thiserror 2.0.19",
"wasmparser", "wasmparser",
"wasmtime-environ", "wasmtime-environ",
"wasmtime-internal-core", "wasmtime-internal-core",
@ -4482,7 +4482,7 @@ dependencies = [
"io-lifetimes 3.0.1", "io-lifetimes 3.0.1",
"rand 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustix", "rustix",
"thiserror 2.0.18", "thiserror 2.0.19",
"tokio", "tokio",
"tracing", "tracing",
"url", "url",

View File

@ -21,7 +21,7 @@ pumpkin-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch
tokio = "1" tokio = "1"
tracing = "0.1" tracing = "0.1"
glob = "0.3.4" glob = "0.3.4"
j4rs = { version = "=0.25.0" } j4rs = { version = "0.25.2" }
rust-embed = { version = "8.12.0", features = ["interpolate-folder-path"] } rust-embed = { version = "8.12.0", features = ["interpolate-folder-path"] }
walkdir = "2" walkdir = "2"
zip = "8.6" zip = "8.6"
@ -39,7 +39,7 @@ prost = "0.14"
toml = "1.1" toml = "1.1"
[build-dependencies] [build-dependencies]
j4rs = { version = "=0.25.0", artifact = "cdylib", lib = true } j4rs = { version = "0.25.2", artifact = "cdylib", lib = true }
env_logger = "0.11.11" env_logger = "0.11.11"
log = "0.4" log = "0.4"
prost-build = "0.14" prost-build = "0.14"

View File

@ -22,6 +22,10 @@ pub fn setup_java(base: PathBuf) {
)])) )]))
.skip_setting_native_lib() .skip_setting_native_lib()
.with_base_path(resources) .with_base_path(resources)
.java_opts(vec![
j4rs::JavaOpt::new("--enable-native-access=ALL-UNNAMED"),
j4rs::JavaOpt::new("-Dcom.google.protobuf.useUnsafe=false"),
])
.build() .build()
.map_err(|err| format!("jvm failed to init: {err:?}")) .map_err(|err| format!("jvm failed to init: {err:?}"))
.unwrap(); .unwrap();

View File

@ -112,14 +112,12 @@ impl ArgumentConsumer for AnyCommandNode {
impl From<&CommandSender> for SimpleCommandSender { impl From<&CommandSender> for SimpleCommandSender {
fn from(val: &CommandSender) -> Self { fn from(val: &CommandSender) -> Self {
match val { match val {
CommandSender::Rcon(_mutex) => todo!(), CommandSender::Console | CommandSender::Rcon(_) | CommandSender::Dummy => Self::Console,
CommandSender::Console => Self::Console,
CommandSender::Player(player) => Self::Player( CommandSender::Player(player) => Self::Player(
player.gameprofile.id.to_string(), player.gameprofile.id.to_string(),
player.gameprofile.name.clone(), player.gameprofile.name.clone(),
), ),
CommandSender::CommandBlock(_block_entity, _world) => todo!(), CommandSender::CommandBlock(_block_entity, _world) => Self::Console,
CommandSender::Dummy => Self::Console,
} }
} }
} }

View File

@ -209,7 +209,13 @@ impl JvmWorker {
fn initialize_jvm(&mut self, j4rs_path: &PathBuf) -> anyhow::Result<()> { fn initialize_jvm(&mut self, j4rs_path: &PathBuf) -> anyhow::Result<()> {
tracing::info!("Initializing JVM with path: {j4rs_path:?}"); tracing::info!("Initializing JVM with path: {j4rs_path:?}");
let jvm = JvmBuilder::new().with_base_path(j4rs_path).build()?; let jvm = JvmBuilder::new()
.with_base_path(j4rs_path)
.java_opts(vec![
j4rs::JavaOpt::new("--enable-native-access=ALL-UNNAMED"),
j4rs::JavaOpt::new("-Dcom.google.protobuf.useUnsafe=false"),
])
.build()?;
initialize_callbacks(&jvm)?; initialize_callbacks(&jvm)?;

View File

@ -169,9 +169,32 @@ impl CommandManager {
&[InvocationArg::try_from(&cmd_name)?, j_plugin_arg], &[InvocationArg::try_from(&cmd_name)?, j_plugin_arg],
)?)); )?));
tracing::info!("Registering Bukkit command: {}", &cmd_name); tracing::info!("Registering Bukkit command: {}", &cmd_name);
let cmd_aliases: Vec<String> = cmd_data.aliases.as_ref().map_or_else(Vec::new, |a| a.to_vec());
let mut names: Vec<String> = vec![cmd_name.clone()];
names.extend(cmd_aliases.clone());
{ {
let cmd_lock = j_plugin_cmd.lock().unwrap(); let cmd_lock = j_plugin_cmd.lock().unwrap();
let j_plugin_cmd_owned = jvm.clone_instance(&cmd_lock)?; let j_plugin_cmd_owned = jvm.clone_instance(&cmd_lock)?;
if let Some(ref desc) = cmd_data.description {
let _ = jvm.invoke(&j_plugin_cmd_owned, "setDescription", &[InvocationArg::try_from(desc)?]);
}
if let Some(ref usage) = cmd_data.usage {
let _ = jvm.invoke(&j_plugin_cmd_owned, "setUsage", &[InvocationArg::try_from(usage)?]);
}
if let Some(ref perm_msg) = cmd_data.permission_message {
let _ = jvm.invoke(&j_plugin_cmd_owned, "setPermissionMessage", &[InvocationArg::try_from(perm_msg)?]);
}
if let Some(ref perm) = cmd_data.permission {
let _ = jvm.invoke(&j_plugin_cmd_owned, "setPermission", &[InvocationArg::try_from(perm)?]);
}
if !cmd_aliases.is_empty() {
let j_aliases = jvm.create_java_array("java.lang.String", &cmd_aliases.iter().map(|a| InvocationArg::try_from(a).unwrap()).collect::<Vec<_>>())?;
let j_list = jvm.invoke_static("java.util.Arrays", "asList", &[InvocationArg::from(j_aliases)])?;
let _ = jvm.invoke(&j_plugin_cmd_owned, "setAliases", &[InvocationArg::from(j_list)]);
}
jvm.invoke( jvm.invoke(
command_map, command_map,
"register", "register",
@ -186,7 +209,7 @@ impl CommandManager {
let node = init_java_command( let node = init_java_command(
cmd_name.clone(), cmd_name.clone(),
command_tx.clone(), command_tx.clone(),
[&cmd_name], names,
cmd_data.description.clone().unwrap_or_default(), cmd_data.description.clone().unwrap_or_default(),
); );