network help:someone please check this code out
Blitz3D Forums/Blitz3D Programming/network help:someone please check this code out
| ||
this is my server i wrote....can I have some suggestions on optmizing this tcp server? I see that some have used banks....can you explain the need and benefits of banks verses strings? Probably takes more bytes to send for string anyway here is code: the client sends 1,x,y,z,rx,ry,rz,animseq,animframe,name$ everytime a move is made to synch up animation and position/rotation here is the server Type netplayer Field netid# Field name$ Field port$ Field ip$ Field stream Field x#,y#,z#,rx#,ry#,rz# Field animframe# Field AniSeq# Field updated# End Type Global currentid# Dim splitdata$(10) Graphics3D 800,600,0,2 AppTitle "Server 1.0 beta" server=CreateTCPServer(8080) Print "Server Again 1.0 beta" If server<>0 Print "Server Accepting Connections..." Print "press escape to close" EndIf Global currentcount=0 While Not KeyDown(1) stream = AcceptTCPStream(server) If stream currentcount=currentcount+1 WriteLine(stream,currentcount) Print "New Net Player Joined : Player ID:"+currentcount n.netplayer=New netplayer n\netid=currentcount n\stream=stream n\ip$=DottedIP$(TCPStreamIP(stream)) n\port$=TCPStreamPort(stream) n\x=0:n\y=0:n\z=0:n\rx=0:n\ry=0:n\rz=0 For existing.netplayer=Each netplayer ; send all player locations - animation positions for existing players If existing\netid<>n\netid WriteLine(n\stream,1+","+existing\netid+","+existing\x+","+existing\y+","+existing\z+","+existing\rx+","+existing\ry+","+existing\rz+","+existing\aniseq+","+existing\animframe+","+existing\name$) ; notify new player of all existing players WriteLine(existing\stream,5+","+n\netid+","+n\x+","+n\y+","+n\z+","+n\rx+","+n\ry+","+n\rz+","+n\aniseq+","+n\animframe+","+n\name$) ; notify existing players of new player EndIf Next EndIf For n.netplayer=Each netplayer If Eof(n\stream)=True currentcount=currentcount-1 Print "player " + n\name$+ " has disconnected from ip address:" + n\ip$ + " and port " + n\port$ + " leaving " + currentcount + " clients connected." For dd.netplayer=Each netplayer WriteLine(dd\stream,6+","+n\netid+","+n\x+","+n\y+","+n\z+","+n\rx+","+n\ry+","+n\rz+","+n\aniseq+","+n\animframe+","+n\name$);notify all players that this player has Left Next Delete n Else If ReadAvail(n\stream)>2 Then message$ = ReadLine$(n\stream) If Instr(message$,",") d=split(message$) Select splitdata$(1) Case 1 ; update coordinates/rotation n\updated=1 n\x=Float(splitdata$(3)):n\y=Float(splitdata$(4)):n\z=Float(splitdata$(5)):n\rx=Float(splitdata$(6)):n\ry=Float(splitdata$(7)):n\rz=Float(splitdata$(8)) n\Aniseq=Int(splitdata$(9)):n\animframe=Int(splitdata$(10)):n\name$=splitdata$(11) ; Print 1+","+n\netid+","+n\x+","+n\y+","+n\z+","+n\rx+","+n\ry+","+n\rz+","+n\aniseq+","+n\animframe+","+n\name$ Case 2 ; send private message Print "sending a private" ; 2,chris,msg For p.netplayer=Each netplayer If p\name$=splitdata$(2) WriteLine(p\stream,"7,"+splitdata$(3)) EndIf Next End Select EndIf EndIf EndIf Next For n.netplayer=Each netplayer If n\updated=1 For q.netplayer=Each netplayer WriteLine(q\stream,1+","+n\netid+","+n\x+","+n\y+","+n\z+","+n\rx+","+n\ry+","+n\rz+","+n\aniseq+","+n\animframe+","+n\name$) Next n\updated=0 EndIf Next Wend CloseTCPServer(server) Function Split(DataToSplit$) ;Declare our variables Local splitcounter = 0, pntr = -1,chris=1, pntr2 = 0, counter = 0 ; Continue to check for splits until we reach the end of the string Local a=0 While pntr <> 0 pntr = Instr(datatosplit$, ",", chris) ; If we found a split then add 1 to the counter If pntr > 0 Then splitcounter = splitcounter + 1 chris=pntr+1 a=a+1 Wend ; Now we have the amount of items (-1) in the string so we can dimension our array Dim SplitData$(splitcounter + 1) ; the first item in the string is handled differently than the rest since there is no comma preceding it pntr = 0:pntr2 = Instr(DataToSplit$, ",", 1) SplitData$(1) = Left$(DataToSplit$, pntr2 - 1) ; After splitting off the first item we move on to the rest of the string. For counter = 2 To splitcounter ; These 2 pointers keep track of the beginning and ending of the item we are looking for in the string. pntr = pntr2 + 1 pntr2 = Instr(DataToSplit$, ",", pntr) ; Now that we have the items location we can pull it from the main string and insert it in to our return array SplitData$(counter) = Mid$(DataToSplit$, pntr, (pntr2 - pntr)) Next ; Once we have done every instance of the comma delimiters we are left with the very end of the string ; This also is handled differently than the rest of the string since there is no comma after it. SplitData$(counter) = Right$(DataToSplit$, Len(DataToSplit$) - pntr2) ; Now we can return the # of items located in the string back to the calling program. Return (splitcounter + 1) End Function |
| ||
does using banks speed things up? |
| ||
I don't think so in this instance. I believe the shortest possible packet size is obtained by sending a string. TBH, unfortunately, there isn't too many people round here that i've noticed, that have done much with multiplayer games, and your unlikely to find much help i'm sorry to say... I found it rather difficult last time round. |
| ||
so do you think sending EVERY time someone moves x,y,z,rx,ry,rz,name,animseq,animframe is too much? |
| ||
if so, whats the better way to handle that? |
| ||
What I do in my space combat sim, and it works quite well so far is this: On the server - every x milliseconds (I've set it to x=100) the server sends an update to all of the clients. Now, because mine is in 'space' with no obstructing terrain/rooms/scenery I am comfortable with sending the network update for all spaceships (read characters if it were an RPG I guess) to all the clients. You may gain some network performance if you only send data that is relevant to a particular client. I do a little bit of compression to keep the packets small, and I combine all the position/rotation values for each spaceship into a single packet, splitting it if it goes over about 500bytes. A basic update packet for my game from the server to the client looks something like this: ShipID -> 2 byte 'short' (converted to a 2 byte string - there will never be more than 65535 ships in a session as far as I'm concerned.) X/Y/Z -> 4 byte floats converted to 4 byte strings. Pitch/Yaw/Roll -> 1 byte for each -> pitch is always between -90 and +90 (I ignore the values after the decimal point) so I simply add 90 to make it between 0 and 180 and store as a single byte. -> Yaw and Roll are always between -180 and +180 (ignoring values after the decimal point), so I add 180 and scale it to fit into a byte (meaning values 0-255 only) by doing this to the angle = 255*((yaw + 180)/360) (same for pitch) Velocity -> 1 Byte converting a float into a single byte value (scaled assuming a maximum forwards velocity of 30 units per frame this scaled to be out of 255 to fit within a byte. To answer your question "do you think sending every time someone moves ....is too much" I would say yes, it is too much. I can only give my opinion based on my own game but here are some other tips: The server may not need to be told what animation frame / animation sequence is currently being played. If the client performs an animation perform it on their PC, send a message to the server saying that "character x has waved their sword about" which the server then sends to the other clients who can actually see the player with the sword. I would not send a 'name' to the server every time - it's not changing every time is it? An ID yes, but a 'name' no. No need to send "IAmTheGreatestGoblinKillerOfAllTime" across the network everytime that character turns around to have a look at something. Some messages are critical and some are allowed to have a bit of error in them. If a player dies or removes something from the world, or spawns something into the world then these are critical and should be 'guaranteed' messages. Other messages are less critical, even position / rotation updates as they can be corrected by a later message. Another thing, Pitch and Roll are not really all that important for characters walking on level ground, even on sloped ground to a large extent, so do you really need to send the pitch/roll values for your characters every time? I could write more but I hope that may be a start of sorts. |