Log in

View Full Version : setting up global high score


isp
07-21-2004, 08:09 PM
Can anyone lead me in the right direction as to how I can set up a global high scoring system on my web server? I'm mainly a C++ programmer, so a C++ programming solution would be preferable.

thanks,

KoekTromL
07-21-2004, 09:51 PM
I haven't tried it yet, but...

How about launching a web-browser to your highscore page much like:
www.mydomain.com/highscorepage.php?name=test&score=10&checksum=14
(the checksum is to prevent cheating)

Then put a php/MySql script on the server comparing & storing the results and displaying them back in HTML.

If you want to do everything within the program, you need to start looking at stuff like IAsyncMonikerFile (if I remember correctly). Basically the same thing, but you could send some data back that the program understands, eg
1 = Test, 10
2 = Other player, 40

You would need to parse that and display it in the program.

The AsyncMoniker uses asynchronous messages and callbacks. I believe there is also CHttpFile, which does a similar thing but synchronously.

Let me know how you go with that!

oNyx
07-21-2004, 10:59 PM
Right now I just do that with php and mySQL. All I do on the client side is sending a http 1.1 request to the server with score, name etc in the query string. For protection I just check the agent... so you can't add new scores with your browser (more than that isn't really necessary imo). The server then sends a status code back together with some optional information.

You'll need a server in your lan (can be your own machine, too) for testing. I can really recommand xampp (it's free). Just download, install and that's it. Everything you need (apache, mysql, php etc) just works straight away ;)

http://www.apachefriends.org/en/xampp.html

I'm not sure what you need to do in order to get it bullet proof, but if you are behind a router (like I am) it isn't an issue (if no one can connect from outside they can't screw anything).

KoekTromL
07-22-2004, 12:58 AM
Do you do any screening for 4-letter words and stuff?

oNyx
07-22-2004, 01:13 AM
Do you do any screening for 4-letter words and stuff?

No.

It's limited to 3 letters(*) ;D

But I guess a bad word list could be a good idea.

(* It's only like that in the current game and I won't do it like that for the next one)

oNyx
07-22-2004, 01:37 AM
Come to think of... right now I store:

-id (int)
-name (varchar)
-score (int)
-date (datetime)
-fkey (int (*))
-version (varchar (**))

(* used for filtering in case there is a change, which makes older scores invalid - each version with different scoring [etc] will use another number)
(** auto generated build id)

But I should also save the ip and additionally store all ips for failed cheating. So if someone tries to access the script, I'll save his ip and if he then gets (my magic) the first place it's most likely cheating ;) <edit> within 24 hours that is </edit>

Oh and I should redirect everyone with the wrong agent to the 404 page hehe.

Oh² and for badwords there should be a control panel. One click for removing the entry plus storing his name as bad word.

Hmm... yes. Sounds like a good framework.

Jason Colman
07-22-2004, 02:01 AM
I'm just in the process of doing this too. I too am sending an http request to a cgi. I've been putting off writing the perl script though.. don't like perl :(

How are you storing the high scores ? In a database ? Seems like overkill. But if you store them in a flat file, how to you deal with concurrency issues ?

Feel free to post whole perl scripts for this guys :)

oNyx
07-22-2004, 02:18 AM
Yes, a database (mySQL) as I already said. Just because it's easy and because I have one. You get a database usually if you pay for your webspace.

A simple highscore system (like the one I outlined before) needs just a single table and a somewhat feature-rich one (like the one I talked about) needs 3. It's easy and fast and you can sort by score and then by date without too much hassle ;)

luggage
07-22-2004, 02:25 AM
We looked into it not long ago and came up with a solution that uses MySQL and c++. It doesn't do anything with http requests. Trouble is was trying to find a way to make it secure. How do you stop someone from just accessing the database directly by peeking at the exe to find out username and password? What about entering fake scores?

What gives the worst impression? No online hiscores? Or a hiscore table that's abused?

What we finally proposed was...

The game has a local hiscore table - this is in case they haven't got web access when playing.

When a user enters their name it gets put straight into their local version. The game also connects to the sql database on the server and enters the score there. This is only the temporary database - the score hasn't been validated yet.

