Creating a delay timer

I made a delay timer using the good ol java way.

        try
        {
            player.sendMessage(Text.of("Teleporting to a random location in a few seconds..."));
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        player.sendMessage(Text.of("Teleporting..."));
        player.setLocationSafely(random);

This makes the whole server “sleep” for 5 seconds, which is something I don’t want.

https://docs.spongepowered.org/master/en/plugin/scheduler.html?highlight=scheduler

1 Like

Keep this in mind for the future - everything happens on the same thread.

Also note that you can just call Task.builder() without asking for the Scheduler.

1 Like

I don’t think I’m getting this. I’ve tried:

        Scheduler scheduler = Sponge.getScheduler();
        Task.Builder taskBuilder = scheduler.createTaskBuilder();

        Task task = taskBuilder.execute(() -> player.sendMessage(Text.of("Teleporting...")))
            .async()
            .delay(5000, TimeUnit.MILLISECONDS)
            .submit(Sponge.getPluginManager().getPlugin("my.plugin"));

Only as a test to see if it would delay the teleport message. I only received errors on the console when I run the command.

  1. Running the task async is good for tasks like network IO, reading from a database, or reading and writing to files.
  2. Most of the SpongeAPI is not thread-safe. This means you should not call most methods in the API from an async task.

So, drop the .async on that task.

1 Like

I suppose that would be useful for Mysql.

I’m still confused with how the scheduler works, so I’m trying to replicate something simple so I can get a better understanding (delaying a message). So I updated the code to this:

        Sponge.getScheduler().createTaskBuilder()
            .execute(() -> player.sendMessage(Text.of("Teleporting...")))
            .delay(5000, TimeUnit.MILLISECONDS);

I’m assuming I don’t need “.submit” since it’s on the same plugin.

You do need to submit the task. A method doesn’t know what’s calling it, and it doesn’t automatically run itself.

Meanwhile, again, remember that EVERYTHING in MC is single threaded. If it interacts with Sponge, it should happen on the main thread.

Also, you could just do 5, TimeUnit.SECONDS. That’s the point of TimeUnit.

1 Like

Thank you for pointing that out. I think I’m starting to understand. :slight_smile:

I do have one more question and it’s probably something I should already know. How do I get the plugin object from itself?

        Sponge.getScheduler().createTaskBuilder()
            .execute(() -> player.sendMessage(Text.of("Teleporting...")))
            .delay(5, TimeUnit.SECONDS)
            .submit(???);

I think I could use an example. :confused:

Sorry I would have replied sooner, but I had logged out of the forums to test something and couldn’t get back in for a while.
Assuming that this is being called from your main plugin class, annotated with @Plugin.

            Sponge.getScheduler().createTaskBuilder()
                .execute(() -> player.sendMessage(Text.of("Teleporting...")))
                .delay(5, TimeUnit.SECONDS)
                .submit(this);

If you are calling it elsewhere, either make a static field on your plugin class with a reference to “this” , or pass it through the constructors.

1 Like

Oh wow, I feel silly. Thank you so much, I was literally pulling my hair. I didn’t think “plugin” was a reference to the main class.