How to structure common module so the sub-modules can get the right type of objects from the APIs?

Viewed 48

Hey so I have common module that contains code show bellow and two additional modules bungee and bukkit. How would I need to structure my code so that I could use common part of code in each module but to not have to cast Object in the ChildCommand to CommandSender, is there a way to actually get the right CommandSender there instead of Object?

Some things to keep in mind:
common module has no dependencies.
bungee module uses Bungeecord API and common module as a dependency.
bukkit module uses Bukkit API and common module as a dependency.
Bukkit and Bungeecord APIs both have its own CommandSender class but they are not the same.
Classes that come from the APIs cant be modified.

This classes are part of common module.

public interface ChildCommand {
    
    void run(Object sender, String[] args);
    
    String getName();
    
}

public abstract class AbstractCommandService<S> {
    
    protected final Set<ChildCommand> childCommands;
    
    protected AbstractCommandService() {
        childCommands = new HashMap<>();
    }
    
    public boolean execute(Object sender, String commandName, String[] args) {
        for (ChildCommand childCommand : childCommands) {
            if (childCommand.getName().equalsIgnoreCase(commandName)) {
                childCommand.run(sender, args);
                return true;
            }
        }
        return false;
    }

    public void addCommand(ChildCommand command) {
        childCommands.add(command);
    }
    
}

This classes are part of bungee module.

public class BungeeReload implements ChildCommand {

    private final String NAME = "reload";

    public BungeeReload() {}

    @Override
    public String getName() {
        return NAME;
    }

    /*how do I structure my code so here I would get `net.md_5.bungee.api.CommandSender` 
    instead of `Object` for the sender parameter.*/
    @Override 
    public void run(Object sender, String[] args) {
        ((CommandSender)sender).sendMessage("Reload command has been ran on bungee.");
    }

}

public class BungeeCommandService extends AbstractCommandService<CommandSender> {}

public class MainBungeeCommand extends Command {

    private BungeeCommandService commandService;    
    
    public MainBungeeCommand() {
        super("cmd-name", "cmd-permission", "cmd-alias");
        commandService = new BungeeCommandService();

        commandService.addCommand(new BungeeReload());
    }

    @Override
    public void execute(CommandSender sender, String[] args) {
        if (args.length > 0) {
            String commandName = args[0];
           
            boolean successfullyExecuted = commandService.execute(sender, commandName, args);
            if (!successfullyExecuted) sender.sendMessage("Unknown command!"));
        } 
    }
    
}

This classes are part of bukkit module.

public class BukkitReload implements ChildCommand {

    private final String NAME = "reload";

    public BukkitReload () {}

    @Override
    public String getName() {
        return NAME;
    }

    /*how do I structure my code so here I would get `org.bukkit.command.CommandSender` 
    instead of `Object` for the sender parameter.*/
    @Override 
    public void run(Object sender, String[] args) {
        ((CommandSender)sender).sendMessage("Reload command has been ran on bukkit.");
    }

}

public class BukkitCommandService extends AbstractCommandService<CommandSender> {}

public class MainBukkitCommand implements CommandExecutor {

    private BukkitCommandService commandService;    
    
    public MainBukkitCommand() {
        commandService = new BukkitCommandService();
        commandService.addCommand(new BukkitReload());
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if (args.length > 0) {
            String commandName = args[0];
           
            boolean successfullyExecuted = commandService.execute(sender, commandName, args);
            if (!successfullyExecuted) sender.sendMessage("Unknown command!"));
            return true;
        }
        return false; 
    }
    
}

Here the classes from the APIs.
CommandSender class from the Bungeecord API.
Command class from the Bungeecord API.
CommandSender class from the Bukkit API.
CommandExecutor class from the Bukkit API.

0 Answers
Related