We write a seperate utility which sits on our machine at home and every 5 minutes (or whatever) grabs the temporary database. It then checks for scores which aren't valid, banned ip's, etc, etc. Once it's cleaned it then moves it onto the final database.

The final database is what the games read (at the end of the every game, when scores are viewed, on startup, etc) to get the new global highscores. This way the permissions on it can be set to read only so no-one can trash it.

The only downside is that the local hiscore table won't be 100% up to date but this shouldn't matter as the users score was entered into their local version so they can see their score immediately. At most it will only be out by 5 mins+whenever the game checks. I don't think the user would even notice.

The presumtion is that the database the games write to (the temporary one) is totally open to abuse and wouldn't matter even if it got totally trashed. The utility can rebuild it from it's last good check. Scores can be validated more accurately, the game can put a list of moves up and have the utility play back the game if it's really wanted.

Something someone else suggested but I can't remember who was that each user can only enter 1 or 2 scores. This stops someone who's great at the game just filling the table up with scores no-one else can beat.

oNyx
07-22-2004, 02:52 AM
We looked into it not long ago and came up with a solution that uses MySQL and c++. It doesn't do anything with http requests. Trouble is was trying to find a way to make it secure. How do you stop someone from just accessing the database directly by peeking at the exe to find out username and password? What about entering fake scores?
[...]

That's really scary. Really. Don't connect directly to the database with username and password. It leaves the doors a million miles wide open.

Anyone could just connect to it and enter html code for installing a trojan... or execute commands on the server (even that works sometimes).

Do it with php. This way you can check the stuff you get.

Faked scores will always be a problem. However, it's usually enough to make it too difficult for the average user (eg by checking the agent and/or simple encryption and/or using some kind of checksums). And well just check the top scores sometimes... if someone is cheating he'll aim for the pole position.

luggage
07-22-2004, 02:57 AM
Lordy! Won't be doing that then!

Jason Colman
07-22-2004, 03:09 AM
Bah, I have to pay £39 extra to get MySQL on my host. At the rate my game is selling that will take a long time to recoup! :( So it's a flat file for me, with some kind of hack to lock the file when it's in use.

oNyx
07-22-2004, 03:28 AM
>Bah, I have to pay £39 extra to get MySQL on my host.

That's damn pricy. I pay 5€ per month / 20€ setup(*). One domain, 500mb, 50gb per month inclusive, php, cgi, mysql (10 databases), ssi, htaccess, 100 sub domains, 500 email adresses etc. If I ever upgrade I'll just have to pay the difference of the setup fee ;)

(* a friend got that, because I used his referer id)

The page of the provider is unfortunately only in german, therefore it would be quite useless to post it here.

illume
07-22-2004, 03:33 AM
Cheating is inevitable if the game is popular. People can change your game to make a massive highscore like 10000909091232312123123198989.

Even bigger if they want to!

For the last LD48h comp I did highscore groups. Where they can enter in the group name of the highscore. So that groups of friends can have their own highscore groups.

You can even seperate highscore players into different groups depending on how well they did in the game, or on some other factor. Eg a highscore table grouped by country/state/city of the player.

One cool highscore thing I saw was where there were highscores for about ten different aspects of the game. eg "most times jumped on one spot" , "most blue gems collected" etc. Just silly things which people can get really good at. Maybe have a suggestion box for players to suggest high score tables for things.



Have fun!

BrewKnowC
07-22-2004, 04:19 AM
I will be facing this problem soon also and I would like to hear more about doing the call/retrieve right from within the program (no http calls). If anyone has any more info on this that would be great.

oNyx
07-22-2004, 04:49 AM
>no http calls

Using http doesn't mean that you need to start the default browser ;)

Actually you don't need much...


to_server.println("GET " + filename + " HTTP/1.1");
to_server.println("Host: "+host);
to_server.println("User-Agent: "+agent);
to_server.println("Accept: */*");
to_server.println("Accept-Language: *");
to_server.println("Accept-Encoding: gzip,deflate");
to_server.println("Accept-Charset: *");
to_server.println("Keep-Alive: 300");
to_server.println("Connection: keep-alive");
to_server.println("");
to_server.flush();


