#include "tier2/ifilesystem.h" #include "tier0/commandline.h" #include "materialsystem/imaterialsystem.h" #include "enginebridge.h" #include "worldrender.h" #include "entitysystem.h" #include "baseentity.h" #include "game.h" #include "cglm/mat4.h" #include "cglm/cglm.h" #include "inetworkclient.h" #include "netprotocol.h" #ifdef STEAM #include "steam/isteamgameserver.h" #include "steam/steam_gameserver.h" #endif IFileSystem *filesystem; IRenderContext *g_pRenderContext; IGameWindow *g_pMainWindow; static CEngineVars s_vars; CEngineVars *g_pEngineVars = &s_vars; EngineConsts_t *g_pEngineConstants; INetworkBase *g_pServerBridge; INetworkBase *g_pServerConnection; class CFunnyGameBridge: public IEngineBridge { virtual void Init() override; virtual void Tick( float fDelta ) override; virtual void Frame( float fDelta ) override; virtual void Shutdown() override; virtual void ConnectInterface( const char *psz, void *pInterface ) override; void TryToConnectToServer(); bool m_bIsConnectedToSteamRelay; bool m_bIsConnectedToServer; }; IEngineBridge *EngineBridge() { static CFunnyGameBridge s_bridge; return &s_bridge; } EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION) void CFunnyGameBridge::Init() { g_pWorldRenderer->Init(); #ifdef STEAM if (g_pEngineConstants->m_bIsSteam) { SteamErrMsg err = { 0 }; m_bIsConnectedToSteamRelay = 0; SteamNetworkingUtils()->InitRelayNetworkAccess(); } #endif m_bIsConnectedToServer = false; g_pServerBridge = g_pEngineConstants->ConnectLocalBridge(0); if (g_pServerBridge) { PlayerJoined_t join = { MESSAGE_PLAYER_JOINED, "LocalPlayer" }; g_pServerBridge->SendPacket({&join, sizeof(join)}); } } void CFunnyGameBridge::Tick( float fDelta ) { } void *ENT_GetNetMapData(C_BaseEntity *pEntity, netmap_t *pMap, uint32_t uIndex ) { netmap_t *pCurrentMap = pMap; uint32_t uCurrentIndex = uIndex; searchIndex: if (uCurrentIndex >= pCurrentMap->m_uFieldCount) { if (!pCurrentMap->m_uFieldCount) return NULL; uCurrentIndex -= pCurrentMap->m_uFieldCount; pCurrentMap = pCurrentMap->m_pBase; if (!pCurrentMap) return NULL; goto searchIndex; } return (char*)pEntity+pCurrentMap->m_pFields[uCurrentIndex].m_uOffset; } void CFunnyGameBridge::TryToConnectToServer() { #ifdef STEAM if (g_pEngineConstants->m_bIsSteam) { if (m_bIsConnectedToSteamRelay != 0 ) return; if ( SteamNetworkingUtils()->GetRelayNetworkStatus(NULL) == k_ESteamNetworkingAvailability_Current) { m_bIsConnectedToSteamRelay = 1; V_printf("%llu\n", SteamUser()->GetSteamID().ConvertToUint64()); if (CommandLine()->ParamValue("-steam-connect")) { char *pEnd = NULL; uint64_t uValue = strtoull(CommandLine()->ParamValue("-steam-connect"), &pEnd, 10); g_pServerConnection = g_pEngineConstants->ConnectSteamServer(uValue, FUNNY_SECURE_PORT); if (g_pServerConnection) { m_bIsConnectedToServer = true; } return; } } } #endif } void CFunnyGameBridge::Frame( float fDelta ) { g_pEngineVars->m_fTime += fDelta; g_pEngineVars->m_fDeltaTime = fDelta; TryToConnectToServer(); INetworkBase *pCurrentServer = g_pServerBridge; pCurrentServer = g_pServerBridge; if (m_bIsConnectedToServer) if (g_pServerConnection->BIsActive()) pCurrentServer = g_pServerConnection; if (pCurrentServer) { pCurrentServer->NetThink(); while ( pCurrentServer->BHasUpdates() ) { NetPacket_t packet = pCurrentServer->PeekPacket(); // discard it if (packet.uSize < sizeof (EMessageType)) continue; PlayerPacket_t *pPacket = (PlayerPacket_t*)packet.pData; C_BaseEntity *pEntity; switch (pPacket->m_eType) { case MESSAGE_ENTITY_CLASS_SYNC: pEntity = EntitySystem()->CreateByClassnameWithIndex( (char*)pPacket->m_entityClass.m_szEntityName, pPacket->m_entityClass.m_uIndex ); if (pEntity == NULL) { pCurrentServer->RecievePacket(); continue; } pEntity->Spawn(); pCurrentServer->RecievePacket(); break; case MESSAGE_ENTITY_DATA_SYNC: pEntity = EntitySystem()->GetEntities()[pPacket->m_entityData.m_uIndex]; if (pEntity == NULL) { pCurrentServer->RecievePacket(); continue; } union { void *pData; char *pcCurrentData; EntityDataSyncValue_t *pcSyncValue; }; pData = pPacket; pcCurrentData += sizeof(EntityDataSync_t); for ( uint32_t u = 0; u < pPacket->m_entityData.m_uCount; u++ ) { uint32_t uVariableSize = pcSyncValue->m_uVariableSize; void *pValueData = (float*)ENT_GetNetMapData( pEntity, pEntity->GetRecvMap(), pcSyncValue->m_uVariableIndex); pcCurrentData += sizeof(EntityDataSyncValue_t); if (pValueData) V_memcpy(pValueData, pcCurrentData, uVariableSize); pcCurrentData += (uVariableSize+7) & ~7; } pCurrentServer->RecievePacket(); break; default: pCurrentServer->RecievePacket(); V_printf("worng packet\n"); continue; } } } EntitySystem()->Think(); g_pWorldRenderer->Frame(fDelta); } void CFunnyGameBridge::Shutdown() { } #define CONNECT_INTERFACE(szName, pGlobal) if (!V_strcmp(psz, szName)) { pGlobal = (typeof(pGlobal))pInterface; return; } void CFunnyGameBridge::ConnectInterface( const char *psz, void *pInterface ) { CONNECT_INTERFACE(RENDER_CONTEXT_INTERFACE_VERSION, g_pRenderContext); CONNECT_INTERFACE(FILESYSTEM_INTERFACE_VERSION, filesystem); CONNECT_INTERFACE("MainWindow", g_pMainWindow); CONNECT_INTERFACE("EngineConstants", g_pEngineConstants); }