Zrips / Jobs

Jobs
Apache License 2.0
174 stars 215 forks source link

API to add custom ActionTypes #1506

Open Neovitalism opened 2 years ago

Neovitalism commented 2 years ago

Description of new idea or improvement on existing one With ActionType being an enum, it's currently not possible to create custom ActionTypes via an external plugin. It would break the current API, but I think allowing this would mean a great deal. I went to do this for a PR, but it basically requires a full re-write.

Detailed information what should do Add a class or interface that you can extend or implement to allow for custom ActionTypes. In the example below, I show my idea to make this possible:

public interface CustomActionType {
    /**
     * Place to register your Listener.
     */
    void start();

    /**
     * Place to disable your Listener.
     */
    void stop();
    // Reason I ask for start() and stop() is in case the event type is not from Bukkit.

    /**
     * Gets the name of the ActionType for use in the config.
     * @return The custom ActionType name.
     */
    String getName();

    /**
     * Checks if the action is valid based on the Jobs config.
     * @param player The causing player.
     * @param world The world the action happened in.
     * @return If the action is valid.
     */
    default boolean isValidAction(Player player, World world) {
    if (!Jobs.getGCManager().canPerformActionInWorld(world)) return false;
    if (!Jobs.getPermissionHandler().hasWorldPermission(player)) return false;
    return !Jobs.getGCManager().disablePaymentIfRiding || !player.isInsideVehicle();
    }
}
public abstract class CustomActionInfo {
    private final String type;

    public CustomActionInfo(CustomActionType customActionType) {
        // This allows for using the same CustomActionInfo for multiple CustomActionTypes.
        this.type = customActionType.getName();
    }

    /**
     * Passes the instruction string in use so you can check it against how you'd like to validate it.
     * @param instruction The action string used in the job config.
     * @return Whether or not the action fits the instruction.
     */
    public boolean validate(String instruction) {
    return false;
    }
}

Usage and Config Example:

public class MyCustomAction implements CustomActionType, Listener {
    public void start() {
    Bukkit.getPluginManager().registerEvents(this, MyCustomPlugin.getInstance());
    }

    public void stop() {
    HandlerList.unregisterAll(this);
    }

    @Override
    public String getName() {
    return "MyCustomAction";
    }

    @EventHandler
    public void onEvent(SomeEvent event) {
    Player player = event.getPlayer();
    if(!this.isValidAction(player, player.getWorld())) return;
    MyCustomActionInfo info = new MyCustomActionInfo(this);
    info.setObject(event.getObject);
    Jobs.action(Jobs.getPlayerManager().getJobsPlayer(player.getUUID()), info);  
    } 
}
public interface MyCustomActionInfo extends CustomActionInfo {
    private Object obj;

    public MyCustomActionInfo(CustomActionType customActionType) {
    super(customActionType);
    }

    public void setObject(Object obj) {
    this.obj = obj;
    }

    @Override
    public boolean validate(String instruction) {
    return obj instanceof String && ((String)obj).equals(instruction);
    // In my example config below, param instruction would be "Hello" and/or "Please", and would progress if the object matches.
    }
}
  Quests:
    '1':
      Objectives:
      - MyCustomAction;Hello;5
  MyCustomAction:
    Please:
      income: 0.25
      points: 0.25
      experience: 0.5
Zrips commented 1 year ago

This would definitely require quite big change in core payment handling if we would change Enum action types to basic Strings. Having Enums simplify things and prevents from mistakes happening. If we could work out solution which would allow for both systems to be a thing, that would be best way to go. Additionally, things like block place and break actions need to go over block protection mechanic, so something like this needs to be accounted in API too.

Neovitalism commented 1 year ago

Yeah, that's why I went for a completely different approach entirely to begin with, to keep the API in-tact. It basically just requires injection of testing for custom action types after running through the initial enum, so that way, it keeps the plugin as is, and allows for custom action types as well.