Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 51 additions & 13 deletions programs/utilities/keepalive.sc
Original file line number Diff line number Diff line change
@@ -1,21 +1,59 @@
// re-logs fake players upon server restart
// must need to place it directly in the world scripts folder

__config() -> {'scope' -> 'global'};
__config() -> {
requires -> {
'minecraft' -> '>=1.8', // spectator was not a thing prior to 1.8
},
'scope' -> 'global'
};

__on_connect(e) -> (
// forcing the fake-players that were spawned in spectator back into creative to retain flight per their data
if(e:'gm' == 'creative' && e:'fly' == 1,
sleep(50); // the direct delay is needed to force it back into the proper gamemode. it cannot for the life of it do so at the exact same moment and requires the delay.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using sleep and running this in a task might introduce other race conditions. I would suggest just running it at the end of the tick with schedule(0, ...) and not in a task

for([str('gamemode %s %s', e:'gm', e:'name')],
logger('warn', _);
run(_);
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For running this single command a loop is not neccesary, and in general, I don't really see a need to also log the command. In my opinion it would suffice to use modify(..., 'gamemode', ...)

);
);

__on_player_connects(player) -> (
data = load_app_data();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading this data on every player connection (even non fake ones and after server startup) feels unnecesary. I would suggest loading this data once in __on_connect and storing it in a global variable (ideally converted to a map with the player names as keys for quick access, instead of the foor loop in line 29). Then on every connect you can just check if the connected player's name is in that map. If so, change the gamemode and remove it from the map, so future connections of this player won't have it's gamemode changed.

if (data && data:'players',
data = parse_nbt(data:'players');

player_name = player()~'name';

for (data,
// we're detecting if the player connecting is a fake-player, thus guaranteeing that the player entity object exists and can be used
if (_:'name' == player_name,
task('__on_connect', _)
);
);
);
);


__spawn_players() -> (
data = load_app_data();
if (data && data:'players',
data = parse_nbt(data:'players');
for (data,
for([str('player %s spawn at %f %f %f facing %f %f in %s',
_:'name', _:'x', _:'y', _:'z', _:'yaw', _:'pitch', _:'dim'),
str('gamemode %s %s', _:'gm', _:'name')],
logger('warn', _);
run(_);
);
modify(player(_:'name'), 'flying', _:'fly')
)
data = load_app_data();
if (data && data:'players',
data = parse_nbt(data:'players');
for (data,
if (_:'gm' == 'creative' && _:'fly' == 1,
// spawning creative fake-players in spectator to force the flying state as using modify throws an error due to potential race conditions
for([str('player %s spawn at %f %f %f facing %f %f in %s in spectator', _:'name', _:'x', _:'y', _:'z', _:'yaw', _:'pitch', _:'dim')],
logger('warn', _);
run(_);
);
, _:'gm' != 'creative',
for([str('player %s spawn at %f %f %f facing %f %f in %s in %s',_:'name', _:'x', _:'y', _:'z', _:'yaw', _:'pitch', _:'dim', _:'gm')],
logger('warn', _);
run(_);
);
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nearly the same thing twice, use a temporary variable for the gamemode and use that in the command (overwrite it to spectator if flying).
The for loop is not needed here.
These two if conditions do not cover non-flying creative players, which makes them be ignored and not respawned at all.

);
);
);

Expand Down