Carpet

Carpet

2M Downloads

schedule() loop sometimes doesn't read global variables properly

Xendergo opened this issue ยท 6 comments

commented

If you have a loop where a function schedules itself, under some circumstances, the function can't read global variables properly

If you paste this into a file:

global_thingy = 1;

x() -> (
    print(global_thingy);
    schedule(20, 'x');
);

x();

run it, and then run /script in *name* run global_thingy = 2, it still prints 1 afterwards. However, if you paste it into chat instead and do the same thing, it works properly. It also works properly if you paste this in a file:

global_thingy = 1;

x() -> (
    print(global_thingy);
    schedule(20, 'x');
);

schedule(60, _() -> (global_thingy = 2));
x();

However it doesn't work properly when doing this:

__config()->{
    'commands' -> {
        'changeValue' -> _() -> (global_thingy = 2)
    }
};

global_thingy = 1;

x() -> (
    print(global_thingy);
    schedule(20, 'x');
);

x();
commented

Its all indended, but indeed hella confusing. Its all because you are running a player scoped app, so sometimes you trigger its global instance (like when loading), and sometimes its player counterpart (when typing commands). I really should find some time some day to write a small piece in the docs with the images explaining how player apps work.

Tl;dr; its not a bug - it works as intended, just the documentation of player scoped apps is not great.

commented

Interesting, that's good to know.

Maybe in that case there should be some way to force scarpet to run something in the global instance?

commented

yes, there is -

// in code
__config() -> {'scope' -> 'global'}

or

/script load app global

https://github.com/gnembon/fabric-carpet/blob/master/docs/scarpet/Full.md#app-structure

commented

I will not close it cause it reminds that more documentation with visuals is needed for that.

commented

Then, is there any way to "pre-set" (on load) variables or schedules for every player scope? (or just run arbitrary code on the player scope when loading)

Or is that currently impossible?

Of course you could do something like

__on_tick() -> (
	preload();
	undef('__on_tick');
);

But is there any "native" way to do that?

(I really thought code running in there would be specific for the player scope, didn't know since I almost never really used the player scope)

EDIT: Maybe __on_player_connects, but still doesn't look native.

commented

well, you can preset whatever you want - the global state (variables, defined functions, imports and a few other things) will be copied over to each player instance. It all should be doubled for the player providing its not volatile.

Just in this case we have seen a scheduled call from that instance that still would target that shared instance when triggered, not the player specific one.