Page 1 of 1
GameServer programming, fast with thread for every player.
Posted: Wed Jun 02, 2004 6:24 am
by DarkDragon
Hello,
I tried to make a GameServer, without threads, but then it was slow for the second, third, ... player, but not for the first.
Then Kooky told me I should create a thread for every player. I have done this, but I'm using a LinkedList. And if many threads are using the LinkedList at the same time, it will crash(I think this is the problem)

.
Here is the source:
http://mitglied.lycos.de/dani008/index.php?down=gam.zip
In the clientfile, I made 2 jumpcomments:
> Bullets network
> Refresh networkdata
They are showing you, where the networklines are.
Please help me with this problem.
Posted: Wed Jun 02, 2004 6:55 am
by Dreglor
having them all synced (there are libs out there that do that)
and have each player a diffrent offset on the timing so that no 2 threads will read the list
Posted: Wed Jun 02, 2004 7:21 am
by DarkDragon
Thx for the fast answer but which librarys do you mean?
Posted: Wed Jun 02, 2004 7:45 am
by Dreglor
Posted: Wed Jun 02, 2004 8:08 am
by DarkDragon
LOL, I made it with Global variables:
Code: Select all
InitNetwork()
Structure Client ;Playerdata
CData.l
Size.l
ID.l
Thread.l
EndStructure
Structure Object ;Bullets of the guns
ID.l
SX.l
SY.l
X.l
Y.l
CData.l
Size.l
EndStructure
OpenConsole() ;Open a primitive console
;Linked Lists for the bullets and the players
NewList Client.Client()
NewList OBJ.Object()
Global Port, Clients, Mode, ToSend, List, Stop.s, Threadmode
Port = 80
Stop.s = "STOP"
Procedure Player(ClientID)
Repeat
OldList = List
Select Mode
Case 0
If ClientID <> Client()\ID
SendNetworkData(ClientID, Client()\CData, Client()\Size)
EndIf
Case 1
SendNetworkData(ClientID, OBJ()\CData, OBJ()\Size)
Case 3
SendNetworkData(ClientID, @Stop, 4)
EndSelect
ToSend - 1
While ToSend > 0 And OldList = List
Delay(1)
Wend
Delay(15)
Until Quit = 1
EndProcedure
Procedure Thread()
Repeat
If Threadmode = 1
Mode = 0
ForEach Client()
List = ListIndex(Client())
ToSend = CountList(Client())
While ToSend > 0
Delay(1)
Wend
Next
Mode = 1
ForEach OBJ()
List = ListIndex(OBJ())
ToSend = CountList(OBJ())
While ToSend > 0
Delay(1)
Wend
Next
Mode = 3
Threadmode = 0
EndIf
Delay(15)
ForEver
EndProcedure
CreateNetworkServer(Port) ;Create the server
MainThread = CreateThread(@Thread(), 0)
Repeat
If Threadmode = 0
ForEach OBJ() ;moving the bullets
OBJ()\X + OBJ()\SX
OBJ()\Y + OBJ()\SY
KString.s = Str(OBJ()\X)+" "+Str(OBJ()\Y)+" "+Str(OBJ()\ID)+Chr(10)
OBJ()\CData = ReAllocateMemory(OBJ()\CData, Len(KString.s))
CopyMemory(@KString, OBJ()\CData, Len(KString))
OBJ()\Size = Len(KString)
Next
Select NetworkServerEvent()
Case 1 ;new client
AddElement(Client())
Client()\ID = NetworkClientID()
Client()\CData = AllocateMemory(1000)
Client()\Thread = CreateThread(@Player(), Client()\ID)
PrintN("Client: Login")
Clients + 1
Case 2
ClientID = NetworkClientID()
String.s = Space(1000)
Size.l = ReceiveNetworkData(ClientID, @String.s, 1000) ;Receiving the data
String = Left(String, Size)
For k=1 To CountString(String, Chr(10))
Text.s = StringField(String, k, Chr(10))
Select LCase(StringField(Text, 1, " "))
Case "del" ;Delete bullet
PauseThread(MainThread)
SelectElement(OBJ(), Val(StringField(Text, 2, " ")))
FreeMemory(OBJ()\CData)
DeleteElement(OBJ())
Case "new" ;New bullet
AddElement(OBJ())
KString.s = StringField(Text, 2, " ")+" "+StringField(Text, 3, " ")+" "+StringField(Text, 4, " ")+Chr(10)
OBJ()\CData = AllocateMemory(Len(KString.s))
CopyMemory(@KString, OBJ()\CData, Len(KString))
OBJ()\Size = Len(KString)
OBJ()\X = Val(StringField(Text, 2, " "))
OBJ()\Y = Val(StringField(Text, 3, " "))
OBJ()\ID = Val(StringField(Text, 4, " "))
OBJ()\SX = Val(StringField(Text, 5, " "))
OBJ()\SY = Val(StringField(Text, 6, " "))
Case "set" ;Playerposition
ForEach Client()
If Client()\ID = ClientID
Break
EndIf
Next
MText.s = Right(Text.s, Len(Text)-4)+Chr(10) ;Text without the command to do
Client()\CData = ReAllocateMemory(Client()\CData, Len(MText))
Client()\Size = Len(MText)
CopyMemory(@MText, Client()\CData, Len(MText))
EndSelect
Next
Case 4 ;Client disconnected
Clients - 1
ClientID = NetworkClientID()
ForEach Client()
If Client()\ID = ClientID
KillThread(Client()\Thread)
FreeMemory(Client()\CData)
DeleteElement(Client())
PrintN("Client: Logout")
Break
EndIf
Next
EndSelect
Threadmode = 1
EndIf
Delay(10)
ForEver
Then the client should have a new refresh proc:
Code: Select all
Procedure Refresh()
String.s = "SET "
String.s + Str(Player\X) + " "
String.s + Str(Player\Y) + " "
String.s + Str(Player\Skill[0]) + " "
String.s + Str(Player\Skill[1]) + " "
String.s + Str(Player\Skill[2]) + " "
String.s + Str(Player\Skill[3]) + " "
String.s + Str(Player\Skill[4]) + " "
SendNetworkString(ConnectionID, String.s+Chr(10))
t = 0
While NetworkClientEvent(ConnectionID) <> 2 And t <= 200 : WindowEvent() : t + 1 : Delay(1) : Wend
If t <= 200
String.s = Space(10000)
Size.l = ReceiveNetworkData(ConnectionID, @String.s, 10000)
String = Left(String, Size)
If CountString(String, Chr(10)) <> 0 ;Is there any data?
ClearList(Player())
ClearList(Bullet())
For k=1 To CountString(String, Chr(10))
Text.s = StringField(String, k, Chr(10))
If Val(StringField(Text, 3, " ")) <= #TEAM4
AddElement(Player())
Player()\X = Val(StringField(Text, 1, " "))
Player()\Y = Val(StringField(Text, 2, " "))
Player()\Skill[0] = Val(StringField(Text, 3, " "))
Player()\Skill[1] = Val(StringField(Text, 4, " "))
Player()\Skill[2] = Val(StringField(Text, 5, " "))
Player()\Skill[3] = Val(StringField(Text, 6, " "))
Player()\Skill[4] = Val(StringField(Text, 7, " "))
ElseIf Val(StringField(Text, 3, " ")) = #BULLET
AddElement(Bullet())
Bullet()\X = Val(StringField(Text, 1, " "))
Bullet()\Y = Val(StringField(Text, 2, " "))
Else : Break : EndIf
Next
EndIf
EndIf
EndProcedure
Posted: Wed Jun 02, 2004 8:16 am
by Dreglor
well what ever solves it

Posted: Wed Jun 02, 2004 11:49 am
by blueznl
just for my understanding, why would threads be faster?
i mean, a cpu has only so much processing power, or am i missing the point?
Posted: Wed Jun 02, 2004 11:54 am
by DarkDragon
Uhm the threads are faster, because they run all at the same time. So no player plays slower than another.
Posted: Wed Jun 02, 2004 12:02 pm
by blueznl
9 players, 0 is idle time
computing in one thread:
123456789
computing in 9 threads:
100000000
020000000
003000000
000400000
000050000
000006000
000000700
000000080
000000009
although cpu power is spread over the different players, each thread runs slower, effectively giving the same speed per player, unless your point is that you want to synchronize the players actions, ie. all players must have completed their actions before the first one can continue
is that the case?
Posted: Wed Jun 02, 2004 12:40 pm
by DarkDragon
thats what I wanted and what I reached.
Posted: Sat Sep 04, 2004 8:13 pm
by Nelligan
I'm toying with my mmorpg project network code. I first built upon a simple chat server and I was having lag and coordinates inconsistencies with just two players.
Then I saw this thread on threads

and I tested it with a friend. I run the server localy and me and my friend connect on it.
Is this code supposed to work well, because we don't see the same thing on our screens. The players positions are off and my friend sees my player at two places on the screen.
I'm searching for a simple working implementation of multiplayer code. I found a mmorpg in blitz basic but it's a little compicated to me.
Any suggestion would be appreciated. Thanks