• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ [TFS 1.2] client crash when creature spawn on player, and player/creature moves

Moba2017

The singing one
Joined
Jun 19, 2017
Messages
29
Reaction score
15
Hello guys, I have some source + server for a 8.60 server with TFS 1.2 that was handed to me.

And I was working on a little custom project.
However, I faced this rather odd problem that I can't seem to figure out.

The problem:
You as player ingame, if a creature spawn on top of you, and you or the monster moves, the client crashes with error report
Code:
Player object is not where it should be, reason: hx: 8 hy: 6 hz: 0

Same thing happens, if you are logged in as gm using ghost mode and spawn a creature.
because the ghost the monster spawn on top of you, and when you or it moves, debug.

I'm not really sure where I should look for the issue, any hints would be very appreciated!

thanks <33
 
Well hard to say what server you are really using in this case, but if you are using the TFS 1.2 from Ninja you can report the issue in the thread if he is still fixing bugs on it;
[8.60] The Forgotten Server 1.2

If thats not the server you are using or if it has protocol changes we can't give you any help without the source code.
All I can say is to try and find out when and where that error is thrown from the client (ex by looking at the last sent byte) and see what the server is trying to send.

Could be a problem that an invalid value is sent or well anything, it's not easy to say without looking at the code of the "problematic function".
 
This is a stack order issue. When a creature spawns, the server tells the client, "hey, there's a new creature object at this coordinate" and it either tells the client the stack position of the creature, and the client inserts the creature at that position in the stack, or it tells the client to figure it out itself, and the client places the creature in the stack at the appropriate position based on the priority of the other objects in the stack. In the second case, the server needs to do the same thing to make sure it puts the creature at the same stack position as the client. Then, when you, or any other creature object (player, monster, npc), moves, the server tells the client, "hey, move the creature object at this coordinate and stack position to this new coordinate and you figure out the new stack position."

Knowing this, the error "Player object is not where it should be" tells us that the client and server aren't in agreement as to where the player object is. As @WibbenZ has stated, without seeing your code, this will be impossible for anyone to really help you with.
 
Well hard to say what server you are really using in this case, but if you are using the TFS 1.2 from Ninja you can report the issue in the thread if he is still fixing bugs on it;
[8.60] The Forgotten Server 1.2

If thats not the server you are using or if it has protocol changes we can't give you any help without the source code.
All I can say is to try and find out when and where that error is thrown from the client (ex by looking at the last sent byte) and see what the server is trying to send.

Could be a problem that an invalid value is sent or well anything, it's not easy to say without looking at the code of the "problematic function".
This is a stack order issue. When a creature spawns, the server tells the client, "hey, there's a new creature object at this coordinate" and it either tells the client the stack position of the creature, and the client inserts the creature at that position in the stack, or it tells the client to figure it out itself, and the client places the creature in the stack at the appropriate position based on the priority of the other objects in the stack. In the second case, the server needs to do the same thing to make sure it puts the creature at the same stack position as the client. Then, when you, or any other creature object (player, monster, npc), moves, the server tells the client, "hey, move the creature object at this coordinate and stack position to this new coordinate and you figure out the new stack position."

Knowing this, the error "Player object is not where it should be" tells us that the client and server aren't in agreement as to where the player object is. As @WibbenZ has stated, without seeing your code, this will be impossible for anyone to really help you with.

Thank you guys, I don't really know where the source comes from, but I've done some work and I can't report the problem there and even if I could I don't want to be the kind reporting a problem waiting for someone else to fix it.
I really want to learn myself how to deal with the issues :)

@Jo3Bingham
I think you're right with the server/client agreement, since when the monster spawn on player, and you move, there's a chance that both the creature and player moves right before the debug.

Could you tell me little more about that problem and maybe where in the sources I should start look for it?
Because as for now, I have no idea where to start look :(

Thanks for the help <3

I tried some for myself to track the issues in the sources,

and I came into this one:
C++:
void ProtocolGame::sendMoveCreature(const Creature* creature, const Position& newPos, int32_t newStackPos, const Position& oldPos, int32_t oldStackPos, bool teleport)
{
    if (creature == player) {
        if (oldStackPos >= 10) {
            sendMapDescription(newPos);
        } else if (teleport) {
            NetworkMessage msg;
            RemoveTileThing(msg, oldPos, oldStackPos);
            writeToOutputBuffer(msg);
            sendMapDescription(newPos);
        } else {
            NetworkMessage msg;
            if (oldPos.z == 7 && newPos.z >= 8) {
                RemoveTileThing(msg, oldPos, oldStackPos);
            } else {
                msg.addByte(0x6D);
                msg.addPosition(oldPos);
                msg.addByte(oldStackPos);
                msg.addPosition(newPos);
            }

            if (newPos.z > oldPos.z) {
                MoveDownCreature(msg, creature, newPos, oldPos);
            } else if (newPos.z < oldPos.z) {
                MoveUpCreature(msg, creature, newPos, oldPos);
            }

            if (oldPos.y > newPos.y) { // north, for old x
                msg.addByte(0x65);
                GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg);
            } else if (oldPos.y < newPos.y) { // south, for old x
                msg.addByte(0x67);
                GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg);
            }

            if (oldPos.x < newPos.x) { // east, [with new y]
                msg.addByte(0x66);
                GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg);
            } else if (oldPos.x > newPos.x) { // west, [with new y]
                msg.addByte(0x68);
                GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg);
            }
            writeToOutputBuffer(msg);
        }
    } else if (canSee(oldPos) && canSee(creature->getPosition())) {
        if (teleport || (oldPos.z == 7 && newPos.z >= 8) || oldStackPos >= 10) {
            sendRemoveTileThing(oldPos, oldStackPos);
            sendAddCreature(creature, newPos, newStackPos, false);
        } else {
            NetworkMessage msg;
            msg.addByte(0x6D);
            msg.addPosition(oldPos);
            msg.addByte(oldStackPos);
            msg.addPosition(creature->getPosition());
            writeToOutputBuffer(msg);
        }
    } else if (canSee(oldPos)) {
        sendRemoveTileThing(oldPos, oldStackPos);
    } else if (canSee(creature->getPosition())) {
        sendAddCreature(creature, newPos, newStackPos, false);
    }
}

