From 0dc8f1b36f192b8b1b6764f7e3da3cd146f58b83 Mon Sep 17 00:00:00 2001 From: kotofyt Date: Mon, 2 Mar 2026 17:31:49 +0200 Subject: [PATCH] steam networking --- engine/steamnetwork.cpp | 10 +++++++++- game/client/assetmgr.cpp | 7 ++++++- game/client/assetmgr.h | 1 + game/client/basemodelentity.cpp | 6 ++++++ game/client/basemodelentity.h | 1 + game/client/entitysystem.cpp | 16 ++++++++++++++++ game/client/entitysystem.h | 3 +++ game/client/game.cpp | 8 ++++++++ game/client/worldrender.cpp | 24 ++++++++++++++++++++++++ game/client/worldrender.h | 2 ++ game/server/entitysystem.cpp | 3 ++- game/server/game.cpp | 23 +++++++++++++++++++---- game/server/milmoba/player.cpp | 1 + public/networkbase.h | 1 + 14 files changed, 99 insertions(+), 7 deletions(-) diff --git a/engine/steamnetwork.cpp b/engine/steamnetwork.cpp index 2515ed1..b3913c4 100644 --- a/engine/steamnetwork.cpp +++ b/engine/steamnetwork.cpp @@ -91,6 +91,13 @@ void CSteamNetworkServer::SendPacket( NetPacket_t stPacket ) m_pInterface->SendMessageToConnection(c, stPacket.pData, stPacket.uSize, k_nSteamNetworkingSend_Reliable, 0); } } + else + { + if (stPacket.m_eArrival == PACKET_MAY_ARRIVE) + m_pInterface->SendMessageToConnection(stPacket.m_uOwner, stPacket.pData, stPacket.uSize, k_nSteamNetworkingSend_Unreliable, 0); + if (stPacket.m_eArrival == PACKET_MUST_ARRIVE) + m_pInterface->SendMessageToConnection(stPacket.m_uOwner, stPacket.pData, stPacket.uSize, k_nSteamNetworkingSend_Reliable, 0); + } } bool CSteamNetworkServer::BIsActive() @@ -123,10 +130,12 @@ void CSteamNetworkServer::ClientConnected( SteamNetConnectionStatusChangedCallba case k_ESteamNetworkingConnectionState_Connecting: callback.m_eType = NET_TRYING_TO_CONNECT; callback.m_ullUserID = pParam->m_info.m_identityRemote.GetSteamID64(); + callback.m_ullUserConnection = pParam->m_hConn; break; case k_ESteamNetworkingConnectionState_Connected: callback.m_eType = NET_CONNECTED; callback.m_ullUserID = pParam->m_info.m_identityRemote.GetSteamID64(); + callback.m_ullUserConnection = pParam->m_hConn; m_pInterface->SetConnectionPollGroup(pParam->m_hConn, m_hPollGroup); m_hConnections.AppendTail(pParam->m_hConn); @@ -135,7 +144,6 @@ void CSteamNetworkServer::ClientConnected( SteamNetConnectionStatusChangedCallba break; } - V_printf("%p\n", m_fnCallback); if (m_fnCallback) uResult = m_fnCallback(&callback); else diff --git a/game/client/assetmgr.cpp b/game/client/assetmgr.cpp index 71894fc..d2f6fcc 100644 --- a/game/client/assetmgr.cpp +++ b/game/client/assetmgr.cpp @@ -64,7 +64,7 @@ uint32_t CAssetManager::LoadModel( const char *szName ) u++; continue; } - if (m->m_szName == szName) + if (m->m_szParentName == szName) { m_modelUsages[uFoundIndex]++; return u; @@ -81,6 +81,8 @@ uint32_t CAssetManager::LoadModel( const char *szName ) IFileHandle *pHandle = filesystem->Open(szName, FILEMODE_READ); CUtlString szProperties = filesystem->ReadString(pHandle); IJSONValue *pRoot = JSONManager()->ReadString(szProperties); + filesystem->Close(pHandle); + IJSONObject *pMainObject; CUtlString szMeshData; IVertexBuffer *pVertices; @@ -97,10 +99,13 @@ uint32_t CAssetManager::LoadModel( const char *szName ) } IJSONValue *pMesh = pMainObject->GetValue("mesh"); IJSONValue *pMaterial = pMainObject->GetValue("material"); + + CUtlString szMesh = pMesh->GetStringValue(); CUtlString szMaterial = pMaterial->GetStringValue(); m_models[uFoundIndex] = LoadModelFromParams(szMesh, szMaterial); + m_models[uFoundIndex]->m_szParentName = szName; m_modelUsages[uFoundIndex]++; return uFoundIndex; diff --git a/game/client/assetmgr.h b/game/client/assetmgr.h index feee259..a66e48a 100644 --- a/game/client/assetmgr.h +++ b/game/client/assetmgr.h @@ -20,6 +20,7 @@ struct FunnyModel_t CUtlString m_szName; IMesh *m_pMesh; FunnyMaterial_t *m_pFunnyMaterial; + CUtlString m_szParentName; }; diff --git a/game/client/basemodelentity.cpp b/game/client/basemodelentity.cpp index 4f00ba2..ceea1be 100644 --- a/game/client/basemodelentity.cpp +++ b/game/client/basemodelentity.cpp @@ -29,6 +29,12 @@ void C_BaseModelEntity::SetModel( const char *szName ) m_pInstance = g_pWorldRenderer->CreateInstance(m_pModel->m_pMesh); } +C_BaseModelEntity::~C_BaseModelEntity() +{ + g_pWorldRenderer->DestroyMeshInstance(m_pModel->m_pMesh, m_pInstance); + g_pAssetManager->UnrefModel(m_uModelIndex); +} + BEGIN_DATADESC(C_BaseModelEntity) END_DATADESC() diff --git a/game/client/basemodelentity.h b/game/client/basemodelentity.h index 17ebb8e..911bc8b 100644 --- a/game/client/basemodelentity.h +++ b/game/client/basemodelentity.h @@ -12,6 +12,7 @@ public: DECLARE_CLASS(C_BaseModelEntity, C_BaseEntity); DECLARE_DATADESC(); + virtual ~C_BaseModelEntity() override; virtual void Precache() override; virtual void Spawn() override; void Think( float fDelta ); diff --git a/game/client/entitysystem.cpp b/game/client/entitysystem.cpp index fb9f840..f85be41 100644 --- a/game/client/entitysystem.cpp +++ b/game/client/entitysystem.cpp @@ -120,6 +120,22 @@ IEntityFactory *CEntitySystem::GetFactoryByClassname( const char *szName ) return NULL; } +void CEntitySystem::DestroyEntityByIndex( uint32_t uIndex ) +{ + if ( uIndex >= MAX_EDICTS ) + return; + if (m_pEntities[uIndex]) + { + V_printf("Deleting: %i\n", uIndex); + delete m_pEntities[uIndex]; + m_pEntities[uIndex] = 0; + } +} + +void CEntitySystem::DestroyEntityByPtr( C_BaseEntity *pEntity ) +{ +} + void CEntitySystem::Think() { diff --git a/game/client/entitysystem.h b/game/client/entitysystem.h index c3e9c33..3baf152 100644 --- a/game/client/entitysystem.h +++ b/game/client/entitysystem.h @@ -25,6 +25,9 @@ public: virtual IEntityFactory *GetFactoryByClassname( const char *szName ); + virtual void DestroyEntityByIndex( uint32_t uIndex ); + virtual void DestroyEntityByPtr( C_BaseEntity *pEntity ); + virtual void Think(); virtual C_BaseEntity **GetEntities(); private: diff --git a/game/client/game.cpp b/game/client/game.cpp index ab1b3f3..a6b6de5 100644 --- a/game/client/game.cpp +++ b/game/client/game.cpp @@ -114,6 +114,11 @@ void CFunnyGameBridge::TryToConnectToServer() if (g_pServerConnection) { m_bIsConnectedToServer = true; + C_BaseEntity **ppEntities = EntitySystem()->GetEntities(); + for ( int i = 0; i < MAX_EDICTS; i++ ) + { + EntitySystem()->DestroyEntityByIndex(i); + } } return; } @@ -133,7 +138,9 @@ void CFunnyGameBridge::Frame( float fDelta ) pCurrentServer = g_pServerBridge; if (m_bIsConnectedToServer) if (g_pServerConnection->BIsActive()) + { pCurrentServer = g_pServerConnection; + } if (pCurrentServer) @@ -150,6 +157,7 @@ void CFunnyGameBridge::Frame( float fDelta ) switch (pPacket->m_eType) { case MESSAGE_ENTITY_CLASS_SYNC: + V_printf("MESSAGE_ENTITY_CLASS_SYNC: %u = %s\n", (uint32_t)pPacket->m_entityClass.m_uIndex, pPacket->m_entityClass.m_szEntityName); pEntity = EntitySystem()->CreateByClassnameWithIndex( (char*)pPacket->m_entityClass.m_szEntityName, pPacket->m_entityClass.m_uIndex ); diff --git a/game/client/worldrender.cpp b/game/client/worldrender.cpp index 9937958..4639d0e 100644 --- a/game/client/worldrender.cpp +++ b/game/client/worldrender.cpp @@ -120,6 +120,8 @@ public: virtual IMesh *CreateMesh( const char *szName ) override; virtual IMeshInstance *CreateInstance( IMesh *pMesh ) override; + virtual void DestroyMeshInstance( IMesh *pMesh, IMeshInstance *pInstance ) override; + virtual void DestroyMesh( IMesh *pMesh ) override; virtual void ConfigureShader( IShader *pShader ) override; private: @@ -355,3 +357,25 @@ IMeshInstance *CFunnyWorldRenderer::CreateInstance( IMesh *pMesh ) return pInstance; } +void CFunnyWorldRenderer::DestroyMeshInstance( IMesh *pMesh, IMeshInstance *pInstance ) +{ + if (!pMesh) + return; + CFunnyMesh *pFunnyMesh = (CFunnyMesh*)pMesh; + for ( uint32_t i = 0; i < pFunnyMesh->m_instances.GetSize(); i++ ) + { + if ( pFunnyMesh->m_instances[i] != pInstance) + continue; + delete pFunnyMesh->m_instances[i]; + pFunnyMesh->m_instances.RemoveAt(i, 1); + break; + + } + +} + +void CFunnyWorldRenderer::DestroyMesh( IMesh *pMesh ) +{ + +} + diff --git a/game/client/worldrender.h b/game/client/worldrender.h index 8e759f2..2d27c0f 100644 --- a/game/client/worldrender.h +++ b/game/client/worldrender.h @@ -42,6 +42,8 @@ public: virtual IMesh *CreateMesh( const char *szName ) = 0; virtual IMeshInstance *CreateInstance( IMesh *pMesh ) = 0; + virtual void DestroyMeshInstance( IMesh *pMesh, IMeshInstance *pInstance ) = 0; + virtual void DestroyMesh( IMesh *pMesh ) = 0; virtual void ConfigureShader( IShader *pShader ) = 0; }; diff --git a/game/server/entitysystem.cpp b/game/server/entitysystem.cpp index ded7242..e09c449 100644 --- a/game/server/entitysystem.cpp +++ b/game/server/entitysystem.cpp @@ -93,7 +93,7 @@ CBaseEntity *CEntitySystem::CreateByClassname( const char *szName ) }; V_strncpy((char*)stClassSync.m_szEntityName, szName, 256); if (g_pCurrentConnection) - g_pCurrentConnection->SendPacket({&stClassSync, sizeof(stClassSync)}); + g_pCurrentConnection->SendPacket({&stClassSync, sizeof(stClassSync), 0, PACKET_MUST_ARRIVE}); return pEntity; } IEntityFactory *CEntitySystem::GetFactoryByClassname( const char *szName ) @@ -109,6 +109,7 @@ IEntityFactory *CEntitySystem::GetFactoryByClassname( const char *szName ) } return NULL; } + void CEntitySystem::Think() { CBaseEntity *pEntity; diff --git a/game/server/game.cpp b/game/server/game.cpp index 9e14cb4..2f46498 100644 --- a/game/server/game.cpp +++ b/game/server/game.cpp @@ -5,6 +5,7 @@ #include "game.h" #include "inetworkserver.h" #include "netprotocol.h" +#include "tier1/utlvector.h" #ifdef STEAM #include "steam/isteamgameserver.h" #include "steam/steam_gameserver.h" @@ -44,7 +45,6 @@ EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION uint32_t NET_ServerCallback( NetCallback_t *pCallback ) { - V_printf("hi %u\n", pCallback->m_eType); if (pCallback->m_eType == NET_SERVER_READY_TO_USE) { V_printf("//--- LAUNCHED SERVER AT ---\n"); @@ -59,6 +59,21 @@ uint32_t NET_ServerCallback( NetCallback_t *pCallback ) if (pCallback->m_eType == NET_CONNECTED) { V_printf("user %llu has connected, hi!\n", pCallback->m_ullUserID); + + CBaseEntity **ppEntitites = EntitySystem()->GetEntities(); + for ( int i = 0; i < MAX_EDICTS; i++ ) + { + if (ppEntitites[i] == NULL) + continue; + EntityClass_t stClassSync = { + MESSAGE_ENTITY_CLASS_SYNC, + i, + }; + V_strncpy((char*)stClassSync.m_szEntityName, ppEntitites[i]->m_szClassName, 256); + if (g_pCurrentConnection) + g_pCurrentConnection->SendPacket({&stClassSync, sizeof(stClassSync), pCallback->m_ullUserConnection, PACKET_MUST_ARRIVE}); + } + CBaseEntity *pEntity; pEntity = EntitySystem()->CreateByClassname("player"); pEntity->Spawn(); @@ -79,7 +94,7 @@ void CFunnyGameBridge::Init() SteamErrMsg err = { 0 }; if (SteamGameServer_InitEx(INADDR_ANY, FUNNY_SECURE_PORT, FUNNY_QUERY_PORT, eServerModeAuthentication, "0.0.0.0", &err)); { - V_printf("SteamGameServer_InitEx: %s", err); + V_printf("SteamGameServer_InitEx: %s\n", err); } SteamNetworkingUtils()->InitRelayNetworkAccess(); } @@ -129,7 +144,7 @@ void NET_ProcessPacket( INetworkBase *pBase ) V_printf("Hi %s\n",pPacket->m_playerJoined.m_szPlayerName); pEntity = EntitySystem()->CreateByClassname("player"); pEntity->Spawn(); - break; + return; default: break; } @@ -144,7 +159,6 @@ void CFunnyGameBridge::Frame( float fDelta ) #ifdef STEAM if (g_pEngineConstants->m_bIsSteam && g_pEngineConstants->m_bIsDedicated) { - SteamGameServer_RunCallbacks(); if (m_bIsConnectedToSteamRelay == 0 && SteamNetworkingUtils()->GetRelayNetworkStatus(NULL) == k_ESteamNetworkingAvailability_Current) { m_bIsConnectedToSteamRelay = 1; @@ -153,6 +167,7 @@ void CFunnyGameBridge::Frame( float fDelta ) g_pCurrentConnection = g_pPublicConnection; return; } + SteamGameServer_RunCallbacks(); } #endif if (g_pCurrentConnection) diff --git a/game/server/milmoba/player.cpp b/game/server/milmoba/player.cpp index dda4512..097eeee 100644 --- a/game/server/milmoba/player.cpp +++ b/game/server/milmoba/player.cpp @@ -6,6 +6,7 @@ void CMOBAPlayer::Spawn() { SetThink(Think); + m_fTimer = 0; }; void CMOBAPlayer::Think( float fDelta ) diff --git a/public/networkbase.h b/public/networkbase.h index e4609d8..bd731b6 100644 --- a/public/networkbase.h +++ b/public/networkbase.h @@ -31,6 +31,7 @@ struct NetCallback_t { ENetCallbackType m_eType; uint64_t m_ullUserID; + uint64_t m_ullUserConnection; }; typedef uint32_t (*NetCallbackFn)( NetCallback_t *pUser );