Making a simple score saver for jcoopz1 (Preliminary thoughts and explanation and working example)

01 Aug

Well lets start with a intro , Before i bore you to death with the technical  details
this week im really not sure what made me decide that you needed to read me explaining how to rewrite jcoop to add serverside saved scores but im going to anyway. because i thought it was interesting.

Some back story:

My ah monsters server is setup so it is pushed to the point where 225 limits start showing , the game locks up quite a lot on many maps despite running on a pretty high  mid-end PC with plenty of ram  , The only thing i can do to remedy that would be to lower the monster counts and I dont want to do that , in fact i really want to raise them even higher, But that will need to wait intill 227i comes out  with “clientcompmode” as one of my main players insists on still using 226f. ^sigh^

In the mean time my biggest complaint from players isnt that it crashes , as it can usually restart in just  a few seconds, but that there scores are lost when it restarts.

now i know that score recovery mod  wont work with jcoopz1 because it saves the values in a different value in a custom pri class in jzPRI. and  i really didn’t care enough to try and make it work somehow. but a few days ago i decided to look at some of bleeder’s  risingsaver code and saw how he choose to save his custom player data , by alliterating the pri classes, ( as oppose to ill iterating the playerpawns which would be how i would have done it) and it just seemed so simple  i decided to try and make it work with jcoopz for fun.

Lets do some stuff:

The irst step was to figure out where jcoopz1 stores  the values , you can clearly see it is seems to be stored in JZPRI , but that class has been stripped of the values , So utpt is needed to view the values here  and it starts to get interesting:

var int EnemyKillCount;
var int FriendKillCount;
var int DeathCount;
var int SuicideCount;
var int jSpree;
var int TScore;
var int STI;
var bool bSTIValid;
var bool bIsTyping;

That a lot of values we can use! Why isnt this data exposed?!

Some are obvious score values, others are validation bools.
While ememykillcount seems usable ,Tscore is what we want to save as it  is the total accumulated score that spans maps.

I modified all the code in rising saver  and comment out all irrelevant values and change the references to jzpri and go to compile , Oh crap… While zombie did technically leave enough code to recompile subclasses and such he wiped out most of the vars in most of the classes , so the compiler cant find the variables to reference. Hmm what can i do about this , Mabye I can write the entire mod and ask zombie to compile it for me ? ah not really  ideal, what other options do i have? Mabye i can add the decompiled variables back into jzpri  and recompile so it can reference the  variables ,  YES it will work!. so i do just that.Now we have something we can build against.

At this point i decided that bleeders actual original  saving code was too over complicated and overly dependent on 227 callbacks ( There isnt any thing wrong with his code but it used alot of checks that made debuging difficult for me using 225), So i trashed all the data save/load functions and substituted it for  my own i wrote a few years ago for my failed ‘statmut’ mod ,  This has the added bonus of basically making it 99% my own work  since the only thing left of his work is a timer call that calls the functions that i wrote and some var definitions that i also completely changed anyway.  Also my code is more suited for 225 as it replaces characters that 225 cant understand in player names or save in a ini.

Since what I am building dosnt have access to any kind of mutatenewplayer calls(yet)  ,We are doing this data raking somewhat blind (Just by timer) So we need to do something simple to detect when a player joins and there score needs to be re loaded. While technically i could write a pickup to hook into the giveitem and do some magic , i wanted to keep this code serverside. So The simplistic  way i thought i could do  it was to just compare the score , If the players score is less then the saved value , the score is loaded to the pri. otherwise is is just saved to the server every 15 seconds, why every 15 seconds tho? Well like i said , we are doing it blind so  it could take up to a full timer cycle to load the score so 15 seconds was a compimize between resources and load time.

There was a problem Tho ,  When the level switches  the players score is ‘recovered’ every map switch again regardless,  But everything apperars to be working,  all kills  are properly added to that number as things are killed,But  It has a bit of weirdness at the map start.  hmm lets look a bit further, Decompile jzplayerpawn and you get this and more:

var string SpareHolder;
var string PlayerIP;
var string ConsoleClass;
var string LocalID;
var string EngineVersion;
var string PlayerUID;
var travel int TScore;
var travel string TPlayerIP;
var travel string TLocalID;
var travel string TPlayerUID;

Alot of  potentially useful variables. But to  get to these we need to repeat what we did before and re add them to jcoopz1.u using unrealed as i dd this  i noticed something  , 2 more vars labeled Tscore under playerpawn. Lets log some crap and play a bit and see what changes

ScriptLog: ip:  76.117.84.XXX
ScriptLog: ConsoleClass:  UMenu.UnrealConsole
ScriptLog: LocalID:  -1549992XXX
ScriptLog: EngineVersion:227
ScriptLog: PlayerUID:  1467642XXX
ScriptLog: TScore:  14
ScriptLog: name:BobIsUnreal

A bit of logging shows that this tscore seems to be the actual live value we want. It is separate  from the totalscore   numbers we saved before ,  that  seemed to count the current score, but  this value  makes up for the  difference we saw ( The highscore of 160000 was loaded and replaced the pri values andshowed in  scoreboard , But you could tell it was not the current value at mapstar).This big block of data also conveniently gives us a lot of usfull security data we can use to secure the stat saving system from being hijacked.

After further testing   it is shown that you need to  reload both variables , The playerpawn one is the actual score that travels , and the pri is what is displayed on the scoreboard ( technicly you dont need to set the pri , But it will only update after a mapswitch).

what about security ?

How am i going to secure the data from  player hijacking?
I honestly don’t care  if someone hijacked another players score , and im pretty sure they are not smart enough to try we have all this data here , but , we cant really  ‘trust’ uid t or ip o be permanent  so I am   currently just using there name. if it was important enough to you you could swap the uid feild for the playername in the code for score table , and let the mod basicly save  data via uid and just save the name as  the original uid feild to identify the entry.

What I finally decided  would be the best plan was to add a option called BeSemiSecure that will validate against the uid saved into the players slot , if that uid matches the slot is used , if the uid’s dont match , a new slot is created for the player .The downside of this is that there can be multiple slots with the same username and if you chose this option , you need to stick with it. If you choose to switch back there will be a ton of duplicate names in the table that will be usefess and need to be manually combined. I did not create this thing primarily for security , so this is a afterthought and was not tested

Outcome and end product:

so what did all this 8 hours of effort   end with?
If ends with a actor that can save total score , engine , uid , ip , playername , ememies killled per map and restore that score data after a server crash.

If Your interested in such a thing you can have it becuase thats how i roll.

download here
code only (pastebin)

You need to add it to the mutators or serveractors it’s name is jsaver.jsaver
It works pretty well if all you need is total score saved, or if you want engine version or a sort of half ass player logger to mess with.You wont be able to edit of rebuild this script without  modifying your jcoopz files as i stated above so its probably not the best thing to build off but a decent example of how to expand jcoopz with limited means.

I had fun doing this over the last 4 days in my spare time , and I even took the time  to make the code well documented and clean. and did some tweaking that increases the code performance quite a bit.

Leave a comment

Posted by on August 1, 2012 in Uncategorized


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: