AppGameKit Cross-Platform Server

Hey everyone!

If anyone out there is an AppGameKit user, this is a core for a multiplayer Server setup that can be used.

This is build with AppGameKit Tier 1 IDE with a BASIC scripting language.

I will post the client and the media assets a little later, but anyone out there is looking to create a Multiplayer Game for Windows, Mac, Linux, iOS, Android or Blackberry, here’s a little code to get you started!

//App Game Kit
//Tier I
//BASIC Server
//Robert Janes
//2014-2015
//Packets from Server to Client!
//1.1 - Connected
//2.0 - Error Message
//2.2 - Moving
//2.3 - Stopping
//2.4 - Update Who's Online
//2.8 - Login Message
//3.0 - Send Projectile
//4.0 - Lobby Chat Message
//5.0 - Back to Lobby
//5.1 - Remove this player from the playing field
//Packets from Client to Server!
//1.0 - Login
//1.1 - New Character
//1.5 - Moving
//1.6 - Stopping
//1.7 - Global Message
//3.0 - Fire Projectile
//4.0 - Lobby Message

//Projectile Data Type
TYPE ProjectileRec
 ID as integer
 X as integer
 Y as integer
 Moving as Integer
 Angle as integer
 ClientID as integer
 Speed as integer
 Active as Integer
 StartTimer as float
 JoystickX as float
 JoystickY as float

ENDTYPE
//Player Data Type
TYPE PlayerRec
    Name as String
    Password as String
    X as Integer
    Y as Integer
    Angle as Integer
    JoystickX as float
    JoystickY as float
    Active as Integer
    Disconnected as integer
 LastPacket as float
 InGame as integer
 Ready as Integer
ENDTYPE

//Player Array
DIM Player[9999] as PlayerRec
global dim Projectile[9999] as ProjectileRec
global NumProjectiles as integer
global FoundProjectile as integer
global ProjectileID as integer
global DataID as integer
// Parsers
global Parser as integer
//Network Identifier
global INetID as integer
global SecondsRunning as integer
//Misc Vars
global ReceivedData as integer
global LastLogin as string
global strDebug as string
global strDebug2 as string
global tmpString as string
//Used for Player File IO tmpName/tmpPassword received as packets, strName,strPassword read from file
global FileName as string
global PlayerFile as integer
global tmpName as string
global tmpPassword as string
global strName as string
global strPassword as string
// Number of "Players" vs "Number of Current Connections"
global NumPlayers as Integer
global NumClients as integer
// IDs of First, Last and Next Connections
global StartID as Integer
global EndID as Integer
global NextID as integer
global i as Integer

// ============================================
// INIT
// ============================================
//Setup the Server
SetupServer()
//Setup the Defaults
SetDefaults()
//Call the Main Loop
MainLoop()

//End the Application
end

// ============================================
// Set Default Variables
// ============================================
function SetDefaults()

 //Number of Players (Default 1 for Server ClientID)
 NumPlayers = 1
 //Bytes Received
 ReceivedData = 0
endfunction
// ============================================
// Setup Server
// ============================================
function SetupServer()
    INetID = HostNetwork("GameNetwork", "Server", 4100)
endfunction
// ============================================
// Check for Disconnects
// ============================================
function CheckDisconnects()
 for i = 0 to NumPlayers
  //Only handle disconnects every 1 second(s)
  if timer() - Player[i].LastPacket > 1
   if GetNetworkClientDisconnected(iNetID,i) = 1
     if Player[i].Active > 0
      //Set their Active Flag to 0
      Player[i].Active = 0
      //If there is a match going!
      if GameRunning = 1
       //Was the player still alive?
       if Player[i].InGame = 1
        //Kill the Player!
        KillPlayer(i)
       endif        
      endif

      DeleteNetworkClient(INetID, i)
      SendDisconnectToAll(i)
     endif
    endif
         endif
 next i

 //3 minute idle timer
 for i = 0 to NumPlayers
  if timer() - Player[i].LastPacket > 180
   if Player[i].Active > 0
    Player[i].Active = 0
    //If there is a match going!
    if GameRunning = 1
     //Was the player still alive?
     if Player[i].InGame = 1
      //Kill the Player!
      KillPlayer(i)
     endif        
    endif
    DeleteNetworkClient(INetID,i)
    SendDisconnectToAll(i)
   endif
  endif
 next i