Then you get something back... and you just save the first line (status code+message) plus the stuff after the first empty line (the actual content if you are interested in getting a message back like the position or so). That's it basically.

EpicBoy
07-22-2004, 08:10 AM
My next game will have this feature and I've opted for sending HTTP requests to run PHP scripts on my server. The PHP script handles opening the database and writing/reading the information.

I also support a local high score board and if you never clink the "Connect" button on the high score dialog, you never need deal with the internet scores if you don't want to. I think that's the way to go ... let people decide if they care about the internet scoreboard or not.

The local and internet scores are displayed side by side for each game type I have and when you connect, new local scores are uploaded to the server.

As for security ... you have to ask yourself WHY someone would cheat. I mean, if you aren't running contests or offering anything in return for the high scores, what's the point? And you can easily do a weekly check up on your database to ensure that the scores in it make sense. If you see something that is obviously bogus, just delete it.

Unless your game becomes hugely, wildly popular (which we all hope they will), I don't think it's anything to lose sleep over.

oNyx
07-22-2004, 08:31 AM
[...]
I also support a local high score board and if you never clink the "Connect" button on the high score dialog, you never need deal with the internet scores if you don't want to. I think that's the way to go ... let people decide if they care about the internet scoreboard or not.
[...]

I also have a offline highscore right now, which is always there (because you said if+never). IMO it's important being able to fight against your own scores especially if the top 10/100/1000 scores are absolutly unreachable for you (or let's say the majority of players - that will just happen if it gets popular).

And don't forget to store the datetime. This way you can give the one who was earlier the better place in case there are two identical scores and another nice thing is that you are able to add dayly/weekly/monthly tables (additonally to the "of all time" table) if you decide to do that ;)

One thing I wasn't sure about... how should I exactly deal with uploading? The way I implemented it these days is like this:

-local highscore table with up to X entries (5)
-session highscore table with up to Y entries (3)
-online highscore table with up to Z entries (doesn't matter at this point)
-each time you beat a local score it's saved
-each time you beat a session highscore it's saved
-on exit you are asked (if it's set to "ask always") if you want to upload your highscores (session only)

I think it's quite nice like that. It prevents flooding to some extend, but you still get a constant flow of new scores (good for dayly/weekly/monthly) and yea... you can try to improve by beating your own scores.

Bluecat
07-22-2004, 09:35 AM
As for security ... you have to ask yourself WHY someone would cheat. I mean, if you aren't running contests or offering anything in return for the high scores, what's the point?

I think the same questions apply to why someone would use an aimbot in Counterstrike. After all there are no prizes offered in those games either, and using an aimbot pretty much defeats the purpose of playing a skill oriented game.

Why would someone cheat?... Because they can. Sad, but true.

ggambett
07-22-2004, 09:46 AM
I've been running the Betty's Beer Bar online high scores (http://www.mysterystudio.com/bbb_highscore.php) for 8 or 9 months, and there weren't any hacking or cheating after 84133 posts (at the time of this writing).

I had only one problem with one player posting his scores using different but similar names, thus filling the tables. I showed him a message when he tried to post (identifying him by his IP), asked him to contact me, and solved the issue in a quite friendly way :)

Technicalities : I launch a browser pointing to a PHP script and pass the data as a GET parameter. The "data" is redundant, has checksums, and it's encoded using something like Base64. You can also do this via HTTP POST, reading back the results and showing them locally. I haven't done it yet but it's a sure feature for my next game.

BrewKnowC
07-22-2004, 01:29 PM
Gabriel, I really like your highscore system in particular. If you don't mind, could you share some of the details involved? I'm not really sure where to start on this one as far as posting and encryption and stuff like that.

fost
07-22-2004, 02:11 PM
I just thought I'd chime in late here and second the whole php/mysql combo.

One of our programmers wrote an encryption scheme for the score codes in the game and mirrored it in php so we can decode it at the other end.

The other great thing with running it from a database is that you can easily extract the data in whatever format you like as things progress. We just added a monthly score table for one of the modes, and even opened up a mode for the demo; mostly just by altering the sql queries used. If it'll give anyone any ideas, you are welcome to try it out (http://www.moonpod.com/English/highscores.php?pid=1) (from 'survival demo') and you can just use the demo version. (I'd love to see what scores people can get ;) )

