Save last pos not working upon serv restart
#1

Hey,

So I created a system that saves the user's last position when they disconnect, which on a daily basis works fine. However when I use /gmx , or use the server control panel, to stop and start the server, all user's spawn in Blueberry, I was wondering if anyone could tell what could cause this?
Код:
public OnPlayerDisconnect(playerid, reason)
{
    KillTimer(stimer[playerid]);
    SaveAccount(playerid);
   	if(reason == 0)
	{
	 	SendConnectionMessage(playerid, 2);
	}
	else if(reason == 1)
	{
	    SendConnectionMessage(playerid, 3);
	}
	else
	{
	    SendConnectionMessage(playerid, 0);
	}
    return 1;
}
Код:
public OnGameModeExit()
{
	for(new i=0; i<MAX_PLAYERS; i++){
	SaveAccount(i);
    TextDrawDestroy(Zones[i]);}
	return 1;
}
Код:
public SaveAccount(playerid)
{
	new Float: x, Float: y, Float:z, Float: a;
	GetPlayerPos(playerid, x,y,z);
	GetPlayerFacingAngle(playerid, a);
	
	PlayerInfo[playerid][pXPos] = x;
	PlayerInfo[playerid][pYPos] = y;
	PlayerInfo[playerid][pZPos] = z;
	PlayerInfo[playerid][pAPos] = a;

	new h, m, s;
    TotalGameTime(playerid, h, m, s);
	new INI:File = INI_Open(UserPath(playerid));
	INI_SetTag(File, "data");
	INI_WriteInt(File, "Cash", GetPlayerMoney(playerid));
	INI_WriteInt(File, "Admin", PlayerInfo[playerid][pAdmin]);
	INI_WriteInt(File, "UCAdmin", PlayerInfo[playerid][pUCAdmin]);
	INI_WriteInt(File, "DriversLicense", PlayerInfo[playerid][pDriverLicense]);
	INI_WriteInt(File, "Hours", h);
	INI_WriteInt(File, "Minutes", m);
	INI_WriteInt(File, "Seconds", s);
	INI_WriteInt(File, "pInJail", PlayerInfo[playerid][pInJail]);
	INI_WriteInt(File, "pInJailTime", PlayerInfo[playerid][pInJailTime]);
	INI_WriteFloat(File, "PosX", PlayerInfo[playerid][pXPos]);
	INI_WriteFloat(File, "PosY", PlayerInfo[playerid][pYPos]);
	INI_WriteFloat(File, "PosZ", PlayerInfo[playerid][pZPos]);
	INI_WriteFloat(File, "PosA", PlayerInfo[playerid][pAPos]);
	INI_WriteInt(File, "Banned", PlayerInfo[playerid][pBanned]);
	INI_WriteString(File, "BannedBy", PlayerInfo[playerid][pBannedBy]);
	INI_WriteString(File, "Reason", PlayerInfo[playerid][pReason]);
	INI_Close(File);
	return 1;
}
public LoadUser_data(playerid,name[],value[])
{
    INI_Int("Password",PlayerInfo[playerid][pPass]);
    INI_Int("Cash",PlayerInfo[playerid][pCash]);
    INI_Int("Admin",PlayerInfo[playerid][pAdmin]);
	INI_Int("UCAdmin",PlayerInfo[playerid][pUCAdmin]);
	INI_Int("DriverLicense",PlayerInfo[playerid][pDriverLicense]);
	INI_Int("Hours",PlayerInfo[playerid][hours]);
	INI_Int("Minutes",PlayerInfo[playerid][minutes]);
	INI_Int("Seconds",PlayerInfo[playerid][seconds]);
	INI_Int("InJail",PlayerInfo[playerid][pInJail]);
	INI_Int("InJailTime",PlayerInfo[playerid][pInJailTime]);
	INI_Float("XPos",PlayerInfo[playerid][pXPos]);
	INI_Float("YPos",PlayerInfo[playerid][pYPos]);
	INI_Float("ZPos",PlayerInfo[playerid][pZPos]);
	INI_Float("APos",PlayerInfo[playerid][pAPos]);
	INI_Int("Banned", PlayerInfo[playerid][pBanned]);
	INI_String("BannedBy", PlayerInfo[playerid][pBannedBy],30);
	INI_String("ReasonBanned", PlayerInfo[playerid][pReason], 128);
    return 1;
}
Код:
public OnPlayerSpawn(playerid)
SetPlayerPos(playerid, PlayerInfo[playerid][pXPos], PlayerInfo[playerid][pYPos], PlayerInfo[playerid][pZPos]);
    SetPlayerFacingAngle(playerid, PlayerInfo[playerid][pAPos]);
    SetSpawnInfo(playerid, NO_TEAM, GetPlayerSkin(playerid),PlayerInfo[playerid][pXPos], PlayerInfo[playerid][pYPos], PlayerInfo[playerid][pZPos],PlayerInfo[playerid][pAPos], 0, 0, 0, 0, 0, 0);
Any help would be appreciated.
Reply
#2

The problem is that you don't check whether the player is connected before saving their accounts. You're saving non-existing data for each non-connected player. In fact, you do that for all entries up till MAX_PLAYERS (the first 500/1000 players?).
Reply
#3

SaveAccount stock would not work. You must make all the players quit first, and if that's not possible and you had to create a whole new stock just to do that work for you, then that was not a great idea. Better creating a mass kick command, anyways, as per my hypothesis, the players must quit, then do the restart. The last location of the player is not being saved, and therefore they are being redirected to the default area, which is Blueberry Acres.
Reply
#4