endfunction
// ============================================
// Handle Network Data
// ============================================
function HandleData()
 //Start Handling Network Data
    msg = GetNetworkMessage(INetID)
    if msg <> 0
  //Get the Client that is Sending the Data
        ClientID = GetNetworkMessageFromClient(msg)
        //Flag to print that we've received data
        ReceivedData = 1
        DataID = ClientID

   //Valid Client
            if ClientID > 1
                //#f is packet identifier
                f# = GetNetworkMessageFloat(msg)
                // ============================================
                // 1.0 LOGIN
                // ============================================
                if f# = 1.0 // Handle Login!
                    tmpName = GetNetworkMessageString(msg)
                    tmpPassword = GetNetworkMessageString(msg)
                    strName = ""
                    strPassword = ""
                    FileName = tmpName + ".txt"
                    //Temporarily set this player's name
                    Player[ClientID].Name = tmpName
                    strDebug2 = "Handled Login Packet: " + tmpName + "/" + tmpPassword
                    //Account Doesn't Exist!
                    if GetFileExists(FileName) = 0
                    endif

                    if GetFileExists(FileName) = 1
      strDebug2 = "File Existed: " + FileName
                        LoadPlayer(ClientID)
                        //Upgrade the number of players
                        NumPlayers = ClientID
                        //Send the Info the User with Current Players!
                        newMsg = CreateNetworkMessage()
                        AddNetworkMessageFloat(newMsg, 1.1)
                        AddNetworkMessageInteger(newMsg, ClientID)
                        AddNetworkMessageInteger(newMsg, NumPlayers)
                        AddNetworkMessageInteger(newMsg, Player[ClientID].X)
                        AddNetworkMessageInteger(newMsg, Player[ClientID].Y)
                        SendNetworkMessage(INetID, ClientID, newMsg)
                        Player[ClientID].LastPacket = Timer()
                        //Send the Login to Everyone!
                        SendPlayerToAll(ClientID)
                        //Send all the Players to the client!
                        SendPlayersToClient(ClientID)
                        DeleteNetworkMessage(newMsg)
                        //Send Login Message to Everyone!
                        SendLoginMessageToAll(ClientID)
                        //Put them in the Lobby
                        Player[ClientID].InGame=0
                        Player[ClientID].Ready = 0
                    endif
                endif

                // ============================================
                // 1.1 NEW CHARACTER
                // ============================================
                if f# = 1.1 // Handle New Character!
                    //Get the Variables sent from the Client
                    tmpName = GetNetworkMessageString(msg)
                    tmpPassword = GetNetworkMessageString(msg)
                    FileName = tmpName + ".txt"
                    //If the account aleady exists!
                    if GetFileExists(FileName) = 1
                        //Error out to the Client that the account exists
                        newMsg = CreateNetworkMessage()
                        AddNetworkMessageFloat(newMsg, 2.0)
                        AddNetworkMessageString(newMsg, "That account name is in use!")
                        SendNetworkMessage(INetID, ClientID, newMsg)
                        DeleteNetworkMessage(newMsg)
      Player[ClientID].LastPacket = Timer()
                    endif
                    //If we have no password and no name in the player file, it's a free account we can use!
                    if GetFileExists(FileName) = 0
      strDebug2 = "No file found for " + tmpName + ".txt"
                        //Set the Player Data!
                        Player[ClientID].Name = tmpName
                        Player[ClientID].Password = tmpPassword
                        Player[ClientID].X = 500
                        Player[ClientID].Y = 500
                        Player[ClientID].Angle = 0
                        Player[ClientID].JoystickX = 0
                        Player[ClientID].JoystickY = 0
                        Player[ClientID].Active = 1
                        Player[ClientID].InGame=0
                        Player[ClientID].Ready = 0
                        Player[ClientID].LastPacket = Timer()
                        //Save the Player File
                        SavePlayer(ClientID)
                        //Upgrade the number of players
                        NumPlayers = ClientID
                        //Send the Info the User with Current Players!
                        newMsg = CreateNetworkMessage()
                        AddNetworkMessageFloat(newMsg, 1.1)
                        AddNetworkMessageInteger(newMsg, ClientID)
                        AddNetworkMessageInteger(newMsg, NumPlayers)
                        AddNetworkMessageInteger(newMsg, Player[ClientID].X)
                        AddNetworkMessageInteger(newMsg, Player[ClientID].Y)
                        SendNetworkMessage(INetID, ClientID, newMsg)
                        //Send the Login to Everyone!
                        SendPlayerToAll(ClientID)
                        //Send all the Players to the client!
                        SendPlayersToClient(ClientID)
                        DeleteNetworkMessage(newMsg)
                    endif
                    strDebug = tmpName + " has been created using Client ID " + str(ClientID)
                endif
                // ============================================
                // 1.2 LOGGING OUT
                // ============================================
                if f# = 1.2 // Handle Stopping!
                    strDebug = "Handled Log Out Packet at " + str(Timer())
                    SendPlayerLoggingOut(ClientID)
                    DeleteNetworkMessage(newMsg)
                endif

                // ============================================
                // 1.5 MOVING
                // ============================================
                if f# = 1.5 // Handle Moving!
                    Player[ClientID].X = GetNetworkMessageInteger(msg)
                    Player[ClientID].Y = GetNetworkMessageInteger(msg)
                    Player[ClientID].Angle = GetNetworkMessageInteger(msg)
                    Player[ClientID].JoystickX = GetNetworkMessageFloat(msg)
                    Player[ClientID].JoystickY = GetNetworkMessageFloat(msg)
                    Player[ClientID].LastPacket = Timer()
                    strDebug = "Handled Moving Packet at " + str(Timer())
                    SendPlayerMoving(ClientID)
                    DeleteNetworkMessage(newMsg)
                endif
                // ============================================
                // 1.6 STOPPING
                // ============================================
                if f# = 1.6 // Handle Stopping!
                    Player[ClientID].X = GetNetworkMessageInteger(msg)
                    Player[ClientID].Y = GetNetworkMessageInteger(msg)
                    Player[ClientID].Angle = GetNetworkMessageInteger(msg)
                    Player[ClientID].JoystickX = GetNetworkMessageFloat(msg)
                    Player[ClientID].JoystickY = GetNetworkMessageFloat(msg)
                    Player[ClientID].LastPacket = Timer()
                    strDebug = "Handled Stopping Packet at " + str(Timer())
                    SendPlayerStopping(ClientID)
                    DeleteNetworkMessage(newMsg)
                endif

    // ============================================
                // 1.7 Global Chat Message
                // ============================================
                if f# = 1.7 // Handle Chatting!
                    tmpString = GetNetworkMessageString(msg)
                    SendChatMessageToAll(ClientID,tmpString)
                    DeleteNetworkMessage(newMsg)
                    Player[ClientID].LastPacket = Timer()
                endif

            endif

  //For now we are deleting the Network Message in Each Condition
        //DeleteNetworkMessage(msg)
    endif
endfunction
// ============================================
// Main Loop
// ============================================
function MainLoop()
do
    // How long has the server been running
    SecondsRunning = GetSeconds ( )
 ProcessProjectiles()

 //Call the CheckDisconnects Function
 CheckDisconnects()

 //Update Num Players if Needed!
 if GetNetworkNumClients(INetID) > NumPlayers
  NumPlayers = GetNetworkNumClients(INetID)
 endif

 //Handle Network Data
 HandleData()

 //What we are printing on screen
    print("Server Listening:")
    print("Online for: "+str(SecondsRunning)+" Seconds")
 //If we haven't received any data so far
    if ReceivedData = 0
    print("No Data Received")
    endif
 //We are Receiving Data - From what Client?
    if ReceivedData = 1
    print("Data Received from Client ID "+str(DataID))
    print(strDebug)
    endif

 //Display Number of Connections
 print(strDebug2)
 print("Num Players: " + str(NumPlayers))
 print("Num Connections: " + str(GetNetworkNumClients(iNetID)))
    Sync()
loop

endfunction

// ============================================
// Send All Players to One Client
// ============================================
function SendPlayersToClient(ClientID as integer)

 for i = 1 to NumPlayers
  if Player[i].Active = 1
   newMsg = CreateNetworkMessage()
   AddNetworkMessageFloat(newMsg, 2.4)
   AddNetworkMessageInteger(newMsg,NumPlayers)
   AddNetworkMessageInteger(newMsg,i)
   AddNetworkMessageString(newMsg,Player[i].Name)
   AddNetworkMessageInteger(newMsg, Player[i].X)
   AddNetworkMessageInteger(newMsg, Player[i].Y)
   SendNetworkMessage(INetID, ClientID, newMsg)
            DeleteNetworkMessage(newMsg)
  endif
 next i

