Code Patterns

Copy-paste examples for common plugin tasks. Commands, events, ECS, GUI, and more.

← Back to Patterns
command

Async Command with World Access

Pattern for async commands that need to access the world/ECS. Based on working AdminUI code.

Example Code

java
public class MyAsyncCommand extends AbstractAsyncCommand {

    public MyAsyncCommand() {
        super("mycommand", "Description here");
    }

    @Override
    protected CompletableFuture<Void> executeAsync(CommandContext context) {
        CommandSender sender = context.sender();

        // Check if sender is a player
        if (!(sender instanceof Player player)) {
            context.sendMessage(Message.raw("Players only!").color(Color.RED));
            return CompletableFuture.completedFuture(null);
        }

        // Get player reference and validate
        Ref<EntityStore> ref = player.getReference();
        if (ref == null || !ref.isValid()) {
            context.sendMessage(Message.raw("Not in world!").color(Color.RED));
            return CompletableFuture.completedFuture(null);
        }

        // Get store and world
        Store<EntityStore> store = ref.getStore();
        World world = store.getExternalData().getWorld();

        // Execute on world thread
        return CompletableFuture.runAsync(() -> {
            PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
            player.sendMessage(Message.raw("Done!").color(Color.GREEN));
        }, world);  // Pass world as executor!
    }
}

Thread Safety

Execute ECS operations inside CompletableFuture.runAsync() with world as executor

Common Mistakes

Not checking if ref.isValid() before use. Forgetting to pass world as executor to runAsync(). Trying to modify ECS outside world thread.