Online game BlitzMax?

Started by Yue, October 28, 2017, 17:00:25

Previous topic - Next topic

Yue

Hello, is there a module for BlitzMax to run network games?


Yue

Hi, error here makemods here.

Build Error: failed to compile C:/BlitzMax/mod/vertex.mod/bnetex.mod/windows.c

Derron

Of course it needs MinGW to be installed...




Also BNetEx is no longer compatible to BlitzMax NG (some void/int-thingies as it extends the now modified TStream class). There might have been other issues (I already resolved most of them in my game).




bye
Ron

EdzUp

Have a look at this I dont know if it will help?

'
' EdzUpNetworkSystem.bmx - Copyright ©EdzUp
' Programmed by Ed 'EdzUp' Upton
'

SuperStrict
Import BRL.LinkedList
Import BRL.System
Import BRL.Socket
Import BRL.SocketStream
Import BRL.Retro
Import MaxGUI.MaxGUI
Import BRL.EventQueue
Import BRL.PNGLoader

' modules which may be required:
' Import BRL.BMPLoader
' Import BRL.TGALoader
' Import BRL.JPGLoader

'network variables
Global LocalSocket:TSocket = Null 'local socket for data transfer
Global LocalStream:TSocketStream = Null 'local stream for data transfer
Global LocalBuffer:String = "" 'the local streams buffer
Global EdzUpNetwork_Connected:Byte = False 'true if networking is up and running
Global EdzUpNetwork_Hosting:Byte = False 'True if this is the server
Global EdzUpNetwork_LocalID:Long = 0 'the ID that the server has sent you
Global EdzUpNetwork_MessageCount:Long = 0 'this is the message count
Global EdzUpNetwork_PacketStart:String = "<EPB>" 'this is the packet beginning
Global EdzUpNetwork_PacketEnd:String = "<EPE>" 'this is the packet end
Global EdzUpNetwork_ServerName:String = "" 'this is the server name for advertising purposes
Global EdzUpNetwork_ServerIP:String = "" 'this is the servers IP address
Global EdzUpNetwork_ServerPassword:String = "" 'the server password, change from "" if the server requires a password
Global EdzUpNetwork_NetworkError:Long = 0 '0 if there is no error
Global EdzUpNetwork_PingTimeout:Long = 120 'after 120 seconds your kicked
Global EdzUpNetwork_LocalPort:Long = 12233 'port for the networking system

Global EdzUpNetwork_PlayerCount:Long = 0 'number of players currently in the game
Global EdzUpNetwork_PlayersMaximum:Long = 64 'number of connections accepted by the system
Global EdzUpNetwork_MaximumID:Long = 0 'this is the Maximum ID that has been allocated

'INTERNAL GLOBALS
Global EdzUpNetwork_Internal_UsingID:Byte = False 'True if a client is using the ID they should be using (not 0)
Global EdzUpNetwork_Internal_ServerPasswordOk:Byte = False 'True if the server password has been accepted
Global EdzUpNetwork_Internal_UserAccepted:Byte = False 'True if the user has been accepted
Global EdzUpNetwork_Internal_Authenticate:Byte = False

'timing system for networking
Global EdzUpNetwork_NetworkTime:String = CurrentTime() 'this is the network time (for ping check etc)
Global EdzUpNetwork_SecondsPassed:Long = 0 'see how many seconds have passed

Global EdzUpNetwork_LocalUsername:String = "" 'the username for the local machine
Global EdzUpNetwork_LocalPassword:String = "" 'the local password for this machine
Global EdzUpNetwork_LocalServerPassword:String = "" 'The password for the local machine to be send to authenticate with the server


Global EdzUpNetwork_LocalNoNetworkGame:Byte = False 'true if this is a local game WITHOUT networking

Global CompressBank:TBank = CreateBank( 4 ) 'used in conversion routines

Global DebugHandle:TStream = Null
Global DebugFileName:String = ""

' -----------------------------------------------------------------------------
' These globals MUST be included in your code!
'James L Boyd code
' -----------------------------------------------------------------------------
Global GT_Start:Long ' Start of game time
Global GT_Last:Int ' Last INTEGER value of MilliSecs ()
Global GT_Current:Long ' LONG value updated by MilliSecs ()

Type UserType
Field Name:String 'the username of this client
Field Password:String 'the password relating to this user
End Type
Global User:UserType = Null
Global UserList:TList = CreateList()

Type BannedType
Field IP:String 'the ip address that is banned
Field Timer:Long 'how long it has left to be banned (-1 permanent)
Field Count:Long 'how many times the ip has been banned
Field Reason:String 'the reason they have been banned
End Type
Global Banned:BannedType = Null
Global BannedList:TList = CreateList()

Type DisplayType
Field Data:String
End Type
Global Display:DisplayType = Null
Global DisplayList:TList = CreateList()
EndRem

Type PacketType
Field PacketFrom:Long 'who the packet is from
Field PacketTo:Long 'the id of who the packet is for
Field Id:Long 'the message ID for receipt checking, so a receipt for message 16853 relates to packet 16853 so it can be deleted
Field Data:String 'the message's data packet
Field Class:Long 'the class of the message
Field Important:Byte 'True if a receipt is required for this message
Field Stream:TSocketStream 'this is who sent it

Function Create:PacketType()
Return New PacketType 'function to create a new packet type
End Function
End Type
Global PacketList:TList = CreateList()
Global Packet:PacketType = Null

Type ReceiptType
Field ReceiptFrom:Long 'who the receipt is from
Field ReceiptTo:Long 'who it is to
Field ID:Long 'the ID of the receipt
Field Data:String 'what the receipt contains (if it needs resending)
Field Class:Long 'the class of the message held as a receipt

Field Timer:Long 'timer to see how long the receipt has got till resending
Field ReceiptCurrentTime:String 'used for timer checking

Function Create:ReceiptType()
Return New ReceiptType
End Function
End Type
Global ReceiptList:TList = CreateList()
Global Receipt:ReceiptType = Null
Global NetworkReceiptTimer:Long = Floor( ( EdzUpNetwork_PingTimeout +2 )/10 )'this is the time that the system will wait before resending the data
If NetworkReceiptTimer>5 Then NetworkReceiptTimer =5 'stop any mad sending problems (minimum 5 seconds)

Global EdzUpNetwork_ReceiptCount:Long = 0
Rem
EdzUpNetwork_ServerStartup:Byte( Port:Int ) . . . this will startup the server [WORKING]
EdzUpNetwork_Connect:Byte( IP:Int, Port:Int ) . . . this will connect the client To the server [WORKING]
EdzUpNetwork_AlreadyExist:Byte( Username:String ). . . returns True If this username is already in use on the server
Rem
NETWORK ERRORS
0) No errors
1) Ping Timeout
2) Server Password failed
3) Username Or password failed
4) Server error, closed connection
EndRem
'System Constants
Const NETWORK_AUTHORISATION:Int = $FFFF 'if someone is authorised
Const NETWORK_SERVERPASSWORD:Int = $FFFE 'Clients server password
Const NETWORK_PASSWORD:Int = $FFFD 'someone is changing thier password
Const NETWORK_PINGTIMEOUT:Int = $FFFC 'someone has pinged out
Const NETWORK_PING:Int = $FFFB 'someone is pinging something
Const NETWORK_DISCONNECT:Int = $FFFA 'a client disconnected from the server
Const NETWORK_SERVERMESSAGE:Int = $FFF9 'a message from the server
Const NETWORK_CLIENTINFORMATION:Int = $FFF8 'this will update all clients with the relevant information
Const NETWORK_CLIENTMESSAGE:Int = $FFF7 'this is a message from the client
Const NETWORK_MESSAGE:Int = $FFF6 'this is a universal network message
Const NETWORK_RECEIPT:Int = $FFF5 'this is a network receipt for a message
Const NETWORK_CHAT:Int = $FFF4 'this is a chat packet
Const NETWORK_CONNECT:Int = $FFF3 'when someone connects
Const NETWORK_FILETRANSFER:Int = $FFF1 'a file is being sent between systems
Const NETWORK_CLIENTID:Int = $FFF0 'for quick permiation of ID's
EndRem

Type ClientType
Field ID:Long 'the ID of the client, given by the server
Field Username:String 'thier username
Field Authenticated:Byte 'True of this user has authenticated thier password
Field Syncronising:Long 'what it is current syncronising (-1 none, >0 that ID or -2 complete)
Field PacketID:Long 'packet ID that is sent on important packets
Field Ping:Long 'ping time for this computer
Field Cheating:Byte 'True if this player is cheating
Field TimesCheated:Long 'how many times they have cheated

Field Socket:TSocket 'thier socket (reqiured for networking)
Field Stream:TSocketStream 'required for networking
Field Buffer:String 'this is the data buffer
End Type
Global Client:ClientType = Null
Global ClientList:TList = CreateList()

'------------------------------------------------------------------------------------------------------------------------
Function KillClientConnections( ID:Long )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = ID
CloseStream( Client.Stream )
CloseSocket( Client.Socket )
EndIf
EndIf
Next
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_ResetNetworkVariables()
LocalSocket = Null 'local socket for data transfer
LocalStream = Null 'local stream for data transfer
LocalBuffer = "" 'the local streams buffer
EdzUpNetwork_Connected = False 'true if networking is up and running
EdzUpNetwork_Hosting = False 'True if this is the server
EdzUpNetwork_LocalID = 0 'the ID that the server has sent you
EdzUpNetwork_MessageCount = 0 'this is the message count
EdzUpNetwork_ServerName = "" 'this is the server name for advertising purposes
EdzUpNetwork_ServerIP = "" 'this is the servers IP address
EdzUpNetwork_ServerPassword = "" 'the server password, change from "" if the server requires a password
EdzUpNetwork_NetworkError = 0 '0 if there is no error
EdzUpNetwork_LocalPort = 12233 'port for the networking system

EdzUpNetwork_Internal_UsingID = False 'True if a client is using the ID they should be using (not 0)
EdzUpNetwork_Internal_ServerPasswordOk = False 'True if the server password has been accepted
EdzUpNetwork_Internal_UserAccepted = False 'True if the user has been accepted
EdzUpNetwork_Internal_Authenticate = False

EdzUpNetwork_LocalServerPassword = "" 'The password for the local machine to be send to authenticate with the server

EdzUpNetwork_LocalNoNetworkGame = False 'true if this is a local game WITHOUT networking
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_UpdateClient:Byte( ID:Long, Operator:Long, Value:String )
'this will update the client with the relevant information
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = ID
Select Operator
Case 1 'Authenticated status change
Client.Authenticated = True
Default 'update the username
Client.Username = Value
End Select
EndIf
EndIf
Next
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_Authenticate:Byte( ServerPassword:String, Username:String, UserPassword:String )
Local Timer:String = CurrentTime()
Local SecsPass:Long = 0
Local Received:String = ""
Local Available:Long = 0
Local CE:Long = 0

'Get a local ID for the connection
EdzUpNetwork_Debug( "Getting ID" )
DebugLog "Getting ID"+Chr(10)
Repeat
If CurrentTime()<>Timer
SecsPass :+ 1
Timer = CurrentTime()

If EdzUpNetwork_LocalID=0
'ask server for ID
EdzUpNetwork_Message( EdzUpNetwork_LocalID, 0, NETWORK_CLIENTID, "ID?", False, LocalStream )
EndIf
EndIf

CE= EdzUpNetwork_UpdateNetwork() 'this will update the whole network then adjust the ID
If CE<>0
'there is an error of sorts
EdzUpNetwork_Debug( "ID:Network Error set to "+CE )
Return False
EndIf

Delay( 1 )
Until EdzUpNetwork_LocalID<>0 Or SecsPass>60

'failed to authenticate
If SecsPass>60 Then Return False

EdzUpNetwork_Debug( "Authenticating server password..." )
DebugLog "Sending server password"+Chr(10)
SecsPass = 0
Repeat
If CurrentTime()<>Timer
SecsPass :+ 1
Timer = CurrentTime()

If EdzUpNetwork_Internal_ServerPasswordOk = False
'Send the server password that the client has
EdzUpNetwork_Message( EdzUpNetwork_LocalID, 0, NETWORK_SERVERPASSWORD, ServerPassword, False, LocalStream )
EndIf

CE = EdzUpNetwork_UpdateNetwork()
If CE<>0
EdzUpNetwork_Debug( "SP:Network error set to "+CE )
Return False
EndIf
EndIf
Delay( 1 )
Until EdzUpNetwork_Internal_ServerPasswordOk = True Or SecsPass>60
If SecsPass>60 Then Return False

EdzUpNetwork_Debug( "Authenticating user details..." )
DebugLog "Sending user details"+Chr(10)
SecsPass = 0
Repeat
If CurrentTime()<>Timer
SecsPass :+ 1
Timer = CurrentTime()

If EdzUpNetwork_Internal_UserAccepted = False
'Send the server password that the client has
EdzUpNetwork_Message( EdzUpNetwork_LocalID, 0, NETWORK_AUTHORISATION, Username+"¬"+MD5( UserPassword ), False, LocalStream )
EndIf

CE = EdzUpNetwork_UpdateNetwork()
If CE<>0
EdzUpNetwork_Debug( "UD:Network error set to "+CE )
Return False
EndIf
EndIf
Delay( 1 )
Until EdzUpNetwork_Internal_UserAccepted = True Or SecsPass>60
If SecsPass>60 Then Return False
Return True
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_UpdateNetwork:Long( )
Local TempClientWaiting:TSocket = Null
Local AvailableBytes:Long = 0
Local CurrentByte:Byte = 0
Local TempReceive:String = ""
Local CB:Long = 0

EdzUpNetwork_NetworkError = 0 'reset the error log
If EdzUpNetwork_Hosting = True 'This computer is hosting
'this application is the server

'
' CHECK FOR NEW CONNECTIONS
'
TempClientWaiting = SocketAccept( LocalSocket, 1 )
If TempClientWaiting
Client:ClientType = New ClientType
Client.UserName = DottedIP( SocketRemoteIP( TempClientWaiting ) ) +"["+String( GameTime() )+"]"
Client.ID = EdzUpNetwork_NextAvailID()
If Client.ID>EdzUpNetwork_MaximumID Then EdzUpNetwork_MaximumID = Client.ID

Client.Authenticated = False
Client.Syncronising = -1
Client.PacketID = 0
Client.Socket = TempClientWaiting
Client.Stream = CreateSocketStream( Client.Socket )
ListAddLast( ClientList, Client )
EdzUpNetwork_AddDisplay( Client.Username+" connected" )
EdzUpNetwork_Debug( "Added client:"+Client.Username+" ID:"+Client.ID )
EdzUpNetwork_Message( -1, EdzUpNetwork_LocalID, NETWORK_CLIENTID, IntToStr( Client.ID ), False, Client.Stream )
EndIf

'****************
'*  PING CHECK  *
'****************
If CurrentTime()<>EdzUpNetwork_NetworkTime
EdzUpNetwork_NetworkTime = CurrentTime()
EdzUpNetwork_SecondsPassed :+ 1

If EdzUpNetwork_SecondsPassed>60
'Ping check every sixty seconds
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.Authenticated = True
EdzUpNetwork_Debug( "Pinging to "+Client.ID+" waiting for a response" )
EdzUpNetwork_Message( EdzUpNetwork_LocalID, Client.ID, NETWORK_PING, "", False )
EndIf
EndIf
Next
EdzUpNetwork_SecondsPassed = 0
EndIf
EndIf

'
' NOW CHECK ALL THE CLIENTS FOR PACKETS BEING SENT
'
For Client:ClientType = EachIn ClientList
If Client<>Null
EdzUpNetwork_Internal_Authenticate = False 'when set to true set the authenticated flag

If EdzUpNetwork_ConnectionOk( Client.Socket )=True
'perform client stuff here
AvailableBytes = SocketReadAvail( Client.Socket ) 'get available bytes on client socket
If AvailableBytes>0
For CB = 0 To AvailableBytes -1 'read in bytes and add them to clients buffer
Client.Buffer = Client.Buffer + Chr( ReadByte( Client.Stream ) )
Next
EndIf

'process a packet from the buffer
Client.Buffer = EdzUpNetwork_ProcessBuffer( Client.Buffer )

If EdzUpNetwork_Internal_Authenticate = True
'they have passed the checks
Client.Authenticated = True
EndIf
Else
'weve lost the client, either they closed the application or the connection was dropped
EdzUpNetwork_Debug( Client.Username+ "disconnected..." )
EdzUpNetwork_KillReceipts( Client.ID ) 'kill thier receipts
EdzUpNetwork_AddDisplay( Client.Username+" left the game" ) 'add a message and they broadcast the termination
EdzUpNetwork_Message( EdzUpNetwork_LocalID, -1, NETWORK_DISCONNECT, IntToStr( Client.ID )+Client.Username, True )
ListRemove( ClientList, Client ) 'remove them from the list
EndIf
EndIf
Next

'END OF SERVER UPDATE SYSTEM
Else
'this application is a client
If EdzUpNetwork_ConnectionOk( LocalSocket ) = True
'READ IN NEW PACKETS AND ADD THEM TO THE BUFFER (LocalBuffer)
AvailableBytes = SocketReadAvail( LocalSocket )
If AvailableBytes>0
For CB = 0 To AvailableBytes -1
LocalBuffer = LocalBuffer + Chr( ReadByte( LocalStream ) )
Next
EndIf

'process a packet from the buffer
LocalBuffer = EdzUpNetwork_ProcessBuffer( LocalBuffer )
Else
'if the connection has been dropped then set it to Network Error
EdzUpNetwork_NetworkError = 4

Return 4
EndIf
EndIf

'UPDATE ALL PACKETS AND RECEIPTS
EdzUpNetwork_UpdatePackets()
EdzUpNetwork_UpdateReceipts()
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_StreamInformation:String( Stream:TSocketStream, Operator:Long = 0 )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.Stream = Stream
Select Operator
Default 'Return ID
Return Client.ID
End Select
EndIf
EndIf
Next
End Function


'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_ProcessBuffer:String( DataBuffer:String )
Local Buffer:String = DataBuffer
Local ExtractedPacket:String = ""
Local TempBuffer:String = ""

Local TempFrom:Long = 0
Local TempTo:Long = 0
Local TempCount:Long = 0
Local TempClass:Long = 0
Local TempData:String = ""
Local TempImportant:String = "F"

EdzUpNetwork_Internal_UsingID = True

If Instr( Buffer, EdzUpNetwork_PacketStart )>0
If Instr( Buffer, EdzUpNetwork_PacketEnd )>0
'trim the buffer to get rid of background noise in the buffer
ExtractedPacket = Right( Buffer, Len( Buffer )-( Instr( Buffer, EdzUpNetwork_PacketStart ) -1 ) )
Buffer = ExtractedPacket
ExtractedPacket = ""

'extract the packet from the buffer, Packetstart...PacketEnd and then process it
TempBuffer = Left( Buffer, Instr( Buffer, EdzUpNetwork_PacketEnd ) +( Len( EdzUpNetwork_PacketEnd ) -1 ) )

'remove the packet from the network buffer
Buffer = Replace( Buffer, TempBuffer, "" )

'remove the packet beginning and packet ending from the temporary buffer
TempBuffer = Replace( TempBuffer, EdzUpNetwork_PacketStart, "" )
TempBuffer = Replace( TempBuffer, EdzUpNetwork_PacketEnd, "" )

'process the temporary buffer and store information
TempFrom = StrToInt( Mid( TempBuffer, 1, 4 ) ) 'Message From
TempTo = StrToInt( Mid( TempBuffer, 5, 4 ) ) 'Message To
TempClass = StrToInt( Mid( TempBuffer, 9, 4 ) ) 'Message Class
TempCount = StrToInt( Mid( TempBuffer, 13, 4 ) ) 'Message ID
TempData = Mid( TempBuffer, 17, Len( TempBuffer ) -17 ) 'Message Data
TempImportant = Right( TempBuffer, 1 ) 'Message Important

If EdzUpNetwork_Hosting = True
If TempFrom = 0
'they dont have the ID they should be using
EdzUpNetwork_Internal_UsingID = False

'erase the clients buffer, ALL data is ignored
Return ""
EndIf
EndIf

'now we need to add the packet to the list for 'processing'
EdzUpNetwork_AddPacket( TempFrom, TempTo, TempClass, TempCount, TempData, TempImportant )

'return the buffer, with the packet removed
Return Buffer
Else
'a beginning but no ending so erase the buffer
Return ""
EndIf
Else
'corrupt data in packet
Return ""
EndIf
End Function


'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_Message( MessageFrom:Long, MessageTo:Long, MessageClass:Long, MessageData:String, Important:Int=False, Stream:TSocketStream = Null )
'broadcast a message to everyone who is in the same galaxy & system as the client
Local SendPacket:String = ""
Local SendIt:Byte = False
Local DontSendTo:Long = 0

If MessageClass=NETWORK_DISCONNECT
'There is no need to send a disconnect message to the person who disconnected
DontSendTo = StrToInt( Left( MessageData, 4 ) )
EndIf

'create the packet
SendPacket = "<"
SendPacket :+ EdzUpNetwork_PacketStart 'build the packet data
SendPacket :+ IntToStr( MessageFrom ) 'add the Message from
SendPacket :+ IntToStr( MessageTo ) 'add the message to
SendPacket :+ IntToStr( MessageClass ) 'add the class
SendPacket :+ IntToStr( EdzUpNetwork_MessageCount ) 'add the Message ID
SendPacket :+ MessageData
If Important = True Then SendPacket :+ "T" Else SendPacket :+ "F"
SendPacket :+ EdzUpNetwork_PacketEnd

If Stream<>Null
'send a specific message to someone (normally from server to client)
WriteLine Stream, SendPacket

'if important keep a receipt
If Important = True Then EdzUpNetwork_AddReceipt( MessageFrom, MessageTo, MessageClass, EdzUpNetwork_MessageCount, MessageData )

EdzUpNetwork_MessageCount :+ 1 'increment the message count
Return
EndIf

If EdzUpNetwork_Hosting = True
'locate the client and send them the packet (-1 if the packet has to be broadcast)
For Client:ClientType = EachIn ClientList
If Client<>Null
'REACHED
If Client.Authenticated = True
SendIt = False
If MessageTo = -1 Then SendIt = True
If Client.ID = MessageTo Then SendIt = True
If DontSendTo<>0 And Client.ID<>DontSendTo Then SendIt = True 'dont send to sender
If SendIt = True
If Client.Authenticated = True
WriteLine Client.Stream, SendPacket

If Important = True
'store a receipt per client for broadcasts
EdzUpNetwork_AddReceipt( MessageFrom, Client.ID, MessageClass, EdzUpNetwork_MessageCount, MessageData )
EndIf
Else
EdzUpNetwork_Debug( Client.ID+" is not authenticated so cannot receive "+MessageData )
EndIf
EndIf
Else
'only authentication packets are sent
If MessageClass = NETWORK_SERVERPASSWORD Or MessageClass = NETWORK_AUTHORISATION Or MessageClass = NETWORK_CLIENTID
WriteLine Client.Stream, SendPacket
EndIf
EndIf
EndIf
Next
Else
'this will send the packet to the server
WriteLine LocalStream, SendPacket
EndIf

If Important = True And MessageTo<>-1
'if this is important then we need to keep a receipt, and its not a broadcast
EdzUpNetwork_AddReceipt( MessageFrom, MessageTo, MessageClass, EdzUpNetwork_MessageCount, MessageData )
EndIf
EdzUpNetwork_MessageCount :+ 1 'increment the message count
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_StartupServer:Byte( Port:Int )
'this will bind a socket and begin listening
LocalSocket = CreateTCPSocket()
If Not BindSocket( LocalSocket, Port ) Or Not SocketListen( LocalSocket )
CloseSocket LocalSocket

Return False
EndIf

EdzUpNetwork_Hosting = True
EdzUpNetwork_LocalID = 0
EdzUpNetwork_LocalPort = Port
EdzUpNetwork_AccessLoginData()

Return True
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_Connect:Byte( IP:Int, Port:Int )
LocalSocket = CreateTCPSocket()
If ConnectSocket( LocalSocket, IP, Port ) = False Then Return False
If LocalSocket<>Null
LocalStream = CreateSocketStream( LocalSocket )

EdzUpNetwork_Connected = True
Else
CloseSocket( LocalSocket ) 'no point leaving it open if it failed to connect
Return False
EndIf

EdzUpNetwork_LocalPort = Port
EdzUpNetwork_Hosting = False
Return True
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_AlreadyExist:Byte( Username:String )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Upper( Client.Username ) = Upper( Username ) Then Return True
EndIf
Next

Return False
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_NextAvailID:Long( )
Local TempID:Long = 1
Local IDInUse:Byte = False

Repeat
IDInUse = False
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = TempID
TempID = TempID +1
IDInUse = True
EndIf
EndIf
Next
Until IDInUse = False

Return TempID
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_ConnectionOk:Byte( Socket:TSocket )
'test socket to see if exception if thrown, if so then return false
Local B:Byte = 5
Local A:Byte Ptr = Varptr( B )

Try
Socket.Send( A, 1 )
Socket.Recv( A, 1 )
Catch o:Object
Return False
EndTry

'try blitzmax's socket connected
If SocketConnected( Socket ) = False Then Return False

Return True
End Function

'------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_CheckUser:Byte( Username:String, Password:String )
For User:UserType = EachIn UserList
If User<>Null
If Upper( User.Name ) = Upper( Username )
If User.Password = Password
Return 1
Else
Return -1
EndIf
EndIf
EndIf
Next

User:UserType = New UserType
User.Name = Username
User.Password = Password
ListAddLast( UserList, User )
EdzUpNetwork_AccessLoginData( True ) 'Save login stuffs with new user added

Return 2
End Function

'------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_CheckIP:Byte( IP:String )
'this will check for a specific ip and see if its in the ban list
For Banned:BannedType = EachIn BannedList
If Banned<>Null
If Banned.IP = IP
Return True
EndIf
EndIf
Next

Return False
End Function

'------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_AccessLoginData( Save:Byte = False )
Local Handle:TStream = Null

Select Save
Case True 'save
Handle = WriteFile( "UserData.txt" )
If Handle<>Null
For User:UserType = EachIn UserList
If User<>Null
WriteLine( Handle, User.Name )
WriteLine( Handle, User.Password )
EndIf
Next
CloseFile( Handle )
EndIf
Default 'Load
Handle = ReadFile( "UserData.txt" )
If Handle<>Null
Repeat
User:UserType = New UserType
User.Name = ReadLine( Handle )
User.Password = ReadLine( Handle )
ListAddLast( UserList, User )
Until Eof( Handle )
CloseFile( Handle )
EndIf
End Select
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_AddPacket( MesFrom:Long, MesTo:Long, MesClass:Long, MesID:Long, MesData:String, MesImportant:String, Stream:TSocketStream =Null )
'this function will add a packet to the list for processing, once it is processed it will be deleted
Packet:PacketType = PacketType.Create()
Packet.PacketFrom = MesFrom
Packet.PacketTo = MesTo
Packet.Class = MesClass
Packet.ID = MesID
Packet.Data = MesData
If MesImportant = "T" Then Packet.Important = True Else Packet.Important = False
Packet.Stream = Stream

ListAddLast( PacketList, Packet )
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_UpdatePackets()
'this function runs through the packets and sorts the ones that need to be sorted by the EdzUpNetwork System
Local RemovePacket:Byte = False
Local TemporaryData:String = ""
Local TemporaryValue:Long = 0
Local TemporaryUsername:String = ""
Local TemporaryPassword:String = ""
Local AlreadyAuthenticated:Byte = False

Local PacketFrom:Long = 0
Local PacketTo:Long = 0
Local PacketID:Long = 0
Local PacketData:String = 0
Local PacketClass:Long = 0
Local PacketImportant:Byte = 0
Local PacketStream:TSocketStream = Null

For Packet:PacketType = EachIn PacketList
If Packet <> Null
'store packet information
PacketFrom = Packet.PacketFrom
PacketTo = Packet.PacketTo
PacketClass = Packet.Class
PacketID = Packet.ID
PacketData = Packet.Data
PacketImportant = Packet.Important
PacketStream = Packet.Stream

Select Packet.Class
Case NETWORK_AUTHORISATION 'AUTHORISATION PACKETS, Username+Password
'remove packet as its already retrieved
ListRemove( PacketList, Packet )
'needs to get username, password
If EdzUpNetwork_Hosting = True
'the server needs to check password against username, and the server password if any required
EdzUpNetwork_Debug( "Authentication Packet..." )
'remove all receipts relating to clientID
EdzUpNetwork_KillReceiptsClass( NETWORK_CLIENTID, PacketFrom )
If Instr( PacketData, "¬" )<>0
TemporaryUsername = Left( PacketData, Instr( PacketData, "¬", 1 ) -1 )
TemporaryPassword = Right( PacketData, Len( PacketData ) - ( Instr( PacketData, "¬", 1 ) ) )

EdzUpNetwork_Debug( "Authentication data:["+TemporaryUsername+"]["+TemporaryPassword+"]" )

'check to see if they are already in
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.Username = TemporaryUsername
'tell them the Id that is already set
EdzUpNetwork_Debug( "Entry located, already in" )
EdzUpNetwork_Message( -1, EdzUpNetwork_LocalID, NETWORK_CLIENTID, IntToStr( Client.ID ), False, Client.Stream )
AlreadyAuthenticated = True
EndIf
EndIf
Next

If AlreadyAuthenticated = False
EdzUpNetwork_Debug( "New Authentication located, creating entry" )
'see if thier details are stored on the host server
If EdzUpNetwork_CheckUser( TemporaryUsername, TemporaryPassword ) >0
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketFrom, NETWORK_AUTHORISATION, "OK", False )
EdzUpNetwork_KillReceipts( PacketFrom ) 'set to true as we dont want to keep sending receipts
EdzUpNetwork_Internal_Authenticate = True 'make it so system authenticates them
EdzUpNetwork_AddDisplay( TemporaryUserName+" authenticated ok." )
EdzUpNetwork_UpdateClient( PacketFrom, 0, TemporaryUsername )
EdzUpNetwork_UpdateClient( PacketFrom, 1, "" ) 'Authenticate them

'broadcast that this player has joined the game
EdzUpNetwork_Message( -1, EdzUpNetwork_LocalID, NETWORK_CLIENTINFORMATION, IntToStr( PacketFrom )+TemporaryUsername, True )
Else
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketFrom, NETWORK_AUTHORISATION, "FAIL", False )
EndIf
EndIf
EndIf
Else
'a authorisation message from the server needs to be processed
If PacketData = "OK"
EdzUpNetwork_Internal_UserAccepted = True
Else
EdzUpNetwork_Internal_UserAccepted = False
EndIf
EndIf

Case NETWORK_SERVERPASSWORD 'see if they got the password correct
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = True
'as this application is the server check the password against the server password
If Packet.Data = EdzUpNetwork_ServerPassword
'the server passwords match, Send OK to client so they can continue authentication
EdzUpNetwork_Debug( "Server password:"+PacketData+" is the same as :"+EdzUpNetwork_ServerPassword )
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketFrom, NETWORK_SERVERPASSWORD, "OK", False )
Else
'it will send FAIL if the passwords dont match
EdzUpNetwork_Debug( "Server password:"+PacketData+" isnt the same as :"+EdzUpNetwork_ServerPassword )
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketFrom, NETWORK_SERVERPASSWORD, "FAIL", False )
EndIf
Else
If PacketData = "OK"
EdzUpNetwork_Internal_ServerPasswordOk = True
Else
EdzUpNetwork_Internal_ServerPasswordOk = False
EndIf
EndIf

Case NETWORK_PASSWORD 'someone is changing thier user password, update list
ListRemove( PacketList, Packet )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = PacketFrom
'we got em
TemporaryData = Client.Username
EndIf
EndIf
Next

Case NETWORK_PINGTIMEOUT 'Server message to client telling them they are out
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = False
EdzUpNetwork_NetworkError = 1 'Set error system to Ping timeout
EndIf

Case NETWORK_PING 'Ping request from server to clients
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = True
'server will need to update clients ping time
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = PacketFrom
'we got em now reset the ping time
DebugLog "Ping From "+Client.Username+", ping time reset"
Client.Ping = 0
EndIf
EndIf
Next
Else
'a ping request from the server
EdzUpNetwork_Message( EdzUpNetwork_LocalID, 0, NETWORK_PING, "PONG", False )
EndIf


Case NETWORK_DISCONNECT 'Someone has quit, Server>>Clients
If EdzUpNetwork_Hosting = False
'remove the local client bits
TemporaryValue = StrToInt( Left( PacketData, 4 ) )
TemporaryUsername = Right( PacketData, Len( PacketData )-4 )
EdzUpNetwork_KillReceipts( TemporaryValue )
For Client:ClientType = EachIn ClientList
If Client.ID = TemporaryValue
ListRemove( ClientList, Client )
EndIf
Next
EndIf
ListRemove( PacketList, Packet )

Case NETWORK_SERVERMESSAGE 'a server message to the client
ListRemove( PacketList, Packet )
EdzUpNetwork_AddDisplay( PacketData )
If PacketFrom<>0 And PacketData = "CHEAT DETECTED"
'Someone is cheating
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = PacketFrom
Client.Cheating = True
Client.TimesCheated :+ 1

If EdzUpNetwork_Hosting=True
EdzUpNetwork_AddDisplay( "***CHEAT DETECTED*** User:"+Client.Username+" Cheated "+Client.TimesCheated )
EndIf
EndIf
EndIf
Next
EndIf

Case NETWORK_MESSAGE 'a message from client to server
ListRemove( PacketList, Packet )
EdzUpNetwork_AddDisplay( PacketData )

Case NETWORK_RECEIPT 'a receipt message telling someone that the message has been received
'we will need to remove the receipt that ID is the same as Packet.Data as its just been acknowledged
ListRemove( PacketList, Packet )
EdzUpNetwork_RemoveReceipt( StrToInt( PacketData ) )

Case NETWORK_CHAT 'A chat packet, To = -1 to broadcast
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = True
'dont send it as important as its just chat, PacketTo=-1 then broadcast
EdzUpNetwork_Debug( ">CHAT : "+PacketTo+" : "+PacketData )
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketTo, NETWORK_CHAT, PacketData, False )
EndIf
EdzUpNetwork_AddDisplay( PacketData ) 'servers send the data, clients just add to display list

Case NETWORK_CONNECT 'someone has connected, Server>>Clients, Data = UserID[4],Name Length[4], Username
ListRemove( PacketList, Packet )
Client:ClientType = New ClientType
Client.ID = StrToInt( Mid( Client.Buffer, 1, 4 ) ) 'convert the Client's ID
TemporaryValue = StrToInt( Mid( Client.Buffer, 5, 4 ) ) 'Get length of the Username
Client.Username = Mid( Client.Buffer, 9, 9 +TemporaryValue ) 'get the username

Case NETWORK_CLIENTINFORMATION 'someone is requesting information on an ID
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = True
TemporaryValue = StrToInt( PacketData )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = TemporaryValue
EdzUpNetwork_Message( 0, PacketFrom, NETWORK_CLIENTINFORMATION, IntToStr( Client.ID )+Client.Username, True )
EndIf
EndIf
Next
Else
'update the client name with the data specified
TemporaryValue = StrToInt( Left( Packet.Data, 4 ) )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = TemporaryValue
Client.Username = Right( PacketData, Len( PacketData ) -4 )
DebugLog "Client updated: "+Client.ID+" changed name to "+Client.Username
EndIf
EndIf
Next
EndIf

Case NETWORK_CLIENTID 'Server has assigned you client id ID
ListRemove( PacketList, Packet )
If EdzUpNetwork_Hosting = False
If EdzUpNetwork_LocalID = 0
EdzUpNetwork_LocalID = StrToInt( PacketData )
DebugLog "LocalID set to "+EdzUpNetwork_LocalID
EndIf
Else
'if server then send them the information they want
EdzUpNetwork_Debug( "Client is requesting ID" )
EdzUpNetwork_Message( -1, EdzUpNetwork_LocalID, NETWORK_CLIENTID, IntToStr( Long( EdzUpNetwork_StreamInformation( PacketStream ) ) ), False, PacketStream )
EndIf

Case NETWORK_FILETRANSFER 'A file transfer has been requested, -1 is start, -2 end, >-1 segment number
ListRemove( PacketList, Packet )

Default 'This is a packet that the EdzUpNetwork system needs to pass on
If EdzUpNetwork_Hosting = True 'server needs to broadcast the packet to all clients
ListRemove( PacketList, Packet )
For Client:ClientType = EachIn ClientList
If Client<>Null
If Client.ID = PacketTo Or PacketTo <1 'send to a specific person or if its a broadcast
'send the data packet to the client as required (-1 or 0 it gets broadcast to all if
'its an unknown packet
EdzUpNetwork_Message( 0, Client.ID, PacketClass, PacketData, PacketImportant )
EndIf
EndIf
Next
EndIf
End Select

If PacketImportant = True
'respond to server for important packets
DebugLog "Sending receipt packet marked important"
EdzUpNetwork_Message( EdzUpNetwork_LocalID, PacketFrom, NETWORK_RECEIPT, IntToStr( PacketID ), False )
EndIf
EndIf
Next
End Function

'------------------------------------------------------------------------------------------------------------------------
Function DottedIPToInt:Long( sIPAddress:String )'pass IP as a String e.g. "127.0.0.1"
'; Author: Perturbatio (converted to BlitzMax(SuperStrict) by EdzUp)
';VARS
Local iIP:Long
Local iDotPos:Int = 0
Local iOldDotPos:Int = 0
Local strTemp:String
Local Counter:Int = 3

'MAIN
While Counter > 0
iOldDotPos = iDotPos
iDotPos = Instr(sIPAddress, ".", iOldDotPos+1)
strTemp = Mid$(sIPAddress,iOldDotPos + 1, (iDotPos - iOldDotPos)-1)
iIP = iIP + (Int( strTemp ) Shl (Counter * 8))
Counter = Counter - 1
Wend

strTemp = Right(sIPAddress, (Len(sIPAddress) - iDotPos) )
iIP = iIP + (Int( strTemp ) Shl 0)

Return iIP
End Function

'------------------------------------------------------------------------------------------------------------------------
Function IntToStr:String( Num:Int )
Local Temp:String = ""
Local BP:Int = 0

PokeInt CompressBank, 0, Num

For BP = 0 To 3
Temp = Temp + Chr$( PeekByte( CompressBank, BP ) )
Next

Return Temp
End Function

'------------------------------------------------------------------------------------------------------------------------
Function FloatToStr:String( num:Float )
'-=-=-=Convert a floating point number To a 4 Byte String
Local st:String = ""
Local i:Int = 0

PokeFloat CompressBank, 0, num

For i = 0 To 3
st$ = st$ + Chr$( PeekByte( CompressBank, i ) )
Next

Return st$
End Function

'------------------------------------------------------------------------------------------------------------------------
Function StrToInt:Int( st:String )
'-=-=-=Take a 4 Byte String And turn it back into a floating point #.
Local i:Int =0

For i = 0 To 3
PokeByte CompressBank, i, Asc( Mid$( st, i+1, 1 ) )
Next

Return PeekInt( CompressBank, 0 )
End Function

'------------------------------------------------------------------------------------------------------------------------
Function StrToFloat:Float( st:String )
Local I:Int =0

For i=0 To 3
PokeByte CompressBank, i, Asc( Mid$( st, i+1, 1 ) )
Next

Return PeekFloat( CompressBank, 0 )
End Function

'------------------------------------------------------------------------------------------------------------------------
Function Encrypt:String( StringToCode:String )
Local Value:Byte = 0
Local Pos:Int = 0
Local NewString:String = ""

For Pos=1 To Len( StringToCode )
Value = Asc( Mid$( StringToCode, Pos, 1 ) ) +Pos
NewString = NewString + Chr$( Value )
Next

Return NewString
End Function

'------------------------------------------------------------------------------------------------------------------------
Function Decrypt:String( StringToUnencode:String )
Local Value:Byte = 0
Local Pos:Int = 0
Local NewString:String = ""

For Pos=1 To Len( StringToUnencode )
Value = Asc( Mid$( StringToUnencode, Pos, 1 ) ) -Pos
NewString = NewString + Chr$( Value )
Next

Return NewString
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_AddReceipt( MesFrom:Long, MesTo:Long, MesClass:Int, MesID:Long, MesData:String )
'setup the receipt for book keeping
Receipt:ReceiptType = ReceiptType.Create()
Receipt.ReceiptFrom = MesFrom
Receipt.ReceiptTo = MesTo
Receipt.Class = MesClass
Receipt.ID = MesID
Receipt.Data = MesData

Receipt.Timer = NetworkReceiptTimer
Receipt.ReceiptCurrentTime = CurrentTime()

ListAddLast( ReceiptList, Receipt )
EdzUpNetwork_ReceiptCount :+ 1
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_KillReceipts( KillID:Long )
'remove receipts for disconnecting people
For Receipt:ReceiptType = EachIn ReceiptList
If Receipt<>Null
If Receipt.ReceiptTo = KillID Or Receipt.ReceiptFrom = KillID
'kill all receipts to and from this ID as acknowledging them will slow network
EdzUpNetwork_ReceiptCount :- 1
ListRemove( ReceiptList, Receipt )
EndIf
EndIf
Next

End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_KillReceiptsClass( Class:Int, ID:Long )
'this function will remove specific receipts from the list with the class and ID
For Receipt:ReceiptType = EachIn ReceiptList
If Receipt<>Null
If Receipt.ReceiptFrom = ID And Receipt.Class = Class
ListRemove( ReceiptList, Receipt )
EndIf
EndIf
Next
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_RemoveReceipt( ReceiptID:Long )
For Receipt:ReceiptType = EachIn ReceiptList
If Receipt<>Null
If Receipt.ID = ReceiptID
ListRemove( ReceiptList, Receipt )
EndIf
EndIf
Next
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_UpdateReceipts()
Local ReceiptFrom:Long = 0
Local ReceiptTo:Long = 0
Local ReceiptClass:Long = 0
Local ReceiptID:Long =0
Local ReceiptData:String = ""

For Receipt:ReceiptType = EachIn ReceiptList
If Receipt<>Null
If CurrentTime()<>Receipt.ReceiptCurrentTime
Receipt.Timer :- 1
Receipt.ReceiptCurrentTime = CurrentTime() 'reset the timer check

If Receipt.Timer <1
ReceiptFrom = Receipt.ReceiptFrom
ReceiptTo = Receipt.ReceiptTo
ReceiptClass = Receipt.Class
ReceiptID = Receipt.ID
ReceiptData = Receipt.Data
ListRemove( ReceiptList, Receipt ) 'must be removed as the send message will create new receipt

EdzUpNetwork_ReceiptCount :- 1
EdzUpNetwork_Message( ReceiptFrom ,ReceiptTo, ReceiptClass, ReceiptData, True )
EndIf
EndIf
EndIf
Next
End Function

'--------------------------------------------------------------------------------------------------
Function EdzUpNetwork_AddDisplay( DataToAdd:String )
Display:DisplayType = New DisplayType
Display.Data = DataToAdd+Chr( 10 )
ListAddLast( DisplayList, Display )
End Function

'--------------------------------------------------------------------------------------------------
Function EdzUpNetwork_DisplayNext:String( )
Local TextToReturn:String = ""
For Display:DisplayType = EachIn DisplayList
If Display<>Null
If TextToReturn = ""
TextToReturn = Display.Data
ListRemove( DisplayList, Display )
EndIf
EndIf
Next

Return TextToReturn
End Function

'--------------------------------------------------------------------------------------------------
Function EdzUpNetwork_DisplayWaiting:Long()
'returns true if text is waiting for display
For Display:DisplayType = EachIn DisplayList
If Display<>Null
Return True
EndIf
Next

Return False
End Function

Function MD5:String( in:String )
Local h0:Long = $67452301
Local h1:Long = $EFCDAB89
Local h2:Long = $98BADCFE
Local h3:Long = $10325476
   
Local r:Int[] = [7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,..
                5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,..
                4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,..
                6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21]
               
Local k:Int[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
                $A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
                $6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
                $265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
                $21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
                $676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
                $A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
                $D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
                $F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
                $FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
                $F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
               
  Local intCount:Long = (((in$.length + 8) Shr 6) + 1) Shl 4
  Local data:Long[intCount]
 
  For Local ac:Long=0 Until in$.length
    data[ac Shr 2] = data[ac Shr 2] | ((in$[ac] & $FF) Shl ((ac & 3) Shl 3))
  Next
  data[in$.length Shr 2] = data[in$.length Shr 2] | ($80 Shl ((in$.length & 3) Shl 3))
  data[data.length - 2] = (Long(in$.length) * 8) & $FFFFFFFF
  data[data.length - 1] = (Long(in$.length) * 8) Shr 32
 
  For Local chunkStart:Long=0 Until intCount Step 16
    Local a:Long = h0
Local b:Long = h1
Local c:Long = h2
Local d:Long = h3
Local i:Long = 0
Local f:Long = 0
Local t:Long = 0
       
    For i=0 To 15
      f = d ~ (b & (c ~ d))
      t = d
     
      d = c ; c = b
      b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
      a = t
    Next
   
    For i=16 To 31
      f = c ~ (d & (b ~ c))
      t = d

      d = c ; c = b
      b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
      a = t
    Next
   
    For i=32 To 47
      f = b ~ c ~ d
      t = d
     
      d = c ; c = b
      b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
      a = t
    Next
   
    For i=48 To 63
      f = c ~ (b | ~d)
      t = d
     
      d = c ; c = b
      b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
      a = t
    Next
   
    h0 :+ a ; h1 :+ b
    h2 :+ c ; h3 :+ d
  Next
 
  Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3)).ToLower() 
End Function

Function SHA1$(in$)
  Local h0:Long = $67452301
Local h1:Long = $EFCDAB89
Local h2:Long = $98BADCFE
Local h3:Long = $10325476
Local h4:Long = $C3D2E1F0
Local a:Long = 0
Local b:Long = 0
Local c:Long = 0
Local d:Long = 0
Local e:Long = 0
Local i:Long = 0
Local f:Long = 0
Local t:Long = 0
 
  Local intCount:Long = (((in$.length + 8) Shr 6) + 1) Shl 4
  Local data:Long[intCount]
 
  For c=0 Until in$.length
    data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
  Next
  data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
  data[data.length - 2] = (Long(in$.length) * 8) Shr 32
  data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
 
  For Local chunkStart:Long=0 Until intCount Step 16
    a = h0
b = h1
c = h2
d = h3
e = h4

    Local w:Long[] = data[chunkStart..chunkStart + 16]
    w = w[..80]
   
    For i=16 To 79
      w[i] = Rol(w[i - 3] ~ w[i - 8] ~ w[i - 14] ~ w[i - 16], 1)
    Next
   
    For i=0 To 19
      t = Rol(a, 5) + (d ~ (b & (c ~ d))) + e + $5A827999 + w[i]
     
      e = d ; d = c
      c = Rol(b, 30)
      b = a ; a = t
    Next
   
    For i=20 To 39
      t = Rol(a, 5) + (b ~ c ~ d) + e + $6ED9EBA1 + w[i]
     
      e = d ; d = c
      c = Rol(b, 30)
      b = a ; a = t
    Next
   
    For i = 40 To 59
      t = Rol(a, 5) + ((b & c) | (d & (b | c))) + e + $8F1BBCDC + w[i]
     
      e = d ; d = c
      c = Rol(b, 30)
      b = a ; a = t
    Next

    For i = 60 To 79
      t = Rol(a, 5) + (b ~ c ~ d) + e + $CA62C1D6 + w[i]
     
      e = d ; d = c
      c = Rol(b, 30)
      b = a ; a = t
    Next
   
    h0 :+ a ; h1 :+ b ; h2 :+ c
    h3 :+ d ; h4 :+ e
  Next
 
  Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4)).ToLower() 
End Function

Function SHA256$(in$)
  Local h0:Long = $6A09E667, h1:Long = $BB67AE85, h2:Long = $3C6EF372, h3:Long = $A54FF53A
  Local h4:Long = $510E527F, h5:Long = $9B05688C, h6:Long = $1F83D9AB, h7:Long = $5BE0CD19
 
  Local k:Int[] = [$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1,..
                $923F82A4, $AB1C5ED5, $D807AA98, $12835B01, $243185BE, $550C7DC3,..
                $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174, $E49B69C1, $EFBE4786,..
                $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA,..
                $983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147,..
                $06CA6351, $14292967, $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13,..
                $650A7354, $766A0ABB, $81C2C92E, $92722C85, $A2BFE8A1, $A81A664B,..
                $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070,..
                $19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A,..
                $5B9CCA4F, $682E6FF3, $748F82EE, $78A5636F, $84C87814, $8CC70208,..
                $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2]

  Local intCount:Long = (((in$.length + 8) Shr 6) + 1) Shl 4
  Local data:Long[intCount]
 
Local a:Long = 0
Local b:Long = 0
Local c:Long = 0
Local d:Long = 0
Local e:Long = 0
Local f:Long = 0
Local i:Long = 0
Local t:Long = 0
Local g:Long = 0
Local h:Long = 0
Local t0:Long = 0
Local t1:Long=0

  For c=0 Until in$.length
    data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
  Next
  data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
  data[data.length - 2] = (Long(in$.length) * 8) Shr 32
  data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
 
  For Local chunkStart:Long=0 Until intCount Step 16
a = h0
b = h1
c = h2
d = h3
e = h4
f = h5
g = h6
h = h7

    Local w:Long[] = data[chunkStart..chunkStart + 16]
    w = w[..64]
   
    For i=16 To 63
      w[i] = w[i - 16] + (Ror(w[i - 15], 7) ~ Ror(w[i - 15], 18) ~ (w[i - 15] Shr 3))..
            + w[i - 7] + (Ror(w[i - 2], 17) ~ Ror(w[i - 2], 19) ~ (w[i - 2] Shr 10))
    Next
   
    For i=0 To 63
      t0 = (Ror(a, 2) ~ Ror(a, 13) ~ Ror(a, 22)) + ((a & b) | (b & c) | (c & a))
      t1 = h + (Ror(e, 6) ~ Ror(e, 11) ~ Ror(e, 25)) + ((e & f) | (~e & g)) + k[i] + w[i]
     
      h = g ; g = f ; f = e ; e = d + t1
      d = c ; c = b ; b = a ;  a = t0 + t1 
    Next
   
    h0 :+ a ; h1 :+ b ; h2 :+ c ; h3 :+ d
    h4 :+ e ; h5 :+ f ; h6 :+ g ; h7 :+ h
  Next
 
  Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4) + Hex(h5) + Hex(h6) + Hex(h7)).ToLower() 
End Function

Function Rol:Long(val:Long, shift:Long)
  Return (val Shl shift) | (val Shr (32 - shift))
End Function

Function Ror:Long( val:Long, shift:Long )
  Return (val Shr shift) | (val Shl (32 - shift))
End Function

Function LEHex:String( val:Long )
  Local out:String = Hex( val )
 
  Return out[6..8] + out[4..6] + out[2..4] + out[0..2]
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_Debug( Message:String )
DebugHandle = OpenFile( DebugFileName )
If DebugHandle<>Null
SeekStream( DebugHandle, FileSize( DebugFileName ) )
WriteLine DebugHandle, Message
CloseFile( DebugHandle )
EndIf
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_StartDebug( FileName:String )
Local Date:String = CurrentDate$()

Date = Replace$( Date, " ", "" )
Date = Replace$( Date, "Jan", "01" )
Date = Replace$( Date, "Feb", "02" )
Date = Replace$( Date, "Mar", "03" )
Date = Replace$( Date, "Apr", "04" )
Date = Replace$( Date, "May", "05" )
Date = Replace$( Date, "Jun", "06" )
Date = Replace$( Date, "Jul", "07" )
Date = Replace$( Date, "Aug", "08" )
Date = Replace$( Date, "Sep", "09" )
Date = Replace$( Date, "Oct", "10" )
Date = Replace$( Date, "Nov", "11" )
Date = Replace$( Date, "Dec", "12" )

Date = Date + "-"
Date = Date + CurrentTime$()
Date = Replace$( Date, ":", "" )

DebugLog FileName+Date+Chr$(10)

DebugHandle = WriteFile( Filename+Date+".txt" )
DebugFileName = Filename+Date+".txt"
If DebugHandle<>Null
WriteLine( DebugHandle, "Network debug log" )
WriteLine( DebugHandle, "Started : "+CurrentDate$() )
WriteLine( DebugHandle, "          "+CurrentTime$() )
WriteLine( DebugHandle, "---------------------------------------------------------------" )
CloseFile( DebugHandle )
EndIf
End Function

'------------------------------------------------------------------------------------------------------------------------
Function EdzUpNetwork_StopDebug()
EdzUpNetwork_Debug( "---------------------------------------------------------------" )
End Function
' -----------------------------------------------------------------------------
' ResetGameTime MUST be called at the start of your game, or at least
' before you first try to use the GameTime function...
' -----------------------------------------------------------------------------

' You can also call this to reset GameTime on reaching a new level, starting
' a new game after the player dies, etc...
Function ResetGameTime:Int ()
GT_Current = 0
GT_Start = Long (MilliSecs ())
GT_Last = GT_Start
End Function

' -----------------------------------------------------------------------------
' Returns milliseconds from when ResetGameTime was called...
' -----------------------------------------------------------------------------
Function GameTime:Long ()
Local msi:Int = MilliSecs ()

GT_Current = GT_Current + (msi - GT_Last)
GT_Last = msi

Return GT_Current
End Function

RonTek

Quote from: Yue on October 29, 2017, 02:11:45
Hi, error here makemods here.

Build Error: failed to compile C:/BlitzMax/mod/vertex.mod/bnetex.mod/windows.c

Hey Yue. Yes, it should work with the default blitzmax installation and MinGW as Derron mentioned.

Yue

Okay, the BNet version is working. I've got mario and luigi on screen at another window. I don't know much about this networking thing and I'm in trial and error. What I wanted to know if I could implement it in my Gear3D engine that I am developing with BlitzMax + Lua.

Greetings.

RonTek

Quote from: Yue on October 30, 2017, 19:47:32
Okay, the BNet version is working. I've got mario and luigi on screen at another window. I don't know much about this networking thing and I'm in trial and error. What I wanted to know if I could implement it in my Gear3D engine that I am developing with BlitzMax + Lua.

Greetings.

I'm sure it will, but I think with the mario demo it is only limited to 1 client.

Yue

Quote from: RonTek on October 31, 2017, 10:52:58
Quote from: Yue on October 30, 2017, 19:47:32
Okay, the BNet version is working. I've got mario and luigi on screen at another window. I don't know much about this networking thing and I'm in trial and error. What I wanted to know if I could implement it in my Gear3D engine that I am developing with BlitzMax + Lua.

Greetings.

I'm sure it will, but I think with the mario demo it is only limited to 1 client.
Hey, do you know of any alternative ways to get at least one more player in?

Derron

All clients communicate with the master ... B sends to A, C sends to A, D sends to A


A spreads incoming information from B to C and D
A spreads incoming information from C to B and D
A spreads incoming information from D to B and C


After this all have the same information. This is a "Server-client" architecture.
"A" is the master and acts as GOD - all information this client spreads to the others are the "valid" ones, valid for all clients.


----
All clients communicate with each other ... B sends to A/C/D, C sends to A/B/D, D sends to A/B/C


In that scenario everyone has to trust the other clients to not send cheated/wrong data. Of course each client could verify the "probability" of the data and eg. react to the "cheated" notices other clients might send (eg. 3 of 5 players report a player for cheating - so it at least looks as if one was cheating).






bye
Ron

Yue

What happens is that they tell me that only with the examples of luigi and mario, it is only possible to have access from a single client to the server.  I wanted to know how to have more customers.

In local testing, I can only connect one client to the server.

http://www.eiksoft.com/multi/multi.htm

Derron

I wont explain that in detail (this is up to you to "learn"):

That page has this piece of code:

If RecvUDPMsg(Stream) Then ' A UDP packet has been received
RecvID = ReadInt(Stream)
Data   = ReadByte(Stream)
IP     = UDPMsgIP(Stream)
Port   = UDPMsgPort(Stream)


And this already explains how to distinguish players.
You get an IP from the client - and a Port.

So each individual players could be identified via "IP:port". There is a difference between "local network" and "online" games. In a LAN each IP:port is unique. If a Port on your computer is used by "client1.exe" then "client2.exe" cannot use the same port. So your local IP "192.168.0.1" (or the likes) will appear twice in the incoming packets on the master.exe-computer. One with Port X and the other with Port Y.

Ok, so what happens with online games? As long as there is just one computer playing per "WAN-IP" no problem: just use again "IP:Port" - this time it is a WAN-IP like "210.209.208.207".
Problems start with multiple players behind one single IP connecting to a master on another IP. Their internal IP is not given, both just send the "210.209.208.207". But their Ports will differ - as the router surely handles that.

Regarding handling (talking about port redirection on your router) there is also the option of hole punching - which I described somewhere in the blitzmax.com-forums (I believe so at least), so you might search wasted.nz for this.


All in all there is another problem you get: many new internet connection are no longer "IPv4" but "DS-Lite" (1000 users share an IPv4 address and have a unique IPv6 each). But BNetEx is IPv4 only. To overcome this you need translator services - eg. a server redirecting incoming ipv6-traffic to the other user ("master.exe").



bye
Ron


Hardcoal

#12
YUE My Man.. how are you :)
I think YUE and I are the only ones who still uses Xors3D On earth :)
and also ALbaLynx.. which is a great GUI..

I may need help on online gaming in the future.. too.. As Well
Code

Yue

Quote from: Hardcoal on November 04, 2017, 20:36:09
YUE My Man.. how are you :)
I think YUE and I are the only ones who still used Xors3D On earth :)
and also ALbaLynx.. which is a great GUI..

I may need help on online gaming in the future.. too.. As Well

Now I'm creating a blitzmax engine called Gear3D + Lua with Spanish commands;)

Hardcoal

Cool.. you and your Spanish ... !
well make an english version too :-X for us poor people

Thanks Gear Master
Code