Jason Colman
07-23-2004, 01:16 AM
For anyone writing their client code in C/C++, I found this web page very helpful. [edit - Or indeed in any language - there's no actual code there :) ]

http://www.jmarshall.com/easy/http/

I still can't bring myself to shell out £40 for a database, even though you have all convinced me it's the best technical solution. :(

fost
07-23-2004, 02:53 AM
I still can't bring myself to shell out £40 for a database, even though you have all convinced me it's the best technical solution.:(
How much do you pay for hosting right now? Our main site is on a dedicated server, so we can set up what we want, but I have an account for testing things with
bluehawkshop (http://www.bluehawkshop.net/) in the uk that costs £25 for the year, that comes with php/mysql. I'm pretty sure you can get lots of great deals for shared hosting with the php/mysql datatbases installed.

Jason Colman
07-23-2004, 03:39 AM
:eek: Oh man, I'm being stiffed. That bluehawkshop deal looks really good. I will threaten my current host with switching, and see if I can get mysql for free. Thanks for the tip!

ggambett
07-23-2004, 09:06 AM
Gabriel, I really like your highscore system in particular. If you don't mind, could you share some of the details involved?
Thanks Bruno!

I don't know, it's nothing special, so there are no interesting "details" to talk about. As I said earlier, this was a temporal hack to launch the game, my intention was to do asymetric encription but this worked fine so I left it.

Say you want to encode a level and a score. The level (L) fits in one byte and the score (S) fits in 4. So it's 5 bytes of data (L, S0, S1, S2, S3)

Do some transforms on the data. For example S'(i) = S(3-i) XOR 0xAA. Now you have L, S0, S1, S2, S3, S'0, S'1, S'2, S'3. Calculate the checksum of that, get the middle 16 bits, you have L S0 S1 S2 S3 S'0 S'1 S'2 S'3 C0 C1. Add some random bytes -> L S0 S1 S2 S3 S'0 S'1 S'2 S'3 C0 C1 R0 R1 R2 R3. Set some constraints of the random data, for example R1's high bit must equal R3's high bit. Then shuffle everything (the mapping must be deterministic, of course), you get L S0 C1 R0 S1 R2 S'1 S2 R3 S'0 S3 R1 S'2 S'3 C0. Base64 encode it with a different mapping than Base64 and you're done : ShellExecute("http://www.werlin.com/highscore.php?data=<the string>").

On the PHP side, revert all the procedure, so you get new values of L S0 S1 S2 S3 S'0 S'1 S'2 S'3 C0 C1 R0 R1 R2 R3. Verify the constraints, verify that the checksums are correct, verify that the S' values calculated from the S values match the S' values you got,... if any of these checks fails, you say "invalid data".

For extra points, gzip the data before Base64ing it, pick a random value, use it as the first byte of the data and XOR the rest of the data with it, and so on.

All of this just prevents the players from modifying the URL and getting an insanely high (or negative) score. It's still trivial to hack the game to generate the string using phony values.

Hope that helps!

fost
07-23-2004, 02:00 PM
I will threaten my current host with switching, and see if I can get mysql for free. Thanks for the tip!
The best tip anyone ever gave us before we started was to register your domain with a roaming dns (not sure that's the correct terminology - dynamic dns?) such as freeparking.com (http://www.freeparking.com/) rather than your hosting company. It makes it really easy to move your website quickly. We had really bad problems with several hosts before we found someone we were comfortable with. With Freeparking, you just copy your website over to your new server, update the ip from freeparking's control panel, wait 24 hours for the data to propagate through the internet, and then close your old account. It's really been a life saver at the times we needed it.

Jason Colman
07-27-2004, 02:46 AM
Alriiight, now I have got mysql! That is good to know about Freeparking - but a bit late for me.. oh well :)

guoly
07-27-2004, 06:14 PM
Players can enter their high scores directly in my website www.guoly.com/upscore.php
Previously I ask players to send their high scores to me by email, then I enter the high score into the mysql database. However this is very annoying when time goes on.
I have noticed some cheating, for example, a user(identified by IP) used two ID entered two scores which is too high to be possible by playing the game.