endfunction

// ============================================
// Send Player Has Logged In!
// ============================================
function SendPlayerToAll(ClientID as integer)
   NextID = GetNetworkFirstClient(INetID)

    Repeat
        //If we have a valid ID!
        if NextID <> 0
           //Send the Player to Everyone connected
            newMsg = CreateNetworkMessage()
            AddNetworkMessageFloat(newMsg, 2.4)
            AddNetworkMessageInteger(newMsg,NumPlayers)
            AddNetworkMessageInteger(newMsg, ClientID)
            AddNetworkMessageString(newMsg, Player[ClientID].Name)
            AddNetworkMessageInteger(newMsg, Player[ClientID].X)
            AddNetworkMessageInteger(newMsg, Player[ClientID].Y)
            SendNetworkMessage(INetID, NextID, newMsg)
            DeleteNetworkMessage(newMsg)
        endif
    NextID = GetNetworkNextClient(INetID)
    Until NextID = 0
endfunction

// ============================================
// Send Player Moving
// ============================================
function SendPlayerMoving(ClientID as integer)
    NextID = GetNetworkFirstClient(INetID)
    Repeat
        //If we have a valid ID!
        if NextID <> 0
           //Send the Moving Packet
            newMsg = CreateNetworkMessage()
            AddNetworkMessageFloat(newMsg, 2.2)
            AddNetworkMessageInteger(newMsg, ClientID)
            AddNetworkMessageInteger(newMsg, Player[ClientID].X)
            AddNetworkMessageInteger(newMsg, Player[ClientID].Y)
            AddNetworkMessageInteger(newMsg, Player[ClientID].Angle)
            AddNetworkMessageFloat(newMsg, Player[ClientID].JoystickX)
            AddNetworkMessageFloat(newMsg, Player[ClientID].JoystickY)
            SendNetworkMessage(INetID, NextID, newMsg)
            DeleteNetworkMessage(newMsg)
        endif
    NextID = GetNetworkNextClient(INetID)
    Until NextID = 0
endfunction

// ============================================
// Send Player Stopping
// ============================================
function SendPlayerStopping(ClientID as integer)
 NextID = GetNetworkFirstClient(INetID)
    Repeat
        //If we have a valid ID!
        if NextID <> 0
           //Send the Stopping Packet
            newMsg = CreateNetworkMessage()
            AddNetworkMessageFloat(newMsg, 2.3)
            AddNetworkMessageInteger(newMsg, ClientID)
            AddNetworkMessageInteger(newMsg, Player[ClientID].X)
            AddNetworkMessageInteger(newMsg, Player[ClientID].Y)
            AddNetworkMessageInteger(newMsg, Player[ClientID].Angle)
            AddNetworkMessageFloat(newMsg, Player[ClientID].JoystickX)
            AddNetworkMessageFloat(newMsg, Player[ClientID].JoystickY)
            SendNetworkMessage(INetID, NextID, newMsg)
            DeleteNetworkMessage(newMsg)
        endif
    NextID = GetNetworkNextClient(INetID)
    Until NextID = 0

endfunction

// ============================================
// Save Player
// ============================================
function SavePlayer(ClientID as integer)
    tmpName = Player[ClientID].Name
    FileName = tmpName + ".txt"
        //Save the Player Data File
        PlayerFile = OpenToWrite(FileName, 0)
        WriteString(PlayerFile,tmpName)
        WriteString(PlayerFile,tmpPassword)
        //Default X/Y for Player
        WriteInteger(PlayerFile,Player[ClientID].X)
        WriteInteger(PlayerFile,Player[ClientID].Y)
        //Default Angle for Player
        WriteInteger(PlayerFile,0)
        //Default Joystick XY for Player
        WriteFloat(PlayerFile,0)
        WriteFloat(PlayerFile,0)
        //Close the PlayerFile
        CloseFile(PlayerFile)

endfunction

// ============================================
// Load Player
// ============================================
function LoadPlayer(ClientID as integer)

 FileName = Player[ClientID].Name + ".txt"
 strDebug2 = "Opening File " + FileName
    //The account exists!
    if GetFileExists(FileName) = 1
       PlayerFile = OpenToRead(FileName)
       strName = ReadString(PlayerFile)
       strPassword = ReadString(PlayerFile)
        //If we have the right login credentials, let's login!
        if tmpPassword = strPassword
           //Set the Player Data!
           Player[ClientID].Name = strName
           Player[ClientID].Password = strPassword
           Player[ClientID].X = ReadInteger(PlayerFile)
           Player[ClientID].Y = ReadInteger(PlayerFile)
           Player[ClientID].Angle = ReadInteger(PlayerFile)
           Player[ClientID].JoystickX = ReadFloat(PlayerFile)
           Player[ClientID].JoystickY = ReadFloat(PlayerFile)
           Player[ClientID].Active = 1
           strDebug2 = "Loaded " + Player[ClientID].Name
           CloseFile(PlayerFile)
       endif
    endif
endfunction

// ===========================================
// Send Disconnect to everyone connected
// ===========================================
function SendDisconnectToAll(ClientID as integer)
 //The Disconnect Flag is used to take us out of the loop if they've already been disconnected'
 // Disconnected = 0 - Connected
 // Disconnected = 1 - Logging Out
 // Disconnected = 2 - Timed Out
 // Disconnected = 3 - Disconnected
 if Player[ClientID].Disconnected < 3
  NextID = GetNetworkFirstClient(INetID)
  Repeat
    //If we have a valid ID!
   if NextID <> 0  
      //Send the Player to Everyone connected
    newMsg = CreateNetworkMessage()
    AddNetworkMessageFloat(newMsg, 2.6)
    AddNetworkMessageInteger(newMsg, ClientID)
    SendNetworkMessage(INetID, NextID, newMsg)
    DeleteNetworkMessage(newMsg)
   endif
  NextID = GetNetworkNextClient(INetID)

  Until NextID = 0
  //Set their Disconnected Flag
  Player[ClientID].Disconnected = 3

    endif
endfunction

// ===========================================
// Send the Login Message to Everyone
// ===========================================
function SendLoginMessageToAll(ClientID as integer)
 NextID = GetNetworkFirstClient(INetID)
 tmpString = Player[ClientID].Name + " has connected!"
    Repeat
        //If we have a valid ID!
        if NextID <> 0
           //Send the Player to Everyone connected
            newMsg = CreateNetworkMessage()
            AddNetworkMessageFloat(newMsg, 2.8)
   AddNetworkMessageString(newMsg, tmpString)
   AddNetworkMessageInteger(newMsg,0)
   AddNetworkMessageInteger(newMsg,255)
   AddNetworkMessageInteger(newMsg,0)
            SendNetworkMessage(INetID, NextID, newMsg)
            DeleteNetworkMessage(newMsg)
        endif
    NextID = GetNetworkNextClient(INetID)
    Until NextID = 0
endfunction

// ===========================================
// In-Game Chat Message
// ===========================================
function SendChatMessageToAll(ClientID as Integer, ChatMessage as String)
 NextID = GetNetworkFirstClient(INetID)
 tmpString = Player[ClientID].Name + ": " + ChatMessage
    Repeat
        //If we have a valid ID!
        if NextID <> 0
           //Send the Message to Everyone
            newMsg = CreateNetworkMessage()
            AddNetworkMessageFloat(newMsg, 2.8)
   AddNetworkMessageString(newMsg, tmpString)
   AddNetworkMessageInteger(newMsg,255)
   AddNetworkMessageInteger(newMsg,255)
   AddNetworkMessageInteger(newMsg,255)
            SendNetworkMessage(INetID, NextID, newMsg)
            DeleteNetworkMessage(newMsg)
        endif
    NextID = GetNetworkNextClient(INetID)
    Until NextID = 0
endfunction

[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]

I plan on using that eventually so thank you for posting this 🙂

Log in to reply