And I replaced the move functions with teleport functions so it looks like this:
C++:
void ProtocolGame::sendMoveCreature(const Creature* creature, const Position& newPos, int32_t newStackPos, const Position& oldPos, int32_t oldStackPos, bool teleport)
{
    if (creature == player) {
        if (oldStackPos >= 10) {
            sendMapDescription(newPos);
        } else if (teleport) {
            NetworkMessage msg;
            RemoveTileThing(msg, oldPos, oldStackPos);
            writeToOutputBuffer(msg);
            sendMapDescription(newPos);
        } else {
            NetworkMessage msg;
            RemoveTileThing(msg, oldPos, oldStackPos);
            writeToOutputBuffer(msg);
            sendMapDescription(newPos);
        }
    } else if (canSee(oldPos) && canSee(creature->getPosition())) {
        if (teleport || (oldPos.z == 7 && newPos.z >= 8) || oldStackPos >= 10) {
            sendRemoveTileThing(oldPos, oldStackPos);
            sendAddCreature(creature, newPos, newStackPos, false);
        } else {
            sendRemoveTileThing(oldPos, oldStackPos);
            sendAddCreature(creature, newPos, newStackPos, false);
        }
    } else if (canSee(oldPos)) {
        sendRemoveTileThing(oldPos, oldStackPos);
    } else if (canSee(creature->getPosition())) {
        sendAddCreature(creature, newPos, newStackPos, false);
    }
}

This solved the crashes, but ofc monsters/players walking isn't smooth anymore as they're just "teleported" in the direction they're walking.
But it came up with another problem,
as I tried different things.

1: in /ghost on admin, spawning monster ontop of me, and I walk out = everything fine, with exception my charcter jumps instead of walk.
2: with same, I spawned a wild rat, then I walked out of it, and summoned an Orc, as the orc left my tile, I became the orc, when orc turns, my "orc char" turns as well, but when I move out of the tile, I become the ghost admin again as normal.
Yh4nn9R.png


I'll try as hard I can to track this down but I'd really appreciate pointers where I should go look next :)

Edit:
This problems occur when it's about fresh spawns, if players/monsters cross eachother at stairs or by TPs, nothing happens, the debug only happens when fresh monster is created ontop of a player and the player or monster moves :)
Thought I should clear that out :)

Edit:
This is what happens when monster spawn on top of me,
If I dance before either moves, no crash but obviously a bug occurs.
If I don't dance and one move, client debugs.

<stupid gif wont work>
 
Last edited by a moderator:
Since you said it's only spawned creatures this affects, I would suggest starting with the code that spawns a creature and walking through it until you get to the code that sends a CreateOnMap (0x6A) packet to the client and the code that stores that creature in the object list of a tile. Then compare the values that are used in each function (mainly the stack position).
 
Since you said it's only spawned creatures this affects, I would suggest starting with the code that spawns a creature and walking through it until you get to the code that sends a CreateOnMap (0x6A) packet to the client and the code that stores that creature in the object list of a tile. Then compare the values that are used in each function (mainly the stack position).

I'll see what I can find, the other day I tried to backtrace the spawn part and found some functions that contained stackpos, and I tried to play around with them (not a good idea).
My tests caused the client to crash whenever something moves.

I've also noticed this problem is not only for spawning monsters, same thing happens with players.
It's not 100% the same (I think) but me and a few friends of mine tried to make a mass log, kinda like server start, so 7 new characters logged in at same time ontop of eachother and caused a few to get debugs.

I'll keep looking, thanks for the reply :)
 
sorry for revive this topic but i had the same issue and its fixed changing this on tile.cpp :
Code:
creatures->insert(creatures->begin(), creature);
for :
Code:
creatures->insert(creatures->end(), creature);
 
Back
Top