VERSION 1.0 CLASS BEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "clsSCGP" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = False 'TO DO NEXT: ' find out what type 0, packet 0x0C means (probly some quit-verify shit) ' find out what to do, when dling map from non-host player and they quit (request map pos from host?) ' track packet/type states better/properly ' track resend requests by update-beat rather than on responce ' handle the switch over from game room to game start ' handle the 0x54(?) packet for clicking "OK" for UMS Mission info when UMS game starts ' detect when we have droped from the game and when other players time out due to no incoming data over x time Private Declare Function GetTickCount Lib "kernel32" () As Long Private Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Source As Any, ByVal numbytes As Long) Private Declare Sub RtlZeroMemory Lib "kernel32" (ByRef Destination As Any, ByVal numbytes As Long) Private Declare Function sendto Lib "ws2_32" (ByVal S As Long, ByRef Buf As Any, ByVal buflen As Long, ByVal Flags As Long, ByRef toaddr As sockaddr_in, ByVal tolen As Long) As Long Private Type sockaddr_in sin_family As Integer sin_port As Integer sin_addr As Long sin_zero(1) As Long End Type Private Declare Function SFileDestroy Lib "Storm" Alias "#262" () As Boolean Private Declare Function SFileSetLocale Lib "Storm" Alias "#272" (ByVal nNewLocale As Long) As Long Private Declare Function SFileOpenArchive Lib "Storm" Alias "#266" (ByVal lpFileName As String, ByVal dwPriority As Long, ByVal dwFlags As Long, ByRef hMpq As Long) As Boolean Private Declare Function SFileOpenFileEx Lib "Storm" Alias "#268" (ByVal hMpq As Long, ByVal lpFileName As String, ByVal dwSearchScope As Long, ByRef hFile As Long) As Boolean Private Declare Function SFileGetFileSize Lib "Storm" Alias "#265" (ByVal hFile As Long, ByRef lpFileSizeHigh As Long) As Long Private Declare Function SFileReadFile Lib "Storm" Alias "#269" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, lpOverlapped As Any) As Boolean Private Declare Function SFileCloseFile Lib "Storm" Alias "#253" (ByVal hFile As Long) As Boolean Private Declare Function SFileCloseArchive Lib "Storm" Alias "#252" (ByVal hMpq As Long) As Boolean Private Type SCGPHEADER Footer As Long Checksum As Integer Lengh As Integer Sent As Long PktType As Byte PktID As Byte pID As Byte ReSend As Byte Recv As Long Addr As Long Port As Integer End Type Private hPLen(&HFF) As Integer Private Type SCGPTIMER TickTime As Long WaitTime As Long Enabled As Boolean End Type 'Public Enum SCGP_STATE ' SPS_UNACTIVE = 0 ' SPS_JOIN_START = 1 'send 0x01/waiting for 0x02 ' SPS_JOIN_ENTER = 2 'sent 0x03/0x07, waiting for the join data 'End Enum Public Enum SCGP_RACE SCR_ZERG = &H0 SCR_TERRAN = &H1 SCR_PROTOSS = &H2 SCR_RANDOM = &H6 End Enum Private Type SCGPRESEND Pos As Long Verifyed(19) As Byte 'used as packet ID, 0xFF = verifyed Sent(19) As Long Data(19) As String End Type Private Type SCGPRERECV Pos As Long Last As Long P(19) As SCGPHEADER Data(19) As String End Type Private Type SCGPPLAYER Addr As Long Port As Integer Sent(2) As Long Recv(2) As Long ID As Byte 'index of this player Slot As Byte DL As Byte T(2) As SCGPTIMER State(2) As Byte Er(2) As Byte Data(2) As SCGPRESEND 'send buffer DataR(2) As SCGPRERECV 'Recv buffer PingTick As Long Ping As Long MapPos As Long 'sending this player the map Account As String Stats As String End Type Private m_P(7) As SCGPPLAYER 'some client states Private Const SCPS0_UNACTIVE As Byte = &H0 Private Const SCPS0_JOIN_START As Byte = &H1 'sent 0x01, waiting for 0x02 Private Const SCPS0_JOIN_ENTER As Byte = &H2 'sent 0x03/0x07, waiting for game data Private Const SCPS0_ACTIVE As Byte = &H3 'idleing Private Const SCPS0_VERIFY As Byte = &H4 'must verify counts Private Const SCPS1_UNACTIVE As Byte = &H0 Private Const SCPS1_JOIN As Byte = &H1 Private Const SCPS1_DOWNLOAD As Byte = &H2 Private Const SCPS2_UNACTIVE As Byte = &H0 Private Const SCPS2_STREAM As Byte = &H1 Private Type SCGPSLOT Slot As Byte ID As Byte State As Byte Race As Byte Team As Byte End Type Private m_Slot(7) As SCGPSLOT Private m_Handle As Long 'socket handle Private m_MyID As Byte Private m_MyClient As Long Private m_MyAccount As String Private m_MyStats As String Private m_IsHost As Boolean Private m_StatsCode As Long '//Map variables Private m_GameName As String Private m_GamePass As String Private m_GameStats As String Private m_MaxPlayers As Long Private m_GameType As Integer Private m_Penalty As Integer Private m_PenaltyEx As Long Private m_MapTitleSet As Integer Private m_MapWidth As Integer Private m_MapHeight As Integer Private m_ForceName(3) As String Private m_ForceIndex(7) As Byte Private m_ForceFlag(3) As Byte Private m_RaceSelect(11) As Byte Private m_RaceBool(7) As Byte Private m_SlotSelect(11) As Byte 'state of slot for UMS: 'OWNR' Private m_SlotSelectB(11) As Byte 'state of slot for UMS: 'OWNR' '//Host variables Private m_LastAddr As Long Private m_Ban() As String Private m_BanCount As Long 'download Private m_MapFileName As String Private m_MapFileLen As Long Private m_MapFileHash As Long Private m_MapData As String Private m_MapPos As Long Private m_MapDLTick As Long '//Stream buffer Private m_Stream(1023) As Byte Private m_StreamPos As Long '//Packet buffer Private m_Buf(1023) As Byte Private m_BufPos As Long 'size of are send buffer Private m_Header(16) As Byte Private m_Addr As sockaddr_in Public Event OnJoinLatency() Public Event OnCreate(ByVal strMAP As String) Public Event OnEnterRoom() Public Event OnJoinReject(ByVal bReassion As Byte) Public Event OnMapStats(ByVal strGameName As String, _ ByVal strGamePass As String, _ ByVal strGameStats As String, _ ByVal intGameType As Integer, _ ByVal intPenaltyA As Integer, _ ByVal lngPenaltyB As Long, _ ByVal lngMaxPlayers As Long, _ ByVal intMapWidth As Integer, _ ByVal intMapHeight As Integer, _ ByVal strSlotSelect As String, _ ByVal strRaceSelect As String) Public Event OnForceName(ByVal strForceA As String, ByVal strForceB As String, ByVal strForceC As String, ByVal strForceD As String) Public Event OnCheckMap(ByVal lngLengh As Long, ByVal lngChecksum As Long, ByVal strMapName As String, ByRef bGotIt As Boolean, ByRef strMapData As String) Public Event OnMapDownloaded(ByVal lngLengh As Long, ByVal lngChecksum As Long, ByVal strMapName As String, ByRef strData As String) Public Event OnMapDownloading(ByVal bPercent As Byte, ByVal bSlot As Byte) Public Event OnSlotUpdate(ByVal bSlot As Byte, ByVal strAccount As String, ByVal bState As Byte, ByVal enRace As SCGP_RACE, ByVal bTeam As Byte, ByVal lngPing As Long, ByVal bDLPer As Byte) Public Event OnChat(ByVal strAccount As String, ByVal strChat As String) Public Event OnSlotPing(ByVal bSlot As Byte, ByVal lngPing As Long) Public Event OnPlayerJoin(ByVal strAccount As String, ByVal strStats As String) Public Event OnPlayerQuit(ByVal bSlot As Byte) Public Event OnGameStart() Public Sub Clear() Call Class_Initialize End Sub Private Sub Class_Initialize() Dim i As Integer For i = 0 To 7 Call ClearPlayer(i) Call ClearSlot(i) Next i m_MapData = vbNullString m_LastAddr = 0 m_StreamPos = 0 m_BanCount = -1 Erase m_Ban() hPLen(&H5) = 1 hPLen(&H9) = -1 hPLen(&HA) = -1 hPLen(&HC) = 8 hPLen(&HE) = 8 hPLen(&H13) = 3 hPLen(&H14) = 10 hPLen(&H15) = 11 hPLen(&H18) = 1 hPLen(&H19) = 1 hPLen(&H1A) = 2 hPLen(&H1E) = 2 hPLen(&H1F) = 3 hPLen(&H20) = 3 hPLen(&H21) = 2 hPLen(&H22) = 2 hPLen(&H23) = 3 hPLen(&H25) = 2 hPLen(&H26) = 2 hPLen(&H27) = 1 hPLen(&H29) = 3 hPLen(&H2A) = 1 hPLen(&H2B) = 2 hPLen(&H2C) = 2 hPLen(&H2D) = 2 hPLen(&H2F) = 5 hPLen(&H30) = 2 hPLen(&H31) = 1 hPLen(&H32) = 2 hPLen(&H33) = 1 hPLen(&H35) = 3 hPLen(&H36) = 1 hPLen(&H37) = 7 hPLen(&H3C) = 1 hPLen(&H3D) = 2 hPLen(&H3E) = 6 hPLen(&H3F) = 8 hPLen(&H40) = 18 hPLen(&H41) = 3 hPLen(&H42) = 2 hPLen(&H43) = 2 hPLen(&H44) = 3 hPLen(&H45) = 3 hPLen(&H48) = 13 hPLen(&H54) = 1 hPLen(&H55) = 2 hPLen(&H5A) = 1 End Sub Private Sub Class_Terminate() '// End Sub Public Sub InitJoin(ByVal lngAddr As Long, _ ByVal intPort As Integer, _ ByVal strMyAccount As String, _ ByVal strMyStats As String, _ ByVal strGamePass As String, _ ByVal lngHandle As Long) '//Clear existing game database Call Class_Initialize '//Set global game variables m_MyID = &HFF m_MyAccount = strMyAccount m_MyStats = strMyStats m_IsHost = False m_GameName = vbNullString m_GamePass = strGamePass '//Set host variables m_P(0).Addr = lngAddr m_P(0).Port = intPort '//Set packet variables m_Handle = lngHandle '//Join the game m_P(0).State(0) = SCPS0_JOIN_START m_P(0).Sent(0) = 2 m_P(0).Recv(0) = 1 Call TSet(m_P(0).T(0), 1500) Call s0_0x01(0) Call s0_0x01(0) Call s0_0x01(0) End Sub Public Function InitCreate(ByVal lngHandle As Long, _ ByVal strMPQ As String, _ ByVal intGameType As Integer, _ ByVal intPenalty As Integer, _ ByVal lngMPQHash As Long, _ ByVal lngStatsCode As Long, _ ByVal lngMyClient As Long, _ ByVal strMyAccount As String, _ ByVal strGameName As String, _ ByVal strGamePass As String, _ ByVal strGameStats As String) As Boolean 'On Error GoTo InitCreateErr '//Clear existing game database Call Class_Initialize Dim i As Long Dim S As String Dim lngHeader As Long Dim lngLengh As Long Dim lngPos As Long Dim strTAB As String 'string table Dim strFORC As String * 20 Dim strOWNR As String * 12 Dim strSIDE As String * 12 If (ReadMPQFile(strMPQ, "staredit\scenario.chk", S) = False) Then Exit Function lngPos = 1 Do Until ((lngPos + 7) > Len(S)) Call RtlMoveMemory(lngHeader, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 Call RtlMoveMemory(lngLengh, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 If (lngLengh < 0) Then Exit Do Select Case lngHeader Case &H43524F46 'FORC' Required for Melee game type strFORC = Mid$(S, lngPos, lngLengh) Case &H45444953 'SIDE' strSIDE = Mid$(S, lngPos, lngLengh) Case &H524E574F 'OWNR' Required strOWNR = Mid$(S, lngPos, lngLengh) Case &H20415245 'ERA ' Required Call RtlMoveMemory(m_MapTitleSet, ByVal Mid$(S, lngPos, 2), 2) m_MapTitleSet = (m_MapTitleSet And &H7) Case &H204D4944 'DIM ' Required Call RtlMoveMemory(m_MapWidth, ByVal Mid$(S, lngPos, 2), 2) Call RtlMoveMemory(m_MapHeight, ByVal Mid$(S, lngPos + 2, 2), 2) m_MapWidth = (m_MapWidth And &H7FFF) m_MapHeight = (m_MapHeight And &H7FFF) Case &H20525453 'Str ' Required for Melee game type strTAB = Mid$(S, lngPos, lngLengh) 'string table End Select lngPos = lngPos + lngLengh Loop S = vbNullString Call RtlMoveMemory(m_SlotSelect(0), ByVal strOWNR, 12) Call RtlMoveMemory(m_RaceSelect(0), ByVal strSIDE, 12) Call RtlMoveMemory(m_SlotSelectB(0), ByVal strOWNR, 12) Call RtlMoveMemory(m_ForceIndex(0), ByVal strFORC, 8) Call RtlMoveMemory(m_ForceFlag(0), ByVal Mid$(strFORC, 17, 4), 4) '//Get the force names lngLengh = 0 For i = 0 To 3 Call RtlMoveMemory(lngLengh, ByVal Mid$(strFORC, 9 + (i * 2), 2), 2) If (lngLengh > 0) Then Call RtlMoveMemory(lngLengh, ByVal Mid$(strTAB, (lngLengh * 2) + 1, 2), 2) lngLengh = (lngLengh And &HFFFF&) m_ForceName(i) = GetSTR(Mid$(strTAB, lngLengh + 1)) If (Len(m_ForceName(i)) > 30) Then m_ForceName(i) = Left$(m_ForceName(i), 30) Else m_ForceName(i) = vbNullString End If Next i '//Get the max players If (intGameType = &HB) Or (intGameType = &HC) Or (intGameType = &HD) Then 'team melee/team ffa/team ctf etc m_MaxPlayers = 8 ElseIf (intGameType = &H4) Then 'one vs one m_MaxPlayers = 2 Else m_MaxPlayers = 0 For i = 0 To 7 If (m_SlotSelectB(i) = &H5) Or (m_SlotSelectB(i) = &H6) Then m_MaxPlayers = m_MaxPlayers + 1 End If Next i If (m_MaxPlayers < 2) Then GoTo InitCreateErr End If '//Get the true race for each player If (intGameType = &HB) Or (intGameType = &HC) Or (intGameType = &HD) Then For i = 0 To 7 m_RaceSelect(i) = &H6 'random m_SlotSelect(i) = &H6 'human selectible Mid$(strOWNR, (i + 1), 1) = Chr$(6) Mid$(strSIDE, (i + 1), 1) = Chr$(6) Next i For i = 8 To 11 m_RaceSelect(i) = &H0 Mid$(strSIDE, (i + 1), 1) = vbNullChar Next i ElseIf (Not intGameType = &HA) Then For i = 0 To 7 If (m_SlotSelectB(i) = &H5) Or (m_SlotSelectB(i) = &H6) Then m_RaceSelect(i) = &H6 'random m_SlotSelect(i) = &H6 'human selectible Mid$(strOWNR, (i + 1), 1) = Chr$(6) Mid$(strSIDE, (i + 1), 1) = Chr$(6) End If Next i For i = 8 To 11 m_RaceSelect(i) = &H0 Mid$(strSIDE, (i + 1), 1) = vbNullChar Next i Else '//UMS For i = 0 To 7 If (m_RaceSelect(i) = &H5) Then m_RaceSelect(i) = &H6 Mid$(strSIDE, (i + 1), 1) = Chr$(6) End If Next i End If '//work out the "change race" booleans For i = 0 To 7 m_RaceBool(i) = IIf((m_RaceSelect(i) = &H6), 1, 0) Next i '//Work out the true force index's If (intGameType = &HA) Or _ (intGameType = &HB) Or _ (intGameType = &HC) Or _ (intGameType = &HD) Or _ (intGameType = &HF) Then For i = 0 To 7 If (Not m_SlotSelectB(i) = &H0) Then If (m_ForceIndex(i) < &HFF) Then m_ForceIndex(i) = m_ForceIndex(i) + 1 End If Next i Else For i = 0 To 7 m_ForceIndex(i) = 0 Next i End If m_Handle = lngHandle m_MyID = 0 m_MyClient = lngMyClient m_MyAccount = strMyAccount m_MyStats = vbNullString m_IsHost = True m_P(m_MyID).Account = strMyAccount m_P(m_MyID).Addr = 1 m_P(m_MyID).Port = 6112 m_P(m_MyID).DL = 100 m_P(m_MyID).State(0) = SCPS0_ACTIVE m_P(m_MyID).State(1) = SCPS1_DOWNLOAD m_P(m_MyID).State(2) = SCPS2_STREAM '//Map variables m_GameName = strGameName m_GamePass = strGamePass m_GameStats = strGameStats '//m_MaxPlayers m_GameType = intGameType If (m_GameType = &HF) Then m_Penalty = (m_MaxPlayers - intPenalty) Else m_Penalty = intPenalty End If '//Calculate the penalty2 value If (m_GameType = &H6) Then m_PenaltyEx = (m_Penalty * 2500) ElseIf (m_GameType = &H7) Then m_PenaltyEx = (m_Penalty * 15) ElseIf (m_GameType = &H9) Or (m_GameType = &HF) Then m_PenaltyEx = m_Penalty ElseIf (m_GameType = &HB) Or (m_GameType = &HC) Or (m_GameType = &HD) Then m_PenaltyEx = m_Penalty + 1 Else m_PenaltyEx = 0 End If 'download m_MapFileName = StrReverse(GetSTR(StrReverse(strMPQ), "\")) m_MapFileLen = FileLen(strMPQ) m_MapFileHash = lngMPQHash i = FreeFile() Open strMPQ For Binary As #i m_MapData = String(LOF(i), 0) Get #i, 1, m_MapData Close #i m_MapPos = -1 m_MapDLTick = GetTickCount() m_StatsCode = lngStatsCode RaiseEvent OnCreate(strMPQ) RaiseEvent OnEnterRoom If (m_GameType = &HA) Then RaiseEvent OnForceName(m_ForceName(0), m_ForceName(1), m_ForceName(2), m_ForceName(3)) End If RaiseEvent OnMapStats(m_GameName, m_GamePass, m_GameStats, m_GameType, m_Penalty, m_PenaltyEx, m_MaxPlayers, m_MapWidth, m_MapHeight, strOWNR, strSIDE) '//find my slot in the room For i = 0 To 7 If (m_SlotSelect(i) = &H6) Then m_P(m_MyID).Slot = i Exit For End If Next i '//set the game slots For i = 7 To 0 Step -1 m_Slot(i).Slot = i m_Slot(i).ID = IIf((i = m_P(m_MyID).Slot), m_MyID, &HFF) m_Slot(i).State = IIf((m_SlotSelect(i) = &H6) And (i = m_P(m_MyID).Slot), &H2, m_SlotSelect(i)) m_Slot(i).Race = m_RaceSelect(i) '//work out the true game room slot teams If (m_GameType = &HF) Then 'TvB m_Slot(i).Team = IIf((i >= m_Penalty), 2, 1) ElseIf (m_GameType = &HB) Or (m_GameType = &HC) Or (m_GameType = &HD) Then '//team games Select Case m_Penalty Case 2: m_Slot(i).Team = IIf((i < 3), 1, IIf((i < 6), 2, 3)) Case 3: m_Slot(i).Team = IIf((i < 2), 1, IIf((i < 4), 2, IIf((i < 6), 3, 4))) Case Else: m_Slot(i).Team = IIf((i < 4), 1, 2) End Select ElseIf (intGameType = &HA) Then 'UMS m_Slot(i).Team = IIf((m_Slot(i).State = &H2) Or (m_Slot(i).State = &H5) Or (m_Slot(i).State = &H6) Or (m_Slot(i).State = &H8), m_ForceIndex(i), 0) End If Call s2_0x3E(i, m_Slot(i).ID, m_Slot(i).State, m_Slot(i).Race, m_Slot(i).Team) Next i 'Debug.Print "OWNR = " & StrToHex(strOWNR) 'Debug.Print "SIDE = " & StrToHex(strSIDE) 'Debug.Print "OWNRB = " & BytesToHex(m_SlotSelectB()) 'Debug.Print "FORC = " & BytesToHex(m_ForceIndex()) 'Debug.Print "RACEBOOL = " & BytesToHex(m_RaceBool()) InitCreate = True Exit Function InitCreateErr: Debug.Print "clsSCGP.InitCreate() " & Err.Description Call Class_Initialize End Function Public Sub Quit() Dim i As Integer For i = 0 To 7 If (Not m_P(i).Addr = 0) Then Call s0_0x0B(i, True) Call s0_0x0B(i, False) Call s0_0x0B(i, False) End If Call ClearPlayer(i) Next i End Sub Public Sub Chat(ByVal strChat As String) Dim i As Integer For i = 0 To 7 If (Not m_P(i).Addr = 0) Then Call s1_0x4C(i, strChat, True) End If Next i End Sub Public Sub ChangeRace(ByVal bSlot As Byte, ByVal enRace As SCGP_RACE) Call s2_0x41(bSlot, enRace) End Sub Public Sub ChangeTeam(ByVal bTeam As Byte) If (m_GameType = &HA) Then Call s2_0x43(bTeam) '(UMS) TEAM NUMBER Else Call s2_0x42(bTeam) '(NOT UMS) TEAM NUMBER End If End Sub Public Sub MovePlayerTeam(ByVal bSlot As Byte, ByVal bTeam As Byte) '//Move player(bSlot) to team(bTeam) If (Not m_GameType = &HF) Then Exit Sub If (bSlot > 7) Then Exit Sub If (bTeam = &H0) Or (bTeam > &H4) Then Exit Sub If (Not m_Slot(bSlot).State = &H2) Then Exit Sub Dim i As Byte i = FindTeamSlot(bTeam, &H6) 'open state If (i > &H7) Then Exit Sub 'no room in this team '//Move this player to this slot Call s2_0x45(bSlot, i) End Sub Public Sub MovePlayerSlot(ByVal bSlot As Byte, ByVal bToSlot As Byte) '//Move player(bSlot) to room(bToSlot) If (Not m_GameType = &HF) Then Exit Sub If (bSlot > 7) Then Exit Sub If (Not m_Slot(bSlot).State = &H2) Then Exit Sub Call s2_0x45(bSlot, bToSlot) End Sub Public Sub ChangeSlotState(ByVal bSlot As Byte, ByVal bState As Byte) If (m_IsHost = False) Then Exit Sub If (bSlot > 7) Then Exit Sub If (bState = 5) Then 'Computer Call s2_0x44(bSlot, 0) ElseIf (bState = 6) Then 'Open Call s2_0x44(bSlot, 1) ElseIf (bState = 8) Then 'Closed Call s2_0x44(bSlot, 2) Else Exit Sub End If End Sub Public Sub BootPlayer(ByVal strAccount As String, Optional ByVal bBan As Boolean = False) Dim i As Byte Dim bSlot As Byte Dim bEvent As Byte If (m_IsHost = False) Then Exit Sub If bBan Then Call AddBanPlayer(strAccount) bEvent = &H1 Else bEvent = &H0 End If For i = 0 To 7 If (Not m_P(i).Addr = 0) And (Not i = m_MyID) Then If (StrComp(strAccount, m_P(i).Account, vbTextCompare) = 0) Then bSlot = m_P(i).Slot Call s1_0x4E(i, bEvent, True) Call s1_0x4E(i, bEvent, False) Call s1_0x4E(i, bEvent, False) Call ClearPlayer(i) If (bSlot < 8) Then RaiseEvent OnPlayerQuit(bSlot) Call s2_0x3E(bSlot, &HFF, &H6, m_Slot(bSlot).Race, m_Slot(bSlot).Team) End If End If End If Next i End Sub Public Sub Update() If (m_P(0).State(0) = SCPS0_UNACTIVE) Then Exit Sub m_LastAddr = 0 Call UpdateStream If m_IsHost Then Call UpdateHost Else Call UpdateJoin End If End Sub Private Sub UpdateHost() '// End Sub Private Sub UpdateJoin() '//Check if still trying to join the game If (m_P(0).State(0) = SCPS0_JOIN_START) Or _ (m_P(0).State(0) = SCPS0_JOIN_ENTER) Then '//STILL TRYING TO JOIN GAME If (TFire(m_P(0).T(0)) = False) Then Exit Sub m_P(0).Er(0) = m_P(0).Er(0) + 1 If (m_P(0).Er(0) > 4) Then Call Class_Initialize RaiseEvent OnJoinLatency Exit Sub End If '//Poke the host again Call TSet(m_P(0).T(0), 1500) If (m_P(0).State(0) = SCPS0_JOIN_START) Then Call s0_0x01(0) Else Call s0_0x03(0) Call s0_0x07(0) End If Exit Sub End If '//Check state of other ingame players For i = 0 To 7 If (i = m_MyID) Then GoTo UpdateJoin0x00Nexti If (m_P(i).Addr = 0) Then GoTo UpdateJoin0x00Nexti If (m_P(i).State(0) = SCPS0_JOIN_ENTER) And (i > 0) Then '//Still havent got responce from this player (0x04/0x05) If (TFire(m_P(i).T(0)) = False) Then Exit Sub m_P(i).Er(0) = m_P(i).Er(0) + 1 ElseIf (m_P(i).State(0) = SCPS0_ACTIVE) Then '//Check if its time to refresh the 0x00 protocol If (TFire(m_P(i).T(0)) = False) Then Exit Sub Call TSet(m_P(i).T(0), 19950) m_P(i).Er(0) = 0 m_P(i).PingTick = GetTickCount() Call s0_0x04(i, True) ElseIf (m_P(i).State(0) = SCPS0_VERIFY) Then End If UpdateJoin0x00Nexti: Next i UpdateJoin0x01: End Sub Private Sub UpdateStream() If m_IsHost Then Call AddPktCount(m_P(m_MyID).Sent(2)) Dim i As Byte Dim lngTest As Long For i = 0 To 7 If (Not m_P(i).Addr = 0) Then If (m_P(i).State(0) = SCPS0_ACTIVE) And (Not i = m_MyID) Then If (Not i = m_MyID) Then Call s2_Stream(i, True) End If End If End If Next i m_StreamPos = 0 End Sub Public Sub OnData(ByRef S As String, ByVal lngAddr As Long, ByVal intPort As Integer) Dim P As SCGPHEADER Call RtlMoveMemory(P, ByVal S, 16) Call RtlMoveMemory(P.Recv, ByVal VarPtr(P.Sent) + 2, 2) Call RtlZeroMemory(ByVal VarPtr(P.Sent) + 2, 2) P.Addr = lngAddr P.Port = intPort If (P.pID = m_MyID) Then Exit Sub If (P.PktType > 2) Then Exit Sub If (P.pID < 8) Then If (Not m_P(P.pID).Addr = lngAddr) Or (Not m_P(P.pID).Port = intPort) Then Exit Sub End If End If If (P.ReSend = 0) Then If (P.PktType = 1) Then Call VerifyRecvCount(P, S) Exit Sub End If End If Call ParseEx(P, S) End Sub Private Sub ParseEx(ByRef P As SCGPHEADER, ByRef S As String) If (P.PktType = 2) Then 'Stream data If (P.pID > 7) Then Exit Sub If (Not P.ReSend = 0) Then: Call h2_Resend(P, S): Exit Sub Call AddPktCount(m_P(P.pID).Recv(2)) '//Split the packets up P.Footer = 17 Do P.PktID = Asc(Mid$(S, P.Footer, 1)) P.Lengh = hPLen(P.PktID) If (P.Lengh = -1) Then If (P.PktID = &H9) Or (P.PktID = &HA) Then P.Lengh = 2 + (Asc(Mid$(S, P.Footer + 1, 1)) * 2) Else P.Lengh = 0 End If End If If (P.Lengh < 1) Then '//Unknown packet lengh Debug.Print "UNHANDLED PACKET(2) FROM " & P.pID & " _ 0x" & Hex(P.PktID) 'Debug.Print " " & StrToHex(Mid$(S, P.Footer)) Exit Sub End If P.Checksum = P.Footer P.PktType = P.PktID P.Recv = P.Lengh P.Footer = P.Footer + P.Lengh 'strData = Mid$(S, P.Checksum, P.Recv) Select Case P.PktType Case &H5: 'Call h2_0x05(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H9: 'Call h2_0x09(P, Mid$(S, P.Checksum, P.Recv)) 'Case &HA: 'Call h2_0x0A(P, Mid$(S, P.Checksum, P.Recv)) 'Case &HC: 'Call h2_0x0C(P, Mid$(S, P.Checksum, P.Recv)) 'Case &HE: 'Call h2_0x0E(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H14: 'Call h2_0x14(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H15: 'Call h2_0x15(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H18: 'Call h2_0x18(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H19: 'Call h2_0x19(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H1A: 'Call h2_0x1A(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H1E: 'Call h2_0x1E(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H1F: 'Call h2_0x1F(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H20: 'Call h2_0x20(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H21: 'Call h2_0x21(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H22: 'Call h2_0x22(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H23: 'Call h2_0x23(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H25: 'Call h2_0x25(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H26: 'Call h2_0x26(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H27: 'Call h2_0x27(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H29: 'Call h2_0x29(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H2A: 'Call h2_0x2A(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H2C: 'Call h2_0x2C(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H2D: 'Call h2_0x2D(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H2F: 'Call h2_0x2F(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H30: 'Call h2_0x30(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H31: 'Call h2_0x31(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H32: 'Call h2_0x32(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H33: 'Call h2_0x33(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H35: 'Call h2_0x35(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H36: 'Call h2_0x36(P, Mid$(S, P.Checksum, P.Recv)) Case &H37: 'Call h2_0x37(P, Mid$(S, P.Checksum, P.Recv)) Case &H3C: Call h2_0x3C(P) Case &H3D: Call h2_0x3D(P, Mid$(S, P.Checksum, P.Recv)) Case &H3E: Call h2_0x3E(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H3F: 'Call h2_0x3F(P, Mid$(S, P.Checksum, P.Recv)) Case &H40: Call h2_0x40(P, Mid$(S, P.Checksum, P.Recv)) Case &H41: Call h2_0x41(P, Mid$(S, P.Checksum, P.Recv)) Case &H42: Call h2_0x42(P, Mid$(S, P.Checksum, P.Recv)) Case &H43: Call h2_0x43(P, Mid$(S, P.Checksum, P.Recv)) Case &H44: Call h2_0x44(P, Mid$(S, P.Checksum, P.Recv)) Case &H45: Call h2_0x45(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H48: Call h2_0x48(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H4A: 'Call h2_0x4A(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H54: 'Call h2_0x54(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H55: 'Call h2_0x55(P, Mid$(S, P.Checksum, P.Recv)) 'Case &H5A: 'Call h2_0x5A(P, Mid$(S, P.Checksum, P.Recv)) Case Else: Debug.Print "UNHANDLED PACKET(2) FROM " & P.pID & " _ 0x" & Hex(P.PktID) 'Debug.Print " " & StrToHex(Mid$(S, P.Checksum, P.Recv)) End Select If (P.Footer > Len(S)) Then Exit Sub Loop ElseIf (P.PktType = 1) Then 'Function data If (P.Lengh > 12) Then P.PktID = Asc(Mid$(S, 17, 1)) If (P.pID > 7) Then Exit Sub If (Not P.ReSend = 0) Then: Call h1_Resend(P): Exit Sub Call AddPktCount(m_P(P.pID).Recv(1)) Select Case P.PktID Case &H0: Call h1_0x00(P, S) '//[C>C] Ingame chat Case &H49: Call h1_0x49(P, S) '//[H>C] tells each player, about another player as now ingame Case &H4A: Call h1_0x4A(P, S) '//[H>C] part of the join process, sent before 0x01->0x50 Case &H4B: Call h1_0x4B(P, S) '//[H>C] Map Forces Name Case &H4C: Call h1_0x4C(P, S) '//[C>C] game room chat Case &H4E: Call h1_0x4E(P, S) '//[H>C] kicks a player from the game Case &H4F: Call h1_0x4F(P, S) '//[C-H] Map downloading Case &H50: Call h1_0x50(P) '//[H>C] part of the join process, expect 0x02->0x40 Case Else '//Unhandled Debug.Print "UNHANDLED PACKET(1) FROM " & P.pID & " _ 0x" & Hex(P.PktID) 'Debug.Print " " & StrToHex(Mid$(S, 17)) End Select ElseIf (P.PktType = 0) Then 'General data If (Not P.ReSend = 0) Then: Call h0_Resend(P): Exit Sub If (P.pID < 8) Then Call AddPktCount(m_P(P.pID).Recv(0)) Select Case P.PktID Case &H1: Call h0_0x01(P, S) '//[C>H] Request to join game Case &H2: Call h0_0x02(P, S) '//[H>C] Responce from host about 1st join request Case &H3: Call h0_0x03(P, S) '//[C>H] Responce to join resoince 0x03 Case &H4: Call h0_0x04(P) '//[C>C] Existance check Case &H5: Call h0_0x05(P) '//[C>C] Existance final Case &H6: Call h0_0x06(P, S) '//[H>C] Notify a player is in/has joined the game Case &H7: Call h0_0x07(P, S) '//[C>H] Join game Case &H8: Call h0_0x08(P, S) '//[H>C] Game/Map main settings (like BNCS 0x09/0x1C) Case &H9: Call h0_0x09(P, S) '//[H>C] game type settings Case &HA: Call h0_0x0A(P) '//[H>C] Unable to join the game Case &HB: Call h0_0x0B(P, S) '//[C>C] Quit game Case &HC: Call h0_0x0C(P, S) '//[C>C] dunno Case &HE: Call h0_0x0E(P, S) '//[H>C] game state?!?!?! Case &HF: Call h0_0x0F(P, S) '//[H>C] Game /stats code for bnet Case Else '//Unhandled Debug.Print "UNHANDLED PACKET(0) FROM " & P.pID & " _ 0x" & Hex(P.PktID) 'Debug.Print " " & StrToHex(Mid$(S, 17)) End Select End If End Sub Private Sub h0_Resend(ByRef P As SCGPHEADER) Dim i As Integer If (P.ReSend = 1) Then '//VERIFYER ElseIf (P.ReSend = 2) Then '//RESEND i = FindResendData(m_P(P.pID).Data(0), P.Sent) If (i = -1) Then Exit Sub Call s0_Buffer(P.pID, i) End If End Sub Private Sub h0_0x01(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] query join game Dim lngTest As Long If (Len(S) < 20) Then Exit Sub If (m_IsHost = False) Then Exit Sub If (Not P.pID = &HFF) Then Exit Sub Call RtlMoveMemory(lngTest, ByVal Mid$(S, 17, 4), 4) If (Not lngTest = &H1) Then Exit Sub If (P.Addr = m_LastAddr) Then Exit Sub m_LastAddr = P.Addr Call s0_0x02(P.Addr, P.Port) End Sub Private Sub h0_0x02(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Start join responce If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call s0_0x03(0) Call s0_0x07(0) End Sub Private Sub h0_0x03(ByRef P As SCGPHEADER, ByRef S As String) '//[C>H] start enter game Dim lngTest As Long If (Len(S) < 20) Then Exit Sub If (m_IsHost = False) Then Exit Sub If (Not P.pID = &HFF) Then Exit Sub Call RtlMoveMemory(lngTest, ByVal Mid$(S, 17, 4), 4) If (Not lngTest = &H1) Then Exit Sub End Sub Private Sub h0_0x04(ByRef P As SCGPHEADER) '//[C>C] Existance Check If (P.pID > 7) Then Exit Sub Call s0_0x05(P.pID, True) If (m_P(P.pID).State(0) = SCPS0_JOIN_ENTER) Then m_P(P.pID).State(0) = SCPS0_ACTIVE m_P(P.pID).Er(0) = 0 m_P(P.pID).PingTick = GetTickCount() Call s0_0x04(P.pID, True) Call s2_Stream(P.pID, True) Call s2_Stream(P.pID, True) End If End Sub Private Sub h0_0x05(ByRef P As SCGPHEADER) '//[C>C] Existance Final If (P.pID > 7) Then Exit Sub Call s0_Verify(P.pID) If (m_P(P.pID).PingTick = 0) Then Exit Sub m_P(P.pID).Ping = (GetTickCount - m_P(P.pID).PingTick) m_P(P.pID).PingTick = 0 If (m_P(P.pID).Slot < 7) Then RaiseEvent OnSlotPing(m_P(P.pID).Slot, m_P(P.pID).Ping) End If End Sub Private Sub h0_0x06(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] About another player If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim bID As Byte 'Call RtlMoveMemory(lngUnknown1, ByVal Mid$(S, 17, 4), 4) bID = Asc(Mid$(S, 21, 1)) If (bID = m_MyID) Then Exit Sub If (bID > 7) Then Exit Sub If (Not bID = 0) Then Call ClearPlayer(bID) End If 'Call RtlMoveMemory(lngIsHost, ByVal Mid$(S, 25, 4), 4) 'Call RtlMoveMemory(lngUnknown2, ByVal Mid$(S, 29, 4), 4) Call RtlMoveMemory(m_P(bID).Recv(2), ByVal Mid$(S, 33, 4), 4) m_P(bID).Sent(2) = m_P(bID).Recv(2) - 2 'Call RtlMoveMemory(intFamily, ByVal Mid$(S, 37, 2), 2) If (Not bID = 0) Then m_P(bID).State(0) = SCPS0_JOIN_ENTER m_P(bID).Sent(0) = -1 m_P(bID).Recv(0) = -1 Call RtlMoveMemory(m_P(bID).Port, ByVal Mid$(S, 39, 2), 2) Call RtlMoveMemory(m_P(bID).Addr, ByVal Mid$(S, 41, 4), 4) End If '0x00 = Mid$(S, 45, 4) '0x00 = Mid$(S, 49, 4) m_P(bID).Account = GetSTR(Mid$(S, 53)) m_P(bID).Stats = GetSTR(Mid$(S, 54 + Len(m_P(bID).Account))) m_P(bID).State(0) = SCPS0_JOIN_ENTER Call TSet(m_P(bID).T(0), 20000) If (m_P(0).State(0) = SCPS0_ACTIVE) Then Call s0_Verify(0) End If End Sub Private Sub h0_0x07(ByRef P As SCGPHEADER, ByRef S As String) '//[C>H] Join Game If (m_IsHost = False) Then Exit Sub If (Not P.pID = &HFF) Then Exit Sub Dim i As Integer Dim i2 As Integer Dim lngClient As Long Dim strAccount As String Dim strStats As String Dim strPass As String strAccount = GetSTR(Mid$(S, 17)) strStats = GetSTR(Mid$(S, 18 + Len(strAccount))) strPass = GetSTR(Mid$(S, 19 + Len(strAccount) + Len(strStats))) '//Check account name is valid If (Len(strAccount) = 0) Then GoTo h0_0x07Reject For i = 1 To Len(strAccount) If (Asc(Mid$(strAccount, i, 1)) < &H21) Then GoTo h0_0x07Reject Next i '//Check client If (Len(strStats) < 4) Then GoTo h0_0x07Reject Call RtlMoveMemory(lngClient, ByVal strStats, 4) If (Not lngClient = m_MyClient) Then GoTo h0_0x07Reject '//Check game password If (Len(m_GamePass) > 0) Then If (Not StrComp(strPass, m_GamePass, vbTextCompare) = 0) Then GoTo h0_0x07Reject End If '//Check this account or IP is not already in the game For i = 0 To 7 If (m_P(i).Addr = P.Addr) And (m_P(i).Port = P.Port) Then GoTo h0_0x07Reject If (StrComp(m_P(i).Account, strAccount, vbTextCompare) = 0) Then GoTo h0_0x07Reject Next i '//Check account is not already banned For i = 0 To m_BanCount If (StrComp(strAccount, m_Ban(i), vbTextCompare) = 0) Then GoTo h0_0x07Reject Next i '//Find an avalible place in the game For i = 0 To 7 If (m_P(i).Addr = 0) Then Call ClearPlayer(i) m_P(i).Addr = P.Addr m_P(i).Port = P.Port m_P(i).Account = strAccount m_P(i).Stats = strStats m_P(i).State(0) = SCPS0_JOIN_START m_P(i).State(0) = SCPS0_ACTIVE m_P(i).Sent(0) = 1 m_P(i).Recv(0) = 3 m_P(i).Sent(2) = m_P(m_MyID).Sent(2) - 3 m_P(i).Recv(2) = m_P(m_MyID).Sent(2) Call s0_0x08(i, True) '//Tell everyone this player is ingame For i2 = 0 To 7 If (Not m_P(i2).Addr = 0) Then '//tell new player about old player If (Not i2 = i) Then Call s0_0x06(i2, i, True) '//Tell old player about new player If (Not i2 = 0) Then Call s0_0x06(i, i2, True) End If End If End If Next i2 Call s0_0x0F(i, True) Call s0_0x09(i, True) m_P(i).State(2) = SCPS2_STREAM Call s2_Stream(i, True) Call s2_Stream(i, True) Call TSet(m_P(i).T(0), 20000) m_P(i).PingTick = GetTickCount() Call s0_0x04(i, True) m_P(i).State(1) = SCPS1_JOIN If (m_GameType = &HA) Then Call s1_0x4B(i, True) Call s1_0x4A(i, True) Call s1_0x50(i, True) Exit Sub End If Next i h0_0x07Reject: Call s0_0x0A(P.Addr, P.Port) End Sub Private Sub h0_0x08(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] About self and map defalts If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub m_MyID = Asc(Mid$(S, 17, 1)) Call RtlMoveMemory(m_MaxPlayers, ByVal Mid$(S, 21, 4), 4) Call RtlMoveMemory(m_P(0).Recv(2), ByVal Mid$(S, 25, 4), 4) m_P(0).Sent(2) = m_P(0).Recv(2) - 2 'lngUnknown1 =Mid$(S, 29, 4) 'GameUpTime = Mid$(S, 33, 4) 'seconds m_GameName = GetSTR(Mid$(S, 37)) m_GameStats = GetSTR(Mid$(S, 38 + Len(m_GameName))) m_GamePass = GetSTR(Mid$(S, 39 + Len(m_GameName) + Len(m_GameStats))) m_P(m_MyID).Account = m_MyAccount m_P(m_MyID).Stats = m_MyStats RaiseEvent OnEnterRoom End Sub Private Sub h0_0x09(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Game type settings If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call RtlMoveMemory(m_GameType, ByVal Mid$(S, 17, 2), 2) Call RtlMoveMemory(m_Penalty, ByVal Mid$(S, 19, 2), 2) Call RtlMoveMemory(m_PenaltyEx, ByVal Mid$(S, 21, 4), 4) End Sub Private Sub h0_0x0A(ByRef P As SCGPHEADER) '//[H>C] Join game rejected If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call Class_Initialize RaiseEvent OnJoinReject(&H4) End Sub Private Sub h0_0x0B(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] Player quits game If (Len(S) < 24) Then Exit Sub If (P.pID > 7) Then Exit Sub Dim lngSent As Long Dim bSlot As Byte Call RtlMoveMemory(lngSent, ByVal Mid$(S, 17, 4), 4) 'lngUnknown1 = Mid$(S, 21, 4) bSlot = m_P(P.pID).Slot Call ClearPlayer(P.pID) If (P.pID = 0) Then RaiseEvent OnJoinReject(&H3) ElseIf (bSlot < 8) Then RaiseEvent OnPlayerQuit(bSlot) Call s2_0x3E(bSlot, &HFF, &H6, m_Slot(bSlot).Race, m_Slot(bSlot).Team) End If End Sub Private Sub h0_0x0C(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] Dunno If (P.pID > 7) Then Exit Sub 'lngValA = Mid$(S, 17, 4) 'lngSent = Mid$(S, 21, 4) 'lngValB = Mid$(S, 25, 4) Call s0_Verify(P.pID) End Sub Private Sub h0_0x0E(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] game state? If m_IsHost Then Exit Sub If (Len(S) < 20) Then Exit Sub If (P.pID > 7) Then Exit Sub Dim lngValue As Long Call RtlMoveMemory(lngValue, ByVal Mid$(S, 17, 4), 4) Call s0_Verify(P.pID) End Sub Private Sub h0_0x0F(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] BNCS /stats code If m_IsHost Then Exit Sub If (Len(S) < 20) Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call RtlMoveMemory(m_StatsCode, ByVal Mid$(S, 17, 4), 4) End Sub Private Sub h1_Resend(ByRef P As SCGPHEADER) Dim i As Integer If (P.ReSend = 1) Then '//VERIFYER ElseIf (P.ReSend = 2) Then '//RESEND i = FindResendData(m_P(P.pID).Data(1), P.Sent) If (i = -1) Then Exit Sub Call s1_Buffer(P.pID, i) End If End Sub Private Sub h1_0x00(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] Ingame Chat If (P.pID > 7) Then Exit Sub Dim bUnknown As Byte Dim strChat As String bUnknown = Asc(Mid$(S, 18, 1)) strChat = GetSTR(Mid$(S, 19)) Call s1_Verify(P.pID) RaiseEvent OnChat(m_P(P.pID).Account, strChat) End Sub Private Sub h1_0x49(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] About Player If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim bID As Byte bID = Asc(Mid$(S, 18, 1)) Call s1_Verify(0) If (Not bID = m_MyID) Then RaiseEvent OnPlayerJoin(m_P(bID).Account, m_P(bID).Stats) End If End Sub Private Sub h1_0x4A(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Map randomizer? If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim lngPos As Long Dim strSlotSelect As String * 12 Dim strRaceSelect As String * 12 Call RtlMoveMemory(m_MapTitleSet, ByVal Mid$(S, 18, 2), 2): m_MapTitleSet = (m_MapTitleSet And &H7) Call RtlMoveMemory(m_MapWidth, ByVal Mid$(S, 20, 2), 2): m_MapWidth = (m_MapWidth And &H7FFF) Call RtlMoveMemory(m_MapHeight, ByVal Mid$(S, 22, 2), 2): m_MapHeight = (m_MapHeight And &H7FFF) lngPos = 24 Call RtlMoveMemory(m_SlotSelect(0), ByVal Mid$(S, lngPos, 12), 12): lngPos = lngPos + 12 Call RtlMoveMemory(m_RaceSelect(0), ByVal Mid$(S, lngPos, 12), 12): lngPos = lngPos + 12 Call RtlMoveMemory(m_SlotSelectB(0), ByVal Mid$(S, lngPos, 12), 12): lngPos = lngPos + 12 Call RtlMoveMemory(m_ForceIndex(0), ByVal Mid$(S, lngPos, 8), 8): lngPos = lngPos + 8 Call RtlMoveMemory(m_ForceFlag(0), ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 Call RtlMoveMemory(m_RaceBool(0), ByVal Mid$(S, lngPos, 8), 8): lngPos = lngPos + 8 Call RtlMoveMemory(ByVal strSlotSelect, m_SlotSelect(0), 12) Call RtlMoveMemory(ByVal strRaceSelect, m_RaceSelect(0), 12) RaiseEvent OnMapStats(m_GameName, m_GamePass, m_GameStats, m_GameType, m_Penalty, m_PenaltyEx, m_MaxPlayers, m_MapWidth, m_MapHeight, strSlotSelect, strRaceSelect) End Sub Private Sub h1_0x4B(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Map forces If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim lngPos As Long: lngPos = 18 m_ForceName(0) = GetSTR(Mid$(S, lngPos, 30)): lngPos = lngPos + 30 m_ForceName(1) = GetSTR(Mid$(S, lngPos, 30)): lngPos = lngPos + 30 m_ForceName(2) = GetSTR(Mid$(S, lngPos, 30)): lngPos = lngPos + 30 m_ForceName(3) = GetSTR(Mid$(S, lngPos, 30)): lngPos = lngPos + 30 RaiseEvent OnForceName(m_ForceName(0), m_ForceName(1), m_ForceName(2), m_ForceName(3)) End Sub Private Sub h1_0x4C(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] Game room chat If (P.pID > 7) Then Exit Sub Dim strChat As String strChat = GetSTR(Mid$(S, 18)) Call s1_Verify(P.pID) RaiseEvent OnChat(m_P(P.pID).Account, strChat) End Sub Private Sub h1_0x4E(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Booted from game If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim bResult As Byte bResult = Asc(Mid$(S, 18, 1)) Call s1_Verify(P.pID) Call Class_Initialize RaiseEvent OnJoinReject(bResult) End Sub Private Sub h1_0x4F(ByRef P As SCGPHEADER, ByRef S As String) '//[H<>C] Map download If (P.pID > 7) Then Exit Sub Dim lngLengh As Long Dim intEvent As Integer Dim bTest As Boolean Dim i As Long Call RtlMoveMemory(lngLengh, ByVal Mid$(S, 18, 2), 2) Call RtlMoveMemory(intEvent, ByVal Mid$(S, 20, 2), 2) h1_0x4FReSelect: Select Case intEvent Case &H0 '//[C>H] Tell's the host if we have the map or not '(WORD) 0x100 '(DWORD) File Lengh If (m_IsHost = False) Then Exit Sub If (Not m_P(P.pID).State(1) = SCPS1_DOWNLOAD) Then Exit Sub Call RtlMoveMemory(lngLengh, ByVal Mid$(S, 24, 4), 4): lngLengh = lngLengh + 1 If (lngLengh < 0) Then Exit Sub ElseIf (lngLengh >= m_MapFileLen) Or (m_P(P.pID).MapPos >= m_MapFileLen) Then m_P(P.pID).MapPos = m_MapFileLen Call s1_Verify(P.pID) Else '//Spoof the packet as event 0x05 m_P(P.pID).MapPos = lngLengh lngLengh = &H7 Mid$(S, 22, 1) = vbNullChar Mid$(S, 23, 4) = Mid$(S, 24, 4) Mid$(S, 27, 1) = vbNullChar Mid$(S, 20, 1) = Chr$(&H5) 'packet event intEvent = &H5 GoTo h1_0x4FReSelect End If Case &H1 '//[H>C] asks a client if they have the map '(DWORD) File Lengh '(DWPRD) File Hash '(STRING) File Name If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call RtlMoveMemory(m_MapFileLen, ByVal Mid$(S, 22, 4), 4) Call RtlMoveMemory(m_MapFileHash, ByVal Mid$(S, 26, 4), 4) m_MapFileName = GetSTR(Mid$(S, 30)) RaiseEvent OnCheckMap(m_MapFileLen, m_MapFileHash, m_MapFileName, bTest, m_MapData) m_MapPos = 1 m_P(m_MyID).DL = 100 If bTest Then 'm_MapData = vbNullString Call s1_0x4F_0x00(P.pID, m_MapFileLen, True) Else m_MapData = String(m_MapFileLen, 0) m_P(m_MyID).DL = 0 m_MapDLTick = GetTickCount() Call s1_0x4F_0x00(P.pID, 0, True) End If Call s2_0x3D Case &H2 '//[H>C] tells a client to send the map to another client If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub If (Len(m_MapData) = 0) Then Exit Sub '(BYTE) Player ID '(DWORD) Map Position? intEvent = Asc(Mid$(S, 22, 1)) Call RtlMoveMemory(lngLengh, ByVal Mid$(S, 23, 4), 4): lngLengh = lngLengh + 1 If ((intEvent = 0) Or (intEvent = m_MyID) Or (intEvent > 7)) Then Exit Sub If (lngLengh < 1) Or (lngLengh > m_MapFileLen) Then Exit Sub m_P(intEvent).MapPos = lngLengh Debug.Print "SENDING MAP TO " & m_P(intEvent).Account Call s1_Verify(P.pID) '//Spoof the packet as event 0x05 Mid$(S, 22, 1) = vbNullChar P.pID = intEvent Mid$(S, 20, 1) = Chr$(&H5) intEvent = &H5 '//Send this player the 1st chunks of the map GoTo h1_0x4FReSelect Case &H3 '//[H>C] checks players maps before starting the game 'Blank Call s1_Verify(P.pID) Case &H4 '//[H>C] sends a chunk of the map to a player '(BYTE) 0x00 '(DWORD) File Pos (0 based) '(WORD) Data Lengh '(VOID) Data If m_IsHost Then Exit Sub 'If (Not P.pID = 0) Then Exit Sub If (m_MapFileLen = 0) Then Exit Sub Call RtlMoveMemory(lngLengh, ByVal Mid$(S, 23, 4), 4): lngLengh = lngLengh + 1 Call RtlMoveMemory(intEvent, ByVal Mid$(S, 27, 2), 2) If (lngLengh = m_MapPos) Then Mid$(m_MapData, lngLengh, intEvent) = Mid$(S, 29, intEvent) m_MapPos = m_MapPos + intEvent m_P(m_MyID).DL = (100 / m_MapFileLen) * m_MapPos '//Request next block Call s1_0x4F_0x05(P.pID, (m_MapPos - 1), True) '//Check if compleat If (m_MapPos > m_MapFileLen) Then lngLengh = m_MapFileLen Call s1_0x4F_0x00(0, m_MapFileLen, True) Call s1_Verify(P.pID) m_MapFileLen = 0 m_MapPos = 1 RaiseEvent OnMapDownloaded(lngLengh, m_MapFileHash, m_MapFileName, m_MapData) m_P(m_MyID).DL = 100 Call s2_0x3D Exit Sub End If End If '//Update download percent If (m_P(m_MyID).DL > 100) Then m_P(m_MyID).DL = 100 lngLengh = (GetTickCount() - m_MapDLTick) If (lngLengh > 1000) Then m_MapDLTick = GetTickCount() Call s2_0x3D End If Case &H5 '//[C>H] Requests part of the map from the host '(BYTE) 0x00 '(DWORD) File Pos (0 based) 'If (m_IsHost = False) Then Exit Sub Call RtlMoveMemory(lngLengh, ByVal Mid$(S, 23, 4), 4): lngLengh = lngLengh + 1 If (lngLengh < 1) Or (lngLengh > m_MapFileLen) Then Exit Sub If (Not m_P(P.pID).MapPos = lngLengh) Then Exit Sub '//Send this player the 1st chunk of the map For intEvent = 1 To 8 If (m_P(P.pID).MapPos >= m_MapFileLen) Then Exit For If (m_P(P.pID).MapPos < (m_MapFileLen - &H100)) Then Call s1_0x4F_0x04(P.pID, (m_P(P.pID).MapPos - 1), Mid$(m_MapData, m_P(P.pID).MapPos, &H100), True) m_P(P.pID).MapPos = m_P(P.pID).MapPos + &H100 Else Call s1_0x4F_0x04(P.pID, (m_P(P.pID).MapPos - 1), Mid$(m_MapData, m_P(P.pID).MapPos, (m_MapFileLen - m_P(P.pID).MapPos) + 1), True) m_P(P.pID).MapPos = m_P(P.pID).MapPos + (m_MapFileLen - m_P(P.pID).MapPos) + 1 End If Next intEvent 'If (lngLengh < (m_MapFileLen - &H80)) Then ' Call s1_0x4F_0x04(P.pID, (lngLengh - 1), Mid$(m_MapData, lngLengh, &H80), True) 'Else ' Call s1_0x4F_0x04(P.pID, (lngLengh - 1), Mid$(m_MapData, lngLengh, (m_MapFileLen - lngLengh)), True) 'End If Case Else End Select End Sub Private Sub h1_0x50(ByRef P As SCGPHEADER) '//[H>C] dunno If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Call s2_0x40(&HAF565C9) Call s1_Verify(P.pID) End Sub Private Sub h2_Resend(ByRef P As SCGPHEADER, ByRef S As String) Dim bID As Byte Dim i As Integer If (P.ReSend = 1) Then '//VERIFYER ElseIf (P.ReSend = 2) Then '//RESEND If (P.Lengh > &HC) Then bID = Asc(Mid$(S, 17, 1)) If (bID = m_MyID) Or (bID = P.pID) Or (bID > 7) Then Exit Sub '//Get the sent for player(bID) i = FindResendData(m_P(bID).Data(2), P.Sent) '//Send it to player(P.pID) as player(bID) If (i = -1) Then Call s1_Callback(bID, P.pID, P.Sent, Chr$(5)) Else Call s1_Callback(bID, P.pID, P.Sent, m_P(bID).Data(2).Data(i)) End If Exit Sub End If i = FindResendData(m_P(P.pID).Data(2), P.Sent) If (i = -1) Then Exit Sub Call s2_Buffer(P.pID, i) ElseIf (P.ReSend = 4) Then '//CALL BACK '//Ignore End If End Sub Private Sub h2_0x3C(ByRef P As SCGPHEADER) '//[H>C] game start If (Not P.pID = 0) Then Exit Sub RaiseEvent OnGameStart End Sub Private Sub h2_0x3D(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] map download percent If (P.pID > 7) Then Exit Sub m_P(P.pID).DL = Asc(Mid$(S, 2, 1)) If (m_P(P.pID).Slot = &HFF) Then Exit Sub RaiseEvent OnMapDownloading(m_P(P.pID).DL, m_P(P.pID).Slot) End Sub Private Sub h2_0x3E(ByRef P As SCGPHEADER, ByRef S As String) '//[H>C] Game room slot update If m_IsHost Then Exit Sub If (Not P.pID = 0) Then Exit Sub Dim bSlot As Byte bSlot = Asc(Mid$(S, 2, 1)) If (bSlot > 7) Then Exit Sub m_Slot(bSlot).ID = Asc(Mid$(S, 3, 1)) m_Slot(bSlot).State = Asc(Mid$(S, 4, 1)) m_Slot(bSlot).Race = Asc(Mid$(S, 5, 1)) m_Slot(bSlot).Team = Asc(Mid$(S, 6, 1)) 'Debug.Print StrToHex(S) '0x00 = slot doesnt exist '0x02 = slot is Taken/Human '0x03 = Slot is Rescuable '0x04 = slot is Unused '0x05 = slot is Computer '0x06 = slot is Open '0x07 = slot is Neutral '0x08 = slot is Closed If (m_Slot(bSlot).ID < 8) Then m_P(m_Slot(bSlot).ID).Slot = bSlot RaiseEvent OnSlotUpdate(bSlot, m_P(m_Slot(bSlot).ID).Account, m_Slot(bSlot).State, m_Slot(bSlot).Race, m_Slot(bSlot).Team, m_P(m_Slot(bSlot).ID).Ping, m_P(m_Slot(bSlot).ID).DL) Else RaiseEvent OnSlotUpdate(bSlot, vbNullString, m_Slot(bSlot).State, m_Slot(bSlot).Race, m_Slot(bSlot).Team, -1, 100) End If End Sub Private Sub h2_0x40(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] about self(?) If (m_IsHost = False) Then Exit Sub If (P.pID = m_MyID) Then Exit Sub Dim i As Integer Dim i2 As Integer If (m_P(P.pID).State(1) = SCPS1_JOIN) Then m_P(P.pID).State(1) = SCPS1_DOWNLOAD '//Find free game slot space For i = 0 To 7 If (m_Slot(i).State = &H6) Then 'slot in open state m_Slot(i).State = &H2 'human m_Slot(i).ID = P.pID m_Slot(i).Race = m_RaceSelect(i) Exit For End If Next i If (i > 7) Then 'no slots avalible Call s1_0x4E(P.pID, &H2, True) Call s1_0x4E(P.pID, &H2, False) Call s1_0x4E(P.pID, &H2, False) Call ClearPlayer(P.pID) Exit Sub End If For i2 = 1 To 7 If (Not m_P(i2).Addr = 0) Then Call s1_0x49(i2, P.pID, True) End If Next i2 RaiseEvent OnPlayerJoin(m_P(P.pID).Account, m_P(P.pID).Stats) Call s1_0x4F_0x01(P.pID, True) Call s2_0x3D '//update the room slots For i2 = 7 To 0 Step -1 Call s2_0x3E(i2, m_Slot(i2).ID, m_Slot(i2).State, m_Slot(i2).Race, m_Slot(i2).Team) Next i2 '//send the 0x3F's For i2 = 7 To 0 Step -1 If (Not m_Slot(i2).ID = &HFF) Then Call s2_0x3F(i2) End If Next i2 End If End Sub Private Sub h2_0x41(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] Change Race If (m_IsHost = False) Then Exit Sub Dim bSlot As Byte Dim bRace As Byte Dim i As Byte Dim bIsTeam As Boolean 'is team melee game? bSlot = Asc(Mid$(S, 2, 1)) bRace = Asc(Mid$(S, 3, 1)) If (Not bRace = &H6) And (bRace > &H2) Then Exit Sub 'invalid race If (bSlot = &H8) Then bSlot = m_P(P.pID).Slot If (bSlot > &H7) Then Exit Sub 'invalid game slot If (m_P(P.pID).Slot > &H7) Then Exit Sub 'they don't have a slot yet If (m_RaceBool(bSlot) = 0) Then Exit Sub 'can't change race for this slot bIsTeam = ((m_GameType = &HB) Or (m_GameType = &HC) Or (m_GameType = &HD)) '//Change own race If (bSlot = m_P(P.pID).Slot) Then m_Slot(bSlot).Race = bRace GoTo h2_0x41ChangeRace Exit Sub End If '//Change own team melee players race If bIsTeam And (m_Slot(bSlot).Team = m_Slot(m_P(P.pID).Slot).Team) Then m_Slot(bSlot).Race = bRace GoTo h2_0x41ChangeRace End If '//Host only change If (P.pID = m_MyID) Then 'Host '//Can change race of computers If (m_Slot(bSlot).State = &H5) Then 'comp If bIsTeam Then 'change race of all team members For i = 0 To 7 If (m_Slot(i).Team = m_Slot(bSlot).Team) And (Not m_Slot(i).Race = bRace) Then m_Slot(i).Race = bRace Call s2_0x3E(i, m_Slot(i).ID, m_Slot(i).State, m_Slot(i).Race, m_Slot(i).Team) End If Next i Else m_Slot(bSlot).Race = bRace GoTo h2_0x41ChangeRace End If End If End If Exit Sub h2_0x41ChangeRace: Call s2_0x3E(bSlot, m_Slot(bSlot).ID, m_Slot(bSlot).State, m_Slot(bSlot).Race, m_Slot(bSlot).Team) End Sub Private Sub h2_0x42(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] change team (NOT UMS) If (m_IsHost = False) Then Exit Sub Dim bTeam As Byte Dim i As Byte bTeam = Asc(Mid$(S, 2, 1)) If (bTeam = &H0) Or (bTeam > &H4) Then Exit Sub 'invalid team If (m_P(P.pID).Slot > &H7) Then Exit Sub 'they don't have a slot If (m_GameType = &HA) Then Exit Sub 'not a UMS packet If (Not m_GameType = &HB) And (Not m_GameType = &HC) And (Not m_GameType = &HD) Then Exit Sub 'cant change teams If (P.pID = m_MyID) Then Exit Sub 'host cant change team in a team game If (m_Slot(m_P(P.pID).Slot).Team = bTeam) Then Exit Sub 'already in this team i = FindTeamSlot(bTeam, &H6) bTeam = m_P(P.pID).Slot If (i = &HFF) Then 'no room in this team '//Refresh their slot, to tell them "fail" Call s2_0x3E(bTeam, m_Slot(bTeam).ID, m_Slot(bTeam).State, m_Slot(bTeam).Race, m_Slot(bTeam).Team) Else 'move them to slot(i) '//Render their old slot as "open" m_P(P.pID).Slot = i Call s2_0x3E(bTeam, &HFF, &H6, m_Slot(bTeam).Race, m_Slot(bTeam).Team) '//update for their new slot Call s2_0x3E(i, P.pID, &H2, m_Slot(i).Race, m_Slot(i).Team) End If End Sub Private Sub h2_0x43(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] change team (UMS) If (m_IsHost = False) Then Exit Sub Dim bTeam As Byte Dim i As Byte bTeam = Asc(Mid$(S, 2, 1)) If (bTeam = &H0) Or (bTeam > &H4) Then Exit Sub 'invalid team If (m_P(P.pID).Slot > &H7) Then Exit Sub 'they don't have a slot If (Not m_GameType = &HA) Then Exit Sub 'UMS only packet If (m_Slot(m_P(P.pID).Slot).Team = bTeam) Then 'move down a slot, in this team i = m_P(P.pID).Slot Do i = i + 1 If (i > 7) Then i = 0 If (i = m_P(P.pID).Slot) Then Exit Do 'done a full loop of the room slots If (m_Slot(i).Team = bTeam) And (m_Slot(i).State = &H6) Then 'same team/open state 'Move them to this slot bTeam = m_P(P.pID).Slot m_P(P.pID).Slot = i '//Render their old slot as "open" Call s2_0x3E(bTeam, &HFF, &H6, m_Slot(bTeam).Race, m_Slot(bTeam).Team) '//update for their new slot Call s2_0x3E(i, P.pID, &H2, m_Slot(i).Race, m_Slot(i).Team) Exit Sub End If Loop i = m_P(P.pID).Slot '//Couldnt find a free spot in their team, refresh their slot to say "fail" Call s2_0x3E(i, m_Slot(i).ID, m_Slot(i).State, m_Slot(i).Race, m_Slot(i).Team) Else 'move to a new team i = FindTeamSlot(bTeam, &H6) bTeam = m_P(P.pID).Slot If (i = &HFF) Then 'no room in this team '//Refresh their slot, to tell them "fail" Call s2_0x3E(bTeam, m_Slot(bTeam).ID, m_Slot(bTeam).State, m_Slot(bTeam).Race, m_Slot(bTeam).Team) Else '//Render their old slot as "open" m_P(P.pID).Slot = i Call s2_0x3E(bTeam, &HFF, &H6, m_Slot(bTeam).Race, m_Slot(bTeam).Team) '//update for their new slot Call s2_0x3E(i, P.pID, &H2, m_Slot(i).Race, m_Slot(i).Team) End If End If End Sub Private Sub h2_0x44(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] change slot state If (m_IsHost = False) Then Exit Sub If (Not P.pID = m_MyID) Then Exit Sub 'only host can change a slot state Dim bSlot As Byte Dim bState As Byte Dim i As Byte Dim bIsTeam As Boolean 'is team melee game? bSlot = Asc(Mid$(S, 2, 1)) bState = Asc(Mid$(S, 3, 1)) If (bState > &H2) Then Exit Sub 'invalid state If (bSlot > &H7) Then Exit Sub 'invalid game slot Select Case bState Case 0: bState = &H5 'Comp Case 1: bState = &H6 'Open Case 2: bState = &H8 'Closed End Select If (Not m_SlotSelect(bSlot) = &H6) Then Exit Sub 'slot cant be changed If (m_Slot(bSlot).State = bState) Then Exit Sub 'already in this state bIsTeam = ((m_GameType = &HB) Or (m_GameType = &HC) Or (m_GameType = &HD)) '//Boot any player in this slot If (m_Slot(bSlot).State = &H2) And (m_Slot(bSlot).ID < &H8) Then 'player Call s1_0x4E(m_Slot(bSlot).ID, &H0, True) Call s1_0x4E(m_Slot(bSlot).ID, &H0, False) Call s1_0x4E(m_Slot(bSlot).ID, &H0, False) Call ClearPlayer(m_Slot(bSlot).ID) RaiseEvent OnPlayerQuit(bSlot) Call s2_0x3E(bSlot, &HFF, bState, m_Slot(bSlot).Race, m_Slot(bSlot).Team) Exit Sub End If If bIsTeam And ((m_Slot(bSlot).State = &H5) Or (bState = &H5)) Then '//Change all slots of this team, to this state For i = 0 To 7 If (m_Slot(i).Team = m_Slot(bSlot).Team) Then Call s2_0x3E(i, &HFF, bState, m_Slot(bSlot).Race, m_Slot(i).Team) End If Next i Else '//Update this slot Call s2_0x3E(bSlot, &HFF, bState, m_Slot(bSlot).Race, m_Slot(bSlot).Team) End If End Sub Private Sub h2_0x45(ByRef P As SCGPHEADER, ByRef S As String) '//[C>C] move player from slotA to slotB If (m_IsHost = False) Then Exit Sub If (Not P.pID = m_MyID) Then Exit Sub 'only host can change a slot state If (Not m_GameType = &HF) Then Exit Sub 'TvB only Dim bSlotA As Byte 'from slot Dim bSlotB As Byte 'to slot Dim T As SCGPSLOT bSlotA = Asc(Mid$(S, 2, 1)) bSlotB = Asc(Mid$(S, 3, 1)) If (bSlotA > 7) Then Exit Sub 'invalid FromSlot If (bSlotB > 7) Then Exit Sub 'invalid ToSlot If (bSlotA = m_MyID) Or (bSlotB = m_MyID) Then Exit Sub 'cant switch with the host If (Not m_Slot(bSlotA).State = &H2) Then Exit Sub 'human If (m_Slot(bSlotB).State = &H6) Then 'open state 'move player to this open slot T.ID = m_Slot(bSlotA).ID m_P(T.ID).Slot = bSlotB T.Race = IIf((m_RaceBool(bSlotA) = 0), m_Slot(bSlotB).Race, m_Slot(bSlotA).Race) '//Render their old slot as "open" Call s2_0x3E(bSlotA, &HFF, &H6, m_Slot(bSlotA).Race, m_Slot(bSlotA).Team) '//update for their new slot Call s2_0x3E(bSlotB, T.ID, &H2, T.Race, m_Slot(bSlotB).Team) ElseIf (m_Slot(bSlotB).State = &H2) Or (m_Slot(bSlotB).State = &H5) Then '//Switch player(a) with comp(b)/player(b) 'get slot A data T.ID = m_Slot(bSlotA).ID T.Race = m_Slot(bSlotA).Race T.State = m_Slot(bSlotA).State 'update slot A with slot B data If (m_Slot(bSlotB).ID < 8) Then m_P(m_Slot(bSlotB).ID).Slot = bSlotA Call s2_0x3E(bSlotA, m_Slot(bSlotB).ID, m_Slot(bSlotB).State, IIf((m_RaceBool(bSlotA) = 0), m_Slot(bSlotA).Race, m_Slot(bSlotB).Race), m_Slot(bSlotA).Team) 'update slot B with slot A data m_P(T.ID).Slot = bSlotB 'playerA = slotb Call s2_0x3E(bSlotB, T.ID, T.State, IIf((m_RaceBool(bSlotB) = 0), m_Slot(bSlotB).Race, T.Race), m_Slot(bSlotB).Team) 'bSlotA is human 'bSlotB is human or computer End If End Sub '##################################################################### '##################################################################### '######################### Packet Senders ############################ '##################################################################### '##################################################################### Private Sub s0_0x01(ByVal i As Integer) Call iClear Call iDWORD(&H1&) Call AddResendData(m_P(i).Data(0), 0, &H1, iBuf()) Call iHEADER(0, 1, 0, &H1, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x02(ByRef lngAddr As Long, ByRef intPort As Integer) Call iClear Call iDWORD(&H1&) Call AddResendData(m_P(i).Data(0), 1, &H2, iBuf()) Call iHEADER(1, 1, 0, &H2, m_MyID, 0) Call iUDP(lngAddr, intPort) End Sub Private Sub s0_0x03(ByVal i As Integer) Call iClear Call iDWORD(&H1&) Call AddResendData(m_P(i).Data(0), 1, &H3, iBuf()) Call iHEADER(1, 2, 0, &H3, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x04(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &H4, vbNullString) Call iClear Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &H4, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x05(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &H5, vbNullString) Call iClear Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &H5, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x06(ByVal ri As Integer, ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Dim bTest As Boolean: bTest = (ri = 0) Call iClear Call iDWORD(&H32&) Call iDWORD(CLng(ri)) Call iDWORD(CLng(IIf(bTest, &H1, &H0))) '1=IsHost Call iDWORD(&H0&) Call iDWORD(m_P(ri).Sent(2)) Call iWORD(CInt(IIf(bTest, &H0, &H2))) 'Family Call iWORD(CInt(IIf(bTest, &H0, m_P(ri).Port))) Call iDWORD(CLng(IIf(bTest, &H0, m_P(ri).Addr))) Call iDWORD(&H0&) Call iDWORD(&H0&) Call iNTSTRING(m_P(ri).Account) Call iNTSTRING(CStr(IIf(bTest, vbNullString, m_P(ri).Stats))) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &H6, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &H6, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x07(ByVal i As Integer) Call iClear Call iNTSTRING(m_MyAccount) Call iNTSTRING(m_MyStats) Call iNTSTRING(m_GamePass) Call AddResendData(m_P(i).Data(0), 2, &H7, iBuf()) Call iHEADER(2, 2, 0, &H7, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x08(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call iClear Call iDWORD(CLng(i)) Call iDWORD(m_MaxPlayers) Call iDWORD(m_P(m_MyID).Sent(2)) Call iDWORD(&H5&) Call iDWORD(&HA&) 'up time of game, in seconds Call iNTSTRING(m_GameName) Call iNTSTRING(m_GameStats) Call iNTSTRING(m_GamePass) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &H8, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &H8, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x09(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Dim A As Integer Dim bData(23) As Byte A = m_GameType Select Case A Case &H4: bData(0) = &H7 Case &H5: bData(0) = &H4 Case &H6: bData(0) = &H3 Case &H7: bData(0) = &H6 Case &H8: bData(0) = &H5 Case &HD: bData(0) = &H4 Case &HA: bData(0) = &H0 Case Else: bData(0) = &H1 End Select bData(1) = IIf((A = &HA), &H0, &H1) bData(2) = IIf((A = &H9) Or (A = &HA), &H0, &H1) bData(3) = &H2 bData(4) = IIf((A = &HA), &H0, &H2) bData(5) = IIf((A = &HA), &H1, &H0) Select Case A Case &H2: bData(6) = &H3 Case &H3: bData(6) = &H3 Case &H4: bData(6) = &H1 Case &HA: bData(6) = &H3 Case &HB: bData(6) = &H1 Case &HC: bData(6) = &H1 Case &HF: bData(6) = &H1 Case Else: bData(6) = &H0 End Select Select Case A Case &H2: bData(7) = &H1 Case &H6: bData(7) = &H1 Case &H8: bData(7) = &H1 Case &HA: bData(7) = &H1 Case &HB: bData(7) = &H1 Case &HF: bData(7) = &H1 Case Else: bData(7) = &H0 End Select bData(8) = IIf((A = &HB) Or (A = &HC) Or (A = &HD), m_Penalty + 1, &H0) 'number of teams bData(9) = &H1 bData(10) = IIf((A = &H9), (m_StatsCode And &HFF), &H0) If (A = &H6) Or (A = &H7) Then Call RtlMoveMemory(bData(11), m_PenaltyEx, 4) Else Call RtlZeroMemory(bData(11), 4) End If bData(15) = IIf((A = &HA), &H0, &H32) Call RtlZeroMemory(bData(16), 8) Call iClear Call iWORD(m_GameType) Call iWORD(m_Penalty) Call iDWORD(m_PenaltyEx) Call iBYTEA(bData(), 24) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &H9, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &H9, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x0A(ByRef lngAddr As Long, ByRef intPort As Integer) Call AddResendData(m_P(i).Data(0), 2, &HA, vbNullString) Call iClear Call iHEADER(2, 3, 0, &HA, m_MyID, 0) Call iUDP(lngAddr, intPort) End Sub Private Sub s0_0x0B(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call iClear Call iDWORD(m_P(i).Recv(2)) Call iDWORD(&H40000001) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &HB, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &HB, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x0E(ByVal i As Integer, ByVal lngValue As Long, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call iClear Call iDWORD(lngValue) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &HE, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &HE, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_0x0F(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(0)) Call iClear Call iDWORD(m_StatsCode) Call AddResendData(m_P(i).Data(0), m_P(i).Sent(0), &HF, iBuf()) Call iHEADER(m_P(i).Sent(0), m_P(i).Recv(0), 0, &HF, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_Verify(ByVal i As Integer) Call iClear Call iHEADER(m_P(i).Recv(0), m_P(i).Recv(0), 0, &H0, m_MyID, 1) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_Resend(ByVal i As Integer, _ ByVal lngSent As Long) Call iClear Call iHEADER(lngSent, lngSent, 0, &H0, m_MyID, 2) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s0_Buffer(ByVal i As Integer, _ ByVal i2 As Integer) Call iClear Call iSTRING(m_P(i).Data(0).Data(i2)) Call iHEADER(m_P(i).Data(0).Sent(i2), m_P(i).Data(0).Sent(i2), 0, m_P(i).Data(0).Verifyed(i2), m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x00(ByVal i As Integer, ByVal strText As String, Optional ByVal bCount As Boolean = False) '//[C>C] Ingame chat If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iBYTE(&H0&) Call iNTSTRING(strText) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H0, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H0, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x49(ByVal i As Integer, ByVal ri As Long, Optional ByVal bCount As Boolean = False) '//[H>C] tells each player, about another player as now ingame If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iDWORD(ri) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H49, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H49, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4A(ByVal i As Integer, Optional ByVal bCount As Boolean = False) '//[H>C] part of the join process, sent before 0x01->0x50 If bCount Then Call AddPktCount(m_P(i).Sent(1)) Dim i2 As Integer Call iClear Call iWORD(m_MapTitleSet) Call iWORD(m_MapWidth) Call iWORD(m_MapHeight) Call iBYTEA(m_SlotSelect(), 12) 'game room slots Call iBYTEA(m_RaceSelect(), 12) 'game room slots Call iBYTEA(m_SlotSelectB(), 12) 'OWNR raw defalt settings Call iBYTEA(m_ForceIndex(), 8) 'force index for each player (1 based, 0 if no player) Call iBYTEA(m_ForceFlag(), 4) '4x force flags from "FORC" Call iBYTEA(m_RaceBool(), 8) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4A, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4A, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4B(ByVal i As Integer, Optional ByVal bCount As Boolean = False) '//[H>C] Force names Dim i2 As Integer Dim strForce As String * 30 If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear For i2 = 0 To 3 strForce = m_ForceName(i2) & vbNullChar Call iSTRING(strForce) Next i2 Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4B, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4B, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4C(ByVal i As Integer, ByVal strText As String, Optional ByVal bCount As Boolean = False) '//[C>C] game room chat If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iNTSTRING(strText) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4C, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4C, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4E(ByVal i As Integer, ByVal bEvent As Byte, Optional ByVal bCount As Boolean = False) '//[H>C] kicks a player from the game If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iBYTE(bEvent) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4E, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4E, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4F_0x00(ByVal i As Integer, ByVal lngLengh As Long, Optional ByVal bCount As Boolean = False) '//[C>H] Tell's the host if we have the map or not If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iWORD(&H8) '(lengh - this value) Call iWORD(&H0) Call iWORD(&H100) Call iDWORD(lngLengh) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4F, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4F, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4F_0x01(ByVal i As Integer, Optional ByVal bCount As Boolean = False) '//[H>C] asks a client if they have the map If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iWORD(CInt(Len(m_MapFileName) + 11)) '(lengh - this value) Call iWORD(&H1) Call iDWORD(m_MapFileLen) Call iDWORD(m_MapFileHash) Call iNTSTRING(m_MapFileName) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4F, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4F, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4F_0x03(ByVal i As Integer, Optional ByVal bCount As Boolean = False) '//[H>C] checks players maps before starting the game If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iWORD(&H2) '(lengh - this value) Call iWORD(&H3) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4F, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4F, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4F_0x04(ByVal i As Integer, ByVal lngPos As Long, ByVal strData As String, Optional ByVal bCount As Boolean = False) '//[H>C] sends a chunk of the map to a player If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iWORD(CInt(Len(strData) + 9)) '(lengh - this value) Call iWORD(&H4) Call iBYTE(&H0) Call iDWORD(lngPos) Call iWORD(CInt(Len(strData))) Call iSTRING(strData) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4F, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4F, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x4F_0x05(ByVal i As Integer, ByVal lngPos As Long, Optional ByVal bCount As Boolean = False) '//[C>H] Requests part of the map from the host If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call iClear Call iWORD(&H7) '(lengh - this value) Call iWORD(&H5) Call iBYTE(&H0) Call iDWORD(lngPos) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H4F, iBuf()) Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H4F, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_0x50(ByVal i As Integer, Optional ByVal bCount As Boolean = False) '//[H>C] part of the join process, expect 0x02->0x40 If bCount Then Call AddPktCount(m_P(i).Sent(1)) Call AddResendData(m_P(i).Data(1), m_P(i).Sent(1), &H50, vbNullString) Call iClear Call iHEADER(m_P(i).Sent(1), m_P(i).Recv(1), 1, &H50, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_Verify(ByVal i As Integer) Call iClear Call iHEADER(m_P(i).Recv(1), m_P(i).Recv(1), 1, &H0, m_MyID, 1) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_Resend(ByVal i As Integer, _ ByVal lngSent As Long) Call iClear Call iHEADER(lngSent, lngSent, 1, &H0, m_MyID, 2) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_Buffer(ByVal i As Integer, _ ByVal i2 As Integer) Call iClear Call iSTRING(m_P(i).Data(1).Data(i2)) Call iHEADER(m_P(i).Data(1).Sent(i2), m_P(i).Data(1).Sent(i2), 1, m_P(i).Data(1).Verifyed(i2), m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s2_0x3C() '//[H>C] start game Dim bData(0) As Byte bData(0) = &H3C m_Stream(m_StreamPos) = bData(0) m_StreamPos = m_StreamPos + 1 End Sub Private Sub s2_0x3D() '//[C>C] current download percent of the map -- updated in 1 second intervals Dim bData(1) As Byte bData(0) = &H3D bData(1) = m_P(m_MyID).DL Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 2) m_StreamPos = m_StreamPos + 2 RaiseEvent OnMapDownloading(m_P(m_MyID).DL, m_P(m_MyID).Slot) End Sub Private Sub s2_0x3E(ByVal bSlot As Byte, ByVal bPlayer As Byte, ByVal bState As Byte, ByVal bRace As Byte, ByVal bTeam As Byte) '//[H>C] game room slot update m_Slot(bSlot).Slot = bSlot m_Slot(bSlot).ID = bPlayer m_Slot(bSlot).State = bState m_Slot(bSlot).Race = bRace m_Slot(bSlot).Team = bTeam m_Stream(m_StreamPos) = &H3E Call RtlMoveMemory(m_Stream(m_StreamPos + 1), m_Slot(bSlot), 5) m_StreamPos = m_StreamPos + 6 'Debug.Print "3E " & _ Right("00" & Hex(bSlot), 2) & " " & _ Right("00" & Hex(bPlayer), 2) & " " & _ Right("00" & Hex(bState), 2) & " " & _ Right("00" & Hex(bRace), 2) & " " & _ Right("00" & Hex(bTeam), 2) If m_IsHost Then If (bPlayer < &H8) Then m_P(bPlayer).Slot = bSlot RaiseEvent OnSlotUpdate(bSlot, m_P(bPlayer).Account, bState, bRace, bTeam, m_P(bPlayer).Ping, m_P(bPlayer).DL) Else RaiseEvent OnSlotUpdate(bSlot, vbNullString, bState, bRace, bTeam, -1, 100) End If End If End Sub Private Sub s2_0x3F(ByVal bPlayer As Byte) '//[H>C] appends 0x3E, 1 for each player ingame Dim bData(7) As Byte bData(0) = &H3F bData(1) = bPlayer bData(4) = &H1 bData(6) = &H5 Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 8) m_StreamPos = m_StreamPos + 8 End Sub Private Sub s2_0x40(ByVal lngValue As Long) '//[C>C] players send this to other players (host does not send) Dim bData(17) As Byte bData(0) = &H40 bData(9) = &H1 bData(11) = &H5 Call RtlMoveMemory(bData(14), lngValue, 4) Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 18) m_StreamPos = m_StreamPos + 18 End Sub Private Sub s2_0x41(ByVal bSlot As Byte, ByVal bRace As Byte) '//[C>C] change race Dim bData(2) As Byte bData(0) = &H41 bData(1) = bSlot bData(2) = bRace Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 3) m_StreamPos = m_StreamPos + 3 If (m_IsHost = False) Then Exit Sub Dim S As String * 3 Dim P As SCGPHEADER P.pID = m_MyID Mid$(S, 2, 1) = Chr$(bSlot) Mid$(S, 3, 1) = Chr$(bRace) Call h2_0x41(P, S) End Sub Private Sub s2_0x42(ByVal bTeam As Byte) '//[C>C] change team (NOT UMS) Dim bData(1) As Byte bData(0) = &H42 bData(1) = bTeam Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 2) m_StreamPos = m_StreamPos + 2 If (m_IsHost = False) Then Exit Sub Dim S As String * 2 Dim P As SCGPHEADER P.pID = m_MyID Mid$(S, 2, 1) = Chr$(bTeam) Call h2_0x42(P, S) End Sub Private Sub s2_0x43(ByVal bTeam As Byte) '//[C>C] change team (UMS) Dim bData(1) As Byte bData(0) = &H43 bData(1) = bTeam Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 2) m_StreamPos = m_StreamPos + 2 If (m_IsHost = False) Then Exit Sub Dim S As String * 2 Dim P As SCGPHEADER P.pID = m_MyID Mid$(S, 2, 1) = Chr$(bTeam) Call h2_0x43(P, S) End Sub Private Sub s2_0x44(ByVal bSlot As Byte, ByVal bState As Byte) '//[C>C] change slot state Dim bData(2) As Byte bData(0) = &H44 bData(1) = bSlot bData(2) = bState Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 3) m_StreamPos = m_StreamPos + 3 If (m_IsHost = False) Then Exit Sub Dim S As String * 3 Dim P As SCGPHEADER P.pID = m_MyID Mid$(S, 2, 1) = Chr$(bSlot) Mid$(S, 3, 1) = Chr$(bState) Call h2_0x44(P, S) End Sub Private Sub s2_0x45(ByVal bFromSlot As Byte, ByVal bToSlot As Byte) '//[C>C] change slot (tvb home/away) Dim bData(2) As Byte bData(0) = &H45 bData(1) = bFromSlot bData(2) = bToSlot Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 3) m_StreamPos = m_StreamPos + 3 If (m_IsHost = False) Then Exit Sub Dim S As String * 3 Dim P As SCGPHEADER P.pID = m_MyID Mid$(S, 2, 1) = Chr$(bFromSlot) Mid$(S, 3, 1) = Chr$(bToSlot) Call h2_0x45(P, S) End Sub Private Sub s2_0x48(ByVal lngUnixTime As Long) '//[H>C] sent the moment the game starts Dim bData(12) As Byte Call RtlMoveMemory(bData(0), lngUnixTime, 4) For bData(0) = 5 To 12 bData(bData(0)) = &H8 Next bData(0) bData(0) = &H48 Call RtlMoveMemory(m_Stream(m_StreamPos), bData(0), 13) m_StreamPos = m_StreamPos + 13 End Sub Private Sub s2_Stream(ByVal i As Integer, Optional ByVal bCount As Boolean = False) If bCount Then Call AddPktCount(m_P(i).Sent(2)) Call iClear If (m_StreamPos > 0) Then Call iBYTEA(m_Stream(), m_StreamPos) Else Call iBYTE(&H5) End If Call AddResendData(m_P(i).Data(2), m_P(i).Sent(2), &H0, iBuf()) Call iHEADER(m_P(i).Sent(2), m_P(i).Recv(2), 2, &H0, m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s2_Resend(ByVal i As Integer, _ ByVal lngSent As Long) Call iClear Call iHEADER(lngSent, lngSent, 2, &H0, m_MyID, 2) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s1_Callback(ByVal ri As Integer, _ ByVal i As Integer, _ ByVal lngSent As Long, _ ByVal strData As String) Call iClear Call iSTRING(strData) Call iHEADER(lngSent, lngSent, 2, &H0, ri, 4) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub Private Sub s2_Buffer(ByVal i As Integer, _ ByVal i2 As Integer) Call iClear Call iSTRING(m_P(i).Data(2).Data(i2)) Call iHEADER(m_P(i).Data(2).Sent(i2), m_P(i).Data(2).Sent(i2), 2, m_P(i).Data(2).Verifyed(i2), m_MyID, 0) Call iUDP(m_P(i).Addr, m_P(i).Port) End Sub '##################################################################### '##################################################################### '######################## Player Functions ########################### '##################################################################### '##################################################################### Private Sub ClearSlot(ByVal i As Integer) If (i < 0) Or (i > 7) Then Exit Sub m_Slot(i).Slot = i m_Slot(i).ID = &HFF m_Slot(i).State = 0 m_Slot(i).Race = &H6 'random m_Slot(i).Team = 0 End Sub Private Sub ClearPlayer(ByVal i As Integer) If (i < 0) Or (i > 7) Then Exit Sub Dim pHead As SCGPHEADER Dim i2 As Integer Dim i3 As Integer m_P(i).Addr = 0 m_P(i).Port = 0 For i2 = 0 To 2 m_P(i).Sent(i2) = 0 m_P(i).Recv(i2) = 0 m_P(i).T(i2).Enabled = False m_P(i).State(i2) = 0 m_P(i).Er(i2) = 0 m_P(i).Data(i2).Pos = 19 For i3 = 0 To 19 m_P(i).Data(i2).Sent(i3) = -1 m_P(i).Data(i2).Data(i3) = vbNullString m_P(i).DataR(i2).Data(i3) = vbNullString m_P(i).DataR(i2).P(i3) = pHead m_P(i).DataR(i2).Pos = -1 m_P(i).DataR(i2).Last = -1 Next i3 Next i2 m_P(i).Sent(1) = -1 m_P(i).ID = i m_P(i).Slot = &HFF m_P(i).PingTick = 0 m_P(i).DL = 0 m_P(i).Ping = -1 m_P(i).MapPos = -1 m_P(i).Account = vbNullString m_P(i).Stats = vbNullString End Sub Private Sub AddBanPlayer(ByVal strAccount As String) Dim i As Integer For i = 0 To m_BanCount If (StrComp(strAccount, m_Ban(i), vbTextCompare) = 0) Then Exit Sub Next i m_BanCount = m_BanCount + 1 ReDim Preserve m_Ban(m_BanCount) m_Ban(m_BanCount) = strAccount End Sub Private Function FindTeamSlot(ByVal bTeam As Byte, Optional ByVal bFindState As Byte = &H6) As Byte '//Search for a free slot with in a team Dim i As Byte For i = 0 To 7 If (m_Slot(i).Team = bTeam) Then If (m_Slot(i).State = bFindState) Then FindTeamSlot = i Exit Function End If End If Next i FindTeamSlot = &HFF End Function Private Sub AddPktCount(ByRef lngCount As Long) lngCount = lngCount + 1 If (lngCount > &HFFFF&) Then lngCount = 0 End Sub Private Sub AddResendData(ByRef R As SCGPRESEND, ByVal lngSent As Long, ByVal bPacketID As Byte, ByVal S As String) Dim i As Integer i = FindResendData(R, lngSent) If (Not i = -1) Then Exit Sub R.Pos = R.Pos + 1 If (R.Pos > 19) Then R.Pos = 0 R.Verifyed(R.Pos) = bPacketID R.Sent(R.Pos) = lngSent R.Data(R.Pos) = S End Sub Private Function FindResendData(ByRef R As SCGPRESEND, ByVal lngSent As Long) As Integer Dim i As Integer Dim i2 As Integer i = R.Pos For i2 = 0 To 19 If (R.Sent(i) = lngSent) Then If (R.Verifyed(i) < &HFF) Then FindResendData = i Exit Function End If End If i = i - 1 If (i < 0) Then i = 19 Next i2 FindResendData = -1 End Function Private Sub VerifyRecvCount(ByRef P As SCGPHEADER, ByRef S As String) Dim bTest As Boolean If (m_P(P.pID).DataR(P.PktType).Last = &HFFFF&) Then m_P(P.pID).DataR(P.PktType).Last = -1 '//Check if this is the packet we are expecting next bTest = (P.Sent = (m_P(P.pID).DataR(P.PktType).Last + 1)) If bTest Then m_P(P.pID).DataR(P.PktType).Last = P.Sent '//Parse this packet Call ParseEx(P, S) '//Check for following packets in the buffer Call CheckRecvBuffer(m_P(P.pID).DataR(P.PktType)) Exit Sub End If '//Check if this is a packet after the expected packet, and buffer If (m_P(P.pID).DataR(P.PktType).Last > &HFFEC&) Then 'also check for packets < (19 - (&HFFFF& - Last) bTest = (P.Sent < (19 - (&HFFFF& - m_P(P.pID).DataR(P.PktType).Last))) Or _ (P.Sent > (m_P(P.pID).DataR(P.PktType).Last + 1)) Else bTest = (P.Sent > (m_P(P.pID).DataR(P.PktType).Last + 1)) End If If bTest Then '//Request a resend If (P.PktType = 0) Then Call s0_Resend(P.pID, m_P(P.pID).DataR(P.PktType).Last + 1) ElseIf (P.PktType = 1) Then Debug.Print "REQUEST RESEND: 0x" & Hex(m_P(P.pID).DataR(P.PktType).Last + 1) & " To " & P.pID Call s1_Resend(P.pID, m_P(P.pID).DataR(P.PktType).Last + 1) ElseIf (P.PktType = 2) Then Call s2_Resend(P.pID, m_P(P.pID).DataR(P.PktType).Last + 1) End If '//Add to the buffer Call AddRecvBuffer(m_P(P.pID).DataR(P.PktType), P, S) Else '//Already handled this packet End If End Sub Private Sub AddRecvBuffer(ByRef R As SCGPRERECV, ByRef P As SCGPHEADER, ByRef S As String) R.Pos = R.Pos + 1 If (R.Pos > 19) Then R.Pos = 0 R.P(R.Pos) = P R.Data(R.Pos) = S End Sub Private Sub CheckRecvBuffer(ByRef R As SCGPRERECV) Dim i As Long Dim i2 As Long While i <= R.Pos If (R.Last = &HFFFF&) Then R.Last = -1 If (R.P(i).Sent = (R.Last + 1)) Then R.Last = R.P(i).Sent '//Parse this Call ParseEx(R.P(i), R.Data(i)) '//Remove this If (i < R.Pos) Then For i2 = i To (R.Pos - 1) R.P(i2) = R.P(i2 + 1) R.Data(i2) = R.Data(i2 + 1) Next i2 End If R.Pos = R.Pos - 1 If (R.Pos < 0) Then R.Pos = -1 i = 0 Else i = i + 1 End If Wend End Sub '##################################################################### '##################################################################### '######################## General Functions ########################## '##################################################################### '##################################################################### Private Sub TSet(ByRef udtT As SCGPTIMER, ByVal lngWaitTime As Long) udtT.Enabled = (lngWaitTime > 0) If udtT.Enabled Then udtT.TickTime = GetTickCount() udtT.WaitTime = lngWaitTime End If End Sub Private Function TFire(ByRef udtT As SCGPTIMER, Optional ByVal lngTime As Long) As Boolean If udtT.Enabled Then lngTime = (GetTickCount() - udtT.TickTime) If lngTime < 0 Then udtT.TickTime = GetTickCount() Else TFire = (lngTime > udtT.WaitTime) End If End If End Function Public Function ReadMPQFile(ByVal strMPQ As String, ByVal strFile As String, ByRef strBuffer As String) As Boolean On Error GoTo ReadMPQFileErr If (Len(Dir$(strMPQ)) = 0) Then Exit Function Dim lngLengh As Long Dim lngMpq As Long 'handle to the archive Dim lngFile As Long 'handle to the file Call SFileDestroy Call SFileSetLocale(&H656E5553) 'SUne If (SFileOpenArchive(strMPQ, 0, 0, lngMpq) = False) Then GoTo ReadMPQFileErr If (SFileOpenFileEx(lngMpq, strFile, 0, lngFile) = False) Then GoTo ReadMPQFileErr lngLengh = SFileGetFileSize(lngFile, 0) If (lngLengh < 0) Then GoTo ReadMPQFileErr strBuffer = String(lngLengh, 0) If (SFileReadFile(lngFile, ByVal strBuffer, lngLengh, dwBytes, ByVal 0&) = False) Then GoTo ReadMPQFileErr Call SFileCloseFile(lngFile) Call SFileCloseArchive(lngMpq) ReadMPQFile = True Exit Function ReadMPQFileErr: End Function Public Sub ParseCHK(ByRef S As String) ''http://www.staredit.net/wiki/scenario.chk_format Dim lngHeader As Long Dim lngLengh As Long Dim lngPos As Long lngPos = 1 ',44,,6,1,2,,1,190508b2,4,,ptitloulou.TheHunters. ',Mapsize,Players,Speed,Icon,Type,League,Penalty,Hash,Title,Blank,Host.MapName Do Until ((lngPos + 7) > Len(S)) '(DWORD) Header '(DWORD) Lengh Call RtlMoveMemory(lngHeader, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 Call RtlMoveMemory(lngLengh, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 If (lngLengh < 0) Then Exit Do Select Case lngHeader Case &H45505954 'TYPE' Required 'RAWS = Starcraft 'RAWB = Broodwar Case &H20524556 'VER ' Required '2 byte Version Byte Case &H32455649 'IVE2' Not Required '2 byte version of the map, 11 for 1.04 or later Case &H444F4356 'VCOD' Required '1040 bytes: Verification code. Only one code is acceptable Case &H4E574F49 'IOWN' Not Required 'specifies the owner of each player '12 bytes: One byte for each player, specifies the owner of the player: '00 - Inactive '01 - Computer(game) '02 - Occupied by Human Player '03 - Rescue Passive '04 - Unused '05 - Computer '06 - Human (Open Slot) '07 - Neutral '08 - Closed slot Case &H524E574F 'OWNR' Required '12 bytes: One byte for each player, specifies the owner of the player: '00 - Inactive '01 - Computer(game) '02 - Occupied by Human Player '03 - Rescue Passive '04 - Unused '05 - Computer '06 - Human (Open Slot) '07 - Neutral '08 - Closed slot Case &H20415245 'ERA ' Required 'WORD & 0x7 '2 byte integer: Designates tileset: '00 - Badlands '01 - Space Platform '02 - Installation '03 - Ashworld '04 - Jungle '05 - Desert '06 - Arctic '07 - Twilight Case &H204D4944 'DIM ' Required '2 byte integer: Width of the map '2 byte integer: Height of the map Case &H45444953 'SIDE' Required '12 bytes: 1 byte/player for species of player: '00 - Zerg '01 - Terran '02 - Protoss '03 - Unused (Independent) '04 - Unused (Neutral) '05 - User Selectable '06 - Random (Forced; Acts as a selected race; Does not randomize race like user select;) '07 - Inactive Case &H4D58544D 'MTXM' Required '(height * width) 2 byte integers: one integer for each tile. 'The Width/Height of the map is measured in the number of square 32x32p tiles. 'Tiles in this section are listed from left to right, top to bottom. Case &H494E5550 'PUNI' Required for UMS '(228 * 12) bytes: 1 byte for each unit in order of its unit id, then each player, for player availability: '228 bytes: 1 byte for each unit in order of it's unit id, for global availability defaults (for all players): '(228 * 12) bytes: 1 byte for each unit in order of its unit id, then each player, indicating whether a player uses the global availability defaults. Case &H54494E55 'UNIT' Required '4 byte long: The unit's class instance (sort of a "serial number") '2 byte integer: X coordinate of unit '2 byte integer: Y coordinate of unit '2 byte integer: Unit ID '2 byte integer: Type of relation to another building (i.e. add-on, nydus link, etc.) '2 bytes: Flags of special properties which can be applied to the unit and are valid: 'Bit 0 - Cloak Is valid 'Bit 1 - Burrow Is valid 'Bit 2 - In transit is valid 'Bit 3 - hallucinated Is valid 'Bit 4 - invincible Is valid 'Bit 5 - 15 - Unused '2 bytes: Out of the elements of the unit data, the properties which can be changed by the map maker: 'Bit 0 - Owner player is valid (the unit is not a critter, start location, etc.; not a neutral unit) 'Bit 1 - HP Is valid 'Bit 2 - SP Is valid 'Bit 3 - Energy is valid (unit is a wraith, etc.) 'Bit 4 - Resource amount is valid (unit is a mineral patch, vespene geyser, etc.) 'Bit 5 - Amount in hangar is valid (unit is a reaver, carrier, etc.) 'Bit 6 - 15 - Unused '1 byte: Player number of owner (0-based) '1 byte: Hit points % (1-100) '1 byte: Shield points % (1-100) '1 byte: Energy points % (1-100) '4 byte long: Resource amount '2 byte integer: Number of units in hangar '2 bytes: Unit state flags 'Bit 0 - Unit Is cloaked 'Bit 1 - Unit Is burrowed 'Bit 2 - Building is in transit 'Bit 3 - Unit Is hallucinated 'Bit 4 - Unit Is invincible 'Bit 5 - 15 - Unused '4 bytes: Unused '4 byte long: Class instance of the unit to which this unit is related to (i.e. via an add-on, nydus link, etc.). It is "0" if the unit is not linked to any other unit. Case &H4D4F5349 'ISOM' Not required Case &H454C4954 'TILE' Not required Case &H20324444 'DD2 ' Not required by starcraft '2 byte integer: Number of the doodad. Size of the doodad is dependent on this. Doodads are different for each tileset. '2 byte integer: X coordinate of the doodad unit '2 byte integer: Y coordinate of the doodad unit '1 byte: Player number that owns the doodad '1 byte: Enabled flag '00 - Doodad is enabled (trap can attack, door is closed, etc) '01 - Doodad is disabled Case &H32474854 'THG2' Required for Melee game type '2 byte integer: Unit number of the doodad '2 byte integer: X coordinate of the doodad unit '2 byte integer: Y coordinate of the doodad unit '1 byte: Player number that owns the doodad '1 byte: Unused '2 bytes: Flags 'Bit 0 - 11 - Unused 'Bit 12 - Draw as sprite (Determines if it is a sprite or a unit) 'Bit 13 - Unused 'Bit 14 - Unused 'Bit 15 - Disabled (Only valid if Draw as sprite is unchecked, disables the unit) Case &H4B53414D 'MASK' Required '(Height * Width) bytes: One byte for each map tile. The bits indicate for each player the fog of war. 'Bit 0 - Player 1's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 1 - Player 2's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 2 - Player 3's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 3 - Player 4's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 4 - Player 5's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 5 - Player 6's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 6 - Player 7's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. 'Bit 7 - Player 8's Fog of War. If on, the tile is covered with fog. if off, the tile is visible. Case &H20525453 'Str ' Required for Melee game type 'This section contains all the strings in the map. '2 byte integer: Number of strings in the section '(# of strings) 2 byte integers: 1 integer for each string specifying the offset (the spot where the string starts in the section from the start of it). 'Strings: After the offsets, this is where every string in the map goes, one after another. Each one is terminated by a null character. Case &H50525055 'UPRP' 'There are 64 of the following structures regardless of how many are used and it cannot exceed 64. '2 bytes: Flag of which special properties can be applied to unit, and are valid. 'Bit 0 - Cloak bit is valid 'Bit 1 - Burrowed bit is valid 'Bit 2 - In transit bit is valid 'Bit 3 - Hallucinated bit is valid 'Bit 4 - Invincible bit is valid 'Bit 5 - 15 - Unknown / unused '2 bytes: Which elements of the unit data are valid, which properties can be changed by the map maker. 'Bit 0 - Owner player is valid (unit is not neutral) 'Bit 1 - HP Is valid 'Bit 2 - SP Is valid 'Bit 3 - Energy Is valid 'Bit 4 - Resource amount is valid (unit is a resource) 'Bit 5 - Amount in hanger is valid 'Bit 6 - Unknown / unused '1 byte: Player number that owns unit. Will always be NULL in this section (0) '1 byte: Hit point % (1-100) '1 byte: Shield point % (1-100) '1 byte: Energy point % (1-100) '4 byte long: Resource amount (for resources only) '2 byte integer: # of units in hangar '2 bytes: Flags 'Bit 0 - Unit Is cloaked 'Bit 1 - Unit Is burrowed 'Bit 2 - Building is in transit 'Bit 3 - Unit Is hallucinated 'Bit 4 - Unit Is invincible 'Bit 5 - 15 - Unknown / unused '4 bytes: Unknown/unused. Padding? Case &H53555055 'UPUS' '64 bytes: 1 byte for each trigger unit properties slot '00 - Properties slot is unused '01 - Properties slot is used Case &H4E47524D 'MRGN' '4 byte long: Starting X coordinate of location (32 pt grid) '4 byte long: Starting Y coordinate of location (32 pt grid) '4 byte long: Ending X coordinate of location (32 pt grid) '4 byte long: Ending Y coordinate of location (32 pt grid) '2 byte integer: String number of the name of this location '2 bytes: Location elevation flags. If an elevation is disabled in the location, it's bit will be on (1) 'Bit 0 - Low elevation 'Bit 1 - Medium elevation 'Bit 2 - High elevation 'Bit 3 - Low air 'Bit 4 - Medium air 'Bit 5 - High air 'Bit 6 - 15 - Unknown / unused Case &H47495254 'TRIG' Case &H4652424D 'MBRF' 'This section contains all of the mission briefings shown by the players. Case &H50525053 'SPRP' '2 byte integer: String number of the scenario name '2 byte integer: String number of the scenarios description. Case &H43524F46 'FORC' Required for Melee game type '8 bytes: 1 byte for each active player, specifying which of the 4 forces (0-based) that the player's on. '(4) 2 byte integers: 1 integer for each force, string number of the name of the force '4 bytes: 1 byte for each force specifying the properties: 'Bit 0 - Random start location 'Bit 1 - Allies 'Bit 2 - Allied victory 'Bit 3 - Shared vision 'Bit 4 - 7 - Unknown / unused Case &H20564157 'WAV ' Not Required by StarCraft '512 longs: 1 long for each WAV. Indicates the string number of the path to the wav file in the MPQ. If the entry is not used, it will be 0. Case &H4D4E5753 'SWNM' Not Required by StarCraft '(256) 4 byte longs: One long for each switch, specifies the string number for the name of each switch. Case &H524C4F43 'COLR' Required for Melee game type (only on Brood War) '8 bytes: 1 byte for each player, indicates the color of the player '00 - Red '01 - Blue '02 - Teal '03 - Purple '04 - Orange '05 - Brown '06 - White '07 - Yellow '08 - Green '09 - Pale yellow '10 - Tan '11 - Neutral color '12 - Pale green '13 - Blueish gray '14 - Pale yellow '15 - Cyan '17 - Black Case &H78505550 'PUPx' 'This section overrides the "UPGR" when the scenario is Brood War. 'This section is identical to UPGR section except it uses the Brood War set of 61 upgrades instead of the original 46 Case &H78455450 'PTEx' 'This section overrides the "PTEC" when the scenario is Brood War. 'This section is identical to PTEC section except it uses the Brood War set of 44 technologies instead of the original 24 Case &H78494E55 'UNIx' 'This section overrides the "UNIS" when the scenario is Brood War. 'This section is indentical to UNIS section except it uses the Brood War set of 130 weapons instead of the original 100 Case &H78475055 'UPGx' 'This section overrides the "UPGS" when the scenario is Brood War. 'This section is pretty much the same as UPGS except for two differences: 'This section uses the Brood War set of 61 upgrades instead of the original 46 'After the first 61 bytes, there is a single 0 before the next set. May not matter? Case &H78434554 'TECx' 'This section overrides the "TECS" when the scenario is Brood War. 'This section is indentical to UNIS section except it uses the Brood War set of 44 technologies instead of the original 24 Case Else 'Unknown End Select lngPos = lngPos + lngLengh Loop End Sub Public Function GetMapStats(ByVal strMPQ As String, _ ByVal bSpeed As Byte, _ ByVal intType As Integer, _ ByVal bPenalty As Byte, _ ByVal strHost As String) As String Dim i As Long Dim S As String Dim lngHeader As Long Dim lngLengh As Long Dim lngPos As Long Dim lngWidth As Long Dim lngHeight As Long Dim lngPlayers As Long 'Dim lngSpeed As Long Dim lngIcon As Long 'Dim lngType As Long 'Dim lngLeague As Long 'Dim lngPenalty As Long Dim lngHash As Long Dim lngTitle As Long 'Dim strHost As String Dim strMAP As String, lngMap As Long Dim strOut As String Dim lngTest As Long lngIcon = GetMapIcon(strMPQ) If (ReadMPQFile(strMPQ, "staredit\scenario.chk", S) = False) Then Exit Function ',Mapsize,Players,Speed,Icon,Type,League,Penalty,Hash,Title,Blank,Host.MapName lngPos = 1 strOut = ",#1,#2,#3,#4,#5,#6,#7,#8,#9,,#B" Do Until ((lngPos + 7) > Len(S)) Call RtlMoveMemory(lngHeader, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 Call RtlMoveMemory(lngLengh, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 If (lngLengh < 0) Then Exit Do Select Case lngHeader Case &H45505954 'TYPE' Required 'RAWS = Starcraft 'RAWB = Broodwar Case &H20524556 'VER ' 2 byte Version Byte Case &H32455649 'IVE2' 2 byte version of the map, 11 for 1.04 or later Case &H444F4356 'VCOD' 1040 bytes: Verification code If (lngLengh >= 1040) Then For i = 0 To 259 Call RtlMoveMemory(lngTest, ByVal Mid$(S, lngPos + (i * 4), 4), 4) lngHash = lngHash Xor lngTest Next i End If Case &H524E574F 'OWNR' Required lngPlayers = 0 For i = 0 To 7 If (Asc(Mid$(S, lngPos + i, 1)) = &H6) Then lngPlayers = lngPlayers + 1 Next i Case &H20415245 'ERA ' Required Call RtlMoveMemory(lngTitle, ByVal Mid$(S, lngPos, 2), 2) lngTitle = (lngTitle And &H7) Case &H204D4944 'DIM ' Required Call RtlMoveMemory(lngWidth, ByVal Mid$(S, lngPos, 2), 2) Call RtlMoveMemory(lngHeight, ByVal Mid$(S, lngPos + 2, 2), 2) lngWidth = (lngWidth And &H7FFF) \ 32 lngHeight = (lngHeight And &H7FFF) \ 32 Case &H20525453 'Str ' Required for Melee game type strMAP = Mid$(S, lngPos, lngLengh) 'string table Case &H50525053 'SPRP' Call RtlMoveMemory(lngMap, ByVal Mid$(S, lngPos, 2), 2) lngMap = (lngMap And &HFFFF&) End Select lngPos = lngPos + lngLengh Loop If (lngHash = -1) Then For i = 1 To (Len(strMAP) - 4) Step 4 Call RtlMoveMemory(lngTest, Mid$(strMAP, i, 4), 4) lngHash = lngHash Xor lngTest Next i End If If (intType = &HF) Then bPenalty = (lngPlayers - bPenalty) If (intType = &HB) Or (intType = &HC) Or (intType = &HD) Then lngPlayers = 8 If (lngMap > 0) Then Call RtlMoveMemory(lngMap, ByVal Mid$(strMAP, (lngMap * 2) + 1), 2) lngMap = (lngMap And &HFFFF&) + 1 strMAP = GetSTR(Mid$(strMAP, lngMap)) End If strOut = Replace(strOut, "#1", IIf(((lngWidth >= 8) And (lngHeight >= 8)), vbNullString, CStr(lngWidth & lngHeight))) strOut = Replace(strOut, "#2", IIf((lngPlayers > 7), vbNullString, CStr("1" & lngPlayers))) strOut = Replace(strOut, "#3", IIf((bSpeed = 4), vbNullString, CStr(bSpeed))) strOut = Replace(strOut, "#4", IIf((lngIcon = 0), vbNullString, CStr(lngIcon))) strOut = Replace(strOut, "#5", CStr(LCase(Hex(intType And &HFF)))) strOut = Replace(strOut, "#6", IIf(((intType \ 256) = 0), vbNullString, CStr(LCase(Hex(intType \ 256))))) strOut = Replace(strOut, "#7", IIf((bPenalty = 0), vbNullString, CStr(bPenalty))) strOut = Replace(strOut, "#8", CStr(LCase(Hex(lngHash)))) strOut = Replace(strOut, "#9", IIf((lngTitle = 0), vbNullString, CStr(lngTitle))) strOut = Replace(strOut, "#A", vbNullString) strOut = Replace(strOut, "#B", CStr(strHost & Chr$(&HD) & strMAP & Chr$(&HD))) GetMapStats = strOut End Function Public Function GetMapInfo(ByVal strMPQ As String, _ ByRef lngWidth As Long, _ ByRef lngHeight As Long, _ ByRef bIcon As Byte, _ ByRef bTitle As Byte, _ ByRef bPlayers As Byte, _ ByRef bComputers As Byte, _ ByRef strTitle As String, _ ByRef strDesc As String) As Boolean On Error GoTo GetMapInfoErr Dim i As Long Dim S As String Dim lngHeader As Long Dim lngLengh As Long Dim lngHash As Long Dim lngPos As Long Dim lngName As Long 'string table idnex to the map name Dim lngDesc As Long 'string table index to the map description bIcon = GetMapIcon(strMPQ) If (ReadMPQFile(strMPQ, "staredit\scenario.chk", S) = False) Then Exit Function strTAB = vbNullString bPlayers = 0 bComputers = 0 lngPos = 1 Do Until ((lngPos + 7) > Len(S)) Call RtlMoveMemory(lngHeader, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 Call RtlMoveMemory(lngLengh, ByVal Mid$(S, lngPos, 4), 4): lngPos = lngPos + 4 If (lngLengh < 0) Then Exit Do Select Case lngHeader Case &H45505954 'TYPE' Required 'RAWS = Starcraft 'RAWB = Broodwar Case &H20524556 'VER ' 2 byte Version Byte Case &H32455649 'IVE2' 2 byte version of the map, 11 for 1.04 or later Case &H444F4356 'VCOD' 1040 bytes: Verification code Case &H524E574F 'OWNR' Required lngPlayers = 0 For i = 0 To 7 lngHash = Asc(Mid$(S, lngPos + i, 1)) If (lngHash = &H6) Then bPlayers = bPlayers + 1 ElseIf (lngHash = &H5) Then bComputers = bComputers + 1 End If Next i Case &H20415245 'ERA ' Required bTitle = (Asc(Mid$(S, lngPos, 1)) And &H7) Case &H204D4944 'DIM ' Required Call RtlMoveMemory(lngWidth, ByVal Mid$(S, lngPos, 2), 2) Call RtlMoveMemory(lngHeight, ByVal Mid$(S, lngPos + 2, 2), 2) lngWidth = (lngWidth And &H7FFF&) lngHeight = (lngHeight And &H7FFF&) Case &H20525453 'Str ' Required for Melee game type strTAB = Mid$(S, lngPos, lngLengh) 'string table Case &H50525053 'SPRP' Call RtlMoveMemory(lngName, ByVal Mid$(S, lngPos, 2), 2) Call RtlMoveMemory(lngDesc, ByVal Mid$(S, lngPos + 2, 2), 2) lngName = (lngName And &HFFFF&) lngDesc = (lngDesc And &HFFFF&) End Select lngPos = lngPos + lngLengh Loop If (lngName > 0) Then Call RtlMoveMemory(lngName, ByVal Mid$(strTAB, (lngName * 2) + 1, 2), 2) lngName = (lngName And &HFFFF&) strTitle = GetSTR(Mid$(strTAB, lngName + 1)) End If If (lngDesc > 0) Then Call RtlMoveMemory(lngDesc, ByVal Mid$(strTAB, (lngDesc * 2) + 1, 2), 2) lngDesc = (lngDesc And &HFFFF&) strDesc = GetSTR(Mid$(strTAB, lngDesc + 1)) End If GetMapInfo = True Exit Function GetMapInfoErr: Debug.Print "clsSCGP.GetMapInfo() Error: " & Err.Description End Function Public Function GetMapIcon(ByVal strMPQ As String) As Long Dim S As String Dim strLine As String Dim lngPos As Long Dim lngResult As Long Dim lngTest As Long If (ReadMPQFile(strMPQ, "(listfile)", S) = False) Then Exit Function lngPos = 1 Do Until (lngPos >= Len(S)) strLine = GetSTR(Mid$(S, lngPos), Chr$(&HD)) If (Len(strLine) >= 4) Then Call RtlMoveMemory(lngTest, ByVal LCase$(Right$(strLine, 4)), 4) If (lngTest = &H646E632E) Then '.cnd If (InStr(1, strLine, "Blizzard_", vbTextCompare) = 1) Then lngResult = 1 ElseIf (InStr(1, strLine, "Ladder_", vbTextCompare) = 1) Then If (Mid$(strLine, 8, 2) = "4.") Or (Mid$(strLine, 8, 2) = "12") Then lngResult = 2 Else lngResult = 1 End If ElseIf (InStr(1, strLine, "PGL_", vbTextCompare) = 1) Or _ (InStr(1, strLine, "Comp", vbTextCompare) = 1) Then lngResult = 3 ElseIf (InStr(1, strLine, "KBK_", vbTextCompare) = 1) Then lngResult = 4 ElseIf (InStr(1, strLine, "Tourn_", vbTextCompare) = 1) Then lngResult = 5 ElseIf (InStr(1, strLine, "WGT_", vbTextCompare) = 1) Then lngResult = 6 Else lngResult = 0 End If 'GetMapIcon = lngResult 'Exit Function Exit Do End If End If lngPos = lngPos + Len(strLine) + 2 Loop GetMapIcon = lngResult End Function Private Sub iClear() m_BufPos = 0 End Sub Private Sub iBYTEA(ByRef bValue() As Byte, ByVal intNumBytes As Integer) If (intNumBytes < 1) Then Exit Sub Call RtlMoveMemory(m_Buf(m_BufPos), bValue(0), intNumBytes) m_BufPos = m_BufPos + intNumBytes End Sub Private Sub iBYTE(ByRef bValue As Byte) m_Buf(m_BufPos) = bValue m_BufPos = m_BufPos + 1 End Sub Private Sub iWORD(ByRef intValue As Integer) Call RtlMoveMemory(m_Buf(m_BufPos), intValue, 2) m_BufPos = m_BufPos + 2 End Sub Private Sub iDWORD(ByRef lngValue As Long) Call RtlMoveMemory(m_Buf(m_BufPos), lngValue, 4) m_BufPos = m_BufPos + 4 End Sub Private Sub iSTRING(ByRef strValue As String) Dim intLen As Integer intLen = Len(strValue) If (intLen = 0) Then Exit Sub Call RtlMoveMemory(m_Buf(m_BufPos), ByVal strValue, intLen) m_BufPos = m_BufPos + intLen End Sub Private Sub iNTSTRING(ByRef strValue As String) Dim intLen As Integer intLen = Len(strValue) If (Not intLen = 0) Then Call RtlMoveMemory(m_Buf(m_BufPos), ByVal strValue, intLen) m_BufPos = m_BufPos + intLen End If Call iBYTE(0) End Sub Private Sub iHEADER(ByVal lngSent As Long, _ ByVal lngRecv As Long, _ ByVal bPacketType As Byte, _ ByVal bPacketID As Byte, _ ByVal bPlayerID As Byte, _ ByVal bReSend As Byte) Dim i As Long '//null the flooter Call RtlZeroMemory(m_Header(0), 4) '//checksum will over write what evers in its place '//packet lengh If (bPacketType = 1) And (bReSend = 0) Then i = 13 + m_BufPos Call RtlMoveMemory(m_Header(6), i, 2) m_Header(16) = bPacketID i = 17 Else i = 12 + m_BufPos Call RtlMoveMemory(m_Header(6), i, 2) i = 16 End If '//sent/recv counters Call RtlMoveMemory(m_Header(8), lngSent, 2) Call RtlMoveMemory(m_Header(10), lngRecv, 2) '//packet type/id m_Header(12) = bPacketType If (bPacketType = 0) Then m_Header(13) = bPacketID Else m_Header(13) = 0 End If '//player id/resend m_Header(14) = bPlayerID m_Header(15) = bReSend '//shift the packet data and copy the header If (m_BufPos > 0) Then Call RtlMoveMemory(m_Buf(i), m_Buf(0), m_BufPos) End If Call RtlMoveMemory(m_Buf(0), m_Header(0), i) m_BufPos = m_BufPos + i '//calculate the checksum Call UDPCheckSum End Sub Private Sub iUDP(ByRef lngAddr As Long, ByRef intPort As Integer) If (m_BufPos = 0) Then Exit Sub 'empty buffer m_Addr.sin_addr = lngAddr m_Addr.sin_port = intPort m_Addr.sin_family = 2 If (sendto(m_Handle, m_Buf(0), m_BufPos, 0&, m_Addr, 16&) = -1) Then 'Debug.Print "[UDP_SOCKET ERROR] Unable to send data" End If Call iClear End Sub Private Function iBuf() As String If (m_BufPos = 0) Then Exit Function iBuf = String(m_BufPos, 0) Call RtlMoveMemory(ByVal iBuf, m_Buf(0), m_BufPos) End Function Private Sub UDPCheckSum() Dim A As Long Dim B As Long Dim C As Long For i = (m_BufPos - 1) To 6 Step -1 B = B + m_Buf(i) If (B > &HFF) Then B = B - &HFF A = A + B Next i C = (B * 256) Or (A Mod 255) A = &HFF - ((C And &HFF) + (C \ 256)) Mod &HFF B = (A + (C \ 256)) B = &HFF - (B Mod &HFF) B = B Or (A * 256) Call RtlMoveMemory(m_Buf(4), B, 2) End Sub Private Function GetSTR(ByVal strData As String, Optional strTerminator As String = vbNullChar) As String Dim i As Integer i = InStr(1, strData, strTerminator) If (i = 0) Then GetSTR = strData Else GetSTR = Mid$(strData, 1, (i - 1)) End If End Function