Client-side SaveConfig();

Discussions about Coding and Scripting
Post Reply
Haxer557
Novice
Posts: 10
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Client-side SaveConfig();

Post by Haxer557 »

Hello,
I need to create a mutator which will be able to assign every client his unique ID (such as NexGen does).

So far I have created sth like that:

This class expands mutator, tick checks all players to see if they already have ThHaxersID2Client instances assigned. If not, it spawns one, and executes login function.

Code: Select all

class ThHaxersID2 expands Mutator;

function Tick(float DeltaTime)
{
	local Pawn P;
	local ThHaxersID2CLient IDActor;
	local bool bPlayerLogged;

	Super.tick(DeltaTime);

	for( P=Level.PawnList; P != None; P=P.nextPawn )
	{
		if(P.bIsPlayer && String(P.Class) != "s_NPCHostage")
		{
			bPlayerLogged=false;
			foreach AllActors(class'ThHaxersID2Client', IDActor)
			{
				if(PlayerPawn(IDActor.Owner)!=None&&PlayerPawn(IDActor.Owner).PlayerReplicationInfo!=None)
					if(caps(PlayerPawn(IDActor.Owner).PlayerReplicationInfo.PlayerName)==caps(P.PlayerReplicationInfo.PlayerName))
						bPlayerLogged=true;
			}
			if(!bPlayerLogged)
			{
				IDActor = Spawn(class'ThHaxersID2Client', P);
				if( IDActor != None )
				{
					IDActor.login();
				}
			}
	
		}
	}
}
The following code is what is attached to all players, login function executes Timer in 2 seconds, and Timer displays a welcome message to new Pawn, showing his ID. If the ID doesn't exist it gets created by CreateNewID function.

Code: Select all

class ThHaxersID2Client expands Info config(user);

var config string PlayersID;

simulated function login()
{
//delay login by 2 seconds
SetTimer(2.0,false);
}
simulated function Timer()
{
	local PlayerPawn P;

	P = PlayerPawn(Owner);

	if(p!=None)
		P.ClientMessage("You have logged in with ID = "$GetID());
	

}

simulated function string GetID()
{
	if(len(PlayersID)!=29)
		CreateNewID();
	return PlayersID;
}

simulated function CreateNewID()
{
	local int Num1, Num2;

	//generate the ID

	//make the id be the exact date plus 2 random 4 digit long numbers (xxxx.xx.xx.xx.xx.xx.xxxx.xxxx)
	PlayersID=GetShortAbsoluteTime(); // I copied that function from StatLog class
	Num1=rand(8999)+1000;
	Num2=rand(8999)+1000;
	PlayersID=PlayersID$"."$Num1$"."$Num2;
	SaveConfig();
}

The result however, is not really what I wanted, because despite the fact the ID is generated and displayed properly, it saves not into clients user.ini file, but into servers one. This is the extract of my servers user.ini file :)

Code: Select all

[ThHaxersID2.ThHaxersID2Client]
PlayersID=2011.06.05.22.39.17.1782.6691
Whereas in clients user.ini there is no trace of it :)

Of course it causes all further clients that log in to be identified as 'registered' and doesn't generate any new ID, it displays the one that got saved at server instead.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Client-side SaveConfig();

Post by JackGriffin »

I've been a proponent of some sort of central player registration for a long time. I'm very interested in where you are going with this. May I ask what you are attempting to accomplish? It appears you are generating an ID that is to be checked against a central database on the server?

Oh, and to your original question I don't see any replication from server to client so that the "key" is agreed upon. Log it out and I'll bet it is returning a null value.
So long, and thanks for all the fish
Haxer557
Novice
Posts: 10
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Re: Client-side SaveConfig();

Post by Haxer557 »

I want to upgrade my Score Recorder mutator, dedicated to Thievery Mod. So far I log players scores, statistics by their names what is not efficient enough as players change their nicknames a lot :) . ScoreRecorder allows me to export stats into a html file, such as this one: http://www.thievery.pl/serverstats/stats.html

