Hi.
Ich habe bereits überlegt auf Client-seite einen Thread zu starten, der permanent auf Netzwerk (Server) Infos hört und in eine To-Do-Liste schreibt. Dies dann, wenn das Hauptprogramm an der zu verarbeitenden Stelle ist eben die Liste abarbeitet.
Mutex und Co sind mir bekannt - allerdings entsprechend langsam. Dies wäre meine Momentane Lösung:
Thread der alle Netzwerkdaten einliest. solange ist dort ein Mutex für reserviert. Kommt das Hauptprogramm an die stelle wird der Thread angehalten (per stop oder mutex) und alles abgearbeitet. Danach sozusagen "zurückgeschaltet" und der Thread bekommt den Mutex. Alle To-Dos in einer Linklist (strukturiert mit ClientID, NetString$).
Das ganze basiert übrigens auf dem TCP-Protokoll.
Gerne würde ich etwas Code zur Verfügung stellen, aber ich kann wohl kaum die 5.900 Zeilen hier posten oder?
Code: Alles auswählen
Procedure GetServerEvents()
Protected x, y, tox, toy, playerid, ammopower, speed, ammotype, playername$, uniqueID, targetuniqueID, spriteID, dummy, angle, attackeruniqueID
Protected DistanceX, DistanceY, attackerElementID, *targetSpriteHND, AttackerSpriteID, *buffer, *hndPackFile
Protected lFile
; get the event
Select NetworkClientEvent(netServerID)
Case #PB_NetworkEvent_Data
netServerString$ = SK_ReceivenetworkString(netServerID)
; netmessage interpreter
Select StringField(netServerString$, 1, Chr(32))
Case "SET"
Select StringField(netServerString$, 2, Chr(32))
Case "OWNER"
; "SET OWNER " + Str(\uniqueID) + Chr(32) + LocalPlayerName$
targetuniqueID = Val(StringField(netServerString$, 3, Chr(32)))
playername$ = StringField(netServerString$, 4, Chr(32))
; Get player ID
ForEach Players()
If Players()\Name$ = playername$
playerid = ListIndex(Players())
Break
EndIf
Next
; Find the right Unit to change owner
ForEach unit()
If unit()\uniqueID = targetuniqueID
unit()\OwnerID = playerid
AddSystemMessage("An Agent has hacked a " + unit()\Name$)
EndIf
Next
EndSelect
Case "+RH"
; NEWRESEARCH TypeofResearch Playername$
playername$ = StringField(netServerString$, 2, Chr(32))
If playername$ <> LocalPlayerName$
dummy = Val( StringField(netServerString$, 3, Chr(32)))
AddResearch(dummy, playername$)
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "MOVE" ; OK
; MOVE playername uniqueID fromx fromy tox toy speed
; 1 2 3 4 5 6 7 8
playername$ = StringField(netServerString$, 2, Chr(32))
If playername$ <> LocalPlayerName$
uniqueID = Val(StringField(netServerString$, 3, Chr(32)))
x = Val(StringField(netServerString$, 4, Chr(32)))
y = Val(StringField(netServerString$, 5, Chr(32)))
tox = Val(StringField(netServerString$, 6, Chr(32)))
toy = Val(StringField(netServerString$, 7, Chr(32)))
speed = Val(StringField(netServerString$, 8, Chr(32)))
ForEach Unit()
With Unit()
; catch the right unit
If \uniqueID = uniqueID
; Clear VP
VirtualPlayfield(px2Coord(x), px2Coord(y)) = #False
; Calculate Distance
DistanceX = Abs(px2Coord(x) + MapPosX - px2Coord(\posX))
DistanceY = Abs(px2Coord(y) + MapPosY - px2Coord(\posY))
\Energy - \EnergyToMove * (DistanceX + DistanceY)
\MoveToX = tox
\MoveToY = toy
\OperationMode = #unit_op_moving
; Play sound
PlayEffect(\SpriteID, #PB_Sound_Loop)
Break
EndIf
EndWith
Next
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "CHAT" ; OK
AddSystemMessage(Right(netServerString$, Len(netServerString$) - 5))
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "WELCOME" ; OK
AddSystemMessage(netServerString$)
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "+PLAYER"
playername$ = StringField(netServerString$, 2, Chr(32))
If playername$ <> LocalPlayerName$
; We think there is a new player
dummy = #True
; check if player is already listed
ForEach Players()
; Player already here
If Players()\Name$ = playername$
dummy = #False
Break
EndIf
Next
; Do we have a new player?
If dummy = #True
SelectElement(Players(), hndLocalPlayerElementID)
AddPlayer(#structure_research, playername$)
AddSystemMessage(playername$ + " has joined the battle")
EndIf
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "STARTUNIT"
Debug netServerString$
; STARTUNIT SpriteID, PlayerName$, x, y, uniqueID
playername$ = StringField(netServerString$, 3, Chr(32))
; Get rest of information
spriteID = Val(StringField(netServerString$, 2, Chr(32)))
x = Val(StringField(netServerString$, 4, Chr(32)))
y = Val(StringField(netServerString$, 5, Chr(32)))
uniqueID = Val(StringField(netServerString$, 6, Chr(32)))
; Find the right player (for listID) and add the unit
ForEach Players()
If Players()\Name$ = playername$
If Players()\Name$ = LocalPlayerName$
AddSystemMessage("You begin with a " + UnitNames(spriteID) + " at " + px2CoordStr(x, y))
MapPosX = px2Coord(x) - PlayfieldViewWidth / 2
MapPosY = px2Coord(y) - PlayfieldViewHeight / 2
If MapPosX <0 : MapPosX = 0 : EndIf
If MapPosY <0 : MapPosY = 0 : EndIf
EndIf
AddUnit(spriteid, ListIndex(players()), x, y, 0, uniqueID)
Break
EndIf
Next
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "+UT" ; OK
; +UNT TypeOfUnit, OwnerPlayername, PositionX.l, PositionY.l, Angle.w = 0, uniqueID.l = 0
; 1 2 3 4 5 6 7
; We need the playername / owner
playername$ = StringField(netServerString$, 3, Chr(32))
; Owner should not the local player
If playername$ <> LocalPlayerName$
; Get rest of information
spriteID = Val(StringField(netServerString$, 2, Chr(32)))
x = Val(StringField(netServerString$, 4, Chr(32)))
y = Val(StringField(netServerString$, 5, Chr(32)))
angle = Val(StringField(netServerString$, 6, Chr(32)))
uniqueID = Val(StringField(netServerString$, 7, Chr(32)))
; Find the right player (for listID) and add the unit
ForEach Players()
If Players()\Name$ = playername$
AddUnit(spriteid, ListIndex(players()), x, y, angle, uniqueID)
EndIf
Next
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "-PLAYER" ; OK
; PLAYERLOST Name$
playername$ = StringField(netServerString$, 2, Chr(32))
AddSystemMessage(playername$ + " has quit the game")
ForEach Players()
If Players()\Name$ = playername$
; Delete players units
ForEach Unit()
If Unit()\OwnerID = ListIndex(Players())
CreateSpriteExplosion(Unit()\PosX, Unit()\PosY, 200)
; Free coords on Virtualplayfield
VirtualPlayfield(px2Coord(Unit()\PosX), px2Coord(Unit()\PosY)) = #False
DeleteElement(unit())
EndIf
Next
; Delete Players Structures
ForEach Structures()
If Structures()\OwnerID = ListIndex(Players())
CreateSpriteExplosion(Structures()\PosX, Structures()\PosY, 400)
; Free coords on Virtualplayfield
; VirtualPlayfield(px2Coord(Structures()\PosX), px2Coord(Structures()\PosY)) = #False
For x = 0 To px2Coord(Structures()\SpriteWidth) -1
For y = 0 To px2Coord(Structures()\SpriteHeight) -1
VirtualPlayfield(px2Coord(Structures()\PosX) + x, px2Coord(Structures()\PosY) + y) = #False
Next y
Next x
DeleteElement(Structures())
EndIf
Next
; Delete Players Projectiles
ForEach Projectiles()
If Projectiles()\OwnerID = ListIndex(Players())
DeleteElement(Projectiles())
EndIf
Next
; Delete Player from List
DeleteElement(Players())
RenewPlayerInfos()
EndIf
Next
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "+SE" ; OK
; +STR " + Str(TypeOfUnit) + Chr(32) + Players()\Name$ + Chr(32) + Str(pxCoord(\PosX)) + Chr(32) + Str(pxCoord(\PosY)) + Chr(32) + Str(\Angle) + Chr(32) + Str(\uniqueID))
; 1 2 3 4 5 6 7
; We need the playername / owner
playername$ = StringField(netServerString$, 3, Chr(32))
; Owner should not the local player
If playername$ <> LocalPlayerName$
; Get rest of information
spriteID = Val(StringField(netServerString$, 2, Chr(32)))
x = Val(StringField(netServerString$, 4, Chr(32)))
y = Val(StringField(netServerString$, 5, Chr(32)))
angle = Val(StringField(netServerString$, 6, Chr(32)))
uniqueID = Val(StringField(netServerString$, 7, Chr(32)))
; Find the right player (for listID) and add the unit
ForEach Players()
If Players()\Name$ = playername$
AddStructure(spriteid, ListIndex(players()), x, y, angle, uniqueID)
EndIf
Next
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
Case "+PE" ; #### TODO
; "+PJT " + Str(SpriteID) + Chr(32) + Players()\Name$ + Chr(32) + Str(\AmmoPower) + Chr(32) + Str(\AmmoSpeed) + Chr(32) + Str(\uniqueID) + Chr(32) + Str(AttackerUniqueID) + Chr(32) + Str(TargetUniqueID))
; 1 2 3 4 5 6 7 8
playername$ = StringField(netServerString$, 3, Chr(32))
Debug "NET: " + netServerString$
; should not be hisself
If playername$ <> LocalPlayerName$
attackerElementID = 0
*targetSpriteHND = 0
; Get rest of information
spriteID = Val(StringField(netServerString$, 2, Chr(32)))
ammopower = Val(StringField(netServerString$, 4, Chr(32))) ; ammopower
speed = Val(StringField(netServerString$, 5, Chr(32))) ; ammospeed
uniqueID = Val(StringField(netServerString$, 6, Chr(32)))
attackeruniqueID = Val(StringField(netServerString$, 7, Chr(32)))
targetuniqueID = Val(StringField(netServerString$, 8, Chr(32)))
ForEach Unit()
; Do we have the attacker? Save Listid
If Unit()\uniqueID = attackeruniqueID
; save ListID
AttackerSpriteID = unit()\SpriteID
; save start-position
x = Unit()\PosX
y = Unit()\PosY
; Do we have the target? Save handle of list
ElseIf Unit()\uniqueID = targetuniqueID
; save Handle of target
*targetSpriteHND = @Unit()
; save end-position
tox = Unit()\PosX
toy = Unit()\PosY
EndIf
Next
ForEach Structures()
; Do we have the attacker? Save Listid
If Structures()\uniqueID = attackeruniqueID
; save ListID
AttackerSpriteID = Structures()\SpriteID
; save start-position
x = Structures()\PosX
y = Structures()\PosY
; Do we Structures the target? Save handle of list
ElseIf Structures()\uniqueID = targetuniqueID
; save Handle of target
*targetSpriteHND = @Structures()
; save end-position
tox = Structures()\PosX
toy = Structures()\PosY
EndIf
Next
; Do we have everything?
If IsSprite(AttackerSpriteID) And *targetSpriteHND
ForEach Players()
; Find the right owner for the projectile
If players()\Name$ = playername$
AddProjectile(spriteID, ListIndex(Players()), AttackerSpriteID, *targetSpriteHND, x, y, tox, toy, ammopower, speed, uniqueID, attackeruniqueID, targetuniqueID)
AddSystemMessage(playername$ + " fired a " + ProjectileName(spriteID) + " from " + px2CoordStr(x, y) + " To " + px2CoordStr(tox, toy))
EndIf
Next
Else
AddSystemMessage("ERROR: Cannot start projectile. Missing Units")
EndIf
EndIf
; Server is waiting, sending an OK so he can continue
SK_SendNetworkString64(netServerID, #server_ok)
; +PJT SpriteID.l, OwnerPlayerID, AttackerElementID, *TargetSpriteHND, FromX, FromY, ToX, ToY, AmmoPower, AmmoSpeed, owneruniqueid, targetuniqueid
; 1 2 3 4 5 6 7 8 9 10 11 12 13
Default
AddSystemMessage("SERVER: " + netServerString$)
SK_SendNetworkString64(netServerID, #server_ok)
EndSelect
Case #PB_NetworkEvent_File
; Receive network file
If ReceiveNetworkFile(netServerID, ExePath$ + LocalPlayerName$ + "_Map.pak")
Debug "received networkfile"
; open packed file
If OpenPack(ExePath$ + LocalPlayerName$ + "_Map.pak")
Debug "map-pak open"
; delete old file
DeleteFile(ExePath$ + LocalPlayerName$ + "_Map.txt")
; unpack file
*hndPackFile = NextPackFile()
If *hndPackFile
Debug "map unpacked"
; *buffer = AllocateMemory(PackFileSize())
; UnpackMemory(*hndPackFile, *buffer)
; create new map-file
lFile = CreateFile(#PB_Any, ExePath$ + LocalPlayerName$ + "_Map.txt")
If lFile
If WriteData(lFile, *hndPackFile, PackFileSize()) = PackFileSize()
Debug "Map saved, loading"
CloseFile(lFile)
ClosePack()
LoadPlayfield(ExePath$ + LocalPlayerName$ + "_Map.txt")
CreateVirtualPlayfield()
AddSystemMessage("New Map received and loaded. Size: " + Str(PlayfieldSizeX) + "x" + Str(PlayfieldSizeY))
Else
AddSystemMessage("ERROR unpacking and saving map")
EndIf
Else
AddSystemMessage("ERROR cannot create map-file (txt)")
EndIf
Else
AddSystemMessage("ERROR no file in pack")
EndIf
Else
AddSystemMessage("ERROR creating map (pakfile)")
EndIf
Else
AddSystemMessage("ERROR receiving map (network)")
EndIf
EndSelect
EndProcedure
Ein Auszug aus dem Server (hier sind die Ankommenden Daten schon in Liste organisiert):