networking

This commit is contained in:
2025-07-13 15:47:42 +03:00
parent f5b26be510
commit a9c28b8940
345 changed files with 142130 additions and 174 deletions

View File

@@ -15,7 +15,7 @@ CUtlVector<CUtlString> engine_CompiledFiles = {
/* io */
"engine/input.cpp",
"engine/net.cpp",
"engine/networking.cpp",
/* entities */
@@ -62,6 +62,8 @@ int engine_build()
compileProject.bFPIC = true;
if (bStaticBuild)
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
if (bSteam)
compileProject.macros.AppendTail((C_Macro_t){"STEAM_ENABLED","1"});
ldProject = compileProject.Compile();
ldProject.libraries = engine_Libraries;
if (bStaticBuild)
@@ -69,7 +71,10 @@ int engine_build()
else
{
ldProject.objects.AppendTail((CObject){tier1_lib});
ldProject.objects.AppendTail((CObject){fgui_lib});
ldProject.objects.AppendTail((CObject){rapier_lib});
if (bSteam)
ldProject.objects.AppendTail((CObject){steam_lib});
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
}
@@ -83,9 +88,6 @@ int engine_build()
engine_lib = outputProject;
}
return 0;
};
DECLARE_BUILD_STAGE(engine, engine_build);

View File

@@ -2,7 +2,7 @@
#include "tier0/platform.h"
#include "tier1/utlstring.h"
CUtlSelfReferencingVector<CBaseEntity*> g_entities;
CUtlVector<CBaseEntity*> g_entities;
CUtlVector<CEntityRegistry*> g_RegisteredEntities;
CBaseEntity::CBaseEntity()

View File

