Code archives/Networking/BlitzPlay Lite + eNet
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Links eNet - http://enet.bespin.org/ Original BlitzPlay Lite - http://members.shaw.ca/blitzplay/BPlitev1.14.zip I was using BlitzPlay Lite which was working just fine for me. But when I tested with someone other than myself, I found out I needed reliable messaging. Since I couldn't get BlitzPlay Pro, I had to find a way to add the reliable messaging myself. Some things I had to take out -Connecting port for client. The client only needs to put in the Hosting port now. -Banning. Since eNet doesn't allow me to see the IPs, you can't ban anyone by IP. Added -Reliable messaging. It is defaulted to True, which can be changed to False if you wish. | |||||
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-Constants=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ;------These are the values that JoinSession will return Const BP_NOREPLY = 0 ;No reply from host within 15 seconds Const BP_IAMBANNED = 1 ;Local player's IP has been banned Const BP_GAMEISFULL = 2 ;The game has maxed out players Const BP_PORTNOTAVAILABLE = 3 ;The local port wasn't available Const BP_SUCCESS = 4 ;The game was joined! Const BP_USERABORT = 5 ;The user pushed ESC while joining Const BP_INVALIDHOSTIP = 6 ;The IP used for the Host was invalid ;------These are all the messages BP can generate for the end user. Const BP_PLAYERHASJOINED = 255 ;msgData = new player name|msgFrom = player's id Const BP_PLAYERHASLEFT = 254 ;msgData = T/F on if intentionally|msgFrom = player's id Const BP_HOSTHASLEFT = 253 ;msgData = T/F on if intentionally|msgFrom = old host's id Const BP_PLAYERWASKICKED = 252 ;msgData = null|msgFrom = kicked player's id ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Globals=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ;---------------The following shouldn't be modified externally------------------ ;**Although these ones might be useful to you** Global BP_Bank = CreateBank(128) Global BP_Bank_PeerID = CreateBank(4) Global BP_Bank_DataSize = CreateBank(4) Global BP_GameType ;Type of game. (0-255) Global BP_TotRecvPacket ;Packets received Global BP_TotSentPacket ;Packets sent Global BP_Host ;T/F, am I the Host? Global BP_Host_ID ;Host's ID # Global BP_Host_IP$ ;Host's IP; (in integer format) not anymore Global BP_Host_Port ;Host's Port Global BP_MaxPlayers = 255 ;Maximum # of players Global BP_My_Name$ ;Local player's Name Global BP_My_ID ;Local player's ID # Global BP_My_Port ;Local port being used by BlitzPlay Global BP_NumPlayers ;How many players are connected to the game right now Global BP_LocalHost = BP_ConvertIp ("127.0.0.1");integer local loopback address Global BP_Online = False ;T/F Global BP_My_IP ;This computers IP. Set to local if no IP Global BP_LogFile$ = "" ;Define if you want logging enabled. Global BP_TimeoutPeriod=15000 ;How long before we assuming connection dropped(in ms) Global BP_Log ;Log file handle, 0 if logging disabled Global BP_AutoLogging ;True or False on if BP should internally do the logging Global BP_UDPdebug ;Odds (in %) that packets do NOT get sent (for testing) ;**These ones probably not as useful.. Global BP_UDP_Stream ;UDP Stream handle Global BP_CompressBank = CreateBank(4);Bank used for converting Floats to Strings ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Types=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Type NetInfo ;--The general player info. Field Name$ ;Player's Name Field Net_id% ;Players unique ID # Field eNet_id ;eNet uses a different ID system Field LastHeard% ;When the last packet was received from them. Field Alive% ;Boolean on if we think this player is still there End Type Type MsgInfo ;--Messages that have arrived are stored here Field msgData$ ;actual packet contents Field msgType% ;Msg type(0-255) Field msgFrom% ;ID of msg sender End Type Type DiscID ;--Keeps track of disconnects' ID's Field id% ;ID of disconnect End Type Type Connecting ;--For players trying to connect Field Name$ ;Connect name Field Net_id% ;new player's ID Field eNet_id ;eNet uses a different ID system Field LastHeard% ;When the last packet was received from them. Field Alive% ;Boolean on if we think this new connect is still trying End Type Type UnrecMsgQueue ;--Messages from unrecognized IP+Port Field msgData$ ;Hm. Self explanatory. Field msgType% Field Time% ;These will be stored for up to 1 second then disregarded Field Net_id% Field eNet_id ;eNet uses a different ID system End Type ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Functions=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Function BP_ClearSession() ;-=-=-=Clears out any data that could be leftover from previous sessions. If First NetInfo<>Null Then Delete Each NetInfo If First UnrecMsgQueue<>Null Then Delete Each UnrecMsgQueue If First Connecting<>Null Then Delete Each Connecting If First MsgInfo<>Null Then Delete Each MsgInfo If First DiscID<>Null Then Delete Each DiscID BP_TotSentPacket = 0 BP_TotRecvPacket = 0 BP_StopLogFile() If BP_Online ENetDeInitialize() End Function Function BP_ConvertIp(IP$) ;-=-=-=Convert an IP from x.x.x.x to integer format. Local dot1 = Instr(IP$,".") Local dot2 = Instr(IP$,".",dot1+1) Local dot3 = Instr(IP$,".",dot2+1) Local Octet1% = Mid$(IP$,1,dot1-1) Local Octet2% = Mid$(IP$,dot1+1,dot2-1) Local Octet3% = Mid$(IP$,dot2+1,dot3-1) Local Octet4% = Mid$(IP$,dot3+1) Return (((((Octet1 Shl 8) Or Octet2) Shl 8) Or Octet3) Shl 8) Or Octet4 End Function Function BP_ConvertDomain(domain$) ;-=-=-=Converts from www.domain.com to integer IP address. Return HostIP(CountHostIPs (domain)) End Function Function BP_EndSession() ;-=-=-=Disconnect from everything If BP_Online If BP_Host Then BP_UDPMessage(0,251,Chr(BP_My_ID)) Else BP_UDPMessage(BP_Host_ID,253,Chr(BP_My_ID)) EndIf BP_Online = False EndIf BP_UDP_Stream = 0 BP_ClearSession() BP_StopLogFile() End Function Function BP_FindConnect.Connecting(id,enet=False) ;-=-=-=Go through the Connecting type list and search by IP+Port Local a.Connecting For a.Connecting = Each Connecting If enet If a\eNet_id = id Then Return a Else If a\Net_id = id Then Return a EndIf Next End Function Function BP_FindID.NetInfo(id,enet=False) ;-=-=-=Go through the NetInfo type list and find a specific instance, based on the ID Local a.NetInfo For a.NetInfo = Each NetInfo If enet If a\eNet_id = id Then Return a Else If a\Net_id = id Then Return a EndIf Next End Function Function BP_FloatToStr$(num#) ;-=-=-=Convert a floating point number to a 4 byte string Local st$ = "",i% PokeFloat BP_CompressBank,0,num For i = 0 To 3 st = st + Chr(PeekByte(BP_CompressBank,i)) Next Return st End Function Function BP_GetGameType() ;-=-=-=Returns the currently set game type Return BP_GameType% End Function Function BP_GetHostID() ;-=-=-=Returns the Host ID Return BP_Host_ID% End Function Function BP_GetHostIP$() ;-=-=-=Returns the Host IP address Return BP_Host_IP End Function Function BP_GetHostPort() ;-=-=-=Returns the Host Port Return BP_Host_Port% End Function Function BP_GetLogFileName$() ;-=-=-=Returns the currently set Log File name Return BP_LogFile$ End Function Function BP_GetMaxPlayers() ;-=-=-=Returns the currently set Max Players value Return BP_MaxPlayers% End Function Function BP_GetMyID() ;-=-=-=Returns this users ID Return BP_My_ID% End Function Function BP_GetMyIP$() ;-=-=-=Returns this users IP address Local ip% If CountHostIPs ("") Then ip = HostIP(CountHostIPs("")) Else ip = BP_LocalHost Return DottedIP$(ip) End Function Function BP_GetMyName$() ;-=-=-=Returns this users name Return BP_My_Name$ End Function Function BP_GetMyPort() ;-=-=-=Returns this users Port Return BP_My_Port% End Function Function BP_GetNumberOfPlayers() ;-=-=-=Returns the current number of players Return BP_NumPlayers% End Function Function BP_GetPacketsReceived() ;-=-=-=Returns the number of packets that have been received Return BP_TotRecvPacket% End Function Function BP_GetPacketsSent() ;-=-=-=Returns the number of packets that have been sent Return BP_TotSentPacket% End Function Function BP_GetPlayerName$(ID) ;-=-=-=Find a player's name based on the ID Local a.NetInfo For a.NetInfo = Each NetInfo If a\Net_id = ID Then Return a\Name$ Next End Function Function BP_GetTimeoutPeriod() ;-=-=-=Returns the current Timeout Period Return BP_TimeoutPeriod / 1000 End Function Function BP_HostSession(HostName$,MaxPlayers%,GameType%,LocalPort%,TimeoutPeriod%) ;-=-=-=Host the game ;First clear out any left over data from a previous session BP_ClearSession() ENetInitialize() ;Now initialize the Host information and open the specified port. BP_NumPlayers = 1 BP_MaxPlayers = MaxPlayers BP_Host = True BP_My_IP = BP_ConvertIp(BP_GetMyIP()) BP_My_Port = LocalPort BP_Host_Port = BP_My_Port BP_Host_ID = 1 BP_Host_IP = BP_My_IP Local nInfo.NetInfo = New NetInfo nInfo\Name = HostName BP_My_Name = HostName BP_My_ID = 1 nInfo\Net_id = 1 nInfo\eNet_id = -1 BP_UDP_Stream = ENetCreate(True,BP_My_IP,BP_My_Port,BP_MaxPlayers,0,0) ;And set up the game information BP_GameType = GameType BP_TimeoutPeriod = TimeoutPeriod * 1000 ;TimeoutPeriod is converted to milliseconds If BP_UDP_Stream Then BP_Online = True Else BP_Online = False ENetDeInitialize() EndIf Return BP_Online End Function Function BP_IntToStr$(Num%, StrLen% = 4) ;-=-=-=Take an Integer and compress it to a string, of "strlen" bytes long. Local shiftin% Local st$ = Chr(Num And 255) For shiftin = 1 To (StrLen - 1) st$ = st$ + Chr(Num Sar (8 * shiftin)) Next Return st End Function Function BP_JoinSession(ClientName$,HostPort%,strHostIP$) ;-=-=-=Join a game already in progress ;JoinSession will return: ;0=No reply from BP_Host ;1=This IP is banned ;2=Game is full ;3=Local port not available ;4=Joined game! ;Also notice the constants which coincide w/ these values: ;BP_NOREPLY, BP_IAMBANNED, BP_GAMEISFULL, BP_PORTNOTAVAILABLE, BP_SUCCESS DebugLog strHostIP Local msg.MsgInfo,nInfo.NetInfo Local Starttime Local Reason Local Counter Local IntHostIP Local Message$ ;Clear out any left over data from a previous session and initialize this session BP_ClearSession() ;Directly convert the Host's IP into an integer, to test to see if the IP entered is simply a number (w/ no periods) IntHostIP = strHostIP If IntHostIP Then ;First, error check for valid IP's If Not(Instr(strHostIP, ".")) Then BP_UpdateLog ("Connection attempt aborted. Host IP is invalid.") Return BP_INVALIDHOSTIP% EndIf EndIf ;Now, convert the IP/Domain to an integer IntHostIP = BP_DotToInt(strHostIP);BP_ConvertDomain(strHostIP) BP_UpdateLog ("New connection attempt for " + ClientName + " on Port " + HostPort + ". Server: " + DottedIP(IntHostIP) + ":" + HostPort) ;Error check again If Not(IntHostIP) Then BP_UpdateLog ("Connection attempt aborted. Host IP is invalid.") Return BP_INVALIDHOSTIP% EndIf BP_Host = False BP_My_IP = BP_ConvertIp(BP_GetMyIP()) ;BP_My_Port = LocalPort BP_Host_IP = strHostIP;IntHostIP BP_Host_Port = HostPort ;Start connecting with BP_Host ENetInitialize() BP_UDP_Stream = ENetCreate(False,"",0,0,0,0) If BP_UDP_Stream Then DebugLog "BP_Host_IP = " + BP_Host_IP Local Connect = ENetConnect(BP_Host_IP,HostPort) If Connect DebugLog "Connected = " + Connect Message = Chr(254) + Chr(0) + Chr(1) + ClientName DebugLog "Message = " + (Chr(254) + Chr(0) + Chr(1) + ClientName) ENetSendData(Message,Len(Message),0,True) BP_NumPlayers = 255 Starttime = MilliSecs() Reason = 0 BP_Online = True ;Receive info on game session as well as other player information Repeat BP_UpdateNetwork () If (MilliSecs() - Starttime) > 15000 Then BP_Online = False Exit EndIf For msg.MsgInfo = Each MsgInfo If msg\msgType = 256 Then Reason = msg\msgData BP_Online = False Exit EndIf Next Counter = 0 For nInfo.NetInfo = Each NetInfo Counter = Counter + 1 Next If Counter = BP_NumPlayers Then Reason = BP_SUCCESS BP_Online = True Exit EndIf If KeyHit(1) Then Reason = BP_USERABORT BP_Online = False EndIf Until Reason If BP_Online Then nInfo.NetInfo = New NetInfo nInfo\Name = ClientName nInfo\Net_id = BP_My_ID nInfo\Alive = True BP_My_Name$ = ClientName Message = Chr(254) + Chr(0) + Chr(2) ENetSendData(Message,Len(Message),0,True) BP_NumPlayers = BP_NumPlayers + 1 Else ENetDeInitialize() BP_UDP_Stream = 0 EndIf Else BP_Online = False Reason = BP_NOREPLY ENetDeInitialize() EndIf Else BP_Online = False Reason = BP_PORTNOTAVAILABLE ENetDeInitialize() EndIf Return Reason End Function Function BP_KickID(id%, ban% = False) ;-=-=-=Kick an ID, maybe even ban 'em Local nInfo.NetInfo Local msg.MsgInfo If BP_My_ID = BP_Host_ID Then nInfo.NetInfo = BP_FindID (id) If nInfo<>Null And id <> BP_My_ID Then BP_UDPMessage (0, 249, Chr(id)+Chr(ban)) msg.MsgInfo = New MsgInfo msg\msgType = 252 msg\msgFrom = id msg\msgData = ban ; If ban Then ; BP_BanIP (nInfo\IP) ; If BP_Log Then BP_UpdateLog ("You banned: " + nInfo\Name) ; Else ; If BP_Log Then BP_UpdateLog ("You kicked: " + nInfo\Name) ; EndIf Delete nInfo BP_NumPlayers = BP_NumPlayers - 1 EndIf EndIf End Function Function BP_NextAvailID%() ;-=-=-=Find out the Next available ID # that is Not in use Local a.NetInfo Local testing Local foundit Local temp_array[256] For a.NetInfo = Each NetInfo temp_array[a\Net_id] = True Next For testing = 1 To BP_MaxPlayers If Not temp_array[testing] Then foundit = testing Exit EndIf Next Return foundit End Function Function BP_SetGameType(GameType%) ;-=-=-=Allows the user to control the numeric game type value If BP_My_ID = BP_Host_ID Then BP_GameType% = GameType% BP_UDPMessage (0,248,"1"+GameType) EndIf End Function Function BP_SetMaxPlayers(MaximumPlayers%) ;-=-=-=Allows the user to control the maximum allowable players If (BP_My_ID = BP_Host_ID) Then If MaximumPlayers > 255 Then MaximumPlayers = 255 If MaximumPlayers < 0 Then MaximumPlayers = 0 BP_MaxPlayers% = MaximumPlayers% BP_UDPMessage (0,248,"2"+MaximumPlayers) EndIf End Function Function BP_SetTimeoutPeriod(TimeoutPeriod%) ;-=-=-=Allows the user to set or change the TimeoutPeriod value BP_TimeoutPeriod% = TimeoutPeriod% End Function Function BP_SimulatePacketLoss(Odds%) ;-=-=-=Allows the user to control simulated packet loss BP_UDPdebug = Odds% End Function Function BP_StartLogFile(FileName$, Append% = True, Automatic% = True) ;-=-=-=Opens up the log file. Also, optionally appends to the file instead of overwriting. ;Will only start a log if there isn't one already, and if the filename is valid. If (Len(FileName$) > 0) And (BP_Log = 0) Then BP_LogFile$ = FileName$ BP_AutoLogging = Automatic ;Check to see if the file exists already If FileType(FileName$) = 1 Then Select Append ;If it does, check to see if we're going to append or overwrite Case True BP_Log = OpenFile (FileName$) SeekFile (BP_Log, FileSize(FileName$)) WriteLine BP_Log, "" Case False DeleteFile FileName$ BP_Log = WriteFile (FileName$) End Select Else BP_Log = WriteFile (FileName$) EndIf ;Now that the file is opened, insert the header information WriteLine BP_Log, "**Logging enabled at " + CurrentTime$() + " for " + BP_GetMyName() + "." If BP_Online Then WriteLine BP_Log, "Connection Status: Online Local IP/Port = " + DottedIP$(BP_GetMyIP()) + "/" + BP_GetMyPort() + " Host IP/Port = " + DottedIP$(BP_GetHostIP()) + "/" + BP_GetHostPort() Else WriteLine BP_Log, "Connection Status: Offline Local IP/Port = " + DottedIP$(BP_GetMyIP()) + "/" + BP_GetMyPort() + " Host IP/Port = " + DottedIP$(BP_GetHostIP()) + "/" + BP_GetHostPort() EndIf WriteLine BP_Log, "Current Session Stats: GameType = " + BP_GetGameType() + " NumPlayers = " + BP_GetNumberOfPlayers() + " Local ID/Host ID = " + BP_GetMyID() + "/" + BP_GetHostID() EndIf End Function Function BP_StopLogFile() ;-=-=-=Allows the user to stop the logfile If BP_Log WriteLine BP_Log, "**Logging stopped at " + CurrentTime$() + "." CloseFile BP_Log BP_Log = 0 EndIf BP_AutoLogging = False End Function Function BP_StrToInt%(st$) ;-=-=-=Take a String of any length and turn it into an integer again. Local shiftin% Local num% For shiftin = 0 To (Len (st$) - 1) num = num Or (Asc (Mid$ (st$, shiftin + 1, 1)) Shl shiftin * 8) Next Return num End Function Function BP_StrToFloat#(st$) ;-=-=-=Take a 4 byte string and turn it back into a floating point #. Local num#,i% For i = 0 To 3 PokeByte BP_CompressBank,i,Asc(Mid$(st$,i+1,1)) Next num# = PeekFloat(BP_CompressBank,0) Return num End Function Function BP_DotToInt%(ip$) Local off1=Instr(ip$,".") :Local ip1=Left$(ip$,off1-1) Local off2=Instr(ip$,".",off1+1):Local ip2=Mid$(ip$,off1+1,off2-off1-1) Local off3=Instr(ip$,".",off2+1):Local ip3=Mid$(ip$,off2+1,off3-off2-1) Local off4=Instr(ip$," ",off3+1):Local ip4=Mid$(ip$,off3+1,off4-off3-1) Return ip1 Shl 24 + ip2 Shl 16 + ip3 Shl 8 + ip4 End Function Function BP_UpdateNetwork() ;This is the -meat- of the library. ;Host mostly uses the eNet ID system for checking clients ;Client only uses the BlitzPlay ID system for checking ;-=-=-=Check for messages, disconnects, new players, and UDP resends. ;First lets get the variables defined as local to this function only Local CurTime Local MsgFrom,eNetID Local MsgType Local MsgTarget Local MsgToSend$ Local MsgData$ Local Counter Local Allowed Local KickedID Local Event ;***Check UDP Messages first If BP_Online If BP_Host ;[Block] Host's UpdateNetwork While( ENetDoEventCheck(0) > 0 ) Event = ENetCheckEvents(BP_Bank_PeerID,BP_Bank_DataSize,BP_Bank) If Event = 3 CurTime = MilliSecs () BP_TotRecvPacket = BP_TotRecvPacket + 1 eNetID = PeekInt(BP_Bank_PeerID,0) ;DebugLog "MsgData1 = " + MsgData MsgData = BP_ReturnMessage(BP_Bank,BP_Bank_DataSize) MsgType = Asc(Mid(MsgData,1,1)) MsgTarget = Asc(Mid(MsgData,2,1)) MsgData = Mid(MsgData,3,Len(MsgData)-2) ;DebugLog "eNetID = " + eNetID ;DebugLog "MsgData2 = " + MsgData ;DebugLog "MsgType = " + MsgType Local nInfo.NetInfo = BP_FindID(eNetID,True) If nInfo<>Null Then nInfo\LastHeard = CurTime : nInfo\Alive = True : MsgFrom = nInfo\Net_id;Make sure we don't timeout ;DebugLog "MsgFrom = " + MsgFrom Select MsgType Case 255 ;If it was a keep alive packet If nInfo <> Null Then nInfo\LastHeard = CurTime nInfo\Alive = True EndIf Case 254 ;A packet with connecting info for a new player Select Asc(MsgData) Case 1 Local c.Connecting = BP_FindConnect(eNetID,True) If c = Null Then ;New join! Time to see if we'll let 'em in ;check to see that they aren't banned ;allowed is the code that we assign to this connect ;1 = banned|2 = no room|4 = allowed! Allowed% = BP_SUCCESS Local ccount.Connecting ;make sure there's room, counting people in middle of connecting Counter = 0 For ccount.Connecting = Each Connecting Counter = Counter + 1 Next If (BP_NumPlayers + Counter) => BP_MaxPlayers Then Allowed = BP_GAMEISFULL If Allowed = BP_SUCCESS Then c.Connecting = New Connecting c\Name = Mid$ (MsgData,2) c\Net_id = BP_NextAvailID() c\eNet_id = eNetID c\LastHeard = CurTime MsgToSend = Chr(254) + Chr(BP_My_ID) + Chr(1) + Chr(c\Net_id) + Chr(BP_My_ID) + Chr(BP_NumPlayers) + Chr(BP_MaxPlayers) + Chr(BP_GameType) + Chr(BP_TimeoutPeriod/1000) ENetSendData(MsgToSend,Len(MsgToSend),c\eNet_id,True) For nInfo.NetInfo = Each NetInfo MsgToSend = Chr(254) + Chr(BP_My_ID) + Chr(2) + Chr(nInfo\Net_id) + nInfo\Name ENetSendData(MsgToSend,Len(MsgToSend),c\eNet_id,True) Next If BP_Log Then BP_UpdateLog (c\Name + " is attempting to join the game..") Else MsgToSend = Chr(254) + Chr(BP_My_ID) + Chr(3) + Chr(Allowed) ENetSendData(MsgToSend,Len(MsgToSend),eNetID,True) EndIf EndIf Case 2 c.Connecting = BP_FindConnect(eNetID,True) If c<>Null Then Local sendmsg$ = Chr(c\Net_id) + c\Name BP_UDPMessage (0,252,sendmsg) nInfo.NetInfo = New NetInfo nInfo\Name = c\Name nInfo\Net_id = c\Net_id nInfo\eNet_id = eNetID nInfo\LastHeard = CurTime nInfo\Alive = True Delete c Local msg.MsgInfo = New MsgInfo msg\msgType = 255 msg\msgFrom = nInfo\Net_id msg\msgData = nInfo\Name BP_NumPlayers = BP_NumPlayers + 1 If BP_Log Then BP_UpdateLog (nInfo\Name + " has joined the game ID #" + nInfo\Net_id) EndIf End Select Case 253 ;Someone has left the game nInfo.NetInfo = BP_FindID(Asc(MsgData)) ;Since this player is the Host, then tell everyone If nInfo<>Null Then ;else about it too Local disc_id = nInfo\Net_id msg.MsgInfo = New MsgInfo msg\msgData = True msg\msgType = BP_PLAYERHASLEFT msg\msgFrom = nInfo\Net_id If BP_Log Then BP_UpdateLog (nInfo\Name + " has left the game.") Delete nInfo BP_UDPMessage(0,253,Chr(disc_id) + Chr(True)) For c.Connecting = Each Connecting MsgToSend = Chr(253) + Chr(BP_My_ID) + Chr(disc_id) + Chr(True) ENetSendData(MsgToSend,Len(MsgToSend),c\eNet_id,True) Next BP_NumPlayers = BP_NumPlayers - 1 EndIf Case 252 ;Someone has successfully joined the game Case 251 ;The Host has disconnected Case 250 ;This was a "are you still there??" packet from someone. MsgToSend = Chr(255) + Chr(BP_My_ID) + "yup" ENetSendData(MsgToSend,Len(MsgToSend),eNetID,True) Case 249 ;Someone got kicked Default ;Nothing internal, a user packet. ***User Message Local nInfo2.NetInfo = nInfo If nInfo2 <> Null Then ;Do we recognize the sender? If MsgTarget <> BP_My_ID Then If MsgTarget = 0 Then ;If its a UDP broadcast.. MsgToSend = Chr(MsgType) + Chr(nInfo2\Net_id) + MsgData For nInfo.NetInfo = Each NetInfo If nInfo\Net_id <> BP_My_ID And nInfo\Net_id <> nInfo2\Net_id Then ENetSendData(MsgToSend,Len(MsgToSend),nInfo\eNet_id,True) EndIf Next Else ;Ah, a specific target. MsgToSend = Chr(MsgType) + Chr(nInfo2\Net_id) + MsgData nInfo.NetInfo = BP_FindID(MsgTarget) ENetSendData(MsgToSend,Len(MsgToSend),nInfo\eNet_id,True) EndIf EndIf If MsgTarget = 0 Or MsgTarget = BP_My_ID Then msg.MsgInfo = New MsgInfo msg\msgData = MsgData msg\msgType = MsgType msg\msgFrom = nInfo2\Net_id nInfo2\LastHeard = CurTime nInfo2\Alive = True If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfo2\Name,20) + " Type: " + LSet(MsgType,3) + " {" + MsgData$ + "}") EndIf Else Local msgq.UnrecMsgQueue = New UnrecMsgQueue msgq\msgData = MsgData msgq\msgType = MsgType msgq\Time = CurTime EndIf End Select Else Exit ;Ah finally done receiving UDP messages? Outta this loop then! EndIf Wend CurTime = MilliSecs () If BP_Online ;Have to check again because something *could* have made us offline in prev loop ;Now look through messages from unrecognized players and see if they've recently joined For msgq.UnrecMsgQueue = Each UnrecMsgQueue nInfo.NetInfo = BP_FindID(eNetID, True) If nInfo <> Null Then msg.MsgInfo = New MsgInfo msg\msgData = MsgData msg\msgType = MsgType msg\msgFrom = nInfo\Net_id If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfo\Name,20) + " Type: " + LSet(msg\msgType,3) + " {" + msg\msgData$ + "}") Delete msgq Else If (msgq\Time + 1000) < CurTime Then Delete msgq EndIf Next ;Check to see who might have been disconnected For nInfo.NetInfo = Each NetInfo If nInfo\Net_id <> BP_My_ID Then If ((nInfo\LastHeard + (BP_TimeoutPeriod / 2)) < CurTime) And (nInfo\Alive) Then ;It's been 5 secs? BP_UDPMessage (nInfo\Net_id, 250, "hello?") nInfo\Alive = False If BP_Log Then BP_UpdateLog (nInfo\Name + " hasn't been heard from in: " + (BP_TimeoutPeriod/1000) + " seconds. Testing to see if still connected.") EndIf If ((nInfo\LastHeard + BP_TimeoutPeriod) < CurTime) And (nInfo\Alive = False) Then ;It's been 10 secs!? disc_id = nInfo\Net_id msg.MsgInfo = New MsgInfo msg\msgType = BP_PLAYERHASLEFT msg\msgFrom = nInfo\Net_id msg\msgData = False BP_UDPMessage (disc_id,249,Chr(disc_id)) If BP_Log Then BP_UpdateLog (nInfo\Name + " has lagged out of the game.") Delete nInfo BP_UDPMessage (0,253,Chr(disc_id) + Chr(False)) BP_NumPlayers = BP_NumPlayers - 1 EndIf EndIf Next ;Scan through the list of people connecting, and see if we haven't heard from them in 10 secs For c.Connecting = Each Connecting If (c\LastHeard + BP_TimeoutPeriod) < CurTime Then ;It's been 10 secs!? If BP_Log Then BP_UpdateLog (c\Name + " didn't reply fast enough. Deleting from connecting queue.") Delete c EndIf Next EndIf ;[End] Else ;[Block] Client's UpdateNetwork While( ENetDoEventCheck(0) > 0 ) Event = ENetCheckEvents(BP_Bank_PeerID,BP_Bank_DataSize,BP_Bank) ;DebugLog "Event = " + Event If Event = 3 CurTime = MilliSecs () BP_TotRecvPacket = BP_TotRecvPacket + 1 eNetID = 0 ; Host MsgData = BP_ReturnMessage(BP_Bank,BP_Bank_DataSize) MsgType = Asc(Mid(MsgData,1,1)) MsgFrom = Asc(Mid(MsgData,2,1)) MsgData = Mid(MsgData,3,Len(MsgData)-2) CurTime = MilliSecs () nInfo.NetInfo = BP_FindID (BP_Host_ID) If nInfo<>Null Then nInfo\LastHeard = CurTime:nInfo\Alive = True BP_TotRecvPacket = BP_TotRecvPacket + 1 ;Msg will be in format: 123 1=Type|2=Sender|3=Data ;DebugLog "MsgData = " + MsgData ;DebugLog "MsgType = " + MsgType ;DebugLog "MsgFrom = " + MsgFrom Select MsgType Case 255 ;If it was a keep alive packet.. nInfo.NetInfo = BP_FindID(MsgFrom) If nInfo<>Null Then nInfo\LastHeard = CurTime nInfo\Alive = True EndIf Case 254 ;A packet with connecting info for a new player Select Asc(MsgData) Case 1 BP_My_ID = Asc(Mid$(MsgData,2)) BP_Host_ID = Asc(Mid$(MsgData,3)) BP_NumPlayers = Asc(Mid$(MsgData,4)) BP_MaxPlayers = Asc(Mid$(MsgData,5)) BP_GameType = Asc(Mid$(MsgData,6)) BP_TimeoutPeriod = Asc(Mid$(MsgData,7)) * 1000 Case 2 nInfo.NetInfo = BP_FindID(Asc(Mid$(MsgData,2))) If nInfo=Null Then MsgData = Mid$(MsgData,2) nInfo.NetInfo = New NetInfo nInfo\Net_id = Asc(Mid$(MsgData,1)) nInfo\Name = Mid$(MsgData,2) nInfo\Alive = True nInfo\LastHeard = CurTime msg.MsgInfo = New MsgInfo msg\msgType = 255 msg\msgFrom = nInfo\Net_id msg\msgData = nInfo\Name EndIf Case 3 Local reason% = Asc(Mid$(MsgData,2,1)) msg.MsgInfo = New MsgInfo msg\msgType = 256 msg\msgFrom = 0 msg\msgData = reason End Select Case 253 ;Someone has left the game nInfo.NetInfo = BP_FindID(Asc(MsgData)) ;If they're still in the game If nInfo<>Null Then msg.MsgInfo = New MsgInfo ;And make a new msg about it msg\msgData = Asc(Mid$(MsgData,2)) msg\msgType = 254 msg\msgFrom = nInfo\Net_id Delete nInfo BP_NumPlayers = BP_NumPlayers - 1 If BP_Log Then If msg\msgData Then BP_UpdateLog (nInfo\Name + " has left the game.") Else BP_UpdateLog (nInfo\Name + " has lagged out of the game." + nInfo\Net_id) EndIf EndIf Case 252 ;Someone has successfully joined the game CurTime = MilliSecs () nInfo.NetInfo = New NetInfo nInfo\Net_id = Asc(Mid$(MsgData,1)) nInfo\eNet_id = MsgFrom nInfo\Name = Mid$(MsgData,2) nInfo\LastHeard = CurTime nInfo\Alive = True BP_NumPlayers = BP_NumPlayers + 1 msg.MsgInfo = New MsgInfo msg\msgData = nInfo\Name msg\msgType = 255 msg\msgFrom = nInfo\Net_id If BP_Log Then BP_UpdateLog (nInfo\Name + " has joined the game w/ ID #" + nInfo\Net_id) Case 251 ;The Host has disconnected nInfo.NetInfo = BP_FindID(Asc(MsgData)) If nInfo<>Null Then BP_Online = False ENetDeInitialize() BP_UDP_Stream = 0 msg.MsgInfo = New MsgInfo msg\msgType = 253 msg\msgFrom = nInfo\Net_id msg\msgData = True If First NetInfo<>Null Then Delete Each NetInfo BP_NumPlayers = 0 EndIf If BP_Log Then BP_UpdateLog ("The Host ended the session.") Case 250 ;This was a "are you still there??" packet from someone. MsgToSend = Chr(255) + Chr(BP_My_ID) + "yup" ENetSendData(MsgToSend,Len(MsgToSend),0,True) Case 249 ;Someone got kicked KickedID = Asc(MsgData) nInfo.NetInfo = BP_FindID(KickedID) If nInfo <> Null Then msg.MsgInfo = New MsgInfo msg\msgType = 252 msg\msgFrom = nInfo\Net_id msg\msgData = Asc(Mid$(MsgData,2)) If BP_Log Then If msg\msgData Then BP_UpdateLog (nInfo\Name + " was banned") Else BP_UpdateLog (nInfo\Name + " was kicked") EndIf If KickedID = BP_My_ID Then If First NetInfo<>Null Then Delete Each NetInfo BP_Online = False ENetDeInitialize() BP_UDP_Stream = 0 BP_NumPlayers = 0 Return Else Delete nInfo BP_NumPlayers = BP_NumPlayers - 1 EndIf EndIf Case 248 Select Asc(MsgData) Case 1 BP_GameType = Asc(Mid$(MsgData,2)) Case 2 BP_MaxPlayers = Asc(Mid$(MsgData,2)) End Select Default ;Nothing 'special' nInfo.NetInfo = BP_FindID(MsgFrom) CurTime = MilliSecs () If nInfo <> Null Then msg.MsgInfo = New MsgInfo msg\msgData = MsgData msg\msgType = MsgType msg\msgFrom = MsgFrom nInfo\LastHeard = CurTime nInfo\Alive = True If BP_AutoLogging Then BP_UpdateLog ("[Incoming] UDP From: " + LSet(nInfo\Name,20) + " Type: " + LSet(MsgType,3) + " {" + MsgData$ + "}") Else msgq.UnrecMsgQueue = New UnrecMsgQueue msgq\msgData = MsgData msgq\msgType = MsgType msgq\Net_id = MsgFrom msgq\Time = CurTime EndIf End Select Else Exit ;Ah finally done receiving messages? Outta this loop then! EndIf Wend If BP_Online ;Have to check again because something *could* have made us offline in prev loop CurTime = MilliSecs () ;Now look through messages from unrecognized players and see if they've recently joined For msgq.UnrecMsgQueue = Each UnrecMsgQueue nInfo.NetInfo = BP_FindID(msgq\Net_id) If nInfo <> Null Then msg.MsgInfo = New MsgInfo msg\msgData = MsgData msg\msgType = MsgType msg\msgFrom = nInfo\Net_id If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfo\Name,20) + " Type: " + LSet(msg\msgType,3) + " {" + msg\msgData$ + "}") Delete msgq Else If (msgq\Time + 1000) < CurTime Then Delete msgq EndIf Next ;Check for disconnection from Host nInfo.NetInfo = BP_FindID (BP_Host_ID) If nInfo<>Null If ((nInfo\LastHeard + (BP_TimeoutPeriod/2)) < CurTime) And (nInfo\Alive) Then ;It's been awhile.. BP_UDPMessage (nInfo\Net_id, 250, "hello?") nInfo\Alive = False EndIf If ((nInfo\LastHeard + BP_TimeoutPeriod) < CurTime) And (nInfo\Alive = False) Then ;It's been BP_TimeoutPeriod secs!? BP_Online = False ENetDeInitialize() BP_UDP_Stream = 0 msg.MsgInfo = New MsgInfo msg\msgType = 253 msg\msgFrom = nInfo\Net_id Delete Each NetInfo BP_NumPlayers = 0 If BP_Log Then BP_UpdateLog ("Host hasn't replied in " + (BP_TimeoutPeriod/1000) + " seconds, game ended") EndIf EndIf;If nInfo<>Null EndIf;If BP_Online ;[End] EndIf EndIf End Function Function BP_UDPMessage(msgTarget%, msgType%, msgData$,reliable=True) Local a.NetInfo ;-=-=-=Prepare a UDP message to send. If BP_Online ;Insert the message type If BP_Host If msgTarget = 0 Then ;If its a UDP broadcast.. msgData = Chr(msgType) + Chr(BP_My_ID) + msgData For a.NetInfo = Each NetInfo If a\Net_id <> BP_My_ID Then If BP_AutoLogging Then BP_UpdateLog ("[Outgoing] UDP To: " + LSet(a\Name,20) + " Type: " + LSet(msgType,3) + " {" + msgData + "}") ENetSendData(msgData,Len(msgData),a\eNet_id,reliable) EndIf Next Else ;Ah, a specific target. msgData = Chr(msgType) + Chr(BP_My_ID) + msgData a.NetInfo = BP_FindID(msgTarget) If BP_AutoLogging Then BP_UpdateLog ("[Outgoing] UDP To: " + LSet(a\Name,20) + " Type: " + LSet(msgType,3) + " {" + msgData + "}") ENetSendData(msgData,Len(msgData),a\eNet_id,reliable) EndIf Else ;Client doing a send msgData = Chr(msgType) + Chr(msgTarget) + msgData If BP_AutoLogging Then BP_UpdateLog ("[Outgoing] UDP To: " + msgTarget + " Type: " + LSet(msgType,3) + " {" + msgData + "}") ENetSendData(msgData,Len(msgData),0,reliable) EndIf EndIf End Function Function BP_ReturnMessage$(bank,dataSize) Local Message$ Local size = PeekInt(dataSize, 0)-1 For n = 0 To size-1 Message = Message + Chr(PeekByte(bank, n)) Next Return Message End Function Function BP_UpdateLog(txt$) ;-=-=-=Updates the log file, checks to see if its been started If BP_Log Then WriteLine BP_Log, txt$ EndIf End Function |
Comments
None.
Code Archives Forum