[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) Select
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-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) Select
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
_______________________________________