@@ -47,6 +47,13 @@ void CBrushEntity::Think( float fDelta )
};
void CBrushEntity::Sync( void *pData, uint32_t nDataSize )
{
};
void CBrushEntity::ReadParameter( const char *szName, const char *szValue )
{
CBaseEntity::ReadParameter(szName, szValue);
@@ -143,6 +150,7 @@ void CBrushRendering::Init()
void CBrushRendering::Frame( float fDelta )
{
IRenderer::ResetState();
IRenderer::SetDepthMode(DEPTH_MODE_LESS);
IRenderer::BindPipeline(g_BrushPipeline);
struct {
mat4 i;

View File

@@ -1,4 +1,10 @@
#include "fgui/fgui.h"
#include "input.h"
#include "networking.h"
#include "steam/isteamgameserver.h"
#include "tier0/network.h"
#include "tier0/platform.h"
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
#include "tier0/lib.h"
@@ -10,15 +16,18 @@
#include "server.h"
#include "physics.h"
#include "signal.h"
#include "steam/steam_api.h"
#include "steam/steam_gameserver.h"
#include "networking.h"
double fPrev = 0;
double fCurrent = 0;
funnyphysics *px;
IIClient g_localClient;
IIClient *g_localClient;
CUtlVector<IIClient*> g_clients;
CUtlVector<IIClient*> g_clients = {};
//-----------------------------------------------------------------------------
// Purpose: Engine entry point
@@ -83,25 +92,66 @@ void IEngine::Init()
signal(SIGTERM, IEngine_Signal);
#endif
#ifdef STEAM_ENABLED
if(SteamAPI_RestartAppIfNecessary(480))
{
Plat_Exit(0);
}
if (!SteamAPI_Init())
{
V_printf("failed to init steam\n");
}
#endif
IFileSystem::InitFilesystem();
px = px_init();
if (!ICommandLine::CheckParam("-dedicated"))
{
g_localClient = {
};
IIEngine::ConnectClient(&g_localClient);
#ifdef STEAM_ENABLED
// Log in into steam
if (!SteamUser()->BLoggedOn())
{
SteamAPI_Shutdown();
Plat_FatalErrorFunc("User must be logged in to Steam");
}
#endif
// Run local client
g_localClient = new IIClient();
IIEngine::ConnectClient(g_localClient);
// Init IO
IVideo::Init();
IInput::Init();
IInput::SetMouseMode(MOUSE_MODE_GAME);
}
IFGUI::Init();
} else {
#ifdef STEAM_ENABLED
// Run dedicated server with steam
SteamGameServer_Init(0, 27015, 27016, eServerModeAuthentication, "0.0.0.0");
SteamGameServer()->SetProduct("funnygame");
SteamGameServer()->SetGameDescription("not that funny but ok");
SteamGameServer()->SetModDir("funnygame");
SteamGameServer()->SetDedicatedServer(true);
SteamGameServer()->LogOnAnonymous();
int nMaxPlayers = atoi(ICommandLine::ParamValue("-maxplayers", "128"));
SteamGameServer()->SetMaxPlayerCount(nMaxPlayers);
SteamGameServer()->SetAdvertiseServerActive(true);
#endif
}
INetworking::Init();
// load game
IServer::LoadGame("funnygame");
IVideo::CreatePipelines();
// create pipelines for rendering
if (!ICommandLine::CheckParam("-dedicated"))
IVideo::CreatePipelines();
// execute default config
IConsole::AddCommand("exec default.cfg;");
IConsole::Execute();
@@ -111,8 +161,16 @@ void IEngine::Init()
//-----------------------------------------------------------------------------
void IEngine::Frame(float fDelta)
{
#ifdef STEAM_ENABLED
SteamAPI_RunCallbacks();
#endif
INetworking::Frame();
IServer::Think(fDelta);
IVideo::Frame(fDelta);
if (!ICommandLine::CheckParam("-dedicated"))
{
IFGUI::Frame();
IVideo::Frame(fDelta);
}
};
//-----------------------------------------------------------------------------
@@ -120,12 +178,15 @@ void IEngine::Frame(float fDelta)
//-----------------------------------------------------------------------------
void IEngine::Shutdown()
{
INetworking::Deinit();
};
//-----------------------------------------------------------------------------
// Purpose: Spawns entity in the world
//-----------------------------------------------------------------------------
uint64_t g_lastServerID = 1;
uint64_t g_lastPredictedID = 1;
CBaseEntity *IIEngine::SpawnEntity( const char *szName )
{
for (auto &entity: g_RegisteredEntities)
@@ -133,7 +194,10 @@ CBaseEntity *IIEngine::SpawnEntity( const char *szName )
if (!V_strcmp(entity->m_szName, szName))
{
CBaseEntity *pEnt = entity->m_pfn();
pEnt->m_id = g_lastPredictedID+=1;
g_entities.AppendTail(pEnt);
if (ICommandLine::CheckParam("-dedicated"))
return pEnt;
if (entity->m_pClientfn)
{
pEnt->pClientEntity = entity->m_pClientfn();
@@ -162,13 +226,27 @@ void IIEngine::InitEntity( CBaseEntity *pEntity )
//-----------------------------------------------------------------------------
void IIEngine::DestroyEntity( CBaseEntity *pEntity )
{
uint32_t i = 0;
if (pEntity == NULL)
return;
for (auto &entity: g_entities)
{
if (pEntity == entity)
{
pEntity->Destroy();
if (pEntity->pClientEntity)
pEntity->pClientEntity->Destroy();
g_entities.RemoveAt(i);
return;
}
i++;
}
};
//-----------------------------------------------------------------------------
// Purpose: Connects client to the server
//-----------------------------------------------------------------------------
void IIEngine::ConnectClient( IIClient *pClient)
void IIEngine::ConnectClient( IIClient *pClient )
{
g_clients.AppendTail(pClient);
}
@@ -176,7 +254,37 @@ void IIEngine::ConnectClient( IIClient *pClient)
//-----------------------------------------------------------------------------
// Purpose: Disconnects client from the server
//-----------------------------------------------------------------------------
void IIEngine::DisconnectClient( IIClient *pClient)
void IIEngine::DisconnectClient( IIClient *pClient )
{
DisconnectClient(pClient->playerID);
}
void IIEngine::DisconnectClient( uint64_t playerID )
{
uint32_t i = 0;
for (auto &client: g_clients)
{
if (client->playerID == playerID)
{
g_clients.RemoveAt(i);
break;
}
i++;
}
};
void IIEngine::DisconnectClientByHandle( uint32_t playerHandle )
{
uint32_t i = 0;
for (auto &client: g_clients)
{
if (client->playerHandle == playerHandle)
{
IIEngine::DestroyEntity((CBaseEntity*)client->pBasePlayer);
g_clients.RemoveAt(i);
break;
}
i++;
}
};

View File

@@ -1,8 +1,14 @@
#include "gamemode.h"
#include "engine.h"
#include "playerstart.h"
#include "networking.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
CGameMode *pCurrentMode = NULL;
CUtlString szCurrentModeName;
CUtlVector<CGameModeRegistry*> g_RegisteredGameModes;
//-----------------------------------------------------------------------------
// Round begin handler
@@ -26,6 +32,17 @@ void CGameMode::RoundBegin( void )
pSelectedStart->RoundStart(player);
i++;
}
for (auto &client: g_clients)
{
CSteamID steamID = CSteamID();
if ( client->playerID == 0)
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
else
V_printf("%s\t", SteamFriends()->GetPersonaName());
V_printf("%llu\t", client->playerID);
V_printf("%u\n", client->playerHandle);
}
}
//-----------------------------------------------------------------------------
@@ -49,25 +66,35 @@ void IGameModeManager::Init( void )
//-----------------------------------------------------------------------------
void IGameModeManager::Frame( void )
{
}
//-----------------------------------------------------------------------------
// Sets gamemode
//-----------------------------------------------------------------------------
void IGameModeManager::StartGameMode(CGameMode *pGameMode)
void IGameModeManager::StartGameMode( const char *szName )
{
V_printf("starting game mode %s\n", szName);
if (pCurrentMode)
{
pCurrentMode->RoundEnd();
pCurrentMode = pGameMode;
if (pCurrentMode)
pCurrentMode->RoundBegin();
delete pCurrentMode;
}
for (auto &mode: g_RegisteredGameModes)
{
if (!V_strcmp(mode->m_szName, szName))
{
pCurrentMode = mode->m_pfn();
pCurrentMode->RoundBegin();
szCurrentModeName = szName;
return;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGameMode *IGameModeManager::GetCurrentMode( void )
CGameMode *IGameModeManager::GetCurrentGameModeClass( void )
{
return pCurrentMode;
}
@@ -75,11 +102,33 @@ CGameMode *IGameModeManager::GetCurrentMode( void )
//-----------------------------------------------------------------------------
// Restarts the gamemode
//-----------------------------------------------------------------------------
void IGameModeManager::RestartCurrentMode( void )
void IGameModeManager::RestartCurrentGameMode( void )
{
if (!pCurrentMode)
return;
if (INetworking::IsServer())
{
PacketGameMode_t mode = {};
mode.type = PACKET_TYPE_GAMEMODE_START;
V_memcpy(mode.szName,szCurrentModeName, min(szCurrentModeName.GetLenght(), 255));
V_printf("%u clients connected\n",g_clients.GetSize());
for (auto &client: g_clients)
{
INetworking::SendData(&mode, sizeof(mode), client, MESSAGE_MODE_RELIABLE);
V_printf("sending to %u\n",client->playerHandle);
};
V_printf("restarting game mode\n");
};
pCurrentMode->RoundEnd();
pCurrentMode->RoundBegin();
}
CGameModeRegistry::CGameModeRegistry(const char *szName, GameModeRegistryFn pfn) :
m_szName(szName), m_pfn(pfn)
{
g_RegisteredGameModes.AppendTail(this);
};

View File

@@ -162,11 +162,13 @@ void IInput_Bind( int argc, char **argv )
if (key == KEY_NONE)
return;
g_bindings[key] = 0;
for ( int i = 2; i<argc; i++ )
{
g_bindings[key] = 0;
g_bindings[key].AppendTail(argv[i]);
g_bindings[key].AppendTail(" ");
}
V_printf("%s\n",g_bindings[key].GetString());
};
//-----------------------------------------------------------------------------

View File

@@ -38,22 +38,7 @@ void ILevel::LoadLevel( const char *szLevelName )
EntityHeader_t* pEntityHeader = (EntityHeader_t*)pData;
pData+=sizeof(EntityHeader_t);
CBaseEntity *pEntity = NULL;
for (auto &entity: g_RegisteredEntities)
{
if (!V_strcmp(entity->m_szName, (char*)szEntityType.GetMemory()))
{
CBaseEntity *pEnt = entity->m_pfn();
g_entities.AppendTail(pEnt);
if (entity->m_pClientfn)
{
pEnt->pClientEntity = entity->m_pClientfn();
pEnt->pClientEntity->pEntity = pEnt;
}
pEntity = pEnt;
break;
}
}
CBaseEntity *pEntity = IIEngine::SpawnEntity(szEntityType);
if (!pEntity)
continue;
@@ -62,6 +47,7 @@ void ILevel::LoadLevel( const char *szLevelName )
CUtlBuffer<char> szParamName(V_strlen(pData)+1);
V_strcpy(szParamName, pData);
pData+=szParamName.GetSize();
CUtlBuffer<char> szParamValue(V_strlen(pData)+1);
V_strcpy(szParamValue, pData);
pData+=szParamValue.GetSize();
@@ -71,11 +57,10 @@ void ILevel::LoadLevel( const char *szLevelName )
CBrushEntity *pBrush = dynamic_cast<CBrushEntity*>(pEntity);
if (!pBrush)
{
pEntity->Spawn();
if (pEntity->pClientEntity)
pEntity->pClientEntity->Spawn();
IIEngine::InitEntity(pEntity);
continue;
}
pBrush->m_mesh = CUtlVector<Triangle_t>(0);
for ( uint32_t j = 0; j<pEntityHeader->nTriangles; j++ )
{
@@ -89,8 +74,6 @@ void ILevel::LoadLevel( const char *szLevelName )
pData+=szTextureName.GetSize();
pBrush->m_mesh.AppendTail(triangle);
};
pBrush->Spawn();
if (pBrush->pClientEntity)
pBrush->pClientEntity->Spawn();
IIEngine::InitEntity(pBrush);
};
};

View File

@@ -44,6 +44,8 @@ static uint32_t s_nNumAttachments;
CUtlVector<MTL::Texture*> g_destroyImageBuffer;
CUtlVector<MTL::Buffer*> g_destroyBuffersBuffer;
extern MTL::PixelFormat g_swapchainFormat;
MTL::PixelFormat IRenderer_FormatToMl( EImageFormat format )
{
switch (format)
@@ -51,6 +53,7 @@ MTL::PixelFormat IRenderer_FormatToMl( EImageFormat format )
case IMAGE_FORMAT_R8G8B8A8: return MTL::PixelFormatRGBA8Unorm;
case IMAGE_FORMAT_R16G16B16A16: return MTL::PixelFormatRGBA16Unorm;
case IMAGE_FORMAT_DEPTH: return MTL::PixelFormatDepth32Float;
case IMAGE_FORMAT_WINDOW: return g_swapchainFormat;
default: return MTL::PixelFormatRGBA8Unorm;
}
};
@@ -294,6 +297,17 @@ void IRenderer::PushBindings()
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
{
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
bool bHasTextures = false;
for ( int i = 0; i < pPipeline->m_inputs.GetSize(); i++ )
{
if (pPipeline->m_inputs[i].type == SHADER_INPUT_TYPE_TEXTURES)
{
bHasTextures = true;
break;
}
}
if (!bHasTextures)
return;
MTL::ArgumentEncoder *argumentEncoder = 0;
for (auto &shader: pPipeline->m_shaders)
@@ -345,7 +359,6 @@ void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingCo
}
s_pEncoder = g_mlCommandBuffer->renderCommandEncoder(s_pRenderPass);
s_pEncoder->setCullMode(MTL::CullModeFront);
}
void IRenderer::ResetState()
@@ -355,7 +368,23 @@ void IRenderer::ResetState()
void IRenderer::SetDepthMode( EDepthMode mode )
{
MTL::DepthStencilDescriptor* depthStencilDesc = MTL::DepthStencilDescriptor::alloc()->init();
if (mode == DEPTH_MODE_DISABLED)
{
depthStencilDesc->setDepthWriteEnabled(false);
} else {
depthStencilDesc->setDepthWriteEnabled(true);
switch (mode)
{
case DEPTH_MODE_LESS:
depthStencilDesc->setDepthCompareFunction(MTL::CompareFunctionLess); break;
default:
break;
}
}
auto depthStencilState = g_mlDevice->newDepthStencilState(depthStencilDesc);
s_pEncoder->setDepthStencilState(depthStencilState);
depthStencilDesc->release();
}
void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex )
@@ -366,11 +395,6 @@ void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex )
{
} else {
MTL::DepthStencilDescriptor* depthStencilDesc = MTL::DepthStencilDescriptor::alloc()->init();
depthStencilDesc->setDepthCompareFunction(MTL::CompareFunctionLess);
depthStencilDesc->setDepthWriteEnabled(true);
auto depthStencilState = g_mlDevice->newDepthStencilState(depthStencilDesc);
s_pEncoder->setDepthStencilState(depthStencilState);
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
@@ -389,8 +413,11 @@ IBuffer *IRenderer::GetCameraMatrix()
return g_cameraProperties;
}
static CMlImage *pOutputImage = new CMlImage;
IImage *IRenderer::GetOutputImage()
{
pOutputImage->m_image = g_mlDrawableTexture;
return pOutputImage;
}
IGraphicsPipeline *IRenderer::CreateGraphicsPipeline(
@@ -479,6 +506,9 @@ uint32_t ITextureManager::GetTextureID(ITexture *pTexture)
ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels )
{
CMlTexture *pTexture = new CMlTexture;
*pTexture = {};
pTexture->x = X;
pTexture->y = Y;
MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init();
pCreateInfo->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
@@ -588,7 +618,6 @@ void IMetal::Frame()
glm_rotate(perspective, glm_rad(90), (vec4){1,0,0,0});
glm_scale(perspective, (vec4){1,-1,1,1});
glm_rotate(perspective, glm_rad(90), (vec4){0,0,1,0});
glm_scale(perspective, (vec4){1,1,-1,1});
glm_mat4_mul(perspective,g_cameraDataMap->viewprojection,g_cameraDataMap->viewprojection);
if (g_bConfigNotify)

View File

@@ -34,6 +34,9 @@ MTL::CommandBuffer *g_mlCommandBuffer;
NS::AutoreleasePool *g_mlPool;
MTL::Texture *g_mlDrawableTexture;
MTL::PixelFormat g_swapchainFormat;
#if defined(__APPLE__) && defined(__MACH__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
@@ -184,6 +187,7 @@ void IVideo::Init()
g_mlLayer->setDevice(g_mlDevice);
g_mlLayer->setPixelFormat(MTL::PixelFormatBGRA8Unorm);
g_swapchainFormat = MTL::PixelFormatBGRA8Unorm;
g_mlCommandQueue = g_mlDevice->newCommandQueue();

View File

356
engine/networking.cpp Normal file
View File

@@ -0,0 +1,356 @@
#include "networking.h"
#include "console.h"
#include "engine.h"
#include "gamemode.h"
#include "server.h"
#include "steam/isteamfriends.h"
#include "steam/isteamnetworking.h"
#include "tier0/platform.h"
#include "tier0/lib.h"
#include "tier1/commandline.h"
#include "tier0/network.h"
#include "tier1/utlvector.h"
#include "baseplayer.h"
#include "steam/steamnetworkingsockets.h"
#include "steam/isteamnetworkingutils.h"
#ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
#include "steam/steam_api.h"
#endif
HSteamNetConnection net_connection = 0;
HSteamNetConnection net_server = 0;
HSteamListenSocket net_listenSocket = -1;
CUtlVector<IIClient*> net_clients;
class CNetworkingCallbacks
{
STEAM_CALLBACK(CNetworkingCallbacks, ClientConnectedCallback, SteamNetConnectionStatusChangedCallback_t);
};
void CNetworkingCallbacks::ClientConnectedCallback( SteamNetConnectionStatusChangedCallback_t *pCallback )
{
INetworking::ClientConnectedCallback(pCallback);
};
bool net_bIsServer = false;
static CNetworkingCallbacks *pCallbacks;
void INetworking::Init()
{
Net_Init();
SteamDatagramErrMsg errMsg = {};
#ifdef STEAMNETWORKINGSOCKETS_OPENSOURCE
GameNetworkingSockets_Init(NULL, &errMsg)
#endif
SteamNetworkingUtils()->SetDebugOutputFunction(k_ESteamNetworkingSocketsDebugOutputType_Msg,
[](ESteamNetworkingSocketsDebugOutputType severity, const char *szMessage) {
V_printf("Steam: %s\n", szMessage);
});
if (ICommandLine::CheckParam("-dedicated"))
{
pCallbacks = new CNetworkingCallbacks;
SteamNetworkingIPAddr localAddress = {};
localAddress.Clear();
localAddress.SetIPv4(0x7F000001, 27015);
net_listenSocket = SteamNetworkingSockets()->CreateListenSocketIP(localAddress, 0, NULL);
net_bIsServer = true;
}
}
void INetworking::Deinit()
{
if (net_listenSocket == -1)
return;
if (ICommandLine::CheckParam("-dedicated"))
SteamNetworkingSockets()->CloseListenSocket(net_listenSocket);
else
SteamNetworkingSockets()->CloseConnection(net_listenSocket, 0, NULL, false);
}
bool INetworking::IsServer()
{
return net_bIsServer;
}
bool INetworking::IsClient()
{
return !net_bIsServer;
}
bool INetworking::IsConnected()
{
return (bool)net_server;
}
void INetworking::Frame()
{
SteamNetworkingSockets()->RunCallbacks();
if (IsServer())
{
for (auto &client: g_clients)
{
SteamNetworkingMessage_t *pMessages[64];
while (true)
{
int nMessages = SteamNetworkingSockets()->ReceiveMessagesOnConnection(client->playerHandle, pMessages, 64);
if ( nMessages <= 0 )
break;
for ( int i = 0; i < nMessages; i++ )
{
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), client);
}
}
}
} else {
SteamNetworkingMessage_t *pMessages[64];
while (true)
{
int nMessages = SteamNetworkingSockets()->ReceiveMessagesOnConnection(net_connection, pMessages, 64);
if ( nMessages <= 0 )
break;
for ( int i = 0; i < nMessages; i++ )
{
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), NULL);
pMessages[i]->Release();
}
}
}
}
void INetworking::SendData( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
{
if (!IsConnected() && IsClient())
return;
int nSendFlags = 0;
switch ( messageMode )
{
case MESSAGE_MODE_UNRELIABLE:
nSendFlags |= k_nSteamNetworkingSend_Unreliable;
break;
case MESSAGE_MODE_RELIABLE:
nSendFlags |= k_nSteamNetworkingSend_Reliable;
break;
};
/* Send to server if client is NULL */
EResult r = k_EResultNone;
if (pClient == NULL)
r = SteamNetworkingSockets()->SendMessageToConnection(net_server, pData, nSize, nSendFlags, NULL);
else
r = SteamNetworkingSockets()->SendMessageToConnection(pClient->playerHandle, pData, nSize, nSendFlags, NULL);
}
void INetworking::SendDataEverybody( void *pData, uint32_t nSize, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
if (client == pClient)
continue;
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, CBasePlayer *pPlayer, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
if (client->pBasePlayer == pPlayer)
continue;
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::ProcessPacket( void *pData, uint32_t nSize, IIClient *pClient )
{
Packet_t *pPacketHeader = (Packet_t*)pData;
if (IsServer() && pPacketHeader->type != PACKET_TYPE_PLAYER_MOVEMENT)
return;
if (nSize < sizeof(Packet_t))
return;
PacketPlayer_t *pPlayerPacket = (PacketPlayer_t*)pData;
PacketGameMode_t *pGameModePacket = (PacketGameMode_t*)pData;
IIClient *pNewClient;
switch(pPacketHeader->type)
{
case PACKET_TYPE_PLAYER_MOVEMENT:
if (nSize < sizeof(PacketPlayer_t))
return;
if (IsServer())
{
if (pClient->pBasePlayer)
pClient->pBasePlayer->Sync(pData, nSize);
}
for (auto &client: g_clients)
{
if (client->playerHandle == pPlayerPacket->playerHandle)
{
if (!client->pBasePlayer)
return;
client->pBasePlayer->Sync(pData, nSize);
return;
}
}
return;
case PACKET_TYPE_PLAYER_JOIN:
if (nSize != sizeof(PacketPlayer_t))
return;
// Player join and leave can be processed only by the clients
pNewClient = new IIClient;
*pNewClient = {
.playerID = pPlayerPacket->playerID,
.playerHandle = pPlayerPacket->playerHandle,
};
IIEngine::ConnectClient(pNewClient);
for (auto &client: g_clients)
{
CSteamID steamID = CSteamID();
if ( client->playerID == 0)
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
else
V_printf("%s\t", SteamFriends()->GetPersonaName());
V_printf("%llu\t", client->playerID);
V_printf("%u\n", client->playerHandle);
if (client->playerHandle == 0)
g_localClient = client;
}
return;
case PACKET_TYPE_PLAYER_LEAVE:
IIEngine::DisconnectClientByHandle(pPlayerPacket->playerHandle);
return;
case PACKET_TYPE_GAMEMODE_START:
V_printf("PacketGameMode\n");
if (nSize != sizeof(PacketGameMode_t))
return;
IGameModeManager::StartGameMode(pGameModePacket->szName);
return;
default:
return;
}
}
void INetworking::GetServerInfo()
{
}
uint32_t INetworking_IPv4ToUint(const char *szIP) {
if (CUtlString(szIP) == "localhost")
return 0x7F000001;
struct in_addr ipAdress;
if (inet_pton(AF_INET, szIP, &ipAdress) != 1) {
V_printf("Invalid IPv4 address: %s\n", szIP);
return 0;
}
return ntohl(ipAdress.s_addr);
}
void INetworking::JoinServer( const char *szIP )
{
if (net_connection)
{
g_clients = {};
SteamNetworkingSockets()->CloseConnection(net_connection, 0, NULL, false);
}
SteamNetworkingIPAddr localAddress = {};
localAddress.Clear();
localAddress.SetIPv4(INetworking_IPv4ToUint(szIP), 27015);
net_connection = SteamNetworkingSockets()->ConnectByIPAddress(localAddress, 0, NULL);
net_server = net_connection;
}
void INetworking::ClientConnectedCallback( SteamNetConnectionStatusChangedCallback_t *pCallback )
{
IIClient *pClient = new IIClient;
switch (pCallback->m_info.m_eState)
{
case k_ESteamNetworkingConnectionState_Connecting:
V_printf("Awaiting connection: %llu\n",pCallback->m_info.m_identityRemote.GetSteamID64());
SteamNetworkingSockets()->AcceptConnection(pCallback->m_hConn);
break;
case k_ESteamNetworkingConnectionState_Connected:
V_printf("Connected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
*pClient = {
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
.playerHandle = pCallback->m_hConn,
};
// send out to all clients
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = pClient->playerID,
.playerHandle = pClient->playerHandle,
};
packet.type = PACKET_TYPE_PLAYER_JOIN;
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
};
IIEngine::ConnectClient(pClient);
// register all clients on connected one
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = client->playerID,
.playerHandle = client->playerHandle,
};
if (client == pClient)
{
packet.playerID = 0;
packet.playerHandle = 0;
}
packet.type = PACKET_TYPE_PLAYER_JOIN;
SendData(&packet, sizeof(packet), pClient, MESSAGE_MODE_RELIABLE);
};
IGameModeManager::RestartCurrentGameMode();
break;
case k_ESteamNetworkingConnectionState_ClosedByPeer:
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
SteamNetworkingSockets()->CloseConnection(pCallback->m_hConn, 0, NULL, false);
V_printf("Disconnected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
IIEngine::DisconnectClientByHandle(pCallback->m_hConn);
// send out to all clients
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
.playerHandle = pCallback->m_hConn,
};
packet.type = PACKET_TYPE_PLAYER_LEAVE;
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
};
break;
default:
break;
}
}
void INetworking_Connect( int argc, char **argv )
{
if (ICommandLine::CheckParam("-dedicated"))
return;
if (argc != 2)
{
V_printf("connect <IPv4>\n");
return;
}
INetworking::JoinServer(argv[1]);
};
ConCommand ConnectCmd("connect", INetworking_Connect);

