Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cRoot:ForEachPlayer does not report players that haven't been spawned yet #5534

Open
sleirsgoevy opened this issue Oct 19, 2023 · 2 comments

Comments

@sleirsgoevy
Copy link
Contributor

Client version: 1.8.9
Server OS: Linux
Cuberite Commit id: ca705be (latest at the time of posting)

If a player has already joined, but hasn't been spawned into a world yet, cRoot:ForEachPlayer does not iterate over them.

Expected behavior

The callback is called for the player.

Actual behavior

The callback is only called for spawned players.

Steps to reproduce the behavior

Use a slow enough HDD and start the server after a cold boot. I'm not sure how to reproduce this reliably.

Server log

[e183258daeca7b2c|22:39:53] Player "sleirsgoevy2" (200ca00062743a1a8b8861272ca8a214) save or statistics file not found, resetting to defaults
[e183258daeca7b2c|22:39:53] Player "sleirsgoevy2" with save file "players/20/0ca000-6274-3a1a-8b88-61272ca8a214.json" is spawning at {-0.00, 181.00, -1.70} in world "world"
[e183258daeca7b2c|22:39:53] Player sleirsgoevy2 has joined the game
StartGame: uuid = f27ab396f620382b8f774f975552102c, name = sleirsgoevy
 => is lonely
[e183258daeca7b2c|22:39:53] LUA: Plugins/myPlugin/game.lua:108: n_players = 1, num_players = 2
[e183258daeca7b2c|22:39:53] Stack trace:
[e183258daeca7b2c|22:39:53]   [C](-1): error
[e183258daeca7b2c|22:39:53]   Plugins/myPlugin/game.lua(108): StartGame
[e183258daeca7b2c|22:39:53]   Plugins/myPlugin/main.lua(45): (no name)
[e183258daeca7b2c|22:39:53] Stack trace end
[e183258daeca7b2c|22:39:53] LUA: BreakIntoDebugger() not found / not a function
[e183258daeca7b2c|22:39:53] Error in <attached> calling function <callback>()
[feea04b9f30180cb|22:39:53] Adding player sleirsgoevy2 to world "world".
[feea04b9f30180cb|22:39:53] Spawning player "sleirsgoevy2" on client "sleirsgoevy" @ ::ffff:127.0.0.1
[feea04b9f30180cb|22:39:53] sleirsgoevy2 is requesting ViewDistance of 10!

Note: StartGame here is being called from a tick callback, not from the PLAYER_JOINED callback.

@tonitch
Copy link
Contributor

tonitch commented Oct 20, 2023

cRoot:ForEachPlayer indeed check for each player per world so if the player is not in the world, it wouldn't call.

cuberite/src/Root.cpp

Lines 681 to 691 in ca705be

bool cRoot::ForEachPlayer(cPlayerListCallback a_Callback)
{
for (auto & Entry : m_WorldsByName)
{
if (!Entry.second.ForEachPlayer(a_Callback))
{
return false;
}
}
return true;
}

can you give us a sample of your code ? I don't see why it give's an error, it should just ignore it I guess ?

@sleirsgoevy
Copy link
Contributor Author

TL;DR: I added an explicit assert that the number of callback calls equals the number reported by cRoot:GetNumPlayers().

I was troubleshooting an issue in my mini-game plugin, that upon starting a game some players were not assigned into teams. Per the plugin logic, 1 tick after the last player has joined and GetNumPlayers reports that the server is full, ForEachPlayer runs and assigns players into teams. Due to this bug, some players were not assigned into any team.

A workaround I've found is the following:

  1. For each player join, only record a join when the SPAWNED callback is called for that player.
  2. Do not use GetNumPlayers to get the number of players, instead count the players manually using cRoot:ForEachPlayer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants