The problem is as follows. Let's say we have two players: Player 1 and Player 2. Both players login. Let's say Player 1 decides to log off. If Player 1 then logs back on his movement will no longer be updating on Player 2's screen. Essentially, a "ghost" of Player 1 is drawn, and then never updated. If Player 2 then leaves and then re-enters the room, this ghost of Player 1 disappears, never to return.
There is a second bug, which occurs when the second player to join is the one who leaves.
I have fixed both bugs. This post documents one fix, and the post below documents the other fix. Please see the below post for "patched" Game Maker files, a.k.a. Basic Engine v1.2!Note: In the spirit of educating others I will leave the following documentation of my thought process for dealing with this bug. I would consider myself a novice/intermediate programmer so I'm not the most efficient, but reading this documentation might help others to contemplate similar problems, or problem solving in general.Conditions that produce the bug:
Player 1 connects
Player 2 connects
Player 2 disconnects
The server-side list contains
[Player2] but should contain
[Player1]. In other words, the server still thinks that Player2 is connected when in fact Player1 is connected! This allows for multiple instances of Player1, which is very bad. Therefore, the server isn't correctly updating the list of players. I am not sure why it is deleting the first entry in the list...
UPDATE 1:When the server deletes a player it uses the following code:
ds_list_delete(global._playernames,list_place)
The player which is deleted is determined by list_place. Each player object has a list_place variable. In theory, the first player to join should get 0, the second 1, the third 2. However as it is right now this variable is never changed so every player object inherits a list_place of 0. This appears to be the root of the problem.
UPDATE 2:I found a solution to this problem. In the server's obj_player Create event, the code is as follows:
/*
This script will be executed once a new Player entered the game.
We'll now refresh some existing variables and inform other Players about this Player.
Also this new Player needs to get informed that other Players are currently connected to the game.
*/
global._playing +=1 //Increase the number of Players that are currently online to draw it on the Server Screen
playerid = iniReadReal(_accpth,'INFO','PlayerID',0) //Read the Id of the Player from his Account file
//The Player logged in and we add his name to the list of currently connected Players
//This is needed to prevent Players to login with the same account twice (Optionally you could use the Player ID to get the same effect)
list_place = ds_list_add(global._playernames,string_lower(_name))
If instead list_place assumes the value of global._playing before this variable is updated, then each object player will refer to the correct position on the array. For example:
list_place = global._playing
global._playing +=1 //Increase the number of Players that are currently online to draw it on the Server Screen
playerid = iniReadReal(_accpth,'INFO','PlayerID',0) //Read the Id of the Player from his Account file
Now the second player to login can log out and back in without any trouble.
Unfortunately, users can now login twice with the same account.
UPDATE 3:I've found a solution to the logging in problem, but it creates another problem. Using the following code:
list_place = global._playing
global._playing +=1 //Increase the number of Players that are currently online to draw it on the Server Screen
playerid = iniReadReal(_accpth,'INFO','PlayerID',0) //Read the Id of the Player from his Account file
//The Player logged in and we add his name to the list of currently connected Players
//This is needed to prevent Players to login with the same account twice.
ds_list_add(global._playernames,string_lower(_name))
The second player can now log in and out and back in. However, if the second player logs out, then the first player logs out, then Player 1 is still on the server list of players. There is still something wrong with list_place's value...
This only occurs when the following happens:
Player 1 joins.
Player 2 joins.
Player 1 quits.
Player 2 quits.
And it appears that this is because the server still thinks Player 2 is in list_place 1. Somehow, I need to decrement all players at a list place above a player that leaves. How would I do this?
UPDATE 4:How? Elementary, dear Watson. The simple approach is to enter a loop for every instance of obj_player on the server-side where list_place is greater than the player who is exiting.
This can be done by entering the following code into obj_player's alarm[0] event (which is executed when a player quits).
k = list_place
if k < global._playing {
do
{
i = (instance_find(obj_player,k+1))
i.list_place -= 1
k+=1
}
until (k = global._playing);
}I have run some tests with up to 4 players and the variables are changing as they should be. Problem solved!
Edited by raubaut, 05 July 2011 - 10:56 PM.