Ah ok, that makes sense then AndySedeyn as even if your not connected to the server and a restart occurs, it makes all accounts in the server spawn at bb, despite their positions being saved in the .ini.


The saved position works usually without a restart, with it spawning you where you left, the only issue is that when a restart occurs, regardless of if your online or offline the next time you spawn, it spawns you at BB.
Reply
#5

I just realised that it probably isn't what I first thought, since you save files with the player's name -- you should still make the check whether a player is connected or not before saving the data, though. In that case, I suspect LoadUser_data not getting called. Can you show me the block of code where INI_ParseFile is used? Putting prints across the script won't do you any harm. It'll show you which data is saved/loaded.
Reply
#6

Well for the MAX_PLAYERS part and scrolling I've implemented foreach, to make it more efficient and sure

Код:
case DIALOG_LOGIN:
        {
            if ( !response ) return Kick ( playerid );
            if( response )
            {
                if(udb_hash(inputtext) == PlayerInfo[playerid][pPass])
                {
                    INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
                    GivePlayerCash(playerid, PlayerInfo[playerid][pCash]);
					PlayerInfo[playerid][hours] = GetPVarInt(playerid, "Hours");
					PlayerInfo[playerid][minutes] = GetPVarInt(playerid, "Minutes");
					PlayerInfo[playerid][seconds] = GetPVarInt(playerid,"Seconds");
                    SpawnPlayer(playerid);
                    SendClientMessage(playerid, -1, "* You have successfully logged in.");

                   	if(PlayerInfo[playerid][pBanned] == 1)
					{
    					Ban(playerid);
					}
					if(PlayerInfo[playerid][pAdmin] != 0)
	                {
	                    new msgID[128], msg[128];
	                    if(PlayerInfo[playerid][pUCAdmin] == 0)
						{
						    format(msgID, 32, "Administration Level - %d", PlayerInfo[playerid][pAdmin]);
						    SendClientMessage(playerid, COLOR_ADMIN, msgID);
						    format(msg, sizeof(msg), "* %s (ID%d) has logged in as Administrator Level %d.", GetName(playerid), playerid, PlayerInfo[playerid][pAdmin]);
						    foreach(Player,i)
						    {
								if(PlayerInfo[i][pAdmin] != 0 && i != playerid) SendClientMessage(i,COLOR_ADMIN,msg);
							}
						}
						else
						{
						    format(msgID, 64, "Administration Level - %d (Undercover)", PlayerInfo[playerid][pAdmin]);
						    SendClientMessage(playerid, COLOR_ADMIN, msgID);
						}
					}
                }
                else
                {
                    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD,"Login","You have entered an incorrect password.\n""Type your password below to login.","Login","Quit");
                }
                return 1;
            }
        }
    }
    return 1;
Код:
public OnPlayerConnect(playerid)
if(fexist(UserPath(playerid)))
    {
        INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
        ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD,"Authentication","{FFFFFF}Welcome to {FF0000}Vexed Roleplay\n{FFFFFF}Please type your password to login.","Login","Quit");
    }
    else
    {
        ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD,"Authentication","{FFFFFF}Welcome to {FF0000}Vexed Roleplay\n{FFFFFF}Please type your password to register.","Register","Quit");
    }
    return 1;
Reply
#7

Why are you loading data twice? Use SetSpawnInfo before SpawnPlayer. And if I could give you a bit of advice: don't use udb_hash - it's not secure at all.
Reply
#8

Ok so deleted the duplicate load, and I can't use setspawninfo before spawnplayer, as the server goes to class/skin selection. Anyway looking into it a bit further, it seems when you /q coords are saving fine, and when you relog in, they are laoding fine, but when you /gmx or stop/start the server those coords are ignored and your spawned by default at bb. Thanks for the help so far.
Reply
#9

I'm a bit confused now. Sending the player to class selection shouldn't be a thing since he will be in it upon connecting. Unless you are toggling on spectate mode, which in that case you forgot to toggle it off. Moreover, spawning the player to send him to class selection seems odd to me when you have a native function to do that: https://sampwiki.blast.hk/wiki/ForceClassSelection , I could be wrong - it's been a long time since I've used the class selection screen.

I've quickly written an example of what I exactly mean:
PHP код:
new 
    
choosenClass[MAX_PLAYERS];

public 
OnGameModeInit() {

    
AddPlayerClass(0, -2455.82352292.97854.9785324.5504000000); // case 0
    
return true;
}

public 
OnPlayerConnect(playerid) {

    
TogglePlayerSpectating(playeridtrue);

    
// Load data - show correct dialog
    
return true;
}

public 
OnDialogResponse(playeriddialogidresponselistiteminputtext[]) {

    switch(
dialogid) {

        case 
DIALOG_LOGIN: {

            
// Authenticate account

            
ForceClassSelection(playerid);
            
TogglePlayerSpectating(playeridfalse); // Player goes back to class selection
        
}
        
// ...
    
}
    return 
false;
}

public 
OnPlayerRequestClass(playeridclassid) {

    switch(
classid) {

        case 
0: {

            
choosenClass[playerid] = 0;
            
// Camera positions and such
        
}
    }
    return 
true;
}

public 
OnPlayerRequestSpawn(playerid) {

    switch(
choosenClass[playerid]) {

        case 
0: {

            
// CJ
            
SetSpawnInfo(playerid, ...); // The coords from AddPlayerClass under OnGameModeInit don't support dynamic coords, hence why you have to set them here.
        
}
    }
    return 
true;

Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)