[bb] BlitzPlay Lite + eNet by GIB3D [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:38

Previous topic - Next topic

BlitzBot

Title : BlitzPlay Lite + eNet
Author : GIB3D
Posted : 1+ years ago

Description : Links
eNet - <a href="http://enet.bespin.org/" target="_blank">http://enet.bespin.org/</a>
Original BlitzPlay Lite - <a href="http://members.shaw.ca/blitzplay/BPlitev1.14.zip" target="_blank">http://members.shaw.ca/blitzplay/BPlitev1.14.zip</a>

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.


Code :
Code: blitzbasic
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-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 aeNet_id = id Then Return a
		Else
			If aNet_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 aeNet_id = id Then Return a
		Else
			If aNet_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 aNet_id = ID Then Return aName$
	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
	nInfoName = HostName
	BP_My_Name = HostName
	BP_My_ID = 1
	nInfoNet_id = 1
	nInfoeNet_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 msgmsgType = 256 Then
						Reason = msgmsgData
						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
				nInfoName = ClientName
				nInfoNet_id = BP_My_ID
				nInfoAlive = 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
			msgmsgType = 252
			msgmsgFrom = id
			msgmsgData = ban
;			If ban Then
;				BP_BanIP (nInfoIP)
;				If BP_Log Then BP_UpdateLog ("You banned: " + nInfoName)
;			Else
;				If BP_Log Then BP_UpdateLog ("You kicked: " + nInfoName)
;			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[aNet_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 nInfoLastHeard = CurTime : nInfoAlive = True : MsgFrom = nInfoNet_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
								nInfoLastHeard = CurTime
								nInfoAlive = 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
											cName = Mid$ (MsgData,2)
											cNet_id = BP_NextAvailID()
											ceNet_id = eNetID
											cLastHeard = CurTime
											MsgToSend = Chr(254) + Chr(BP_My_ID) + Chr(1) + Chr(cNet_id) + Chr(BP_My_ID) + Chr(BP_NumPlayers) + Chr(BP_MaxPlayers) + Chr(BP_GameType) + Chr(BP_TimeoutPeriod/1000)
											ENetSendData(MsgToSend,Len(MsgToSend),ceNet_id,True)
											
											For nInfo.NetInfo = Each NetInfo
												MsgToSend = Chr(254) + Chr(BP_My_ID) + Chr(2) +  Chr(nInfoNet_id) + nInfoName
												ENetSendData(MsgToSend,Len(MsgToSend),ceNet_id,True)
											Next
											If BP_Log Then BP_UpdateLog (cName + " 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(cNet_id) + cName
										BP_UDPMessage (0,252,sendmsg)
										nInfo.NetInfo = New NetInfo
										nInfoName = cName
										nInfoNet_id = cNet_id
										nInfoeNet_id = eNetID
										nInfoLastHeard = CurTime
										nInfoAlive = True
										Delete c
										Local msg.MsgInfo = New MsgInfo
										msgmsgType = 255
										msgmsgFrom = nInfoNet_id
										msgmsgData = nInfoName
										BP_NumPlayers = BP_NumPlayers + 1
										If BP_Log Then BP_UpdateLog (nInfoName + " has joined the game  ID #" + nInfoNet_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 = nInfoNet_id
								msg.MsgInfo = New MsgInfo
								msgmsgData = True
								msgmsgType = BP_PLAYERHASLEFT
								msgmsgFrom = nInfoNet_id
								If BP_Log Then BP_UpdateLog (nInfoName + " 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),ceNet_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(nInfo2Net_id) + MsgData
										For nInfo.NetInfo = Each NetInfo
											If nInfoNet_id <> BP_My_ID And nInfoNet_id <> nInfo2Net_id Then
												ENetSendData(MsgToSend,Len(MsgToSend),nInfoeNet_id,True)
											EndIf
										Next
									Else							;Ah, a specific target.
										MsgToSend = Chr(MsgType) + Chr(nInfo2Net_id) + MsgData
										nInfo.NetInfo = BP_FindID(MsgTarget)
										ENetSendData(MsgToSend,Len(MsgToSend),nInfoeNet_id,True)
									EndIf
								EndIf
								
								If MsgTarget = 0 Or MsgTarget = BP_My_ID Then
									msg.MsgInfo = New MsgInfo
									msgmsgData = MsgData
									msgmsgType = MsgType
									msgmsgFrom = nInfo2Net_id
									nInfo2LastHeard = CurTime
									nInfo2Alive = True
									If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfo2Name,20) + " Type: " + LSet(MsgType,3) + " {" + MsgData$ + "}")
								EndIf
							Else
								Local msgq.UnrecMsgQueue = New UnrecMsgQueue
								msgqmsgData = MsgData
								msgqmsgType = MsgType
								msgqTime = 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
						msgmsgData = MsgData
						msgmsgType = MsgType
						msgmsgFrom = nInfoNet_id
						If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfoName,20) + " Type: " + LSet(msgmsgType,3) + " {" + msgmsgData$ + "}")
						Delete msgq
					Else
						If (msgqTime + 1000) < CurTime Then Delete msgq
					EndIf
				Next
				
				;Check to see who might have been disconnected
				For nInfo.NetInfo = Each NetInfo
					If nInfoNet_id <> BP_My_ID Then
						If ((nInfoLastHeard + (BP_TimeoutPeriod / 2)) < CurTime) And (nInfoAlive) Then	;It's been 5 secs?
							BP_UDPMessage (nInfoNet_id, 250, "hello?")
							nInfoAlive = False
							If BP_Log Then BP_UpdateLog (nInfoName + " hasn't been heard from in: " + (BP_TimeoutPeriod/1000) + " seconds. Testing to see if still connected.")
						EndIf
						If ((nInfoLastHeard + BP_TimeoutPeriod) < CurTime) And (nInfoAlive = False) Then					;It's been 10 secs!?
							disc_id = nInfoNet_id
							msg.MsgInfo = New MsgInfo
							msgmsgType = BP_PLAYERHASLEFT
							msgmsgFrom = nInfoNet_id
							msgmsgData = False
							BP_UDPMessage (disc_id,249,Chr(disc_id))
							If BP_Log Then BP_UpdateLog (nInfoName + " 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 (cLastHeard + BP_TimeoutPeriod) < CurTime Then						;It's been 10 secs!?
						If BP_Log Then BP_UpdateLog (cName + " 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 nInfoLastHeard = CurTime:nInfoAlive = 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
								nInfoLastHeard = CurTime
								nInfoAlive = 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
										nInfoNet_id = Asc(Mid$(MsgData,1))
										nInfoName = Mid$(MsgData,2)
										nInfoAlive = True
										nInfoLastHeard = CurTime
										msg.MsgInfo = New MsgInfo
										msgmsgType = 255
										msgmsgFrom = nInfoNet_id
										msgmsgData = nInfoName
									EndIf
									
								Case 3
									Local reason% = Asc(Mid$(MsgData,2,1))
									msg.MsgInfo = New MsgInfo
									msgmsgType = 256
									msgmsgFrom = 0
									msgmsgData = 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
								msgmsgData = Asc(Mid$(MsgData,2))
								msgmsgType = 254
								msgmsgFrom = nInfoNet_id
								Delete nInfo
								BP_NumPlayers = BP_NumPlayers - 1
								If BP_Log Then
									If msgmsgData Then BP_UpdateLog (nInfoName + " has left the game.") Else BP_UpdateLog (nInfoName + " has lagged out of the game." + nInfoNet_id)
								EndIf
							EndIf
							
						Case 252		;Someone has successfully joined the game
							CurTime = MilliSecs ()
							nInfo.NetInfo = New NetInfo
							nInfoNet_id = Asc(Mid$(MsgData,1))
							nInfoeNet_id = MsgFrom
							nInfoName = Mid$(MsgData,2)
							nInfoLastHeard = CurTime
							nInfoAlive = True
							BP_NumPlayers = BP_NumPlayers + 1
							msg.MsgInfo = New MsgInfo
							msgmsgData = nInfoName
							msgmsgType = 255
							msgmsgFrom = nInfoNet_id
							If BP_Log Then BP_UpdateLog (nInfoName + " has joined the game w/ ID #" + nInfoNet_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
								msgmsgType = 253
								msgmsgFrom = nInfoNet_id
								msgmsgData = 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
								msgmsgType = 252
								msgmsgFrom = nInfoNet_id
								msgmsgData = Asc(Mid$(MsgData,2))
								
								If BP_Log Then
									If msgmsgData Then BP_UpdateLog (nInfoName + " was banned") Else BP_UpdateLog (nInfoName + " 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
								msgmsgData = MsgData
								msgmsgType = MsgType
								msgmsgFrom = MsgFrom
								nInfoLastHeard = CurTime
								nInfoAlive = True
								If BP_AutoLogging Then BP_UpdateLog ("[Incoming] UDP From: " + LSet(nInfoName,20) + " Type: " + LSet(MsgType,3) + " {" + MsgData$ + "}")
							Else
								msgq.UnrecMsgQueue = New UnrecMsgQueue
								msgqmsgData = MsgData
								msgqmsgType = MsgType
								msgqNet_id = MsgFrom
								msgqTime = 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(msgqNet_id)
					If nInfo <> Null Then
						msg.MsgInfo = New MsgInfo
						msgmsgData = MsgData
						msgmsgType = MsgType
						msgmsgFrom = nInfoNet_id
						If BP_AutoLogging Then BP_UpdateLog ("[Incoming] From: " + LSet(nInfoName,20) + " Type: " + LSet(msgmsgType,3) + " {" + msgmsgData$ + "}")
						Delete msgq
					Else
						If (msgqTime + 1000) < CurTime Then Delete msgq
					EndIf
				Next		
				
				;Check for disconnection from Host
				nInfo.NetInfo = BP_FindID (BP_Host_ID)
				If nInfo<>Null
					If ((nInfoLastHeard + (BP_TimeoutPeriod/2)) < CurTime) And (nInfoAlive) Then	;It's been awhile..
						BP_UDPMessage (nInfoNet_id, 250, "hello?")
						nInfoAlive = False
					EndIf
					If ((nInfoLastHeard + BP_TimeoutPeriod) < CurTime) And (nInfoAlive = False) Then	;It's been BP_TimeoutPeriod secs!?
						BP_Online = False
						ENetDeInitialize()
						BP_UDP_Stream = 0
						msg.MsgInfo = New MsgInfo
						msgmsgType = 253
						msgmsgFrom = nInfoNet_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 aNet_id <> BP_My_ID Then
						If BP_AutoLogging Then BP_UpdateLog ("[Outgoing] UDP   To: " + LSet(aName,20) + " Type: " + LSet(msgType,3) + " {" + msgData + "}")
						ENetSendData(msgData,Len(msgData),aeNet_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(aName,20) + " Type: " + LSet(msgType,3) + " {" + msgData + "}")
				ENetSendData(msgData,Len(msgData),aeNet_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...

Rick Nasher

Bit of a pity there's no demo on how to actually use this..
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RonTek

Hey Rick,

I was into Blitz3D networking for quite a bit and think I have managed to save a copy of the demo included in the zip download before it became unavailable.

Let me know if this works :)

Code: blitzbasic
Include "BPlite.bb"
Const kUp% = 200, KDown% = 208, KLeft% = 203, KRight% = 205, fps% = 40, KF1% = 59, KF11% = 87
Const kShift% = 42, KTab% = 15
Global send_freq% = 4, chat$
Global width% = 400, height% = 100
Global logging% = False
Global myname$
Global sendupdates% = True
Global DebugInfo% = 0
Global WindowCount% = 0
Global fullscreen%
Global Host%

Type pdata
Field x#,y#,r#,name$,net_id%
Field xvel#,yvel#,rvel#
End Type

Type Info
Field txt$
End Type

tmr = CreateTimer(fps)
SeedRnd MilliSecs()


Graphics width,height,16,2
AppTitle "BlitzPlay - Lite Demo"

ClsColor 10,15,30
Cls
Color 100,150,100
Text 0,0,"Would you like to:"
Text 20,FontHeight()*2,"[H]ost a game"
Text 10,FontHeight()*3,"or"
Text 20,FontHeight()*4,"[J]oin one in progress?"

FlushKeys()
Repeat
If KeyHit(35) Then
Host = True
Exit
End If
If KeyHit(36) Then
Host = False
Exit
End If
Forever

Cls
FlushKeys
myname$ = Input$ ("Your name? ")
FlushKeys
fullscreen = Input$ ("Run fullscreen? (0=false,1=true)")
width = 800
height = 600
If Host Then
If Not fullscreen Then
width = 600
height = 600
End If
My_Port = 2222
If Not BP_HostSession (myname,10,1,2222,10) Then
Cls
Locate 0,0
Print "Host port was unavailable..Push a key to exit.."
WaitKey
End
End If
p.pdata = New pdata
p\name = myname
p\x = width/2
p\y = height/2
p\r = 90
p\net_id = BP_My_ID
Else
Print "Host port = 2222"
Print "(Blank for Local IP)"
IP$ = Input$("Please enter the host's IP? ")
Select IP
Case ""
IP$ = "127.0.0.1"
My_Port = Rand(3000,4000)
If Not fullscreen Then
width = 600
height = 200
End If
Default
My_Port = Input$ ("What port would you like to use? ")
If Not My_Port Then My_Port = Rand (3000,4000)
If Not fullscreen
width = 600
height = 600
End If
End Select
Cls
Text 200,50,"Connecting! (Hit [esc] to cancel)",True,True
Select BP_JoinSession (myname,2222,IP)
;Handle any of the reasons if we couldn't join.
Case BP_NOREPLY
Cls
Text 0,0,"No reply in specified timeout period.. exiting"
WaitKey
End
Case BP_IAMBANNED
Cls
Text 0,0,"You have been banned from joining this game.. exiting"
WaitKey
End
Case BP_GAMEISFULL
Cls
Text 0,0,"The game is full.. exiting"
WaitKey
End
Case BP_PORTNOTAVAILABLE
Cls
Text 0,0,"Port: " + My_Port + " was not available.. exiting"
WaitKey
End
Case BP_USERABORT
Cls
Text 0,0,"Connection attempt aborted!"
WaitKey
End
End Select
;Oh, we're allowed in? here we go!
p.pdata = New pdata
p\name = myname
p\x = width/2
p\y = height/2
p\r = 90
p\net_id = BP_My_ID
End If

If fullscreen Then Graphics width,height,32,1 Else Graphics width,height,16,2
ClsColor 10,15,30
Cls
SetBuffer BackBuffer()

While Not KeyHit(1)
frames = WaitTimer(tmr)
For k = 1 To frames
BP_UpdateNetwork()
HandleMessages()
UpdatePlayers()
send_count = send_count - 1
If send_count <= 0 Then
send_count = send_freq
p.pdata = First pdata
msgtosend$ = BP_IntToStr(Int(p\x),2) + BP_IntToStr(Int(p\y),2) + BP_IntToStr(Int(p\r),2)
If sendupdates Then BP_UDPMessage (0,1,msgtosend)
End If
Next
RenderAll()
Wend

BP_EndSession ()

End
;******************************Functions*******************************
Function HandleMessages ()
For msg.MsgInfo = Each MsgInfo
Select msg\msgType
Case 255 ;A new player has joined!
p.pdata = New pdata
p\name = msg\msgData
p\x = width/2
p\y = height/2
p\r = 90
p\net_id = msg\msgFrom
nInfo.NetInfo = BP_FindID(p\net_id)
Info ("**" + p\Name + " has joined!")
Case 254 ;A player has left
p.pdata = Find_pdata(msg\msgFrom)
If p<>Null Then
If msg\msgData = True Then Info ("**" + p\Name + " has left!") Else Info ("**" + p\Name + " lagged out!")
Delete p
End If
Case 253 ;The host has disconnected
For p.pdata = Each pdata
If p\net_id <> BP_My_ID Then Delete p
Next
If msg\msgData = True Then Info ("**The host ended the game!") Else Info ("**No reply from host in " + (BP_TimeoutPeriod / 1000) + " seconds. Exiting game..")
Case 252 ;Someone got kicked/banned
p.pdata = Find_pdata(msg\msgFrom)
If p\net_id = BP_My_ID Then ;It was -me-??
If msg\msgData = False Then Info ("**You have been kicked!") Else Info ("**You have been banned!")
For p.pdata = Each pdata
If p\net_id <> BP_My_ID Then
Delete p
End If
Next
Else ;It wasn't? Ok then.
If msg\msgData = False Then Info ("**" + p\Name + " has been kicked!") Else Info ("**" + p\Name + " has been banned!")
Delete p
End If
Case 1 ;a position update packet
newx% = BP_StrToInt (Mid$(msg\msgData,1,2))
newy% = BP_StrToInt (Mid$(msg\msgData,3,2))
newr% = BP_StrToInt (Mid$(msg\msgData,5,2))
p.pdata = Find_pdata(msg\msgFrom)
;This demo handles movement by calculating an average speed to bring the player to the point indicated
;in the packet by the time we think the next update should arrive.
;This is fairly accurate in describing where the player moved, at one point, but unfortunately is not very
;accurate for predicting where the player is "now" so to speak.
p\xvel = (newx - p\x) / send_freq
p\yvel = (newy - p\y) / send_freq
p\rvel = rotarydir(p\r,newr,send_freq)
Case 2 ;a chat packet
p.pdata = Find_pdata(msg\msgFrom)
Info (p\Name + ":" + msg\msgData)
End Select
Delete msg
Next
End Function

Function Info (t$)
i.Info=New Info
i\txt$=t$
Insert i Before First Info
End Function

Function UpdatePlayers ()
For p.pdata = Each pdata
If p\net_id = BP_My_ID Then
p\xvel = 0
p\yvel = 0
;'Ship' control
If KeyDown(KUp) Then
p\xvel = Cos(p\r) * 3
p\yvel = -Sin(p\r) * 3
End If
If KeyDown(KDown) Then
p\xvel = Cos(p\r + 180) * 3
p\yvel = -Sin(p\r + 180) * 3
End If
If KeyDown(KRight) Then
p\r = p\r - 5
If p\r < 0 Then p\r = p\r + 360
End If
If KeyDown(KLeft) Then
p\r = p\r + 5
If p\r > 360 Then p\r = p\r - 360
End If
;Other input
If KeyHit(KF1) Then
logging = 1 - logging
If logging Then
BP_StartLogFile (myname + ".txt")
Else
BP_StopLogFile ()
End If
End If
If BP_My_ID = BP_Host_ID
For keycheck = 60 To 68
If KeyHit(keycheck) Then
If keycheck - 58 <> My_ID Then ;No kicking yourself!
If KeyDown(kShift) Then
nInfo.NetInfo = BP_FindID(keycheck - 58)
If nInfo<>Null Then
Info("**You banned: " + nInfo\Name)
BP_KickID(keycheck - 58, True)
End If
Else
nInfo.NetInfo = BP_FindID(keycheck - 58)
If nInfo<>Null Then
Info("**You kicked: " + nInfo\Name)
BP_KickID(keycheck - 58, False)
End If
End If
End If
End If
Next
End If
If KeyHit(KF11) Then
sendupdates = 1 - sendupdates
End If
If KeyDown(KTab) Then DebugInfo = 1 Else DebugInfo = 0
;Chat
key=GetKey()
If key
If key=13
If chat$<>"" Then
BP_UDPMessage (0,2,chat$)
Info (p\name + ":" + chat)
chat$=""
End If
Else If key=8
If Len(chat$)>0 Then chat$=Left$(chat$,Len(chat$)-1)
Else If key>=32 And key<127
chat$=chat$+Chr$(key)
EndIf
EndIf
p\y = p\y + p\yvel
p\x = p\x + p\xvel
p\r = p\r + p\rvel
If p\y > height Then p\y = height
If p\y < 0 Then p\y = 0
If p\x > width Then p\x = width
If p\x < 0 Then p\x = 0
Else
p\y = p\y + p\yvel
p\x = p\x + p\xvel
p\r = p\r + p\rvel
If p\y > height Then p\y = height
If p\y < 0 Then p\y = 0
If p\x > width Then p\x = width
If p\x < 0 Then p\x = 0
If p\r < 0 Then p\r = p\r + 360
If p\r > 360 Then p\r = p\r - 360
End If
Next
End Function

Function RenderAll ()
Local st$
Local counter%
For p.pdata = Each pdata
counter = counter + 1
Next
Color 100,100,100
Rect 0,FontHeight()*2,width,FontHeight()*(counter) + 1,False
Color 10,10,50
Rect 1,(FontHeight()*2)+1,width-2,FontHeight()*(counter) - 1,True
textcounter = 2
Color 20,150,150
Text width/2,0,"-=[BlitzPlay - Lite Demo]=-",True
For p.pdata = Each pdata
If p\net_id = BP_My_ID Then
Text 1,FontHeight()*textcounter, p\net_id + "] " + "**" + p\name + "**"
Else
Text 1,FontHeight()*textcounter, p\net_id + "] " + p\name
End If
st$ = "X/Y: " + Int(p\x) + "/" + Int(p\y)
Text width-StringWidth(st$),FontHeight()*textcounter,st$
textcounter = textcounter + 1
Next
Color 0,200,50
textcounter = textcounter + 1
Text 0,FontHeight()*textcounter, ">" + chat$ + "_"
textcounter = textcounter + 1
counter = 0
Color 150,150,150
For i.Info = Each Info
counter = counter + 1
If counter > 15 Then
Delete i
Else
Text 0,FontHeight()*textcounter, i\txt
textcounter = textcounter + 1
End If
Next

Color 0,140,160
If logging Then Text 0,height-FontHeight(),"Logging: Enabled    (f1 to toggle)" Else Text 0,height-FontHeight(),"Logging: Disabled   (f1 to toggle)"
If sendupdates Then Text 0,height-FontHeight()*2,"Sending updates: True    (f11 to toggle)" Else Text 0,height-FontHeight()*2,"Sending updates: False  (f11 to toggle)"
Text 0,height-FontHeight()*3,"[TAB] displays debug information",False, False
If host Then Text 0,height-FontHeight()*4,"F2-10 to boot that player, hold [SHIFT] to ban"

For p.pdata = Each pdata
x1=p\x+Cos(p\r)*8
y1=p\y-Sin(p\r)*8
x2=p\x+Cos(p\r+150)*8
y2=p\y-Sin(p\r+150)*8
x3=p\x+Cos(p\r-150)*8
y3=p\y-Sin(p\r-150)*8

Color 100,100,100
Line x1,y1,x2,y2:Line x2,y2,x3,y3:Line x3,y3,x1,y1

Color 150,20,0
Text p\x+12,p\y,p\name,0,1
Next

If DebugInfo Then
p.pdata = First pdata
Color 40,100,150
Rect (width/2) - WindowCount - 1,(height/2)-51,(WindowCount * 2) + 2, 102,False
Color WindowCount/4,WindowCount/3,WindowCount/2
Rect (width/2) - WindowCount,(height/2)-50,WindowCount * 2, 100,True
If WindowCount < 210 Then
WindowCount = WindowCount + 10
If WindowCount > 210 Then WindowCount = 210
Else
If BP_Online Then
Color 100,200,100
Text (width/2) - WindowCount,(height/2)-50,"Online",False,False
Else
Color 200,50,50
Text (width/2) - WindowCount,(height/2)-50,"Offline",False,False
End If

Color 200,200,200

st$ = "-=[" + p\Name + "]=-"
Text (width/2),(height/2) - (FontHeight() * 3),st$,True,True

st$ = "GameType: " + BP_GetGameType()
Text (width/2) - (WindowCount),(height/2) - FontHeight(),st$,False,True
st$ = "TimeoutPeriod: " + BP_GetTimeoutPeriod() + "s."
Text (width/2) - (WindowCount),(height/2),st$,False,True
st$ = "My IP: " + BP_GetMyIP()
Text (width/2) - (WindowCount),(height/2) + FontHeight(),st$,False,True
st$ = "Host IP: " + DottedIP$(BP_GetHostIP())
Text (width/2) - (WindowCount),(height/2) + (FontHeight() * 2),st$,False,True

st$ = "# Of Players: " + BP_GetNumberOfPlayers()
Text (width/2),(height/2) - FontHeight(),st$,False,True
st$ = "Max. # Of Players: " + BP_GetMaxPlayers()
Text (width/2),(height/2),st$,False,True
st$ = "Packets Sent: " + BP_GetPacketsSent()
Text (width/2),(height/2) + FontHeight(),st$,False,True
st$ = "Packets Received: " + BP_GetPacketsReceived()
Text (width/2),(height/2) + (FontHeight() * 2),st$,False,True
End If
Else
If WindowCount > 0 Then
Color 40,100,150
Rect (width/2) - WindowCount - 1,(height/2)-51,(WindowCount * 2) + 2, 102,False
Color WindowCount/4,WindowCount/3,WindowCount/2
Rect (width/2) - WindowCount,(height/2)-50,WindowCount * 2, 100,True
WindowCount = WindowCount - 10
If WindowCount < 0 Then WindowCount = 0
End If
End If
Flip
Cls
End Function

Function Find_pdata.pdata (ID)
For p.pdata = Each pdata
If p\net_id = ID Then Return p
Next
End Function

Function rotarydir#(Asource#,Adest#,smooth#) ;Taken from the Code Archives on blitzbasic.com,
If Asource#>Adest# ;Thanks Skully!
Diff1#=Asource-Adest
diff2#=(360.0-Asource)+Adest
If diff2<diff1
dir#=diff2/smooth
Else
dir#=diff1/smooth*-1
EndIf
Else
If Asource#<Adest#
diff1=Adest-Asource
diff2=(360.0-Adest)+Asource
If diff2<diff1
dir#=diff2/smooth*-1
Else
dir#=diff1/smooth
EndIf
Else
dir=0
EndIf
EndIf
Return dir
End Function

Rick Nasher

#3
Many thanks RonTek. First brief test(running low on time here, in the mids of home construction) appears to work fine, besides the little bit of jerky movement, but reliable networking is very BIG plus. 8)

(I wasn't fully aware of the fact that this would just replace some of the BPLite networking and transparently making it reliable.)

2 Questions:
1) Is there an easy way to smooth the movement using BPLite? I want to use this in a 3d environment and I think it would require something known as interpolation but I'm under the impression that's part of the Pro version(which is unobtainable apparently).

2) Do you happened to know if BPLite also allows for host switching on the fly? So that if for instance in a game of 4 players the host(Player1) leaves and then gets replaced by Player2(or the player who's IP is best and longest in the game), effectively making him the new host so the game can continue?
*)I forsee some issues implementing this using the BlitzPlay+eNet version as the creator mentions:
QuoteSome 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.


I would really like this feature for it greatly enhances the continuity without the need for a dedicated server, making ad-hoc gaming possible.
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________

RonTek

Sure thing Rick. :) I have not checked with the demo code thoroughly, but I see some other network libraries that does interpolation. As for the host switching, I'm not quite sure but I think it is possible.

Quote
I would really like this feature for it greatly enhances the continuity without the need for a dedicated server, making ad-hoc gaming possible.

That would be using P2P and looks like WebRTC is the future and one solution that can do the job.  :D

GW

It looks like the BP example is sending location information each step.  You might get better results if you send just the remote key-press events and update objects in the client locally that way. That's how most modern games work.

Rick Nasher

Quote from: GW on July 20, 2017, 15:46:52
It looks like the BP example is sending location information each step.  You might get better results if you send just the remote key-press events and update objects in the client locally that way. That's how most modern games work.
That indeed would make more sense. And then check for other events that influence positions, rotation and states and only update when required.
_______________________________________
B3D + physics + shaders + X-platform = AGK!
:D ..ALIENBREED *LIVES* (thanks to Qube).. :D
_______________________________________