Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
194 lines
7.5 KiB
QBasic
194 lines
7.5 KiB
QBasic
Attribute VB_Name = "modDplay"
|
|
Option Explicit
|
|
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
|
|
|
|
'We want to keep the amount of data we send down to a bare minimum. Use the lowest
|
|
'data type we can. For example, even though Enums are by default Long's
|
|
'We will never have more than 255 messages for this application so we will convert
|
|
'them all to bytes when we send them
|
|
Public Enum vbDplayHockeyMsgType
|
|
MsgSendGameSettings 'The settings for the application to run under
|
|
MsgPaddleLocation 'The location of a particular paddle
|
|
MsgPuckLocation 'The location of the puck
|
|
MsgPlayerScored 'Someone just scored
|
|
MsgClientConnectedAndReadyToPlay 'The client is connected, has received the game settings and is ready to play
|
|
MsgRestartGame 'Time to restart the game
|
|
MsgCollidePaddle 'Used only for sound effects...
|
|
End Enum
|
|
|
|
'Constants
|
|
Public Const AppGuid = "{AC35AAB4-32D3-465d-96C3-4F4137FBF9A1}"
|
|
'Minimum frequency to allow sending data (in ms)
|
|
'Regardless of network latency, we never want to send more than 20 msgs/second
|
|
'which equates to a minimum send frequency of 50
|
|
Public Const glMinimumSendFrequency As Long = 1000 \ 20
|
|
'Main Peer object
|
|
Public dpp As DirectPlay8Peer
|
|
'PlayerID of the user who is connected
|
|
Public glOtherPlayerID As Long
|
|
|
|
'App specific variables
|
|
Public gsUserName As String
|
|
'Our connection form and message pump
|
|
Public DPlayEventsForm As DPlayConnect
|
|
'How often we should send our paddles information
|
|
Public glSendFrequency As Long
|
|
'The amount of latency between two systems
|
|
'(calculated as Avg(RoundTripLatency)/2)
|
|
Public glOneWaySendLatency As Long
|
|
'We have disconnected from the session. Stop sending data
|
|
Public gfNoSendData As Boolean
|
|
|
|
Public Sub InitDPlay()
|
|
'Create our DX/DirectPlay objects
|
|
If dx Is Nothing Then Set dx = New DirectX8
|
|
Set dpp = dx.DirectPlayPeerCreate
|
|
glSendFrequency = glMinimumSendFrequency
|
|
End Sub
|
|
|
|
Public Sub CleanupDPlay()
|
|
On Error Resume Next
|
|
If Not (DPlayEventsForm Is Nothing) Then
|
|
If Not (dpp Is Nothing) Then dpp.UnRegisterMessageHandler
|
|
DPlayEventsForm.DoSleep 50
|
|
'Get rid of our message pump
|
|
DPlayEventsForm.GoUnload
|
|
'Close down our session
|
|
If Not (dpp Is Nothing) Then dpp.Close
|
|
'Lose references to peer and dx objects
|
|
Set dpp = Nothing
|
|
Set dx = Nothing
|
|
End If
|
|
End Sub
|
|
|
|
Public Sub UpdateNetworkSettings()
|
|
|
|
Dim lMsg As Long, lNumMsg As Long, lNumByte As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
Static lLastSendTime As Long
|
|
Static lLastSendCount As Long
|
|
|
|
On Error Resume Next 'in case we are already in this sub when we receive our connection terminated message
|
|
If gfGameOver Then Exit Sub
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfGameCanBeStarted Then Exit Sub
|
|
'First lets check the current send queue information. IF the queue is building up,
|
|
'then we need to bump up the frequency so we don't oversaturate our line.
|
|
dpp.GetSendQueueInfo glOtherPlayerID, lNumMsg, lNumByte
|
|
If lNumMsg > 3 Or lNumByte > 256 Then
|
|
'We are sending data to fast, slow down
|
|
glSendFrequency = glSendFrequency + glMinimumSendFrequency
|
|
End If
|
|
'Here we will send the current game state (puck, and paddle information), and we will send this information
|
|
'not faster than the glSendFrequency (which will be throttled according to latency)
|
|
If timeGetTime - lLastSendTime > glSendFrequency Then
|
|
If gfHost Then
|
|
lLastSendCount = lLastSendCount + 1
|
|
'We will not send the puck every time
|
|
If lLastSendCount > 3 Then
|
|
'Update puck
|
|
'SendPuck 0
|
|
lLastSendCount = 0
|
|
End If
|
|
End If
|
|
|
|
'Now send our paddle
|
|
lMsg = MsgPaddleLocation
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset 'Msg
|
|
AddDataToBuffer oBuf, CByte(glMyPaddleID), SIZE_BYTE, lOffset 'Paddle ID
|
|
AddDataToBuffer oBuf, goPaddle(glMyPaddleID).Position, LenB(goPaddle(glMyPaddleID).Position), lOffset 'Paddle information
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, 0
|
|
lLastSendTime = timeGetTime
|
|
End If
|
|
|
|
End Sub
|
|
|
|
Public Sub NotifyClientReady()
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
If gfHost Then Exit Sub 'Only the client needs to tell the host
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgClientConnectedAndReadyToPlay
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH
|
|
gfGameCanBeStarted = True
|
|
End Sub
|
|
|
|
Public Sub NotifyPlayersWeScored()
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
If Not gfHost Then Exit Sub
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgPlayerScored
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH
|
|
End Sub
|
|
|
|
Public Sub NotifyGameRestart()
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgRestartGame
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH
|
|
End Sub
|
|
|
|
Public Sub SendGameSettings()
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
If Not gfHost Then Exit Sub
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgSendGameSettings
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
AddDataToBuffer oBuf, gnVelocityDamp, LenB(gnVelocityDamp), lOffset
|
|
AddDataToBuffer oBuf, glUserWinningScore, LenB(glUserWinningScore), lOffset
|
|
AddDataToBuffer oBuf, gnPaddleMass, LenB(gnPaddleMass), lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH
|
|
End Sub
|
|
|
|
Public Sub SendPuck(Optional ByVal lFlags As Long = (DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH))
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgPuckLocation
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
AddDataToBuffer oBuf, goPuck.Position, LenB(goPuck.Position), lOffset
|
|
AddDataToBuffer oBuf, goPuck.Velocity, LenB(goPuck.Velocity), lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, lFlags
|
|
End Sub
|
|
|
|
Public Sub SendCollidePaddle()
|
|
Dim lMsg As Long
|
|
Dim lOffset As Long, oBuf() As Byte
|
|
|
|
If gfNoSendData Then Exit Sub
|
|
If Not gfMultiplayer Then Exit Sub
|
|
'Here we will tell the host we are ready to play
|
|
lMsg = MsgCollidePaddle
|
|
AddDataToBuffer oBuf, CByte(lMsg), SIZE_BYTE, lOffset
|
|
'We will send this information to the other player only
|
|
dpp.SendTo glOtherPlayerID, oBuf, glSendFrequency, DPNSEND_GUARANTEED Or DPNSEND_PRIORITY_HIGH
|
|
End Sub
|
|
|