FlashyReese / CommandAliases

Alternate short commands for complex commands
MIT License
25 stars 6 forks source link

Better Command Action Scheduling System #51

Open FlashyReese opened 1 year ago

FlashyReese commented 1 year ago

The issue at hand: https://github.com/FlashyReese/CommandAliases/blob/44c88ee30c565e7e7cc1edc521094aaef67bafda/src/main/java/me/flashyreese/mods/commandaliases/command/builder/custom/AbstractCustomCommandBuilder.java#L300-L376

The current implementation of the custom command builder method is less efficient than the previous version. The previous version utilized a new thread to call variables, but this caused issues with certain mods like Immersive Portals. The current version uses a scheduler for commands, but this approach has a drawback in that it does not wait for custom commands to finish before scheduling the next one. This can lead to issues with sub-actions not completing before the next action is scheduled.

This is a problem because we use an atomic integer to return the state of our custom commands when we call them within command actions. When the scheduler is used, it can interfere with the state of our data if we are working with the database, leading to unexpected results.

We are seeking suggestions for alternative methods of implementation that do not involve summoning new threads. Feedback on this issue is greatly appreciated.

image (An outdated image sketch that inadequately demonstrates the current issue)

FlashyReese commented 1 year ago

To better illustrate the issue, I have created a custom command using an older version of the software. The command is structured as shown below:

{
  "commandMode": "COMMAND_CUSTOM",
  "customCommand" : {
    "parent": "example",
    "actions": [
      {
        "command": "say action 1",
        "commandType": "SERVER",
        "successfulActions": [
          {
            "command": "say action1 subaction 1",
            "commandType": "SERVER",
            "requireSuccess": true
          },
          {
            "command": "say action1 subaction 2",
            "commandType": "SERVER"
          }
        ],
        "unsuccessfulActions": [
          {
            "command": "say action1 subaction 1 failed",
            "commandType": "SERVER",
            "requireSuccess": true
          },
          {
            "command": "say action1 subaction 2 failed",
            "commandType": "SERVER"
          }
        ]
      },
      {
        "command": "say action 3",
        "commandType": "SERVER"
      }
    ]
  }
}

When the command is run, it produces the following output: image

To work around this implementation issue, one solution is to add a delay. However, this is not ideal as we want our code to be as fast as possible. An example of this workaround is shown below:

{
  "commandMode": "COMMAND_CUSTOM",
  "customCommand" : {
    "parent": "example",
    "actions": [
      {
        "command": "say action 1",
        "commandType": "SERVER",
        "successfulActions": [
          {
            "command": "say action1 subaction 1",
            "commandType": "SERVER",
            "requireSuccess": true
          },
          {
            "command": "say action1 subaction 2",
            "commandType": "SERVER"
          }
        ],
        "unsuccessfulActions": [
          {
            "command": "say action1 subaction 1 failed",
            "commandType": "SERVER",
            "requireSuccess": true
          },
          {
            "command": "say action1 subaction 2 failed",
            "commandType": "SERVER"
          }
        ]
      },
      {
        "triggerTime": "50",
        "command": "say action 3",
        "commandType": "SERVER"
      }
    ]
  }
}
FlashyReese commented 1 year ago

One idea that comes to my mind is replacing/refactoring the scheduler system to use CompletableFuture. This should eliminate certain pitfalls like needing to wait for command return states.