Originally posted by Verrigan
Difficulty: Medium 3/5
This tutorial is designed to show you how to put a buffer system in your game. Why would you want to do that? Think about it. When a player connects, there are a series of messages sent to that player, and in Mirage, they are sent one right after the other.. If you have large maps, or you have a bunch of items/npcs/spells/etc., the server will send all that data to a user who is connecting.. For small games with small sized maps, this isn't a problem.. Lag is minimal. However, for games with tons of items, spells, etc., you will experience lag when another player connects.
Okay, now introduce a buffering (queue) system.. The server form has a timer that calls a subroutine that is solely responsible for dropping the size of the queue. How does the queue get filled? Instead of immediately sending any data to a player, you make the server add it to the queue. The server then hits the timer's interval, calls the subroutine to drop the queue, which sends messages to each user that is waiting for those messages. The subroutine will go through all connections, check the queue, and deliver messages to each user up to a predefined size limit for each user.. (This tutorial limits that size to 32K per user, per loop, but you can easily customize that limit.)
All that said, I must say that I have only tested this buffer system with one connection, so it might need some work, which is why I set the difficulty at 3.. Some of you might think the difficulty should be 5, but that's why I'm going to tell you this: BACKUP YOUR SERVER BEFORE ADDING THIS TUTORIAL.
Now, on with the tutorial..
Files to Modify
- frmServer.frm
- modGeneral.bas
- modServerTCP.bas
- modTypes.bas
*** In addition to the above files, you will need to change any line from:
Code:
Call CloseSocket(<whatever variable is used... Index, i, etc.>)
to:
Code:
QueueDisconnect(<same variable name... Index, i, etc.>) = True
frmServer.frmFrmServer is where timers and sockets are stored.. I don't like to do this, but my tutorials are based on the already existing code in the Mirage Source, not redoing the whole thing.. :P So...
Add a timer to the form named: tmrStartMsgQueue with an interval of 100. Then, in the code of frmServer, add the following code:
Code:
Private Sub tmrStartMsgQueue_Timer()
Call SendQueuedData
End Sub
modGeneral.basModGeneral is where general stuff happens.. The server is initialized here, the AI is in here, etc.
Add the following code somewhere:
Code:
Sub SendQueuedData()
Dim i As Integer, n As Long
Dim TmpStr As String
For i = 1 To MAX_PLAYERS
TmpStr = ""
With ConQueues(i)
If Not .Lock Then
If frmServer.Socket(i).State <> 7 Then
.Lines = ""
End If
If Len(.Lines) = 0 And QueueDisconnect(i) = True Then
Call CloseSocket(i)
QueueDisconnect(i) = False
Else
If Len(.Lines) > 0 Then
If Len(.Lines) < MAX_PACKETLEN Then
TmpStr = .Lines
Else
TmpStr = Left(.Lines, MAX_PACKETLEN)
End If
.Lines = Right(.Lines, Len(.Lines) - Len(TmpStr))
End If
End If
If Len(TmpStr) > 0 Then
Call frmServer.Socket(i).SendData(TmpStr)
End If
End If
End With
Next
DoEvents
End Sub
In Sub InitServer
After this code:
Code:
' Init all the player sockets
For i = 1 To MAX_PLAYERS
Call SetStatus("Initializing player array...")
Call ClearPlayer(i)
Load frmServer.Socket(i)
add this code:
Code:
ConQueues(i).Lines = "" 'Initialize the lines.
modServerTCP.basModServerTCP handles the data being sent from/received to the server.
In Sub SendDataTo()
Change this code:
Code:
If IsConnected(Index) Then
frmServer.Socket(Index).SendData Data
DoEvents
End If
to this code:
Code:
If IsConnected(Index) Then
With ConQueues(Index)
.Lock = True
.Lines = .Lines & Data
.Lock = False
End With
'DoEvents
End If
modTypes.basModTypes is where all the data types are stored, and other stuff...
Under this code:
Code:
Type GuildRec
Name As String * NAME_LENGTH
Founder As String * NAME_LENGTH
Member(1 To MAX_GUILD_MEMBERS) As String * NAME_LENGTH
End Type
add this code:
Code:
Type ConDataQueue
Lock As Boolean
Lines As String
End Type
Public ConQueues(MAX_PLAYERS) As ConDataQueue
Public Const MAX_PACKETLEN As Long = 32768 'About 32K
Public QueueDisconnect(MAX_PLAYERS) As Boolean
This was tested in a vanilla Mirage Source 3.0.3. So, if you add this to your game, and I only tested this with one player connected.. (I don't have a bunch of users, cause I don't run a Mirage server..
) Anyways.. Just like any other tutorials on here... BACKUP YOUR SOURCE!!! I said it twice, now... Hopefully you will take my advice..
It is also possible that I failed to put something in here.. In the event that you find that I forgot something, or you tried this in a vanilla server and it didn't work.. Please post here, but I'm pretty sure I remembered everything..