Show black screen while creating new World

Discussion in 'Plugin Development' started by JimiIT92, Nov 2, 2022.

Thread Status:
Not open for further replies.
  1. Offline

    JimiIT92

    I'm developing a Realms plugin where Players can create their own Worlds and teleport to them.
    While their World is created I want to show a black screen to them and I found that a way to do that is to constantly send the ClientboundGameEventPacket with the WIN_GAME action and the value of 1 every 5 o 10 ticks. Essentially I'm constantly starting the end credits, since they have the black screen in the beginning.
    What I've tried so far is this:
    - Run a looping async task where I send the packet to the player
    - Run a sync task where I create the World and then, when done, cancel the async task sending another packet with the value of 0 (so the credits ends)

    However I've noticed something odd: the async task runs the first time but as soon as the World creation start, the task freeze. As soon as the World is created, the looping async task continues and after a while it gets cancelled as expected.
    But this defeates the purpose, since when the first task freezes the screen is not showing (is too quick to continue).
    I don't understand why it freeze, since both the packet sending and the World generation happens on different Threads.

    Codewise this is how I handle those threads:
    First I start the async packet sending task

    Code:
    new BukkitRunnable(){
                @Override
                public void run() {
                    ClientboundGameEventPacket packet = new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, 1);
                    ((CraftPlayer)player).getHandle().connection.send(packet);
                }
            }.runTaskTimerAsynchronously(Realms.getInstance(), 0L, 5L);
    Then I start the sync World generation task

    Code:
    new BukkitRunnable() {
                @Override
                public void run() {
                              World world = new WorldCreator("test")
                                            .type(WorldType.NORMAL)
                                            .environment(World.Environment.NORMAL)
                                            .createWorld();
                               if(world != null) {
                                              world.setKeepSpawnInMemory(false);
                                              WorldBorder worldBorder =  world.getWorldBorder();
                                              worldBorder.setSize(200);
                                              worldBorder.setCenter(0, 0);
                              }
                }
    }.runTaskLater(Realms.getInstance(), 20L);
    By the way I know I can use the scheduler, but I'm not sure if it can handle async correctly since the async methods are marked as deprecated.

    Anyway, if I put a log inside both tasks, the logger will output this

    Code:
    [10:21:51 INFO]: [ebl-realms] [STDOUT] async
    [10:21:52 INFO]: [ebl-realms] [STDOUT] async
    [10:21:52 INFO]: [ebl-realms] [STDOUT] async
    [10:21:52 INFO]: [ebl-realms] [STDOUT] async
    [10:21:52 INFO]: [ebl-realms] [STDOUT] sync
    [10:21:57 INFO]: [ebl-realms] [STDOUT] async
    [10:21:57 INFO]: [ebl-realms] [STDOUT] async
    ....
    
    so what it does is running the async task for a while, then freeze it for a while (until the sync task ends) and then continue.
    But how can I avoid the sync task interferee with the execution of the async one? How can I run both tasks at the same time?

    I would like to run both async, but World creation must be called from a sync task :/
     
  2. Offline

    timtower Administrator Administrator Moderator

    @JimiIT92 Server can only do one thing at the time.
     
  3. Offline

    JimiIT92

    That's unfortunate... So then how can I generate a world "in background", without having the server hang for a while?
     
  4. Offline

    Kars

    That's weird that shouldn't happen. That is the whole purpose of async tasks. Unless Bukkit's async is handled different somehow?
    Try using an executor. A SingleThreadExecutor will do. This handles everything in a different thread and so it is asynchronous by default.

    Let me know the results.
     
  5. Offline

    timtower Administrator Administrator Moderator

    Maybe networking is on the main thread?
     
  6. Offline

    Kars

    Could be.
     
Thread Status:
Not open for further replies.

Share This Page