#include "tier2/ifilesystem.h" #include "entitysystem.h" #include "baseentity.h" #include "enginebridge.h" #include "game.h" #include "inetworkserver.h" #include "netprotocol.h" #include "tier1/utlvector.h" #include "iphysics.h" #ifdef STEAM #include "steam/isteamgameserver.h" #include "steam/steam_gameserver.h" #endif 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; bool m_bIsConnectedToSteamRelay; float m_fNetUpdateTimer; }; IEngineBridge *EngineBridge() { static CFunnyGameBridge s_bridge; return &s_bridge; } EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION) uint32_t NET_ServerCallback( NetCallback_t *pCallback ) { if (pCallback->m_eType == NET_SERVER_READY_TO_USE) { V_printf("//--- LAUNCHED SERVER AT ---\n"); V_printf("// %llu\n", SteamGameServer()->GetSteamID().ConvertToUint64()); return 0; } if (pCallback->m_eType == NET_TRYING_TO_CONNECT) { V_printf("user %llu is trying to connect\n", pCallback->m_ullUserID); return 1; } 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}); } int iIndex = -1; CBaseEntity *pEntity; pEntity = EntitySystem()->CreateByClassname("player", &iIndex); pEntity->Spawn(); SetLocalEntity_t stLocalEntity = { k_EMessage_PlayerSetLocalEntity, iIndex, }; if (g_pCurrentConnection) g_pCurrentConnection->SendPacket({&stLocalEntity, sizeof(stLocalEntity), pCallback->m_ullUserConnection, PACKET_MUST_ARRIVE}); return 1; } return 0; } void CFunnyGameBridge::Init() { if (g_pEngineConstants->m_bIsDedicated == false) g_pClientBridge = g_pEngineConstants->LaunchLocalBridge(0); g_pPublicConnection = NULL; g_pCurrentConnection = g_pClientBridge; #ifdef STEAM if (g_pEngineConstants->m_bIsSteam) { 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\n", err); } SteamNetworkingUtils()->InitRelayNetworkAccess(); } if (g_pEngineConstants->m_bIsDedicated && g_pEngineConstants->m_bIsSteam) { SteamGameServer()->SetModDir("funnygame"); SteamGameServer()->SetProduct("funnygame"); SteamGameServer()->SetGameDescription("not that funny but ok"); SteamGameServer()->LogOnAnonymous(); SteamNetworkingUtils()->InitRelayNetworkAccess(); SteamGameServer()->SetDedicatedServer(true); SteamGameServer()->SetMaxPlayerCount(128); SteamGameServer()->SetAdvertiseServerActive(true); } if (g_pEngineConstants->m_bIsSteam) { } #endif m_fNetUpdateTimer = 0; CreateInterfaceFn fnPhysicsFactory = Sys_GetFactory("RapierPhysics"); g_pPhysics = (IPhysics*)fnPhysicsFactory(PHYSICS_INTERFACE_VERSION, NULL); g_pPhysicsWorld = g_pPhysics->CreateWorld(); } void CFunnyGameBridge::Tick( float fDelta ) { } void NET_ProcessPacket( INetworkBase *pBase ) { NetPacket_t packet = pBase->PeekPacket(); // discard it if (packet.uSize < sizeof (EMessageType)) { pBase->RecievePacket(); return; } PlayerPacket_t *pPacket = (PlayerPacket_t*)packet.pData; CBaseEntity *pEntity; switch (pPacket->m_eType) { case MESSAGE_PLAYER_JOINED: { // online packets don't generate these if (g_pEngineConstants->m_bIsDedicated) break; pBase->RecievePacket(); int iIndex = -1; V_printf("Hi %s\n",pPacket->m_playerJoined.m_szPlayerName); pEntity = EntitySystem()->CreateByClassname("player", &iIndex); pEntity->Spawn(); SetLocalEntity_t stLocalEntity = { k_EMessage_PlayerSetLocalEntity, iIndex, }; if (g_pCurrentConnection) g_pCurrentConnection->SendPacket({&stLocalEntity, sizeof(stLocalEntity), 0, PACKET_MUST_ARRIVE}); } return; default: break; } pBase->RecievePacket(); } void CFunnyGameBridge::Frame( float fDelta ) { g_pEngineVars->m_fTime += fDelta; g_pEngineVars->m_fDeltaTime = fDelta; #ifdef STEAM if (g_pEngineConstants->m_bIsSteam && g_pEngineConstants->m_bIsDedicated) { if (m_bIsConnectedToSteamRelay == 0 && SteamNetworkingUtils()->GetRelayNetworkStatus(NULL) == k_ESteamNetworkingAvailability_Current) { m_bIsConnectedToSteamRelay = 1; g_pPublicConnection = g_pEngineConstants->LaunchServer( FUNNY_SECURE_PORT ); g_pPublicConnection->SetCallback(NET_ServerCallback); g_pCurrentConnection = g_pPublicConnection; return; } SteamGameServer_RunCallbacks(); } #endif if (g_pCurrentConnection) { g_pCurrentConnection->NetThink(); while (g_pCurrentConnection->BHasUpdates()) NET_ProcessPacket(g_pCurrentConnection); } float fTickRate = 1.0/60.0; m_fNetUpdateTimer += fDelta; while (m_fNetUpdateTimer >= fTickRate) { m_fNetUpdateTimer-=fTickRate; if (g_pCurrentConnection) { g_pPhysicsWorld->Frame(fTickRate); EntitySystem()->Think(); EntitySystem()->NetThink(g_pCurrentConnection); } } } 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(FILESYSTEM_INTERFACE_VERSION, filesystem); CONNECT_INTERFACE("EngineConstants", g_pEngineConstants) }