2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
#include <engine/textrender.h>
|
|
|
|
#include <engine/sound.h>
|
|
|
|
#include <engine/demo.h>
|
|
|
|
#include <engine/map.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
#include <engine/serverbrowser.h>
|
2010-09-12 10:16:51 +00:00
|
|
|
#include <engine/shared/demo.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/shared/config.h>
|
|
|
|
|
|
|
|
#include <game/generated/protocol.h>
|
|
|
|
#include <game/generated/client_data.h>
|
|
|
|
|
|
|
|
#include <game/localization.h>
|
|
|
|
#include <game/version.h>
|
|
|
|
#include "render.h"
|
|
|
|
|
|
|
|
#include "gameclient.h"
|
|
|
|
|
|
|
|
#include "components/binds.h"
|
|
|
|
#include "components/broadcast.h"
|
|
|
|
#include "components/camera.h"
|
|
|
|
#include "components/chat.h"
|
|
|
|
#include "components/console.h"
|
|
|
|
#include "components/controls.h"
|
|
|
|
#include "components/damageind.h"
|
|
|
|
#include "components/debughud.h"
|
|
|
|
#include "components/effects.h"
|
|
|
|
#include "components/emoticon.h"
|
|
|
|
#include "components/flow.h"
|
|
|
|
#include "components/hud.h"
|
|
|
|
#include "components/items.h"
|
|
|
|
#include "components/killmessages.h"
|
|
|
|
#include "components/mapimages.h"
|
|
|
|
#include "components/maplayers.h"
|
|
|
|
#include "components/menus.h"
|
|
|
|
#include "components/motd.h"
|
|
|
|
#include "components/particles.h"
|
|
|
|
#include "components/players.h"
|
|
|
|
#include "components/nameplates.h"
|
|
|
|
#include "components/scoreboard.h"
|
|
|
|
#include "components/skins.h"
|
|
|
|
#include "components/sounds.h"
|
|
|
|
#include "components/voting.h"
|
2010-08-25 14:15:59 +00:00
|
|
|
#include "components/race_demo.h"
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
CGameClient g_GameClient;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// instanciate all systems
|
2010-05-29 07:25:38 +00:00
|
|
|
static CKillMessages gs_KillMessages;
|
|
|
|
static CCamera gs_Camera;
|
|
|
|
static CChat gs_Chat;
|
|
|
|
static CMotd gs_Motd;
|
|
|
|
static CBroadcast gs_Broadcast;
|
|
|
|
static CGameConsole gs_GameConsole;
|
|
|
|
static CBinds gs_Binds;
|
|
|
|
static CParticles gs_Particles;
|
|
|
|
static CMenus gs_Menus;
|
|
|
|
static CSkins gs_Skins;
|
|
|
|
static CFlow gs_Flow;
|
|
|
|
static CHud gs_Hud;
|
|
|
|
static CDebugHud gs_DebugHud;
|
|
|
|
static CControls gs_Controls;
|
|
|
|
static CEffects gs_Effects;
|
|
|
|
static CScoreboard gs_Scoreboard;
|
|
|
|
static CSounds gs_Sounds;
|
|
|
|
static CEmoticon gs_Emoticon;
|
|
|
|
static CDamageInd gsDamageInd;
|
|
|
|
static CVoting gs_Voting;
|
2010-08-25 14:15:59 +00:00
|
|
|
static CRaceDemo gs_RaceDemo;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
static CPlayers gs_Players;
|
|
|
|
static CNamePlates gs_NamePlates;
|
|
|
|
static CItems gs_Items;
|
|
|
|
static CMapImages gs_MapImages;
|
|
|
|
|
|
|
|
static CMapLayers gs_MapLayersBackGround(CMapLayers::TYPE_BACKGROUND);
|
|
|
|
static CMapLayers gs_MapLayersForeGround(CMapLayers::TYPE_FOREGROUND);
|
|
|
|
|
|
|
|
CGameClient::CStack::CStack() { m_Num = 0; }
|
|
|
|
void CGameClient::CStack::Add(class CComponent *pComponent) { m_paComponents[m_Num++] = pComponent; }
|
|
|
|
|
|
|
|
static int gs_LoadCurrent;
|
|
|
|
static int gs_LoadTotal;
|
|
|
|
|
|
|
|
/*static void load_sounds_thread(void *do_render)
|
2008-08-30 21:16:58 +00:00
|
|
|
{
|
|
|
|
// load sounds
|
|
|
|
for(int s = 0; s < data->num_sounds; s++)
|
|
|
|
{
|
2008-08-31 21:50:14 +00:00
|
|
|
if(do_render)
|
2008-08-30 22:38:56 +00:00
|
|
|
gameclient.menus->render_loading(load_current/(float)load_total);
|
2008-08-30 21:16:58 +00:00
|
|
|
for(int i = 0; i < data->sounds[s].num_sounds; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int id = Sound()->LoadWV(data->sounds[s].sounds[i].filename);
|
2008-08-30 21:16:58 +00:00
|
|
|
data->sounds[s].sounds[i].id = id;
|
|
|
|
}
|
|
|
|
|
2008-08-30 22:38:56 +00:00
|
|
|
if(do_render)
|
|
|
|
load_current++;
|
2008-08-30 21:16:58 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
}*/
|
2008-08-30 21:16:58 +00:00
|
|
|
|
2010-08-25 14:15:59 +00:00
|
|
|
|
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
static void ConServerDummy(IConsole::IResult *pResult, void *pUserData, int ClientID)
|
2010-08-25 14:15:59 +00:00
|
|
|
{
|
|
|
|
dbg_msg("client", "this command is not available on the client");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <base/tl/sorted_array.h>
|
2009-06-15 06:45:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
const char *CGameClient::Version() { return GAME_VERSION; }
|
|
|
|
const char *CGameClient::NetVersion() { return GAME_NETVERSION; }
|
|
|
|
const char *CGameClient::GetItemName(int Type) { return m_NetObjHandler.GetObjName(Type); }
|
2009-06-15 06:45:44 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnConsoleInit()
|
|
|
|
{
|
|
|
|
m_pClient = Kernel()->RequestInterface<IClient>();
|
|
|
|
m_pGraphics = Kernel()->RequestInterface<IGraphics>();
|
|
|
|
m_pTextRender = Kernel()->RequestInterface<ITextRender>();
|
|
|
|
m_pSound = Kernel()->RequestInterface<ISound>();
|
|
|
|
m_pInput = Kernel()->RequestInterface<IInput>();
|
|
|
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
|
|
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
|
|
|
m_pDemoPlayer = Kernel()->RequestInterface<IDemoPlayer>();
|
2010-08-09 12:14:15 +00:00
|
|
|
m_pDemoRecorder = Kernel()->RequestInterface<IDemoRecorder>();
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>();
|
2009-06-15 06:45:44 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// setup pointers
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pBinds = &::gs_Binds;
|
|
|
|
m_pGameConsole = &::gs_GameConsole;
|
|
|
|
m_pParticles = &::gs_Particles;
|
|
|
|
m_pMenus = &::gs_Menus;
|
|
|
|
m_pSkins = &::gs_Skins;
|
|
|
|
m_pChat = &::gs_Chat;
|
|
|
|
m_pFlow = &::gs_Flow;
|
|
|
|
m_pCamera = &::gs_Camera;
|
|
|
|
m_pControls = &::gs_Controls;
|
|
|
|
m_pEffects = &::gs_Effects;
|
|
|
|
m_pSounds = &::gs_Sounds;
|
|
|
|
m_pMotd = &::gs_Motd;
|
|
|
|
m_pDamageind = &::gsDamageInd;
|
|
|
|
m_pMapimages = &::gs_MapImages;
|
|
|
|
m_pVoting = &::gs_Voting;
|
2010-08-25 14:15:59 +00:00
|
|
|
m_pRaceDemo = &::gs_RaceDemo;
|
2010-08-18 01:57:35 +00:00
|
|
|
m_pScoreboard = &::gs_Scoreboard;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// make a list of all the systems, make sure to add them in the corrent render order
|
2010-05-29 07:25:38 +00:00
|
|
|
m_All.Add(m_pSkins);
|
|
|
|
m_All.Add(m_pMapimages);
|
|
|
|
m_All.Add(m_pEffects); // doesn't render anything, just updates effects
|
|
|
|
m_All.Add(m_pParticles);
|
|
|
|
m_All.Add(m_pBinds);
|
|
|
|
m_All.Add(m_pControls);
|
|
|
|
m_All.Add(m_pCamera);
|
|
|
|
m_All.Add(m_pSounds);
|
|
|
|
m_All.Add(m_pVoting);
|
|
|
|
m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles
|
2010-08-25 14:15:59 +00:00
|
|
|
m_All.Add(m_pRaceDemo);
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
m_All.Add(&gs_MapLayersBackGround); // first to render
|
|
|
|
m_All.Add(&m_pParticles->m_RenderTrail);
|
|
|
|
m_All.Add(&m_pParticles->m_RenderExplosions);
|
|
|
|
m_All.Add(&gs_Items);
|
|
|
|
m_All.Add(&gs_Players);
|
|
|
|
m_All.Add(&gs_MapLayersForeGround);
|
|
|
|
m_All.Add(&gs_NamePlates);
|
|
|
|
m_All.Add(&m_pParticles->m_RenderGeneral);
|
|
|
|
m_All.Add(m_pDamageind);
|
|
|
|
m_All.Add(&gs_Hud);
|
|
|
|
m_All.Add(&gs_Emoticon);
|
|
|
|
m_All.Add(&gs_KillMessages);
|
|
|
|
m_All.Add(m_pChat);
|
|
|
|
m_All.Add(&gs_Broadcast);
|
|
|
|
m_All.Add(&gs_DebugHud);
|
|
|
|
m_All.Add(&gs_Scoreboard);
|
|
|
|
m_All.Add(m_pMotd);
|
|
|
|
m_All.Add(m_pMenus);
|
|
|
|
m_All.Add(m_pGameConsole);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// build the input stack
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key
|
|
|
|
m_Input.Add(&m_pBinds->m_SpecialBinds);
|
|
|
|
m_Input.Add(m_pGameConsole);
|
|
|
|
m_Input.Add(m_pChat); // chat has higher prio due to tha you can quit it by pressing esc
|
|
|
|
m_Input.Add(m_pMotd); // for pressing esc to remove it
|
|
|
|
m_Input.Add(m_pMenus);
|
|
|
|
m_Input.Add(&gs_Emoticon);
|
|
|
|
m_Input.Add(m_pControls);
|
|
|
|
m_Input.Add(m_pBinds);
|
2009-06-13 17:18:06 +00:00
|
|
|
|
2008-09-04 21:36:44 +00:00
|
|
|
// add the some console commands
|
2010-08-25 20:30:21 +00:00
|
|
|
Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team", 0);
|
|
|
|
Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself", 0);
|
2009-01-24 12:16:02 +00:00
|
|
|
|
|
|
|
// register server dummy commands for tab completion
|
2010-08-25 14:15:59 +00:00
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
Console()->Register("tune", "si", CFGFLAG_SERVER, ConServerDummy, 0, "Tune variable to value", 0);
|
|
|
|
Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConServerDummy, 0, "Reset tuning", 0);
|
|
|
|
Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConServerDummy, 0, "Dump tuning", 0);
|
|
|
|
Console()->Register("change_map", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Change map", 0);
|
|
|
|
Console()->Register("restart", "?i", CFGFLAG_SERVER, ConServerDummy, 0, "Restart in x seconds", 0);
|
|
|
|
Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Broadcast message", 0);
|
2010-08-25 14:15:59 +00:00
|
|
|
//MACRO_REGISTER_COMMAND("say", "r", CFGFLAG_SERVER, con_serverdummy, 0);
|
2010-08-25 20:30:21 +00:00
|
|
|
Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConServerDummy, 0, "Set team of player to team", 0);
|
|
|
|
Console()->Register("addvote", "r", CFGFLAG_SERVER, ConServerDummy, 0, "Add a voting option", 0);
|
2010-08-25 14:15:59 +00:00
|
|
|
//MACRO_REGISTER_COMMAND("vote", "", CFGFLAG_SERVER, con_serverdummy, 0);
|
2010-08-25 20:30:21 +00:00
|
|
|
Console()->Register("map_hack", "", CFGFLAG_CLIENT, ConMapHack, 0, "Tune variable to value", 0);
|
2010-08-25 14:15:59 +00:00
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
Console()->Register("tune", "si", CFGFLAG_SERVER, 0, 0, "Tune variable to value", 0);
|
|
|
|
Console()->Register("tune_reset", "", CFGFLAG_SERVER, 0, 0, "Reset tuning", 0);
|
|
|
|
Console()->Register("tune_dump", "", CFGFLAG_SERVER, 0, 0, "Dump tuning", 0);
|
|
|
|
Console()->Register("change_map", "r", CFGFLAG_SERVER, 0, 0, "Change map", 0);
|
|
|
|
Console()->Register("restart", "?i", CFGFLAG_SERVER, 0, 0, "Restart in x seconds", 0);
|
|
|
|
Console()->Register("broadcast", "r", CFGFLAG_SERVER, 0, 0, "Broadcast message", 0);
|
|
|
|
Console()->Register("say", "r", CFGFLAG_SERVER, 0, 0, "Say in chat", 0);
|
|
|
|
Console()->Register("set_team", "ii", CFGFLAG_SERVER, 0, 0, "Set team of player to team", 0);
|
|
|
|
Console()->Register("addvote", "r", CFGFLAG_SERVER, 0, 0, "Add a voting option", 0);
|
|
|
|
Console()->Register("vote", "r", CFGFLAG_SERVER, 0, 0, "Force a vote to yes/no", 0);
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
|
2010-08-25 14:15:59 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// propagate pointers
|
|
|
|
m_UI.SetGraphics(Graphics(), TextRender());
|
|
|
|
m_RenderTools.m_pGraphics = Graphics();
|
|
|
|
m_RenderTools.m_pUI = UI();
|
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->m_pClient = this;
|
2008-09-23 07:43:41 +00:00
|
|
|
|
|
|
|
// let all the other components register their console commands
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnConsoleInit();
|
2009-06-15 14:01:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2010-05-29 07:25:38 +00:00
|
|
|
Console()->Chain("player_name", ConchainSpecialInfoupdate, this);
|
|
|
|
Console()->Chain("player_use_custom_color", ConchainSpecialInfoupdate, this);
|
|
|
|
Console()->Chain("player_color_body", ConchainSpecialInfoupdate, this);
|
|
|
|
Console()->Chain("player_color_feet", ConchainSpecialInfoupdate, this);
|
|
|
|
Console()->Chain("player_skin", ConchainSpecialInfoupdate, this);
|
2009-06-15 14:01:36 +00:00
|
|
|
|
2008-12-19 11:41:17 +00:00
|
|
|
//
|
2010-05-29 07:25:38 +00:00
|
|
|
m_SuppressEvents = false;
|
2008-09-04 21:36:44 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnInit()
|
2008-09-04 21:36:44 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
//m_pServerBrowser = Kernel()->RequestInterface<IServerBrowser>();
|
2009-06-15 08:15:53 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// set the language
|
2010-08-17 22:06:00 +00:00
|
|
|
g_Localization.Load(g_Config.m_ClLanguagefile, Console());
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// init all components
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnInit();
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
// setup item sizes
|
|
|
|
for(int i = 0; i < NUM_NETOBJTYPES; i++)
|
2010-05-29 07:25:38 +00:00
|
|
|
Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 Start = time_get();
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2009-06-07 14:36:54 +00:00
|
|
|
// load default font
|
2010-05-29 07:25:38 +00:00
|
|
|
static CFont *pDefaultFont;
|
2009-06-07 16:06:03 +00:00
|
|
|
//default_font = gfx_font_load("data/fonts/sazanami-gothic.ttf");
|
2010-05-29 07:25:38 +00:00
|
|
|
pDefaultFont = TextRender()->LoadFont("data/fonts/vera.ttf");
|
|
|
|
TextRender()->SetDefaultFont(pDefaultFont);
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
g_Config.m_ClThreadsoundloading = 0;
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
// setup load amount
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_LoadTotal = g_pData->m_NumImages;
|
|
|
|
gs_LoadCurrent = 0;
|
|
|
|
if(!g_Config.m_ClThreadsoundloading)
|
|
|
|
gs_LoadTotal += g_pData->m_NumSounds;
|
2008-08-30 22:38:56 +00:00
|
|
|
|
|
|
|
// load textures
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < g_pData->m_NumImages; i++)
|
2008-08-30 22:38:56 +00:00
|
|
|
{
|
2010-09-21 22:30:08 +00:00
|
|
|
g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal);
|
2010-05-29 07:25:38 +00:00
|
|
|
g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, CImageInfo::FORMAT_AUTO, 0);
|
|
|
|
gs_LoadCurrent++;
|
2008-08-30 22:38:56 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
::gs_Skins.Init();
|
|
|
|
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// TODO: Refactor: fix threaded loading of sounds again
|
|
|
|
// load sounds
|
|
|
|
{
|
|
|
|
bool DoRender = true;
|
|
|
|
for(int s = 0; s < g_pData->m_NumSounds; s++)
|
|
|
|
{
|
|
|
|
if(DoRender)
|
|
|
|
g_GameClient.m_pMenus->RenderLoading(gs_LoadCurrent/(float)gs_LoadTotal);
|
|
|
|
for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
|
|
|
|
{
|
|
|
|
int id = Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
|
|
|
|
g_pData->m_aSounds[s].m_aSounds[i].m_Id = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(DoRender)
|
|
|
|
gs_LoadCurrent++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*if(config.cl_threadsoundloading)
|
2008-08-30 22:38:56 +00:00
|
|
|
thread_create(load_sounds_thread, 0);
|
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
load_sounds_thread((void*)1);*/
|
2008-10-08 18:19:45 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnReset();
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 End = time_get();
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "initialisation finished after %f.2ms", ((End-Start)*1000)/(float)time_freq());
|
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf);
|
2008-08-30 22:38:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ServerMode = SERVERMODE_PURE;
|
2010-08-25 14:15:59 +00:00
|
|
|
|
|
|
|
m_IsRace = false;
|
|
|
|
m_RaceMsgSent = false;
|
|
|
|
m_ShowOthers = -1;
|
|
|
|
m_FlagPos = vec2(-1, -1);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::DispatchInput()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// handle mouse movement
|
|
|
|
int x=0, y=0;
|
2010-05-29 07:25:38 +00:00
|
|
|
Input()->MouseRelative(&x, &y);
|
2008-09-12 07:20:26 +00:00
|
|
|
if(x || y)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int h = 0; h < m_Input.m_Num; h++)
|
2008-09-12 07:20:26 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Input.m_paComponents[h]->OnMouseMove(x, y))
|
2008-09-12 07:20:26 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handle key presses
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < Input()->NumEvents(); i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IInput::CEvent e = Input()->GetEvent(i);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int h = 0; h < m_Input.m_Num; h++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Input.m_paComponents[h]->OnInput(e))
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
//dbg_msg("", "%d char=%d key=%d flags=%d", h, e.ch, e.key, e.flags);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear all events for this frame
|
2010-05-29 07:25:38 +00:00
|
|
|
Input()->ClearEvents();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CGameClient::OnSnapInput(int *pData)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
return m_pControls->SnapInput(pData);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnConnected()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Layers.Init(Kernel());
|
|
|
|
m_Collision.Init(Layers());
|
|
|
|
|
|
|
|
RenderTools()->RenderTilemapGenerateSkip(Layers());
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
2008-10-08 18:19:45 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_All.m_paComponents[i]->OnMapLoad();
|
|
|
|
m_All.m_paComponents[i]->OnReset();
|
2008-10-08 18:19:45 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CServerInfo CurrentServerInfo;
|
|
|
|
Client()->GetServerInfo(&CurrentServerInfo);
|
2009-01-11 10:40:14 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ServerMode = SERVERMODE_PURE;
|
|
|
|
m_LastSendInfo = 0;
|
2009-01-11 10:40:14 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// send the inital info
|
2010-05-29 07:25:38 +00:00
|
|
|
SendInfo(true);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnReset()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// clear out the invalid pointers
|
2010-05-29 07:25:38 +00:00
|
|
|
m_LastNewPredictedTick = -1;
|
|
|
|
mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[i].m_aName[0] = 0;
|
|
|
|
m_aClients[i].m_SkinId = 0;
|
|
|
|
m_aClients[i].m_Team = 0;
|
|
|
|
m_aClients[i].m_Angle = 0;
|
|
|
|
m_aClients[i].m_Emoticon = 0;
|
|
|
|
m_aClients[i].m_EmoticonStart = -1;
|
|
|
|
m_aClients[i].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(0)->m_ColorTexture;
|
|
|
|
m_aClients[i].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
|
|
|
|
m_aClients[i].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
|
2010-08-25 14:15:59 +00:00
|
|
|
m_aClients[i].m_Score = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[i].UpdateRenderInfo();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnReset();
|
2010-08-25 14:15:59 +00:00
|
|
|
|
|
|
|
// Race
|
|
|
|
m_IsRace = false;
|
|
|
|
m_RaceMsgSent = false;
|
|
|
|
m_ShowOthers = -1;
|
|
|
|
m_FlagPos = vec2(-1, -1);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::UpdateLocalCharacterPos()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pLocalCharacter->m_Health < 0) || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver))
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// don't use predicted
|
|
|
|
}
|
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick());
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_LocalCharacterPos = mix(
|
|
|
|
vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y),
|
|
|
|
vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick());
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static void Evolve(CNetObj_Character *pCharacter, int Tick)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CWorldCore TempWorld;
|
|
|
|
CCharacterCore TempCore;
|
2010-08-30 19:25:04 +00:00
|
|
|
CTeamsCore TempTeams;
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(&TempCore, sizeof(TempCore));
|
2010-08-30 19:25:04 +00:00
|
|
|
TempCore.Init(&TempWorld, g_GameClient.Collision(), &TempTeams);//????
|
2010-05-29 07:25:38 +00:00
|
|
|
TempCore.Read(pCharacter);
|
2008-10-14 12:11:42 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
while(pCharacter->m_Tick < Tick)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
pCharacter->m_Tick++;
|
|
|
|
TempCore.Tick(false);
|
|
|
|
TempCore.Move();
|
|
|
|
TempCore.Quantize();
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2008-11-16 15:10:57 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
TempCore.Write(pCharacter);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnRender()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2009-10-27 14:38:53 +00:00
|
|
|
/*Graphics()->Clear(1,0,0);
|
|
|
|
|
|
|
|
menus->render_background();
|
|
|
|
return;*/
|
|
|
|
/*
|
|
|
|
Graphics()->Clear(1,0,0);
|
|
|
|
Graphics()->MapScreen(0,0,100,100);
|
|
|
|
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
Graphics()->SetColor(1,1,1,1);
|
|
|
|
Graphics()->QuadsDraw(50, 50, 30, 30);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
|
|
|
return;*/
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// update the local character position
|
2010-05-29 07:25:38 +00:00
|
|
|
UpdateLocalCharacterPos();
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// dispatch all input to systems
|
2010-05-29 07:25:38 +00:00
|
|
|
DispatchInput();
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// render all systems
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnRender();
|
2009-01-11 15:51:43 +00:00
|
|
|
|
|
|
|
// clear new tick flags
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NewTick = false;
|
|
|
|
m_NewPredictedTick = false;
|
|
|
|
|
|
|
|
// check if client info has to be resent
|
|
|
|
if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get())
|
|
|
|
{
|
|
|
|
// resend if client info differs
|
|
|
|
if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalCid].m_aName) ||
|
|
|
|
str_comp(g_Config.m_PlayerSkin, m_aClients[m_Snap.m_LocalCid].m_aSkinName) ||
|
|
|
|
(g_GameClient.m_Snap.m_pGameobj && !(g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS) && // no teamgame?
|
|
|
|
(g_Config.m_PlayerUseCustomColor != m_aClients[m_Snap.m_LocalCid].m_UseCustomColor ||
|
|
|
|
g_Config.m_PlayerColorBody != m_aClients[m_Snap.m_LocalCid].m_ColorBody ||
|
|
|
|
g_Config.m_PlayerColorFeet != m_aClients[m_Snap.m_LocalCid].m_ColorFeet)))
|
|
|
|
{
|
|
|
|
SendInfo(false);
|
|
|
|
}
|
|
|
|
m_LastSendInfo = 0;
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-09-12 10:43:03 +00:00
|
|
|
void CGameClient::OnRelease()
|
|
|
|
{
|
|
|
|
// release all systems
|
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnRelease();
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-08-29 05:34:18 +00:00
|
|
|
|
|
|
|
// special messages
|
2010-05-29 07:25:38 +00:00
|
|
|
if(MsgId == NETMSGTYPE_SV_EXTRAPROJECTILE)
|
2008-08-29 05:34:18 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
int num = msg_unpack_int();
|
|
|
|
|
|
|
|
for(int k = 0; k < num; k++)
|
|
|
|
{
|
|
|
|
NETOBJ_PROJECTILE proj;
|
|
|
|
for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
|
|
|
|
((int *)&proj)[i] = msg_unpack_int();
|
|
|
|
|
|
|
|
if(msg_unpack_error())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(extraproj_num != MAX_EXTRA_PROJECTILES)
|
|
|
|
{
|
|
|
|
extraproj_projectiles[extraproj_num] = proj;
|
|
|
|
extraproj_num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;*/
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(MsgId == NETMSGTYPE_SV_TUNEPARAMS)
|
2008-08-29 05:34:18 +00:00
|
|
|
{
|
|
|
|
// unpack the new tuning
|
2010-05-29 07:25:38 +00:00
|
|
|
CTuningParams NewTuning;
|
|
|
|
int *pParams = (int *)&NewTuning;
|
|
|
|
for(unsigned i = 0; i < sizeof(CTuningParams)/sizeof(int); i++)
|
|
|
|
pParams[i] = pUnpacker->GetInt();
|
2008-08-29 05:34:18 +00:00
|
|
|
|
|
|
|
// check for unpacking errors
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pUnpacker->Error())
|
2008-08-29 05:34:18 +00:00
|
|
|
return;
|
2009-01-11 10:40:14 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ServerMode = SERVERMODE_PURE;
|
2008-08-29 05:34:18 +00:00
|
|
|
|
|
|
|
// apply new tuning
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Tuning = NewTuning;
|
2008-08-29 05:34:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker);
|
|
|
|
if(!pRawMsg)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgId), MsgId, m_NetObjHandler.FailedMsgOn());
|
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf);
|
2008-08-27 15:48:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this should be done smarter
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg);
|
2008-08-27 20:17:04 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(MsgId == NETMSGTYPE_SV_READYTOENTER)
|
2008-08-27 20:17:04 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Client()->EnterGame();
|
2008-08-27 20:17:04 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if (MsgId == NETMSGTYPE_SV_EMOTICON)
|
2008-08-27 20:17:04 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Sv_Emoticon *pMsg = (CNetMsg_Sv_Emoticon *)pRawMsg;
|
2008-08-27 20:17:04 +00:00
|
|
|
|
|
|
|
// apply
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[pMsg->m_Cid].m_Emoticon = pMsg->m_Emoticon;
|
|
|
|
m_aClients[pMsg->m_Cid].m_EmoticonStart = Client()->GameTick();
|
2008-08-27 20:17:04 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL)
|
2008-08-27 20:17:04 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_SuppressEvents)
|
2009-01-11 15:51:43 +00:00
|
|
|
return;
|
2010-07-17 17:55:17 +00:00
|
|
|
|
|
|
|
// don't enqueue pseudo-global sounds from demos (created by PlayAndRecord)
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Sv_SoundGlobal *pMsg = (CNetMsg_Sv_SoundGlobal *)pRawMsg;
|
2010-07-17 17:55:17 +00:00
|
|
|
if(pMsg->m_Soundid == SOUND_CTF_DROP || pMsg->m_Soundid == SOUND_CTF_RETURN ||
|
|
|
|
pMsg->m_Soundid == SOUND_CTF_CAPTURE || pMsg->m_Soundid == SOUND_CTF_GRAB_EN ||
|
|
|
|
pMsg->m_Soundid == SOUND_CTF_GRAB_PL)
|
|
|
|
g_GameClient.m_pSounds->Enqueue(pMsg->m_Soundid);
|
|
|
|
else
|
|
|
|
g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_Soundid, 1.0f, vec2(0,0));
|
2010-08-25 14:15:59 +00:00
|
|
|
}
|
|
|
|
else if(MsgId == NETMSGTYPE_SV_PLAYERTIME)
|
|
|
|
{
|
|
|
|
CNetMsg_Sv_PlayerTime *pMsg = (CNetMsg_Sv_PlayerTime *)pRawMsg;
|
|
|
|
m_aClients[pMsg->m_Cid].m_Score = (float)pMsg->m_Time/100;
|
|
|
|
}
|
2010-09-11 20:45:56 +00:00
|
|
|
else if(MsgId == NETMSGTYPE_SV_PLAYERTEAM)
|
|
|
|
{
|
|
|
|
CNetMsg_Sv_PlayerTeam *pMsg = (CNetMsg_Sv_PlayerTeam *)pRawMsg;
|
|
|
|
m_Teams.Team(pMsg->m_Cid, pMsg->m_Team);
|
|
|
|
char aBuf[512];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "Id = %d Team = %d",pMsg->m_Cid, pMsg->m_Team);
|
|
|
|
dbg_msg("Teams", aBuf);
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnStateChange(int NewState, int OldState)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// reset everything when not already connected (to keep gathered stuff)
|
|
|
|
if(NewState < IClient::STATE_ONLINE)
|
|
|
|
OnReset();
|
2008-10-17 11:23:21 +00:00
|
|
|
|
|
|
|
// then change the state
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_All.m_Num; i++)
|
|
|
|
m_All.m_paComponents[i]->OnStateChange(NewState, OldState);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnShutdown() {}
|
|
|
|
void CGameClient::OnEnterGame() {}
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnRconLine(const char *pLine)
|
|
|
|
{
|
|
|
|
m_pGameConsole->PrintLine(1, pLine);
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::ProcessEvents()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_SuppressEvents)
|
2008-12-19 11:41:17 +00:00
|
|
|
return;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int SnapType = IClient::SNAP_CURRENT;
|
|
|
|
int Num = Client()->SnapNumItems(SnapType);
|
|
|
|
for(int Index = 0; Index < Num; Index++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IClient::CSnapItem Item;
|
|
|
|
const void *pData = Client()->SnapGetItem(SnapType, Index, &Item);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_Type == NETEVENTTYPE_DAMAGEIND)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_DAMAGEIND *ev = (NETEVENT_DAMAGEIND *)pData;
|
|
|
|
g_GameClient.m_pEffects->DamageIndicator(vec2(ev->m_X, ev->m_Y), GetDirection(ev->m_Angle));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETEVENTTYPE_EXPLOSION)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_EXPLOSION *ev = (NETEVENT_EXPLOSION *)pData;
|
|
|
|
g_GameClient.m_pEffects->Explosion(vec2(ev->m_X, ev->m_Y));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETEVENTTYPE_HAMMERHIT)
|
2008-10-17 11:23:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_HAMMERHIT *ev = (NETEVENT_HAMMERHIT *)pData;
|
|
|
|
g_GameClient.m_pEffects->HammerHit(vec2(ev->m_X, ev->m_Y));
|
2008-10-17 11:23:21 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETEVENTTYPE_SPAWN)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)pData;
|
|
|
|
g_GameClient.m_pEffects->PlayerSpawn(vec2(ev->m_X, ev->m_Y));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETEVENTTYPE_DEATH)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_DEATH *ev = (NETEVENT_DEATH *)pData;
|
|
|
|
g_GameClient.m_pEffects->PlayerDeath(vec2(ev->m_X, ev->m_Y), ev->m_ClientId);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
NETEVENT_SOUNDWORLD *ev = (NETEVENT_SOUNDWORLD *)pData;
|
|
|
|
g_GameClient.m_pSounds->Play(CSounds::CHN_WORLD, ev->m_SoundId, 1.0f, vec2(ev->m_X, ev->m_Y));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnNewSnapshot()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NewTick = true;
|
2009-01-11 15:51:43 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// clear out the invalid pointers
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
|
|
|
|
m_Snap.m_LocalCid = -1;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-08-25 14:15:59 +00:00
|
|
|
// mark all clients offline here
|
|
|
|
bool Online[MAX_CLIENTS] = { 0 };
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// secure snapshot
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
|
|
|
|
for(int Index = 0; Index < Num; Index++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IClient::CSnapItem Item;
|
|
|
|
void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
|
|
|
|
if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_Debug)
|
2010-08-17 22:06:00 +00:00
|
|
|
{
|
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_Id);
|
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
ProcessEvents();
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_DbgStress)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if((Client()->GameTick()%100) == 0)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
char aMessage[64];
|
|
|
|
int MsgLen = rand()%(sizeof(aMessage)-1);
|
|
|
|
for(int i = 0; i < MsgLen; i++)
|
|
|
|
aMessage[i] = 'a'+(rand()%('z'-'a'));
|
|
|
|
aMessage[MsgLen] = 0;
|
2008-12-19 11:41:17 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Cl_Say Msg;
|
|
|
|
Msg.m_Team = rand()&1;
|
|
|
|
Msg.m_pMessage = aMessage;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// go trough all the items in the snapshot and gather the info we want
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Snap.m_aTeamSize[0] = m_Snap.m_aTeamSize[1] = 0;
|
2008-09-23 07:43:41 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
|
|
|
|
for(int i = 0; i < Num; i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IClient::CSnapItem Item;
|
|
|
|
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_Type == NETOBJTYPE_CLIENTINFO)
|
2008-10-08 20:47:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData;
|
|
|
|
int Cid = Item.m_Id;
|
|
|
|
IntsToStr(&pInfo->m_Name0, 6, m_aClients[Cid].m_aName);
|
|
|
|
IntsToStr(&pInfo->m_Skin0, 6, m_aClients[Cid].m_aSkinName);
|
2008-10-08 20:47:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].m_UseCustomColor = pInfo->m_UseCustomColor;
|
|
|
|
m_aClients[Cid].m_ColorBody = pInfo->m_ColorBody;
|
|
|
|
m_aClients[Cid].m_ColorFeet = pInfo->m_ColorFeet;
|
2008-10-08 20:47:56 +00:00
|
|
|
|
|
|
|
// prepare the info
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_aClients[Cid].m_aSkinName[0] == 'x' || m_aClients[Cid].m_aSkinName[1] == '_')
|
|
|
|
str_copy(m_aClients[Cid].m_aSkinName, "default", 64);
|
2008-10-08 20:47:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].m_SkinInfo.m_ColorBody = m_pSkins->GetColor(m_aClients[Cid].m_ColorBody);
|
|
|
|
m_aClients[Cid].m_SkinInfo.m_ColorFeet = m_pSkins->GetColor(m_aClients[Cid].m_ColorFeet);
|
|
|
|
m_aClients[Cid].m_SkinInfo.m_Size = 64;
|
2008-10-08 20:47:56 +00:00
|
|
|
|
|
|
|
// find new skin
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find(m_aClients[Cid].m_aSkinName);
|
|
|
|
if(m_aClients[Cid].m_SkinId < 0)
|
2009-01-21 21:00:06 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find("default");
|
|
|
|
if(m_aClients[Cid].m_SkinId < 0)
|
|
|
|
m_aClients[Cid].m_SkinId = 0;
|
2009-01-21 21:00:06 +00:00
|
|
|
}
|
2008-10-08 20:47:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_aClients[Cid].m_UseCustomColor)
|
|
|
|
m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_ColorTexture;
|
2008-10-08 20:47:56 +00:00
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_OrgTexture;
|
|
|
|
m_aClients[Cid].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
|
|
|
|
m_aClients[Cid].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
|
2008-10-08 20:47:56 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[Cid].UpdateRenderInfo();
|
|
|
|
g_GameClient.m_Snap.m_NumPlayers++;
|
2008-10-08 20:47:56 +00:00
|
|
|
|
2010-08-25 14:15:59 +00:00
|
|
|
// mark Player as online
|
|
|
|
Online[Cid] = true;
|
2008-10-08 20:47:56 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[pInfo->m_ClientId].m_Team = pInfo->m_Team;
|
|
|
|
m_Snap.m_paPlayerInfos[pInfo->m_ClientId] = pInfo;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pInfo->m_Local)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Snap.m_LocalCid = Item.m_Id;
|
|
|
|
m_Snap.m_pLocalInfo = pInfo;
|
2008-09-09 15:50:41 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if (pInfo->m_Team == -1)
|
|
|
|
m_Snap.m_Spectate = true;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-01 18:17:01 +00:00
|
|
|
|
|
|
|
// calculate team-balance
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pInfo->m_Team != -1)
|
|
|
|
m_Snap.m_aTeamSize[pInfo->m_Team]++;
|
2008-09-01 18:17:01 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETOBJTYPE_CHARACTER)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_Id);
|
|
|
|
if(pOld)
|
2008-09-23 07:43:41 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Snap.m_aCharacters[Item.m_Id].m_Active = true;
|
|
|
|
m_Snap.m_aCharacters[Item.m_Id].m_Prev = *((const CNetObj_Character *)pOld);
|
|
|
|
m_Snap.m_aCharacters[Item.m_Id].m_Cur = *((const CNetObj_Character *)pData);
|
|
|
|
|
|
|
|
if(m_Snap.m_aCharacters[Item.m_Id].m_Prev.m_Tick)
|
|
|
|
Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Prev, Client()->PrevGameTick());
|
|
|
|
if(m_Snap.m_aCharacters[Item.m_Id].m_Cur.m_Tick)
|
|
|
|
Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Cur, Client()->GameTick());
|
2008-09-23 07:43:41 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Item.m_Type == NETOBJTYPE_GAME)
|
|
|
|
m_Snap.m_pGameobj = (CNetObj_Game *)pData;
|
|
|
|
else if(Item.m_Type == NETOBJTYPE_FLAG)
|
|
|
|
m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData;
|
2008-09-23 07:43:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup local pointers
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Snap.m_LocalCid >= 0)
|
2008-09-23 07:43:41 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalCid];
|
|
|
|
if(c->m_Active)
|
2008-09-23 07:43:41 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Snap.m_pLocalCharacter = &c->m_Cur;
|
|
|
|
m_Snap.m_pLocalPrevCharacter = &c->m_Prev;
|
|
|
|
m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2010-08-10 11:54:13 +00:00
|
|
|
else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_Snap.m_LocalCid))
|
|
|
|
{
|
|
|
|
// player died
|
|
|
|
m_pControls->OnPlayerDeath();
|
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-11-16 13:58:27 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Snap.m_Spectate = true;
|
2009-01-11 10:40:14 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CTuningParams StandardTuning;
|
2010-08-25 14:15:59 +00:00
|
|
|
StandardTuning.m_PlayerCollision = 1;
|
|
|
|
StandardTuning.m_PlayerHooking = 1;
|
2010-05-29 07:25:38 +00:00
|
|
|
CServerInfo CurrentServerInfo;
|
|
|
|
Client()->GetServerInfo(&CurrentServerInfo);
|
|
|
|
if(CurrentServerInfo.m_aGameType[0] != '0')
|
2009-01-11 10:40:14 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0)
|
|
|
|
m_ServerMode = SERVERMODE_MOD;
|
|
|
|
else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
|
|
|
|
m_ServerMode = SERVERMODE_PURE;
|
2009-01-11 10:40:14 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ServerMode = SERVERMODE_PUREMOD;
|
2009-01-11 10:40:14 +00:00
|
|
|
}
|
|
|
|
|
2010-08-25 14:15:59 +00:00
|
|
|
// send race msg
|
|
|
|
if(m_Snap.m_pLocalInfo)
|
|
|
|
{
|
|
|
|
CServerInfo CurrentServerInfo;
|
|
|
|
Client()->GetServerInfo(&CurrentServerInfo);
|
|
|
|
if(str_find_nocase(CurrentServerInfo.m_aGameType, "race") || str_find_nocase(CurrentServerInfo.m_aGameType, "fastcap") || str_find_nocase(CurrentServerInfo.m_aGameType, "ddrace"))
|
|
|
|
{
|
|
|
|
if(!m_IsRace)
|
|
|
|
m_IsRace = true;
|
|
|
|
if(str_find_nocase(CurrentServerInfo.m_aGameType, "fastcap"))
|
|
|
|
{
|
|
|
|
m_IsFastCap = true;
|
|
|
|
|
|
|
|
// get Flag Pos (for demo recording)
|
|
|
|
m_FlagPos = vec2(-1, -1);
|
|
|
|
int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
|
|
|
|
for(int i = 0; i < Num; i++)
|
|
|
|
{
|
|
|
|
IClient::CSnapItem Item;
|
|
|
|
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);
|
|
|
|
|
|
|
|
if(Item.m_Type == NETOBJTYPE_FLAG)
|
|
|
|
{
|
|
|
|
const CNetObj_Flag *pFlag = (const CNetObj_Flag *)pData;
|
|
|
|
if(pFlag->m_CarriedBy == -2 && pFlag->m_Team != m_aClients[m_Snap.m_LocalCid].m_Team)
|
|
|
|
m_FlagPos = vec2(pFlag->m_X, pFlag->m_Y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!m_RaceMsgSent && m_Snap.m_pLocalInfo)
|
|
|
|
{
|
|
|
|
CNetMsg_Cl_IsRace Msg;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
|
|
|
m_RaceMsgSent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_ShowOthers == -1 || (m_ShowOthers > -1 && m_ShowOthers != g_Config.m_ClShowOthers))
|
|
|
|
{
|
|
|
|
if(m_ShowOthers == -1 && g_Config.m_ClShowOthers)
|
|
|
|
m_ShowOthers = 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CNetMsg_Cl_RaceShowOthers Msg;
|
|
|
|
Msg.m_Active = g_Config.m_ClShowOthers;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
|
|
|
|
|
|
|
m_ShowOthers = g_Config.m_ClShowOthers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset all scores of offline players
|
|
|
|
if(m_IsRace)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
if(!Online[i])
|
|
|
|
m_aClients[i].m_Score = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// update render info
|
2008-08-27 15:48:50 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aClients[i].UpdateRenderInfo();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::OnPredict()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-09-23 07:43:41 +00:00
|
|
|
// store the previous values so we can detect prediction errors
|
2010-05-29 07:25:38 +00:00
|
|
|
CCharacterCore BeforePrevChar = m_PredictedPrevChar;
|
|
|
|
CCharacterCore BeforeChar = m_PredictedChar;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// we can't predict without our own id or own character
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Snap.m_LocalCid == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalCid].m_Active)
|
2008-09-23 07:43:41 +00:00
|
|
|
return;
|
2008-11-16 15:10:57 +00:00
|
|
|
|
|
|
|
// don't predict anything if we are paused
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_Paused)
|
2008-11-16 15:10:57 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Snap.m_pLocalCharacter)
|
|
|
|
m_PredictedChar.Read(m_Snap.m_pLocalCharacter);
|
|
|
|
if(m_Snap.m_pLocalPrevCharacter)
|
|
|
|
m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter);
|
2008-11-16 15:10:57 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
// repredict character
|
2010-05-29 07:25:38 +00:00
|
|
|
CWorldCore World;
|
|
|
|
World.m_Tuning = m_Tuning;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// search for players
|
2008-09-23 07:43:41 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!m_Snap.m_aCharacters[i].m_Active)
|
2008-09-23 07:43:41 +00:00
|
|
|
continue;
|
|
|
|
|
2010-08-30 19:25:04 +00:00
|
|
|
g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision(), &m_Teams);
|
2010-05-29 07:25:38 +00:00
|
|
|
World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted;
|
2010-09-11 20:45:56 +00:00
|
|
|
World.m_apCharacters[i]->m_Id = m_Snap.m_LocalCid;
|
2010-05-29 07:25:38 +00:00
|
|
|
g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// predict
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// fetch the local
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid])
|
|
|
|
m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalCid];
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// first calculate where everyone should move
|
|
|
|
for(int c = 0; c < MAX_CLIENTS; c++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!World.m_apCharacters[c])
|
2008-08-27 15:48:50 +00:00
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input));
|
|
|
|
if(m_Snap.m_LocalCid == c)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// apply player input
|
2010-05-29 07:25:38 +00:00
|
|
|
int *pInput = Client()->GetInput(Tick);
|
|
|
|
if(pInput)
|
|
|
|
World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput);
|
|
|
|
World.m_apCharacters[c]->Tick(true);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-09-23 07:43:41 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
World.m_apCharacters[c]->Tick(false);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// move all players and quantize their data
|
|
|
|
for(int c = 0; c < MAX_CLIENTS; c++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!World.m_apCharacters[c])
|
2008-08-27 15:48:50 +00:00
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
World.m_apCharacters[c]->Move();
|
|
|
|
World.m_apCharacters[c]->Quantize();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2008-09-23 07:43:41 +00:00
|
|
|
// check if we want to trigger effects
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Tick > m_LastNewPredictedTick)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_LastNewPredictedTick = Tick;
|
|
|
|
m_NewPredictedTick = true;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Snap.m_LocalCid != -1 && World.m_apCharacters[m_Snap.m_LocalCid])
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Pos = World.m_apCharacters[m_Snap.m_LocalCid]->m_Pos;
|
|
|
|
int Events = World.m_apCharacters[m_Snap.m_LocalCid]->m_TriggeredEvents;
|
|
|
|
if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos);
|
2009-01-11 15:51:43 +00:00
|
|
|
|
|
|
|
/*if(events&COREEVENT_AIR_JUMP)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
GameClient.effects->air_jump(pos);
|
|
|
|
GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
|
2009-01-11 15:51:43 +00:00
|
|
|
}*/
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
|
|
|
|
//if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos);
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos);
|
|
|
|
if(Events&COREEVENT_HOOK_HIT_NOHOOK) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos);
|
2008-08-27 15:48:50 +00:00
|
|
|
//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalCid])
|
|
|
|
m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalCid];
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick())
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0};
|
|
|
|
BeforeChar.Write(&Before);
|
|
|
|
BeforePrevChar.Write(&BeforePrev);
|
|
|
|
m_PredictedChar.Write(&Now);
|
|
|
|
m_PredictedPrevChar.Write(&NowPrev);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "prediction error");
|
2010-05-29 07:25:38 +00:00
|
|
|
for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++)
|
|
|
|
if(((int *)&Before)[i] != ((int *)&Now)[i])
|
2008-09-23 07:43:41 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), " %d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]);
|
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
|
2008-09-23 07:43:41 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_PredictedTick = Client()->PredGameTick();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::CClientData::UpdateRenderInfo()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_RenderInfo = m_SkinInfo;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
// force team colors
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_GameClient.m_Snap.m_pGameobj && g_GameClient.m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const int TeamColors[2] = {65387, 10223467};
|
|
|
|
if(m_Team >= 0 || m_Team <= 1)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_RenderInfo.m_Texture = g_GameClient.m_pSkins->Get(m_SkinId)->m_ColorTexture;
|
|
|
|
m_RenderInfo.m_ColorBody = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]);
|
|
|
|
m_RenderInfo.m_ColorFeet = g_GameClient.m_pSkins->GetColor(TeamColors[m_Team]);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::SendSwitchTeam(int Team)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Cl_SetTeam Msg;
|
|
|
|
Msg.m_Team = Team;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::SendInfo(bool Start)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Start)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Cl_StartInfo Msg;
|
|
|
|
Msg.m_pName = g_Config.m_PlayerName;
|
|
|
|
Msg.m_pSkin = g_Config.m_PlayerSkin;
|
|
|
|
Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor;
|
|
|
|
Msg.m_ColorBody = g_Config.m_PlayerColorBody;
|
|
|
|
Msg.m_ColorFeet = g_Config.m_PlayerColorFeet;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Cl_ChangeInfo Msg;
|
|
|
|
Msg.m_pName = g_Config.m_PlayerName;
|
|
|
|
Msg.m_pSkin = g_Config.m_PlayerSkin;
|
|
|
|
Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor;
|
|
|
|
Msg.m_ColorBody = g_Config.m_PlayerColorBody;
|
|
|
|
Msg.m_ColorFeet = g_Config.m_PlayerColorFeet;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
|
|
|
|
|
|
|
// activate timer to resend the info if it gets filtered
|
|
|
|
if(!m_LastSendInfo || m_LastSendInfo+time_freq()*5 < time_get())
|
|
|
|
m_LastSendInfo = time_get();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::SendKill(int ClientId)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetMsg_Cl_Kill Msg;
|
|
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2008-08-31 13:36:30 +00:00
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData, int ClientID)
|
2008-08-31 13:36:30 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
((CGameClient*)pUserData)->SendSwitchTeam(pResult->GetInteger(0));
|
2008-08-31 13:36:30 +00:00
|
|
|
}
|
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
void CGameClient::ConKill(IConsole::IResult *pResult, void *pUserData, int ClientID)
|
2008-08-31 13:36:30 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
((CGameClient*)pUserData)->SendKill(-1);
|
2008-08-31 13:36:30 +00:00
|
|
|
}
|
2009-06-15 14:01:36 +00:00
|
|
|
|
2010-08-25 20:30:21 +00:00
|
|
|
void CGameClient::ConMapHack(IConsole::IResult *pResult, void *pUserData, int ClientID) {
|
2010-08-25 14:15:59 +00:00
|
|
|
g_Config.m_GfxClearFull ^= 1;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CGameClient::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
2009-06-15 14:01:36 +00:00
|
|
|
{
|
2010-08-25 20:30:21 +00:00
|
|
|
pfnCallback(pResult, pCallbackUserData, -1);
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pResult->NumArguments())
|
|
|
|
((CGameClient*)pUserData)->SendInfo(false);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
IGameClient *CreateGameClient()
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
return &g_GameClient;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|