View File

@@ -1,12 +1,14 @@
#include "server.h"
#include "engine.h"
#include "input.h"
#include "steam/steam_api_common.h"
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
#include "baseentity.h"
#include "console.h"
#include "physics.h"
#include "input.h"
#include "net.h"
#include "networking.h"
void *g_serverdll;
ConVar g_tickrate("tickrate","64",FCVAR_PROTECTED);
@@ -23,12 +25,14 @@ void IServer::LoadGame( const char *psz )
#ifndef STATIC_BUILD
#ifdef __linux__
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.so", psz));
Plat_LoadLibrary(CUtlString("%s/bin/libclient.so", psz));
if (!ICommandLine::CheckParam("-dedicated"))
Plat_LoadLibrary(CUtlString("%s/bin/libclient.so", psz));
#endif
#ifdef __APPLE__
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.dysim", psz));
Plat_LoadLibrary(CUtlString("%s/bin/libclient.dysim", psz));
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.dylib", psz));
if (!ICommandLine::CheckParam("-dedicated"))
Plat_LoadLibrary(CUtlString("%s/bin/libclient.dylib", psz));
#endif
void (*GameLoadfn)() = (void(*)())Plat_GetProc(g_serverdll, "IGame_Load");
if (!GameLoadfn)
@@ -50,13 +54,16 @@ void IServer::Think( float fDelta )
/* tickrate */
while(g_fAccumulator>=fTickrate)
{
#ifdef STEAM_ENABLED
SteamGameServer_RunCallbacks();
#endif
IInput::Frame();
IConsole::Execute();
g_fAccumulator-=fTickrate;
for (auto &entity: g_entities)
{
entity->Think(fTickrate);
entity->Sync(0, 0);
}
px_frame(px, fTickrate);
}
@@ -68,6 +75,7 @@ void IServer::Think( float fDelta )
};
void IGame_Exit( int argc, char **argv ) {
IEngine::Shutdown();
Plat_Exit(0);
}
ConCommand ExitCmd("exit", IGame_Exit, 0);