Thievery community is quite small, We have only few servers, and the number of active players is not greater than 30-40.

I have a function that returns Players ID, I didn't include it in the code above as it does not bring anything about. I didn't check if it works actually.

Code: Select all

function string GetPlayerNamesID(string PlayerName)
{
	local ThHaxersID2CLient IDActor;

	foreach AllActors(class'ThHaxersID2Client', IDActor)
	{
		if(PlayerPawn(IDActor.Owner)!=None&&PlayerPawn(IDActor.Owner).PlayerReplicationInfo!=None)
			if(caps(PlayerPawn(IDActor.Owner).PlayerReplicationInfo.PlayerName)==caps(PlayerName))
				return IDActor.GetID();
	}
	return "None";
}
I think that the moment ThHaxersID2CLient actor spawns, the only variable PlayersID is assigned by server instead of being assigned by client. The same is with saving it. It is done in Nexgen in some way. I tried to base on it but I must have missed something, Nexgen is quite huge, and it's hard to get around all that code.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Client-side SaveConfig();

Post by JackGriffin »

If you are using nexgen, just grab the player's nexgen ID. It's going to be much easier and it's already unique.
So long, and thanks for all the fish
Haxer557
Novice
Posts: 10
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Re: Client-side SaveConfig();

Post by Haxer557 »

Well, I stopped using Nexgen some time ago, but I decided to give it a try and bring it back to support my score recorder. It took me hours to code it, however the mutator doesn't seem to work fine all the time.

First of all, the moment it loads, my logs get spammed a little bit:

Code: Select all

Log: Spawning: Nexgen112.NexgenActor
Log: Spawning: ThHaxersScoreRecorderPlus.ThHaxersScoreRecorderPlus
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Bad termination
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Illegal or missing key name
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Warning: ImportText: Bad termination
Log: Spawning: ServerAdds.ServerAdds
You can see that the moment my mutator loads, those errors turn up. I searched through the internet and found out it may have something to do with variables I load from ini files - this could be true because I store a lot of information in inis.
One of the ini files holds just config variables, etc - I dont think it is the one causing problems, however I store each players statistics(there is a lot of them) in a struct which looks like that:

Code: Select all

struct PlayerStats
{
//General Vars
var string ClientID;
var string PlayerName;
var int RoundsSpectated;
//var int RoundsPlayed;
//var int RoundsWon;
//var int RoundsLost;
//no longe needed
var float SpectatorTime;

//Thief Vars
var int ThiefScore;
var int ObjectivePoints;
var int Loot;
var float Stealth; // in fact it shows Light Rating
var int GuardKills;
var int GuardKOs;
var int ThiefNumberOfRangedShots;
var int ThiefNumberOfRangedShotsThatHit;
var int RoundsAsAThief;
var int TimesKilledByGuard;
var int RoundsWonAsAThief;
var int RoundsLostAsAThief;
var int TInvisPotsUsed;
var int TSpeedPotsUsed;
var int THealthPotsUsed;
var int TCatfallPotsUsed;
var int TFlashesUsed;
var float ThiefTime;
var float TTimeInvis;
var float TTimeSpeed;
var float TTimeCatfall;
var float TTimeCracked;
var float TTimeFlashed;
var float TTimeParalysed;
var float TTimeEmptyHanded;
var float TTimeBlackJack;
var float TTimeSword;
var float TTimeBow;
var int TFoodEaten;

//Guard Vars
var int GuardScore;
var int LootReturned;
var int GuardNumberOfRangedShots;
var int GuardNumberOfRangedShotsThatHit;
var int RoundsAsAGuard;
var int RoundsWonAsAGuard;
var int RoundsLostAsAGuard;
var int TorchesRelit;
var int ThiefKills;
var int DamageDealt;
var int TrapPoints;
var int GInvisPotsDestroyed;
var int GSpeedPotsUsed;
var int GHealthPotsUsed;
var int GCatfallPotsUsed;
var float GuardTime;
var float GTimeSpeed;
var float GTimeCatfall;
var float GTimeCracked;
var float GTimeFlashed;
var float GTimeParalysed;
var float GTimeEmptyHanded;
var float GTimeSword;
var float GTimeMace;
var float GTimeCrossbow;
var int GFoodEaten;

};
Perhaps this leads to some problems with loading and saving data from files - each Players Stats looks in ini file like this:

