#Next tick execution

8 messages · Page 1 of 1 (latest)

peak dew
#

Hi,

I'm playing around with different screens to display information with pure server side code. (MC 1.21.11, yarn mapping (I want to make this work before transitioning to mojang mapping for 26.1 update) )
I've got most of it working except for switching back to a screen.

The flow of screens that causes issues:

Main screen (generic 9x6 inventory) -> Merchant screen (overriden to be mostly Read Only) <--------- this works fine

Merchant Screen -> to Main screen <-------- this causes issues

  • Overrides onClosed(PlayerEntity) to return to the main screen (new Screenhandler and factories are used, so no lingering / cached values)

I know that Screenhandlers are not thread safe, so I try to separate the opening of the new Main Screenhandler to the next tick with

// server is retrieved from the onClosed(PlayerEntity player with
if (/*some other checks*/ && player instanceof ServerPlayerEntity serverPlayer) {
  MinecraftServer server = serverPlayer.getEntityWorld().getServer();
  // from everything i read, executeSync is supposedly queing it on the Main thread, effectively the next tick, but doesn't seem to work
  server.executeSync(this::returnToMainScreenOnClose);
}

private void returnToMainScreenOnClose() {
  if (returnInfo != null && returnInfo.player().isAlive() && !returnInfo.player().isDisconnected()) {
    returnInfo.view().openMainPage(returnInfo.player(), returnInfo.page());
  }
}

But this doesn't seem to work.
The returned to Main Screen still is bugged (as in acting like a normal inventory instead of my custom logic on slots clicked. leading me to believe that the opening happens on the same tick as the closing of the previous screenhandler, causing issues with the interaction handling.)

Is there any method on the server class or elsewhere to queue something the next tick reliably or do i have to inject a tick counter in some "tick()" method and call it there?

thorny locust
peak dew
#

I'll try thanks. I've read somewhere that i shouldn't reuse screen because of the syncids but if it's in the official docs. I'll give it a try.
Just have to see if this works on server side^^

#

sadly no

INFO

This page refers to normal screens, not handled ones - these screens are the ones that are opened by the player on the client, not the ones that are handled by the server.

thorny locust
#

ah my bad im not too familiar with those

reef vortex
# peak dew Hi, I'm playing around with different screens to display information with pure ...

Is there any method on the server class or elsewhere to queue something the next tick reliably or do i have to inject a tick counter in some "tick()" method and call it there?

If there's a tick method more related to what you're doing, inject there. Otherwise, there's events for the start and end of server ticks. You can also queue stuff for execution on the server, but it's not guarenteed to execute the next tick (I think it's like within 3 ticks or something)

#

!!timer if it's been updated

elder tundraBOT
#

Fabric itself does not include APIs to schedule something in the future.

DO NOT use threads or java.util.Timer. (This can cause a crash!) Instead:

  • If you are making a block do something in the future: world.scheduleBlockTick + override scheduledTick in your Block.
  • If you are making a custom tickable stuff (usually block entity/entity) do something in the future/periodically: see below, but instead of Mixin just implement yourself
  • If you are making a vanilla tickable thing (world, server, etc) do something in the future/periodically: use the relevant tick event similar to the following.
    public static class StuffTimer implements ServerTickEvents.EndTick {
        public static final StuffTimer INSTANCE = new StuffTimer();
        private long ticksUntilSomething;
        public void setTimer(long ticksUntilSomething) {
            this.ticksUntilSomething = ticksUntilSomething;
        }
        @Override
        public void onEndTick(MinecraftServer server) {
            if (--this.ticksUntilSomething == 0L) {
                doSomething();
                // If you want to repeat this, reset ticksUntilSomething here.
            }
        }
        public static void register() {
            ServerTickEvents.END_SERVER_TICK.register(INSTANCE);
        }
    }

Usage:

    StuffTimer.INSTANCE.setTimer(100L); // do something after 100 ticks