Posted: 30th Dec 2011 3:25
I am working on creating a High Score server app where I can post my high scores on a server and allow players to see other global high scores. I know there is probably a better way, but if I can figure it out, then it opens up a bunch of other options in later game development.

I started with the code that was in the multiplayer guide. I was adding the ability for my app to read from a file and write to a file. This way, if the app stops unexpectedly, I can just run it again and it will read the last saved file and continue.

Here's what I have:

+ Code Snippet
rem
rem AGK Application
rem

type sHighScore
	init as string = ""
    score as Integer = 0
    level as Integer = 0
endtype

global totHighScores as integer = 10
global dim HiScores [ totHighScores ] as sHighScore
global msg as integer


//iNetID = HostNetwork("crazytiles.no-ip.org", "Server", 4100)
iNetID = HostNetwork("myNetwork", "Server", 4100)


// First, check to see if previous high scores files exists.  If so, load it as the starting scores.
if GetFileExists("highscores.txt") > 0
    fileID = OpenToRead("HighScores.txt")

    if fileID > 0
        x = 0
        do
            x = x + 1
            HiScores[x].init = ReadString(fileID)
            HiScores[x].score = ReadInteger(fileID)
            HiScores[x].level = ReadInteger(fileID)

            if FileEOF(fileID) > 0 then exit
        loop

        CloseFile(fileID)
    endif
endif


// finish initalizing scores.
If x < totHighScores
    for y = x + 1 to totHighScores
        HiScores[x].init = ""
        HiScores[x].score = 0
        HiScores[x].level = 0
    next y
endif

// Main program loop.
do
    Print("INetID:" + Str(INetID))
    Print("GetNetworkNumClients:" + Str(GetNetworkNumClients(iNetID)))

    for x = 1 to totHighScores
        Print("["+Str(x)+"]:" + HiScores[x].init + " S: " + Str(HiScores[x].score) + " L:" + Str(HiScores[x].level))
    next x

    // Clean up old connections
    for x = 1 to 50
        if x = 1
            id = GetNetworkFirstClient(iNetID)
        else
            id = GetNetworkNextClient(iNetID)
        endif
        if id = 0 then exit
        if GetNetworkClientDisconnected(iNetID, id) = 1
            DeleteNetworkClient(iNetID, id)
        endif
    next x

    id = GetNetworkFirstClient(iNetID)
    Print("Client:" + Str(id))
    do
        id = GetNetworkNextClient(iNetID)
        if id = 0
            exit
        else
            Print("Client:" + Str(id))
        endif
    loop


    // Check for Messages.
    msg = GetNetworkMessage(iNetID)

    if msg > 0
        ClientID = GetNetworkMessageFromClient(msg)
        //Print ("ClientID:" + Str(ClientID))

        if ClientID > 1
            f# = GetNetworkMessageFloat(msg)
            if f# = 1.0 // Send High Score List
                newMsg = CreateNetworkMessage()
                AddNetworkMessageFloat(newMsg, 1.0)
                for x = 1 to 10
                    AddNetworkMessageString(newMsg, HiScores[x].init)
                    AddNetworkMessageInteger(newMsg, HiScores[x].score)
                    AddNetworkMessageInteger(newMsg, HiScores[x].level)
                next x
                SendNetworkMessage(iNetID, ClientID, newMsg)
                DeleteNetworkMessage(newMsg)
            endif
            if f# = 1.1
                // Receive Score from Client
                init$ = GetNetworkMessageString(msg)
                score = GetNetworkMessageInteger(msg)
                level = GetNetworkMessageInteger(msg)
                // See if the submitted score is high enough for the top 10
                // If it is, place it where it belongs and shuffle the rest
                // of the scores down one position.
                for x = 1 to totHighScores
                    if score > HiScores[x].score then exit
                next x

                if x <= totHighScores
                    for y = totHighScores to x+1 step -1
                        HiScores[y].init = HiScores[y-1].init
                        HiScores[y].score = HiScores[y-1].score
                        HiScores[y].level = HiScores[y-1].level
                    next y
                    HiScores[x].init = init$
                    HiScores[x].score = score
                    HiScores[x].level = level
                endif
            endif
        endif
        DeleteNetworkMessage(msg)
    endif


    //if GetFileExists("highscores.txt") > 0 then DeleteFile("HighScores.txt")

    fileID = OpenToWrite("HighScores.txt", 0)
    if fileID > 0
        for x = 1 to totHighScores
            //WriteString(fileID, HiScores[x].init)
            //WriteInteger(fileID, HiScores[x].score)
            //WriteInteger(fileID, HiScores[x].level)
            WriteString(fileID, "badkneecap")
            WriteInteger(fileID, Random(1000, 2000))
            WriteInteger(fileID, x)
        next x
        CloseFile(fileID)
    endif


    Sync()