View File

@@ -9,6 +9,7 @@ public:
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
virtual void Sync( void *pData, uint32_t nDataSize ) override;
};
void CLight::Precache()
@@ -33,7 +34,10 @@ void CLight::Destroy()
}
void CLight::Think( float fDelta )
{
};
void CLight::Sync( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(light, CLight)

View File

@@ -4,7 +4,7 @@
#include "tier1/utlvector.h"
CUtlVector<CPlayerStart*> g_PlayerStarts;
CUtlVector<CPlayerStart*> g_PlayerStarts = {};
void CPlayerStart::Precache()
{
@@ -22,6 +22,16 @@ void CPlayerStart::ReadParameter( const char *szName, const char *szValue )
void CPlayerStart::Destroy()
{
uint32_t i = 0;
for (auto &start: g_PlayerStarts)
{
if (start == this)
{
g_PlayerStarts.RemoveAt(i);
break;
}
i++;
}
}
void CPlayerStart::Think( float fDelta )
@@ -51,4 +61,9 @@ void CPlayerStart::RoundStart(IIClient *pClient)
pClient->pBasePlayer = pOwningPlayer;
};
void CPlayerStart::Sync( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(info_player_start, CPlayerStart);

View File

@@ -9,6 +9,7 @@ public:
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
virtual void Sync( void *pData, uint32_t nDataSize ) override;
};
void CWorldSpawn::Precache()
@@ -36,4 +37,9 @@ void CWorldSpawn::Think( float fDelta )
CBrushEntity::Think(fDelta);
}
void CWorldSpawn::Sync( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(worldspawn, CWorldSpawn)

View File

@@ -57,7 +57,7 @@ extern VkImageView g_swapchainImageView;
extern VkImage g_swapchainImage;
extern VkFormat g_swapchainFormat;
extern bool g_bConfigNotify;
extern char g_bConfigNotify;
extern uint32_t g_nWindowWidth;
extern uint32_t g_nWindowHeight;

View File

@@ -75,6 +75,7 @@ VkFormat IRenderer_FormatToVk( EImageFormat format )
case IMAGE_FORMAT_R8G8B8A8: return VK_FORMAT_R8G8B8A8_UNORM;
case IMAGE_FORMAT_R16G16B16A16: return VK_FORMAT_R16G16B16A16_UNORM;
case IMAGE_FORMAT_DEPTH: return VK_FORMAT_D32_SFLOAT;
case IMAGE_FORMAT_WINDOW: return g_swapchainFormat;
default: return VK_FORMAT_R8G8B8A8_UNORM;
}
};
@@ -173,6 +174,7 @@ void IVulkan::Init()
};
void IVulkan::CreatePipelines()
{
V_printf("Created %i pipelines\n",g_StepMeshRendering.GetSize());
for (auto &step: g_StepPrepass)
step.pPipeline->Init();
for (auto &step: g_StepMeshRendering)
@@ -231,15 +233,15 @@ void IVulkan::Frame()
IRenderer::Begin(g_nWindowWidth, g_nWindowHeight,
{
{
0,
g_meshColor,
0,
ATTACHMENT_LOAD_MODE_CLEAR,
ATTACHMENT_STORE_MODE_STORE,
}
},
{
0,
g_meshDepth,
0,
ATTACHMENT_LOAD_MODE_CLEAR,
ATTACHMENT_STORE_MODE_STORE,
});
@@ -640,6 +642,8 @@ ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uin
{
CVkTexture *pTexture = new CVkTexture;
*pTexture = {};
pTexture->x = X;
pTexture->y = Y;
VkDeviceSize imageSize = X*Y*4;
vk_buffer_t gpu_buffer = {};
gpu_buffer.Create(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
@@ -1059,7 +1063,7 @@ void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingCo
{
VkRenderingAttachmentInfo vkattachment = {};
vkattachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
CVkImage *pImage = (CVkImage*)attachment.pTemporary;
CVkImage *pImage = (CVkImage*)attachment.pOutput;
CVkImage *pTemporary = (CVkImage*)attachment.pTemporary;
if (attachment.pTemporary)
{
@@ -1077,8 +1081,10 @@ void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingCo
colorAttachments.AppendTail(vkattachment);
}
depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
CVkImage *pDepthImage = (CVkImage*)depth.pTemporary;
CVkImage *pDepthImage = (CVkImage*)depth.pOutput;
CVkImage *pDepthTemporary = (CVkImage*)depth.pTemporary;
if (!depth.pOutput)
goto skip_depth;
if (depth.pTemporary)
{
depthAttachment.imageView = pDepthTemporary->m_image.m_imageView;
@@ -1094,13 +1100,14 @@ void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingCo
depthAttachment.storeOp = IRenderer_StoreOpVk(depth.storeMode);
depthAttachment.clearValue = (VkClearValue){.depthStencil = {.depth = 1}};
skip_depth:
VkRenderingInfo renderInfo = {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = {{0, 0}, {nWidth, nHeight}},
.layerCount = 1,
.colorAttachmentCount = (uint32_t)colorAttachments.GetSize(),
.pColorAttachments = colorAttachments.GetData(),
.pDepthAttachment = &depthAttachment,
.pDepthAttachment = depth.pOutput ? &depthAttachment : 0,
};
vkCmdBeginRendering(g_vkCommandBuffer, &renderInfo);
}
@@ -1113,10 +1120,11 @@ void IRenderer::ResetState()
vkCmdSetCullMode(g_vkCommandBuffer, VK_CULL_MODE_BACK_BIT);
vkCmdSetFrontFace(g_vkCommandBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
vkCmdSetDepthTestEnable(g_vkCommandBuffer, VK_TRUE);
vkCmdSetDepthWriteEnable(g_vkCommandBuffer, VK_TRUE);
vkCmdSetDepthCompareOp(g_vkCommandBuffer, VK_COMPARE_OP_LESS);
vkCmdSetStencilTestEnable(g_vkCommandBuffer, VK_FALSE);
vkCmdSetDepthTestEnable(g_vkCommandBuffer, VK_FALSE);
vkCmdSetDepthWriteEnable(g_vkCommandBuffer, VK_FALSE);
_vkCmdSetPolygonModeEXT(g_vkCommandBuffer, VK_POLYGON_MODE_FILL);
_vkCmdSetRasterizationSamplesEXT(g_vkCommandBuffer, VK_SAMPLE_COUNT_1_BIT);
@@ -1135,7 +1143,16 @@ void IRenderer::ResetState()
void IRenderer::SetDepthMode( EDepthMode mode )
{
if (mode == DEPTH_MODE_DISABLED)
{
vkCmdSetDepthTestEnable(g_vkCommandBuffer, VK_FALSE);
vkCmdSetDepthWriteEnable(g_vkCommandBuffer, VK_FALSE);
return;
}
vkCmdSetDepthTestEnable(g_vkCommandBuffer, VK_TRUE);
vkCmdSetDepthWriteEnable(g_vkCommandBuffer, VK_TRUE);
vkCmdSetDepthCompareOp(g_vkCommandBuffer, VK_COMPARE_OP_LESS);
vkCmdSetStencilTestEnable(g_vkCommandBuffer, VK_FALSE);
}
void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex )