Attribute VB_Name = "Lists"
Option Explicit

'One player's complete data block
Public Type PlayerInfo
    PlayerName              As String           'User's name
    mID                     As Long             'Stored machine ID
    IP                      As Long             'Stored IP
    UserID                  As Long             'Connection ID
    ChannelName(1 To 9)     As String           'Chat channels
    TotalChannels           As Integer          'Total number of chat channels
    StoredID                As Long             'Database ID
    Op(0 To 4)              As Boolean          'Operator status
    YellNewbies             As Boolean          'Should I transmit new players?
    AttemptedLogins         As Integer          'How many times has he run ?login or ?blogin
                                                ' unsuccessfully?  Ignore after 3
    AttemptedMsgs           As Integer          'Number of message attempts in the last 5 seconds
                                                'If this exceeds 4, ignore any more for 20 seconds
    IgnoreCounter           As Integer          'Ignoring..
End Type

'Operator Access levels
Public Enum LEVEL
    AnyStatus = 0
    Messaging = 1
    Ban = 2
    Account = 3
    Server = 4
End Enum

'One server's complete data block
Public Type ServerInfo
    SessionID               As Long             'Current Session ID
    ServerName              As String           'Name of the connected server
    Remote                  As sockaddr         'How I tell one from the other
    pList(0 To 512)         As PlayerInfo       'Player List
    TotalPlayers            As Integer          'Total number of players logged in
    ScoreID                 As Long             'Not implemented yet
    VPlayerData             As String           'Virtual copy of user.raw
    TotalLoggedPlayers      As Long             'Total number of, um, logged players
    VSquadData              As String           'Virtual copy of squad.raw
    TotalLoggedSquads       As Long             'Total number of squads on this server
    VBanData                As String           'Virtual copy of ban.raw
    TotalLoggedBans         As Long             'Total bans on this server
    VBanfreeData            As String           'Virtual copy of banfree.raw
    TotalLoggedBanfrees     As Long             'Total banfrees on this server
End Type

Public ServerList(0 To 255) As ServerInfo       'Connected servers
Public TotalServers         As Integer          'Total connected servers

'Add a new server to the server list
Public Sub NewServer(Remote As sockaddr, ServerName As String, ScoreID As Long)
    TotalServers = TotalServers + 1
    ServerList(TotalServers).Remote = Remote
    ServerList(TotalServers).ServerName = ServerName
    ServerList(TotalServers).ScoreID = ScoreID
    ServerList(TotalServers).SessionID = 0
    ServerList(TotalServers).TotalPlayers = 0

    Call ReadServer(TotalServers)
End Sub

'Remove a server by pushing the server values down one
Public Sub DeleteServer(ServerIndex As Integer)
    Dim I As Integer
    
    Call UDPSend(ServerList(ServerIndex).Remote, Chr(0) + Chr(7))
    Call WriteServer(ServerIndex)

    For I = ServerIndex To TotalServers - 1
        ServerList(I) = ServerList(I + 1)
    Next
    TotalServers = TotalServers - 1
End Sub

'Add a new user to the given server
Public Sub NewUser(ServerIndex As Integer, PlayerName As String, mID As Long, IP As Long, UserID As Long, StoredID As Long)
    ServerList(ServerIndex).TotalPlayers = ServerList(ServerIndex).TotalPlayers + 1

    Call PutData(ServerIndex, StoredID, P_LastIP, GetString(IP))
    Call PutData(ServerIndex, StoredID, P_LastID, GetString(mID))
    Call PutData(ServerIndex, StoredID, P_LastPlayed, GetTimeString)
    Call PutData(ServerIndex, StoredID, P_TotalLogins, GetString(GetLong(GetData(ServerIndex, StoredID, P_TotalLogins)) + 1))

    With ServerList(ServerIndex).pList(ServerList(ServerIndex).TotalPlayers)
        .StoredID = StoredID
        .UserID = UserID
        .PlayerName = PlayerName
        .IP = IP
        .mID = mID
        .Op(LEVEL.AnyStatus) = False
        .Op(LEVEL.Messaging) = False
        .Op(LEVEL.Ban) = False
        .Op(LEVEL.Account) = False
        .Op(LEVEL.Server) = False
        .YellNewbies = False
        .TotalChannels = 0
        .AttemptedLogins = 0
    End With
End Sub

'Remove a user by pushing the user values down by one
Public Sub DeleteUser(ServerIndex As Integer, PlayerIndex As Integer)
    Dim I As Integer
    
    With ServerList(ServerIndex)
        For I = PlayerIndex To .TotalPlayers - 1
            .pList(I) = .pList(I + 1)
        Next
        .TotalPlayers = .TotalPlayers - 1
    End With
End Sub

'Search a connected SubSpace Server for players with the given Connection ID
Public Function getPlayerID(ServerID As Integer, UserID As Long) As Integer
    Dim I As Integer

    For I = 1 To ServerList(ServerID).TotalPlayers
        If ServerList(ServerID).pList(I).UserID = UserID Then getPlayerID = I: Exit Function
    Next
End Function

'Get the next session ID.  It's a number which identifies packets
Public Function NextSessionID(ServerID As Integer) As String
    With ServerList(ServerID)
        Call CopyMemory(ByVal Pointer, .SessionID, 4)
        .SessionID = .SessionID + 1             'Increment afterwards: always starts at zero
        NextSessionID = Pointer
    End With
End Function

'Compare sockaddr of Sender and stored Servers for a match
Public Function getServerID(Remote As sockaddr) As Integer
    Dim ServerID As Integer, I As Integer

    For I = 1 To TotalServers
        If ServerList(I).Remote.sin_addr = Remote.sin_addr And ServerList(I).Remote.sin_port = Remote.sin_port Then ServerID = I: Exit For
    Next

    getServerID = ServerID
End Function
