Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose a way to wait until blueprints have finished loading #985

Closed
leonardochaia opened this issue Oct 13, 2019 · 2 comments
Closed

Expose a way to wait until blueprints have finished loading #985

leonardochaia opened this issue Oct 13, 2019 · 2 comments
Assignees
Labels
Status: Done This issue has been completed or answered. This pull request has been merged. Type: Bug
Milestone

Comments

@leonardochaia
Copy link
Contributor

leonardochaia commented Oct 13, 2019

Description

Is your feature request related to a problem?

In a GameModeAddon, I'd like to pragmatically create an Island "on startup" and set it as spawn point.

My initial approach:

class MyAddon extends GameModeAddon {

    @Override
    public void onEnable() {
        // [..]
        BentoBox.getInstance().getBlueprintsManager().paste(this, island, bundle, task);
    }
}

But this causes an error since blueprints have not been loaded at this stage.

[16:04:58 ERROR]: [BentoBox] Tried to paste 'island' but the bundle is not loaded!

It was suggested on Discord to try using BentoBoxReadyEvent and the new 1.8's allLoaded method, but unfortunately, these also appear to happen before blueprints are loaded as per logs below:

[15:34:09 INFO]: [BentoBox] Addons successfully enabled.
[15:34:09 INFO]:
  ____             _        ____
 |  _ \           | |      |  _ \             by tastybento and Poslovitch
 | |_) | ___ _ __ | |_ ___ | |_) | _____  __  2017 - 2019
 |  _ < / _ \ '_ \| __/ _ \|  _ < / _ \ \/ /
 | |_) |  __/ | | | || (_) | |_) | (_) >  <   v1.8.0-SNAPSHOT-LOCAL
 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\  Loaded in 1096ms.

[15:34:09 INFO]: [BentoBox] [TestSkyblock] ALL LOADED
[15:34:09 INFO]: [BentoBox] ALL LOADED: No blueprints :(
[15:34:09 INFO]: [BentoBox] BENTOBOX READY EVENT
[15:34:09 INFO]: [BentoBox] READY EVENT: No blueprints :(
[15:34:09 INFO]: [BentoBox] Added world TestSkyblock (NORMAL)
[15:34:09 INFO]: [BentoBox] Loaded Blueprint Bundle 'harder_island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded Blueprint Bundle 'custom_island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded Blueprint Bundle 'double_island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded Blueprint Bundle 'default' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'end-island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'nether-island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'double' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'custom-island' for TestSkyblock
[15:34:09 INFO]: [BentoBox] Loaded blueprint 'harder' for TestSkyblock

Describe the solution you'd like us to implement.

Maybe BentoBox could have some sort of pipeline, a queue, where tasks are pushed to and a final event or addon method is invoked when the queue has been cleared.

This would allow sync/async operations to be pushed to this "global" queue of operations, and addon developers would have a way of waiting for these to be finished.

Perhaps addon developers should be able to add tasks to this queue too.
i.e my addon requires the outcome of an async operation to start functioning properly.
If I just run an async task, other addons that could potentially use my addon's API will get an error if they use it before the task has finished.
My addon could emit an event when it's ready, or it could add it's tasks to this "global queue" and consumers would use the standard BentoBox way of "waiting for all to be ready"

Describe alternatives you've considered.

Additional context

I'm using the code below for logging the events:

public class TestAddon extends GameModeAddon {
   /// [...]

    @Override
    public void onEnable() {
        this.registerListener(new RingSkyblockBentoBoxReadyEventListener(this));

       // This of course works since it executes after.
       // If bp loading is truly async, this only works by chance.
        //Bukkit.getScheduler().runTaskLater(BentoBox.getInstance(), () -> {

        // Map<String, BlueprintBundle> bundles =
        // getPlugin().getBlueprintsManager().getBlueprintBundles(this);
        // if (bundles.size() > 0) {
        // log("Got bps");
        // } else {
        // logError("No bps");
        // }

        // }, 50);
    }

    @Override
    public void allLoaded() {
        log("ALL LOADED");

        Map<String, BlueprintBundle> bundles = getPlugin().getBlueprintsManager().getBlueprintBundles(this);
        if (bundles.size() > 0) {
            BentoBox.getInstance().log("ALL LOADED: Got Blueprints!");
        } else {
            BentoBox.getInstance().log("ALL LOADED: No blueprints :(");
        }
    }

     private class RingSkyblockBentoBoxReadyEventListener implements Listener {

        private RingSkyblockAddon addon;

        public RingSkyblockBentoBoxReadyEventListener(RingSkyblockAddon addon) {
            this.addon = addon;
        }

        @EventHandler(priority = EventPriority.LOWEST)
        public void onChunkLoad(BentoBoxReadyEvent event) {
            BentoBox.getInstance().log("BENTOBOX READY EVENT");

            Map<String, BlueprintBundle> bundles = getPlugin().getBlueprintsManager().getBlueprintBundles(addon);
            if (bundles.size() > 0) {
                BentoBox.getInstance().log("READY EVENT: Got Blueprints!");
            } else {
                BentoBox.getInstance().log("READY EVENT: No blueprints :(");
            }

        }
    }

}

Thank you guys.

@Poslovitch Poslovitch added Status: Pending Waiting for a developer to start working on this issue. Type: Enhancement Improvement or modification which is usually a new feature. labels Oct 13, 2019
@tastybento tastybento self-assigned this Oct 14, 2019
@tastybento
Copy link
Member

Hmm, I actually think this is a bug because the ready event state should only be called after the blueprints are loaded. Currently, loading is not just one async operation: It's an indeterminate number of individual async Runnables - one of each Game Mode Addon. And as it is stateless, any particular task does not know about any other task. Individual tasks could fire "I'm finished" events, but this bug needs to know when all of them are finished and for that, they need to be registered.
To fix this bug, I am going to use a list of tasks and when the list is empty, fire the event, etc. There will be a poll every tick to check if the tasks are all complete. If there's a better approach, I'm happy for someone to implement it, but this works.

@tastybento tastybento added Status: In progress Working on the issue. and removed Status: Pending Waiting for a developer to start working on this issue. Type: Enhancement Improvement or modification which is usually a new feature. labels Oct 14, 2019
@tastybento tastybento added Status: Done This issue has been completed or answered. This pull request has been merged. and removed Status: In progress Working on the issue. labels Oct 14, 2019
@Poslovitch Poslovitch added this to the 1.8.0 milestone Oct 14, 2019
@leonardochaia
Copy link
Contributor Author

Thank you very much for your quick response!

So with this change I should be able to just override allLoaded in my addon or use the event.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Done This issue has been completed or answered. This pull request has been merged. Type: Bug
Projects
None yet
Development

No branches or pull requests

3 participants