Code: Select all

Array[2]=(clientID="**********************************************",PlayerName="Haxer557^Tomcats^",RoundsSpectated=4,SpectatorTime=3552.845215,ThiefScore=819,ObjectivePoints=23,Loot=165,Stealth=158.265060,GuardKills=2,GuardKOs=0,ThiefNumberOfRangedShots=7,ThiefNumberOfRangedShotsThatHit=4,RoundsAsAThief=2,TimesKilledByGuard=0,RoundsWonAsAThief=2,RoundsLostAsAThief=0,TInvisPotsUsed=0,TSpeedPotsUsed=2,THealthPotsUsed=0,TCatfallPotsUsed=0,TFlashesUsed=0,ThiefTime=490.861084,TTimeInvis=20.156853,TTimeSpeed=11.318522,TTimeCatfall=0.000000,TTimeCracked=0.000000,TTimeFlashed=0.000000,TTimeParalysed=0.000000,TTimeEmptyHanded=464.282684,TTimeBlackJack=6.965969,TTimeSword=0.000000,TTimeBow=19.612556,TFoodEaten=0,GuardScore=1867,LootReturned=0,GuardNumberOfRangedShots=56,GuardNumberOfRangedShotsThatHit=19,RoundsAsAGuard=4,RoundsWonAsAGuard=3,RoundsLostAsAGuard=1,TorchesRelit=8,ThiefKills=4,DamageDealt=905,TrapPoints=72,GInvisPotsDestroyed=0,GSpeedPotsUsed=4,GHealthPotsUsed=0,GCatfallPotsUsed=0,GuardTime=1736.312988,GTimeSpeed=40.111130,GTimeCatfall=0.000000,GTimeCracked=0.000000,GTimeFlashed=0.000000,GTimeParalysed=0.000000,GTimeEmptyHanded=0.000000,GTimeSword=0.000000,GTimeMace=0.000000,GTimeCrossbow=0.000000,GFoodEaten=0)
These are my personal stats, I have played enough rounds to have all values greater than 0, whereas, a huge part of them is still 0. The problem is not with counting them during the game, because other player looged have some of those values greater than 0. The problem is that despite using SaveConfig(), not all values are saved. Is it connected with the amount of memory that struct holds? (it is ~252 bytes)

At the end of the round - the moment stats are read and updated into ini file, I got even more warnings.

Note: The variables stored mid-game are stored in variables that do not use any default values - this means that the first time PlayerStats are read is at the end of the round - therefore I have no idea why do those errors occur while loading mutator.

Perhaps the solution is just to split the PlayerStats struct into smaller structs?

Edit: Fixed! The solution was to split the struct PlayerStats - although it took me some time to rearrange the whole code, it payed off, as for now everything seems to work fine.
iDeFiX
Average
Posts: 70
Joined: Sat May 15, 2010 10:11 am

Re: Client-side SaveConfig();

Post by iDeFiX »

Offtopic:
JackGriffin wrote:I've been a proponent of some sort of central player registration for a long time. I'm very interested in where you are going with this. May I ask what you are attempting to accomplish? It appears you are generating an ID that is to be checked against a central database on the server?
A lot of people want it :). The only known public version is UTGL. I think it could be fairly easy adopted to use NexGen/ACE/etc.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Client-side SaveConfig();

Post by JackGriffin »

When Anthrax gets done with v9 I'm going to cash in my chips with him and try to get something like this attached to ACE. At the very least he could generate a hash from the gathered physical equipment stuff and feed this as a unique ID. We could code everything else from there.
So long, and thanks for all the fish
Post Reply