loop


You should be able to drop in a new project locally and run to follow.

First, the code above does not run. I have to uncomment line 131. It deletes the file if it exists. This is problem #1. Shouldn't "OpenToWrite("HighScores.txt", 0) do that for me?

Second, I would like to use lines 136 - 138, but it does not like the "WriteString" command that I have. As you can see, it works if I use a statis string instead. Again, is this a bug, or am I doing something wrong?

Thanks in advance for any input on what the problem is.
Posted: 30th Dec 2011 9:36
//if GetFileExists("highscores.txt") > 0 then DeleteFile("HighScores.txt")


You can replace this with OpenToWrite() as you say, and it works for me. I use this for debugging, so every AppGameKit program I have written does this every time it runs, and it has never failed me.
In your code I quoted here, you have used upper and lower case "S", maybe this is the problem? I have heard that file names in AppGameKit are case sensitive.

I haven't looked at your other code lines in the context of the entire program, but again this method works fine for me, there must be a bug in your code somewhere.
Posted: 30th Dec 2011 15:22
I have heard that file names in AppGameKit are case sensitive.

Not on PC, but are in iOS, and Android. (Probably others too)
Posted: 30th Dec 2011 17:51
I have had problems with upper and lower case in filenames, but not in this case. I know for a fact that the DeleteFile function works, it's the OpenToWrite function that does not. Again, I expect setting the "append" parameter to delete the file if it exists, and it's not. And that's what's causing the error, because if I delete the file using code, it works.

So, I'm thinking that it might be my computer, and not AGK. I noticed that when I delete the file and run the app, the file does not show up in the directory until I close the app. I'm running Windows Vista. Has anyone else come across this problem with Vista? Does it have anything to do with DEP?
Posted: 30th Dec 2011 19:02
I found part of the problem. I have to run the .exe as "administrator".

However, this does not solve my problem with the "WriteString". Anyone come across a problem like this?
Posted: 30th Dec 2011 19:15
Well, it must be a coding problem. I updated the b bottom of the code as follows:

+ Code Snippet
    fileID = OpenToWrite("HighScores.txt", 0)
    if fileID > 0
        for x = 1 to totHighScores
            tString = HiScores[x].init

            WriteString(fileID, tString)
            WriteInteger(fileID, HiScores[x].score)
            WriteInteger(fileID, HiScores[x].level)
        next x
        CloseFile(fileID)
    endif


So, I declared tString as a string at the top of the program and it worked. So, it must be something I am doing in my code.
Posted: 1st Jan 2012 18:25
One issue I see here is that you're attempting to write the file every loop rather than just when it changes. Your poor filesystem never gets a break

As to the write problem, I would suggest compiling the details into a string and writing the whole lot in one go using writeLine.

Reading and writing whole lines and splitting it up yourself may involve more work, but is better for validation and error checking of data as you read it.
Posted: 1st Jan 2012 18:49
It's funny you say that, because I quickly realized that when I checked my CPU and fixed it. So, right now I just write to the file when a new high score comes in.

As far as the coding, I think you solution is about the same as the one I came up with. It seems to me there is a problem trying to use the "HiScores[x].init" directly in the "WriteString" function. If I build a string like you said and save the entire line as the concatenated string, then it's ultimately doing the same thing. But, it's a good alternative to the problem. Thanks.