mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-07-18 04:43:58 +00:00
O-o .o-o. o-O
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package art.arcane.iris;
|
||||
|
||||
import art.arcane.iris.core.pack.DefaultPackBootstrapProvisioner;
|
||||
import art.arcane.iris.core.pack.DefaultPackBootstrapProvisioner.ProvisionResult;
|
||||
import io.papermc.paper.datapack.Datapack;
|
||||
import io.papermc.paper.datapack.DatapackRegistrar;
|
||||
import io.papermc.paper.datapack.DiscoveredDatapack;
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public final class IrisBootstrap implements PluginBootstrap {
|
||||
static final String PACK_ID = "generated";
|
||||
|
||||
@Override
|
||||
public void bootstrap(BootstrapContext context) {
|
||||
ProvisionResult provisioned = provision(context);
|
||||
Path datapackRoot = provisioned.datapackRoot();
|
||||
context.getLogger().info("Iris startup datapack is {} at {}", provisioned.status(), datapackRoot);
|
||||
context.getLifecycleManager().registerEventHandler(LifecycleEvents.DATAPACK_DISCOVERY, event -> {
|
||||
try {
|
||||
discoverPack(event.registrar(), datapackRoot);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unable to discover the Iris startup datapack at " + datapackRoot, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static DiscoveredDatapack discoverPack(DatapackRegistrar registrar, Path datapackRoot) throws IOException {
|
||||
DiscoveredDatapack datapack = registrar.discoverPack(
|
||||
datapackRoot,
|
||||
PACK_ID,
|
||||
configurer -> configurer
|
||||
.autoEnableOnServerStart(true)
|
||||
.position(true, Datapack.Position.TOP)
|
||||
);
|
||||
if (datapack == null) {
|
||||
throw new IllegalStateException("Paper did not accept the Iris startup datapack at " + datapackRoot);
|
||||
}
|
||||
return datapack;
|
||||
}
|
||||
|
||||
private static ProvisionResult provision(BootstrapContext context) {
|
||||
try {
|
||||
return DefaultPackBootstrapProvisioner.provision(
|
||||
context.getDataDirectory(),
|
||||
message -> context.getLogger().info(message)
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unable to provision the Iris startup datapack", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import art.arcane.iris.core.IrisWorlds;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.lifecycle.WorldLifecycleService;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.iris.core.service.StudioSVC;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
@@ -460,10 +461,11 @@ public class CommandIris implements DirectorExecutor {
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
boolean overwrite
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (overwrite ? " overwriting" : ""));
|
||||
if (pack.equals("overworld")) {
|
||||
Iris.service(StudioSVC.class).downloadBranch(sender(), "IrisDimensions/overworld", "master", overwrite);
|
||||
if (PackDownloader.isDefaultOverworld(pack)) {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + " (beta release)" + (overwrite ? " overwriting" : ""));
|
||||
Iris.service(StudioSVC.class).downloadDefaultOverworld(sender(), overwrite);
|
||||
} else {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (overwrite ? " overwriting" : ""));
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), "IrisDimensions/" + pack + "/" + branch, overwrite);
|
||||
}
|
||||
ServerConfigurator.installDataPacksIfChanged(true);
|
||||
|
||||
@@ -50,6 +50,8 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -64,14 +66,13 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
PluginCommand command = Iris.instance.getCommand(ROOT_COMMAND);
|
||||
if (command == null) {
|
||||
Iris.warn("Failed to find command '" + ROOT_COMMAND + "'");
|
||||
return;
|
||||
PluginCommand command = findBukkitCommand();
|
||||
if (command != null) {
|
||||
command.setExecutor(this);
|
||||
command.setTabCompleter(this);
|
||||
} else {
|
||||
registerPaperCommand();
|
||||
}
|
||||
|
||||
command.setExecutor(this);
|
||||
command.setTabCompleter(this);
|
||||
J.a(this::getDirector);
|
||||
}
|
||||
|
||||
@@ -139,12 +140,7 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<String> v = runDirectorTab(sender, alias, args);
|
||||
if (sender instanceof Player player && IrisSettings.get().getGeneral().isCommandSounds()) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 0.25f, RNG.r.f(0.125f, 1.95f));
|
||||
}
|
||||
|
||||
return v;
|
||||
return tabCompleteRoot(sender, alias, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,13 +149,52 @@ public class CommandSVC implements IrisService, CommandExecutor, TabCompleter, D
|
||||
return false;
|
||||
}
|
||||
|
||||
executeRoot(sender, label, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
void executeRoot(CommandSender sender, String label, String[] args) {
|
||||
if (!sender.hasPermission(ROOT_PERMISSION)) {
|
||||
sender.sendMessage("You lack the Permission '" + ROOT_PERMISSION + "'");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
J.aBukkit(() -> executeCommand(sender, label, args));
|
||||
return true;
|
||||
}
|
||||
|
||||
List<String> tabCompleteRoot(CommandSender sender, String alias, String[] args) {
|
||||
List<String> suggestions = runDirectorTab(sender, alias, args);
|
||||
if (sender instanceof Player player && IrisSettings.get().getGeneral().isCommandSounds()) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 0.25f, RNG.r.f(0.125f, 1.95f));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
private PluginCommand findBukkitCommand() {
|
||||
try {
|
||||
return Iris.instance.getCommand(ROOT_COMMAND);
|
||||
} catch (UnsupportedOperationException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPaperCommand() {
|
||||
try {
|
||||
Class<?> registrarType = Class.forName(
|
||||
"art.arcane.iris.core.service.PaperCommandRegistrar",
|
||||
true,
|
||||
getClass().getClassLoader()
|
||||
);
|
||||
Method register = registrarType.getDeclaredMethod("register", Iris.class, CommandSVC.class);
|
||||
register.invoke(null, Iris.instance, this);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause() == null ? e : e.getCause();
|
||||
throw new IllegalStateException("Paper command registration failed", cause);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new IllegalStateException("Paper command registrar is unavailable", e);
|
||||
} catch (LinkageError e) {
|
||||
throw new IllegalStateException("Paper command APIs are unavailable", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeCommand(CommandSender sender, String label, String[] args) {
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package art.arcane.iris.core.service;
|
||||
|
||||
import art.arcane.iris.Iris;
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
final class PaperCommandRegistrar {
|
||||
private static final String ROOT_COMMAND = "iris";
|
||||
|
||||
private PaperCommandRegistrar() {
|
||||
}
|
||||
|
||||
static void register(Iris plugin, CommandSVC commandService) {
|
||||
plugin.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event ->
|
||||
event.registrar().register(
|
||||
ROOT_COMMAND,
|
||||
"Iris world generation command.",
|
||||
List.of("ir", "irs"),
|
||||
command(commandService)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static BasicCommand command(CommandSVC commandService) {
|
||||
return new PaperCommand(commandService);
|
||||
}
|
||||
|
||||
private record PaperCommand(CommandSVC commandService) implements BasicCommand {
|
||||
@Override
|
||||
public void execute(CommandSourceStack source, String[] args) {
|
||||
commandService.executeRoot(source.getSender(), ROOT_COMMAND, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> suggest(CommandSourceStack source, String[] args) {
|
||||
return commandService.tabCompleteRoot(source.getSender(), ROOT_COMMAND, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(CommandSender sender) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
name: ${name}
|
||||
version: ${version}
|
||||
main: ${main}
|
||||
bootstrapper: ${bootstrapper}
|
||||
folia-supported: true
|
||||
api-version: '${apiVersion}'
|
||||
load: STARTUP
|
||||
authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
|
||||
website: volmit.com
|
||||
description: More than a Dimension!
|
||||
@@ -0,0 +1,199 @@
|
||||
package art.arcane.iris;
|
||||
|
||||
import io.papermc.paper.datapack.Datapack;
|
||||
import io.papermc.paper.datapack.DatapackRegistrar;
|
||||
import io.papermc.paper.datapack.DatapackSource;
|
||||
import io.papermc.paper.datapack.DiscoveredDatapack;
|
||||
import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.FeatureFlag;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisBootstrapTest {
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void discoverPackAutoEnablesAtFixedTop() throws Exception {
|
||||
File datapackDirectory = temporaryFolder.newFolder("datapack");
|
||||
RecordingRegistrar registrar = new RecordingRegistrar(DiscoveryBehavior.ACCEPT);
|
||||
|
||||
DiscoveredDatapack discovered = IrisBootstrap.discoverPack(registrar, datapackDirectory.toPath());
|
||||
|
||||
assertSame(registrar.discoveredDatapack, discovered);
|
||||
assertEquals(datapackDirectory.toPath(), registrar.discoveredPath);
|
||||
assertEquals(IrisBootstrap.PACK_ID, registrar.discoveredId);
|
||||
assertTrue(registrar.configurer.autoEnableOnServerStart);
|
||||
assertTrue(registrar.configurer.fixedPosition);
|
||||
assertEquals(Datapack.Position.TOP, registrar.configurer.position);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectedDiscoveryReportsDatapackPath() throws Exception {
|
||||
File datapackDirectory = temporaryFolder.newFolder("datapack");
|
||||
RecordingRegistrar registrar = new RecordingRegistrar(DiscoveryBehavior.REJECT);
|
||||
|
||||
IllegalStateException failure = assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> IrisBootstrap.discoverPack(registrar, datapackDirectory.toPath())
|
||||
);
|
||||
|
||||
assertTrue(failure.getMessage().contains(datapackDirectory.toPath().toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoveryIoFailurePropagates() throws Exception {
|
||||
File datapackDirectory = temporaryFolder.newFolder("datapack");
|
||||
RecordingRegistrar registrar = new RecordingRegistrar(DiscoveryBehavior.FAIL);
|
||||
|
||||
IOException failure = assertThrows(
|
||||
IOException.class,
|
||||
() -> IrisBootstrap.discoverPack(registrar, datapackDirectory.toPath())
|
||||
);
|
||||
|
||||
assertEquals("discovery failed", failure.getMessage());
|
||||
}
|
||||
|
||||
private enum DiscoveryBehavior {
|
||||
ACCEPT,
|
||||
REJECT,
|
||||
FAIL
|
||||
}
|
||||
|
||||
private static final class RecordingConfigurer implements DatapackRegistrar.Configurer {
|
||||
private boolean autoEnableOnServerStart;
|
||||
private boolean fixedPosition;
|
||||
private Datapack.Position position;
|
||||
|
||||
@Override
|
||||
public DatapackRegistrar.Configurer title(Component title) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatapackRegistrar.Configurer autoEnableOnServerStart(boolean autoEnableOnServerStart) {
|
||||
this.autoEnableOnServerStart = autoEnableOnServerStart;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatapackRegistrar.Configurer position(boolean fixed, Datapack.Position position) {
|
||||
this.fixedPosition = fixed;
|
||||
this.position = position;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RecordingRegistrar implements DatapackRegistrar {
|
||||
private final DiscoveryBehavior behavior;
|
||||
private final RecordingConfigurer configurer;
|
||||
private final DiscoveredDatapack discoveredDatapack;
|
||||
private Path discoveredPath;
|
||||
private String discoveredId;
|
||||
|
||||
private RecordingRegistrar(DiscoveryBehavior behavior) {
|
||||
this.behavior = behavior;
|
||||
this.configurer = new RecordingConfigurer();
|
||||
this.discoveredDatapack = new StubDiscoveredDatapack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPackDiscovered(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveredDatapack getDiscoveredPack(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeDiscoveredPack(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, DiscoveredDatapack> getDiscoveredPacks() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveredDatapack discoverPack(URI uri, String id, Consumer<Configurer> configurer) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveredDatapack discoverPack(Path path, String id, Consumer<Configurer> configurer) throws IOException {
|
||||
this.discoveredPath = path;
|
||||
this.discoveredId = id;
|
||||
if (behavior == DiscoveryBehavior.FAIL) {
|
||||
throw new IOException("discovery failed");
|
||||
}
|
||||
configurer.accept(this.configurer);
|
||||
return behavior == DiscoveryBehavior.ACCEPT ? discoveredDatapack : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveredDatapack discoverPack(PluginMeta pluginMeta, URI uri, String id, Consumer<Configurer> configurer) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveredDatapack discoverPack(PluginMeta pluginMeta, Path path, String id, Consumer<Configurer> configurer) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StubDiscoveredDatapack implements DiscoveredDatapack {
|
||||
@Override
|
||||
public String getName() {
|
||||
return IrisBootstrap.PACK_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTitle() {
|
||||
return Component.text(IrisBootstrap.PACK_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDescription() {
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Datapack.Compatibility getCompatibility() {
|
||||
return Datapack.Compatibility.COMPATIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FeatureFlag> getRequiredFeatures() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatapackSource getSource() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package art.arcane.iris;
|
||||
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginLoadOrder;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PaperPluginMetadataTest {
|
||||
@Test
|
||||
public void paperMetadataDeclaresBootstrapAndFoliaSupport() throws Exception {
|
||||
String metadata;
|
||||
try (InputStream stream = PaperPluginMetadataTest.class.getResourceAsStream("/paper-plugin.yml")) {
|
||||
assertNotNull(stream);
|
||||
metadata = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
assertTrue(metadata.contains("bootstrapper: " + IrisBootstrap.class.getName()));
|
||||
assertTrue(metadata.contains("folia-supported: true"));
|
||||
assertTrue(metadata.contains("load: STARTUP"));
|
||||
assertFalse(metadata.contains("commands:"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bukkitMetadataRetainsStartupCommandAndAliases() throws Exception {
|
||||
PluginDescriptionFile metadata;
|
||||
try (InputStream stream = PaperPluginMetadataTest.class.getResourceAsStream("/plugin.yml")) {
|
||||
assertNotNull(stream);
|
||||
metadata = new PluginDescriptionFile(stream);
|
||||
}
|
||||
|
||||
assertEquals(Iris.class.getName(), metadata.getMain());
|
||||
assertEquals(PluginLoadOrder.STARTUP, metadata.getLoad());
|
||||
Map<String, Map<String, Object>> commands = metadata.getCommands();
|
||||
assertTrue(commands.containsKey("iris"));
|
||||
assertEquals(List.of("ir", "irs"), commands.get("iris").get("aliases"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processedResourcesContainBothMetadataFormats() throws Exception {
|
||||
URL paperMetadata = PaperPluginMetadataTest.class.getResource("/paper-plugin.yml");
|
||||
assertNotNull(paperMetadata);
|
||||
assertEquals("file", paperMetadata.getProtocol());
|
||||
Path bukkitMetadata = Path.of(paperMetadata.toURI()).resolveSibling("plugin.yml");
|
||||
assertTrue(Files.isRegularFile(bukkitMetadata));
|
||||
assertFalse(Files.readString(bukkitMetadata, StandardCharsets.UTF_8).contains("${"));
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package art.arcane.iris.core.service;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PaperCommandRegistrarTest {
|
||||
@Test
|
||||
public void paperCommandDelegatesExecutionAndSuggestions() {
|
||||
RecordingCommandService service = new RecordingCommandService();
|
||||
BasicCommand command = PaperCommandRegistrar.command(service);
|
||||
CommandSender sender = sender();
|
||||
CommandSourceStack source = new TestCommandSourceStack(sender);
|
||||
String[] arguments = {"create", "world"};
|
||||
|
||||
command.execute(source, arguments);
|
||||
assertSame(sender, service.sender);
|
||||
assertEquals("iris", service.label);
|
||||
assertArrayEquals(arguments, service.arguments);
|
||||
assertEquals(List.of("first", "second"), command.suggest(source, new String[]{"cr"}));
|
||||
assertTrue(command.canUse(sender));
|
||||
}
|
||||
|
||||
private static CommandSender sender() {
|
||||
return (CommandSender) Proxy.newProxyInstance(
|
||||
CommandSender.class.getClassLoader(),
|
||||
new Class<?>[]{CommandSender.class},
|
||||
(proxy, method, arguments) -> primitiveDefault(method.getReturnType())
|
||||
);
|
||||
}
|
||||
|
||||
private static Object primitiveDefault(Class<?> type) {
|
||||
if (type == boolean.class) {
|
||||
return false;
|
||||
}
|
||||
if (type == byte.class) {
|
||||
return (byte) 0;
|
||||
}
|
||||
if (type == short.class) {
|
||||
return (short) 0;
|
||||
}
|
||||
if (type == int.class) {
|
||||
return 0;
|
||||
}
|
||||
if (type == long.class) {
|
||||
return 0L;
|
||||
}
|
||||
if (type == float.class) {
|
||||
return 0F;
|
||||
}
|
||||
if (type == double.class) {
|
||||
return 0D;
|
||||
}
|
||||
if (type == char.class) {
|
||||
return '\0';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class RecordingCommandService extends CommandSVC {
|
||||
private CommandSender sender;
|
||||
private String label;
|
||||
private String[] arguments;
|
||||
|
||||
@Override
|
||||
void executeRoot(CommandSender sender, String label, String[] args) {
|
||||
this.sender = sender;
|
||||
this.label = label;
|
||||
this.arguments = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
List<String> tabCompleteRoot(CommandSender sender, String alias, String[] args) {
|
||||
return List.of("first", "second");
|
||||
}
|
||||
}
|
||||
|
||||
private record TestCommandSourceStack(CommandSender sender) implements CommandSourceStack {
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getExecutor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withLocation(Location location) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withExecutor(Entity executor) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user