local function readspawn()
local inp = io.open(minetest.get_modpath('fixed_spawn')..'/spawn')
local x = inp:read("*n")
if x == nil then
io.close(inp)
return {x = 0,y = 0,z = 0}
end
local y = inp:read("*n")
local z = inp:read("*n")
io.close(inp)
return {x = x,y = y,z = z}
end
minetest.register_on_newplayer(function(player)
if player ~= nil then
player:setpos(readspawn())
return true
end
return false
end)
minetest.register_on_respawnplayer(function(player)
print(dump(player))
if player ~= nil then
player:setpos(readspawn())
return true
end
return false
end)
I tried your code on my computer and it works fine. 'player' is not nil for me.
Edit1: The first time I cut and pasted just the "register_on_respawnplayer" function and it worked. Now that I copied all of the code it doesn't.
Edit2: Make readspawn() not local and try again. I don't know why that would make player nil, but you can't call a local function from another function like that.
Last edited by randomproof on Sun Jan 15, 2012 05:37, edited 1 time in total.
I suspect there are some weird issues with active objects going on here. When a player dies, its m_remove flag is set to true, so the environment might remove it. When respawning, the player gets a new ID but that isn't properly registered on the Lua side... or something strange like that. (Disclaimer; I haven't actually read the code so all of that might be wrong.)
randomproof wrote:I tried your code on my computer and it works fine. 'player' is not nil for me.
Edit1: The first time I cut and pasted just the "register_on_respawnplayer" function and it worked. Now that I copied all of the code it doesn't.
Edit2: Make readspawn() not local and try again. I don't know why that would make player nil, but you can't call a local function from another function like that.
07:25:19: ACTION[ServerThread]: Steven5 damaged by 34 hp at (-25.045,15.942,29.322)
07:25:19: INFO[ServerThread]: Server::HandlePlayerHP(): Player Steven5 dies
07:25:19: INFO[ServerThread]: Server: Sent object remove/add: 1 removed, 0 added, packet size is 8 <---Here
07:25:19: INFO[main]: ClientEnvironment::removeActiveObject(): id=1 <--- And here
07:25:20: INFO[ServerThread]: Server::RespawnPlayer(): Player Steven5 respawns
07:25:20: ACTION[ServerThread]: Server::RespawnPlayer(): srp != NULL
07:25:20: ACTION[ServerThread]: scriptapi_on_respawnplayer(): player != NULL id=1 <---See, same id that was removed
I'll look some more for a code, now that I know what functions are involved.
randomproof wrote:Added some debug code to the function involved and found that the player is being removed from "object_refs" before the on_respawn code is run.
07:25:19: ACTION[ServerThread]: Steven5 damaged by 34 hp at (-25.045,15.942,29.322)
07:25:19: INFO[ServerThread]: Server::HandlePlayerHP(): Player Steven5 dies
07:25:19: INFO[ServerThread]: Server: Sent object remove/add: 1 removed, 0 added, packet size is 8 <---Here
07:25:19: INFO[main]: ClientEnvironment::removeActiveObject(): id=1 <--- And here
07:25:20: INFO[ServerThread]: Server::RespawnPlayer(): Player Steven5 respawns
07:25:20: ACTION[ServerThread]: Server::RespawnPlayer(): srp != NULL
07:25:20: ACTION[ServerThread]: scriptapi_on_respawnplayer(): player != NULL id=1 <---See, same id that was removed
I'll look some more for a code, now that I know what functions are involved.
Can you make a Patch which fixed this?
Last edited by sfan5 on Thu Jan 19, 2012 15:49, edited 1 time in total.
m_removed is set to 'true' here. On the next server:step the object ref is deleted from LUA. I think this is to remove a players character from the environment so other players can't see him anymore. So the problem is that 'void Server::RespawnPlayer(Player *player)' is called before the player ref is re-added to LUA.
sfan5 wrote:
Can you make a Patch which fixed this?
I'm working on it. I think you could just comment out the "srp->m_removed = true;" line.
The other option is to find where the player obj is added back into LUA and make sure that happens before on_respawn is called.
Last edited by randomproof on Thu Jan 19, 2012 15:56, edited 1 time in total.
diff --git a/src/server.cpp b/src/server.cpp
index d704bf8..92f8815 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1291,6 +1291,11 @@ void Server::AsyncRunStep()
player->m_removed = false;
player->setId(0);
m_env->addActiveObject(player);
+ if (player->hp == 0)
+ {
+ RespawnPlayer(player);
+
+ actionstream<<player->getName()<<" respawns at "
+ <<PP(player->getPosition()/BS)<<std::endl;
+ }
}
}
}
@@ -2819,10 +2824,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
srp->m_respawn_active = false;
- RespawnPlayer(player);
- actionstream<<player->getName()<<" respawns at "
- <<PP(player->getPosition()/BS)<<std::endl;
// ActiveObject is added to environment in AsyncRunStep after
// the previous addition has been succesfully removed
@@ -4520,7 +4524,7 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
{
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
- if(srp->m_respawn_active)
+ if(srp->m_respawn_active || !srp->m_is_in_environment)
return;
if(player->hp > damage)
This moves the call to RespawnPlayer to after the player's obj ref is added back into the environment. I'll start testing this and get back to you in a few if it seems to work.
EDIT1: Nope. One minute.
EDIT2: OK. I think this works. Someone try it and tell me if it is good.
Last edited by randomproof on Fri Jan 20, 2012 20:37, edited 1 time in total.