Lua API: on_respawnplayer doesn't work

For people working on the C++ code.
Post Reply
sfan5
Moderator
Posts: 4095
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5
Location: Germany

Lua API: on_respawnplayer doesn't work

by sfan5 » Post

I'm trying to make a Fixed-Spawn Mod, but on_respawnplayer always gets called with nil.
My Code:

Code: Select all

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)
Mods: Mesecons | WorldEdit | Nuke & Minetest builds for Windows (32-bit & 64-bit)

User avatar
IPushButton2653
Member
Posts: 666
Joined: Wed Nov 16, 2011 22:47
Location: Mississippi
Contact:

by IPushButton2653 » Post

I think someone already did that. I kept respawning at the same place on his server..........i forgot who though..

User avatar
redcrab
Member
Posts: 833
Joined: Tue Dec 13, 2011 13:45
Location: France
Contact:

by redcrab » Post

got same issue.
0.4 for serious builder click here
Dedicated Minetest redcrab server forum at http://minetestbb.suret.net

It's nice to be important but it is more important to be nice.

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

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.

kahrl
Member
Posts: 236
Joined: Fri Sep 02, 2011 07:51
Location: Rös̓̇chenhof

by kahrl » Post

I don't think it has anything to do with "local".

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.)

sfan5
Moderator
Posts: 4095
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5
Location: Germany

by sfan5 » Post

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.
Doesn't help
Mods: Mesecons | WorldEdit | Nuke & Minetest builds for Windows (32-bit & 64-bit)

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

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.

Code: Select all

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.

sfan5
Moderator
Posts: 4095
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5
Location: Germany

by sfan5 » Post

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.

Code: Select all

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.
Mods: Mesecons | WorldEdit | Nuke & Minetest builds for Windows (32-bit & 64-bit)

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

Here I found the problem:

function: void Server::HandlePlayerHP(Player *player, s16 damage)

Code: Select all

    // Trigger scripted stuff
    scriptapi_on_dieplayer(m_lua, srp);
    
    // Handle players that are not connected
    if(player->peer_id == PEER_ID_INEXISTENT){
        RespawnPlayer(player);
        return;
    }

    SendPlayerHP(player);
    
    RemoteClient *client = getClient(player->peer_id);
    if(client->net_proto_version >= 3)
    {
        SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
        srp->m_removed = true;            <--  HERE
        srp->m_respawn_active = true;
    }
    else
    {
        RespawnPlayer(player);
    }
}
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.

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

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.

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

Ok, here is what I think needs to be changed:

Code: Select all

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.

randomproof
Member
Posts: 214
Joined: Thu Nov 17, 2011 06:31
Location: California, USA

by randomproof » Post

Hmm, noticed that my changes are causing you to be "respawned" when you login instead of being placed where you were when you logout.

EDIT: Ok, fixed it.
Last edited by randomproof on Fri Jan 20, 2012 20:38, edited 1 time in total.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests