Code archives/Networking/Online Game Code

This code has been declared by its author to be Public Domain code.

Download source code

Online Game Code by Xzider
(Posted 19 years ago)
Anyone attempting to learn blitz tcp and are new, heres a good step. You will have to just study the code because I did not comment all of it. Its very simple, 3D, players are spheres on infinite plane, and only supports Coordinate Updates/Displays Name/Deletes player on leaving-I was in a hurry writing this for someone and the coordinate update has alot better way of doing it, but for beginning, just study it. Hope it helps! By the way, the square in the middle is just to show you where you start at. In case you get lost or something.

** Revisions **

3/31/08:

Update: Made the coordinate updates appear a lot smoother.
Fixed: Fixed a server crash when server didn't delete the player properly.
/////////////////////
///////Server///////
///////////////////

;;Coded by Leaedas (Xzider);;

AppTitle "Server"

Global Server%
Global Stream%
Global Port% = 5000
Global PID% ;Player ID to use with NewPID() Function
Global P.Player
Global ServerUpdate% = MilliSecs()
Global ServerUpdateDelay% = 200

Type Player

  Field Stream%
  Field ID%
  Field Name$
  Field X#
  Field Y#
  Field Z#
  Field Linkdead%

End Type

		Server% = CreateServer(Port%)

While Not KeyHit(1)

		Stream% = AcceptTCPStream(Server%)

  If Stream% ;If somone connected

		;Create Player
		
		P.Player = New Player
		P\Stream% = Stream% ;This is now the players stream, this is how you would send him messages
		P\ID% = NewPID()
		P\Name$ = ReadLine(P\Stream%) ;Expecting client to send name as soon as he connects
		Print P\Name$ + " connected!"
		
		UpdatePlayerToAll(0,P\ID%)
		UpdatePlayerToAll(1,P\ID%)
		
  End If

		;Scan players
		
  For P.Player = Each Player

  If ReadAvail(P\Stream%)

		;Check messages sent from client to server
		Msg% = ReadByte(P\Stream%)
		CheckMsg(Msg%)
		
  End If

  If Eof(P\Stream%)

		P\Linkdead% = 1
		
  End If

  If P\LinkDead% = 1

		TempID% = P\ID%
		
  For Ld.Player = Each Player

  If Ld\ID% <> TempID%

		WriteByte(Ld\Stream%,3)
		WriteByte(Ld\Stream%,TempID%)

  End If
	
  Next

		Print P\Name$ + " disconnected!"
		Delete P.Player
		
  End If

  Next

  If MilliSecs() >= ServerUpdate% + ServerUpdateDelay%

		ServerUpdate% = MilliSecs()

  For P.Player = Each Player

		TempID% = P\ID%
		TempX# = P\X#
		TempY# = P\Y#
		TempZ# = P\Z#
		
  For Coord.Player = Each Player

  If Coord\ID% <> TempID% ; Dont send to the person we are updating, he already knows his own coords!:)

		WriteByte(Coord\Stream%,2)
		WriteByte(Coord\Stream%,TempID%)
		WriteFloat(Coord\Stream%,TempX#)
		WriteFloat(Coord\Stream%,TempY#)
		WriteFloat(Coord\Stream%,TempZ#)
		
  End If

  Next

  Next

  End If

		Delay 10
Wend

Function CreateServer(TempPort%)

		TempServer% = CreateTCPServer(TempPort%)
		
  If TempServer%

		Print "Server started on port " + TempPort% + "!"
		
  Else

		Print "Server could not be started!"
		Print "Press any key to quit."
		WaitKey
		End
		
  End If


  Return TempServer%

End Function

Function CheckMsg(TempMsg%)

Select TempMsg%

  Case 1

		;Could be used to update coords here.
		TempX# = ReadFloat(P\Stream%)
		TempY# = ReadFloat(P\Stream%)
		TempZ# = ReadFloat(P\Stream%)
		
		P\X# = TempX#
		P\Y# = TempY#
		P\Z# = TempZ#
		
		Print "<"+P\ID%+"> " + P\Name$ + " - X:" + P\X# + " - Y:" + P\Y# + " - Z:" + P\Z# ;DELETE THIS CODE, LAGS SERVER,FOR DEBUG ONLY
		
Default

		Print "Opcode not recognized " + TempMsg%
		
End Select

End Function

Function NewPID()

		PID% = PID% + 1
		
  Return PID%

End Function

;;;;;

Function UpdatePlayerToAll(TempAll%,TempID%)
		
  If TempAll% = 0
			
  For Find.Player = Each Player
				
  If Find\ID% = TempID%
					
		TempName$ = Find\Name$
					
  End If
				
  Next
			
  For Send.Player = Each Player
				
  If Send\ID% <> TempID%
					
		WriteByte(Send\Stream%,1)
		WriteByte(Send\Stream%,TempID%)
		WriteLine(Send\Stream%,TempName$)
		
  End If

  Next
			
  ElseIf TempAll% = 1
			
  For Find.Player = Each Player
				
  If Find\ID% = TempID%
					
		TempID% = Find\ID%
		TempStream% = Find\Stream%
					
  End If
				
  Next
			
  For Send.Player = Each Player
						
  If Send\ID% <> TempID%

		WriteByte(TempStream%,1)
		WriteByte(TempStream%,Send\ID%)
		WriteLine(TempStream%,Send\Name$)			
					
  End If
				
  Next
			
  End If
		
		TempSucess% = 1
		
  Return TempSucess%

End Function

////////////////////
//Client////////////
////////////////////

;;Coded by Leaedas (Xzider);;

Graphics3D 800,600,32,2
AppTitle "Client"

Global Client%
Global IP$ = "127.0.0.1"
Global Port% = 5000
Global Name$
Global Camera% = CreateCamera()
Global UpdateCounter% = MilliSecs()
Global UpdateDelay% = 500
Global X#
Global Y#
Global Z#

Type Player

  Field ID%
  Field Entity%
  Field Name$
  Field X#
  Field Y#
  Field Z#
  Field DeltaX#
  Field DeltaY#
  Field DeltaZ#

End Type

		Name$ = Input("Your name: ")
		
		Client% = Connect(IP$,Port%)
		
		WriteLine(Client%,Name$)
		
		ConstructWorld()
		
While Not KeyHit(1)

  Cls

		UpdateWorld
		RenderWorld
		
		Handle_Coords()
		UpdatePlayers()
		Update()
		
  If ReadAvail(Client%) > 0

		Msg% = ReadByte(Client%)
		CheckMsg(Msg%)
		
  End If

  If Eof(Client%)

		RuntimeError "Disconnected from server!"
		
  End If

  Flip

Wend

Function Connect(TempIP$,TempPort%)

		TempClient% = OpenTCPStream(TempIP$,TempPort%)
		
  If TempClient%

		Print "Connected to " + TempIP$ + " on port " + TempPort%  + "!"
		
  Else

		Print "Could not connect!"
		Print "Press any key to quit."
		WaitKey
		End
		
  End If

  Return TempClient%

End Function

Function CheckMsg(TempMsg%)

Select TempMsg%

  Case 1

		;Add new player
		
		P.Player = New Player
		
		P\ID% = ReadByte(Client%)
		P\Name$ = ReadLine(Client%)
		P\Entity% = CreateSphere()
		EntityColor P\Entity%,0,0,200
		
  Case 2


		TempID% = ReadByte(Client%)
		
  For P.Player = Each Player

  If P\ID% = TempID%

		P\X# = ReadFloat(Client%)
		P\Y# = ReadFloat(Client%)
		P\Z# = ReadFloat(Client%)
		
	    P\DeltaX# = P\X# - EntityX(P\Entity%)
        P\DeltaY# = P\Y# - EntityY(P\Entity%)
        P\DeltaZ# = P\Z# - EntityZ(P\Entity%)

		;Delta the coordinates so he doesnt warp.
        P\DeltaX# = P\DeltaX#/100
        P\DeltaY# = P\DeltaY#/100
        P\DeltaZ# = P\DeltaZ#/100
 		Exit

  End If

  Next

  Case 3

		TempID% = ReadByte(Client%)
		
  For P.Player = Each Player

  If P\ID% = TempID%

		FreeEntity P\Entity%
		Delete P.Player
		
  End If

  Next

Default

		RuntimeError "Opcode not recognized " + TempMsg%

		WaitKey 
		End
		
End Select

End Function

Function ConstructWorld()

		PositionEntity Camera%,0,5,0
		Terrain% = CreatePlane()
		EntityColor Terrain%,0,150,0
		CreateCube()
		
End Function

Function Update()

  If KeyDown(200)

		MoveEntity Camera%,0,0,0.2
		
  End If


  If KeyDown(208)

		MoveEntity Camera%,0,0,-0.2
		
  End If


  If KeyDown(203)

		TurnEntity Camera%,0,0.5,0
		
  End If


  If KeyDown(205)

		TurnEntity Camera%,0,-0.5,0
		
  End If

		X# = EntityX(Camera%)
		Y# = EntityY(Camera%)
		Z# = EntityZ(Camera%)
		
		PositionEntity Camera%,X#,Y#,Z#

End Function

Function Handle_Coords()

  If MilliSecs() >= UpdateCounter% + UpdateDelay

		UpdateCounter% = MilliSecs()
		
		WriteByte(Client%,1)
		WriteFloat(Client%,X#)
		WriteFloat(Client%,Y#)
		WriteFloat(Client%,Z#)

  End If

End Function

Function UpdatePlayers()

  For P.Player = Each Player

  Color 0,0,255


  If EntityInView(P\Entity%,Camera%)

		CameraProject Camera%,EntityX(P\Entity%),EntityY(P\Entity%),EntityZ(P\Entity%)
		Text ProjectedX(),ProjectedY(),">" + P\Name$ + "<"
		
  End If

		TranslateEntity P\Entity%,P\DeltaX#,P\DeltaY#,P\DeltaZ#
		
  Next

End Function