Merge pull request #635 from heinrich5991/pr_dummy_input_demo_filter

Refactor dummy input and demo filtering
This commit is contained in:
Dennis Felsing 2017-03-01 07:59:24 +01:00 committed by GitHub
commit 4c1053c6c4
14 changed files with 187 additions and 220 deletions

View file

@ -8,7 +8,6 @@
#include <engine/friends.h> #include <engine/friends.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <versionsrv/versionsrv.h> #include <versionsrv/versionsrv.h>
#include <game/generated/protocol.h>
enum enum
{ {
@ -18,6 +17,8 @@ enum
RECORDER_MAX=3, RECORDER_MAX=3,
}; };
typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
class IClient : public IInterface class IClient : public IInterface
{ {
MACRO_INTERFACE("client", 0) MACRO_INTERFACE("client", 0)
@ -39,14 +40,9 @@ protected:
int m_GameTickSpeed; int m_GameTickSpeed;
public: public:
int m_LocalIDs[2];
char m_aNews[NEWS_SIZE]; char m_aNews[NEWS_SIZE];
int64 m_ReconnectTime; int64 m_ReconnectTime;
CNetObj_PlayerInput m_DummyInput;
bool m_DummySendConnInfo;
class CSnapItem class CSnapItem
{ {
public: public:
@ -190,7 +186,7 @@ public:
virtual void DemoSliceBegin() = 0; virtual void DemoSliceBegin() = 0;
virtual void DemoSliceEnd() = 0; virtual void DemoSliceEnd() = 0;
virtual void DemoSlice(const char *pDstPath, bool RemoveChat) = 0; virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) = 0;
virtual void RequestDDNetSrvList() = 0; virtual void RequestDDNetSrvList() = 0;
virtual bool EditorHasUnsavedData() = 0; virtual bool EditorHasUnsavedData() = 0;
@ -220,10 +216,9 @@ public:
virtual void OnPredict() = 0; virtual void OnPredict() = 0;
virtual void OnActivateEditor() = 0; virtual void OnActivateEditor() = 0;
virtual int OnSnapInput(int *pData) = 0; virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0;
virtual void OnDummySwap() = 0;
virtual void SendDummyInfo(bool Start) = 0; virtual void SendDummyInfo(bool Start) = 0;
virtual void ResetDummyInput() = 0;
virtual const CNetObj_PlayerInput &getPlayerInput(int dummy) = 0;
virtual const char *GetItemName(int Type) = 0; virtual const char *GetItemName(int Type) = 0;
virtual const char *Version() = 0; virtual const char *Version() = 0;

View file

@ -324,14 +324,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
m_CurrentInput[1] = 0; m_CurrentInput[1] = 0;
m_LastDummy = 0; m_LastDummy = 0;
m_LastDummy2 = 0; m_LastDummy2 = 0;
m_LocalIDs[0] = 0;
m_LocalIDs[1] = 0;
m_Fire = 0;
mem_zero(&m_aInputs, sizeof(m_aInputs)); mem_zero(&m_aInputs, sizeof(m_aInputs));
mem_zero(&m_DummyInput, sizeof(m_DummyInput));
mem_zero(&HammerInput, sizeof(HammerInput));
HammerInput.m_Fire = 0;
m_State = IClient::STATE_OFFLINE; m_State = IClient::STATE_OFFLINE;
m_aServerAddressStr[0] = 0; m_aServerAddressStr[0] = 0;
@ -481,106 +475,44 @@ void CClient::SendInput()
if(m_PredTick[g_Config.m_ClDummy] <= 0) if(m_PredTick[g_Config.m_ClDummy] <= 0)
return; return;
// fetch input if(m_LastDummy != g_Config.m_ClDummy)
int Size = GameClient()->OnSnapInput(m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_aData);
if(Size)
{ {
// pack input
CMsgPacker Msg(NETMSG_INPUT);
Msg.AddInt(m_AckGameTick[g_Config.m_ClDummy]);
Msg.AddInt(m_PredTick[g_Config.m_ClDummy]);
Msg.AddInt(Size);
m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_Tick = m_PredTick[g_Config.m_ClDummy];
m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_PredictedTime = m_PredictedTime.Get(Now);
m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_Time = Now;
// pack it
for(int i = 0; i < Size/4; i++)
Msg.AddInt(m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_aData[i]);
m_CurrentInput[g_Config.m_ClDummy]++;
m_CurrentInput[g_Config.m_ClDummy]%=200;
SendMsgEx(&Msg, MSGFLAG_FLUSH);
}
if(m_LastDummy != (bool)g_Config.m_ClDummy)
{
m_DummyInput = GameClient()->getPlayerInput(!g_Config.m_ClDummy);
m_LastDummy = g_Config.m_ClDummy; m_LastDummy = g_Config.m_ClDummy;
GameClient()->OnDummySwap();
if (g_Config.m_ClDummyResetOnSwitch)
{
m_DummyInput.m_Jump = 0;
m_DummyInput.m_Hook = 0;
if(m_DummyInput.m_Fire & 1)
m_DummyInput.m_Fire++;
m_DummyInput.m_Direction = 0;
GameClient()->ResetDummyInput();
}
} }
if(!g_Config.m_ClDummy) bool Force = false;
m_LocalIDs[0] = ((CGameClient *)GameClient())->m_Snap.m_LocalClientID; // fetch input
else for(int Dummy = 0; Dummy < 2; Dummy++)
m_LocalIDs[1] = ((CGameClient *)GameClient())->m_Snap.m_LocalClientID;
if(m_DummyConnected)
{ {
if(!g_Config.m_ClDummyHammer) if(!m_DummyConnected && Dummy != 0)
{ {
if(m_Fire != 0) break;
{
m_DummyInput.m_Fire = HammerInput.m_Fire;
m_Fire = 0;
}
if(!Size && (!m_DummyInput.m_Direction && !m_DummyInput.m_Jump && !m_DummyInput.m_Hook))
return;
// pack input
CMsgPacker Msg(NETMSG_INPUT);
Msg.AddInt(m_AckGameTick[!g_Config.m_ClDummy]);
Msg.AddInt(m_PredTick[!g_Config.m_ClDummy]);
Msg.AddInt(sizeof(m_DummyInput));
// pack it
for(unsigned int i = 0; i < sizeof(m_DummyInput)/4; i++)
Msg.AddInt(((int*) &m_DummyInput)[i]);
SendMsgExY(&Msg, MSGFLAG_FLUSH, true, !g_Config.m_ClDummy);
} }
else int i = g_Config.m_ClDummy ^ Dummy;
int Size = GameClient()->OnSnapInput(m_aInputs[i][m_CurrentInput[i]].m_aData, Dummy, Force);
if(Size)
{ {
if ((((float) m_Fire / 12.5) - (int ((float) m_Fire / 12.5))) > 0.01)
{
m_Fire++;
return;
}
m_Fire++;
HammerInput.m_Fire+=2;
HammerInput.m_WantedWeapon = 1;
vec2 Main = ((CGameClient *)GameClient())->m_LocalCharacterPos;
vec2 Dummy = ((CGameClient *)GameClient())->m_aClients[m_LocalIDs[!g_Config.m_ClDummy]].m_Predicted.m_Pos;
vec2 Dir = Main - Dummy;
HammerInput.m_TargetX = Dir.x;
HammerInput.m_TargetY = Dir.y;
// pack input // pack input
CMsgPacker Msg(NETMSG_INPUT); CMsgPacker Msg(NETMSG_INPUT);
Msg.AddInt(m_AckGameTick[!g_Config.m_ClDummy]); Msg.AddInt(m_AckGameTick[i]);
Msg.AddInt(m_PredTick[!g_Config.m_ClDummy]); Msg.AddInt(m_PredTick[i]);
Msg.AddInt(sizeof(HammerInput)); Msg.AddInt(Size);
m_aInputs[i][m_CurrentInput[i]].m_Tick = m_PredTick[i];
m_aInputs[i][m_CurrentInput[i]].m_PredictedTime = m_PredictedTime.Get(Now);
m_aInputs[i][m_CurrentInput[i]].m_Time = Now;
// pack it // pack it
for(unsigned int i = 0; i < sizeof(HammerInput)/4; i++) for(int k = 0; k < Size/4; k++)
Msg.AddInt(((int*) &HammerInput)[i]); Msg.AddInt(m_aInputs[i][m_CurrentInput[i]].m_aData[k]);
SendMsgExY(&Msg, MSGFLAG_FLUSH, true, !g_Config.m_ClDummy); m_CurrentInput[i]++;
m_CurrentInput[i] %= 200;
SendMsgExY(&Msg, MSGFLAG_FLUSH, true, i);
Force = true;
} }
} }
} }
@ -887,21 +819,6 @@ int CClient::SendMsgExY(CMsgPacker *pMsg, int Flags, bool System, int NetClient)
return 0; return 0;
} }
void CClient::DummyInfo()
{
CNetMsg_Cl_ChangeInfo Msg;
Msg.m_pName = g_Config.m_ClDummyName;
Msg.m_pClan = g_Config.m_ClDummyClan;
Msg.m_Country = g_Config.m_ClDummyCountry;
Msg.m_pSkin = g_Config.m_ClDummySkin;
Msg.m_UseCustomColor = g_Config.m_ClDummyUseCustomColor;
Msg.m_ColorBody = g_Config.m_ClDummyColorBody;
Msg.m_ColorFeet = g_Config.m_ClDummyColorFeet;
CMsgPacker Packer(Msg.MsgID());
Msg.Pack(&Packer);
SendMsgExY(&Packer, MSGFLAG_VITAL);
}
void CClient::GetServerInfo(CServerInfo *pServerInfo) void CClient::GetServerInfo(CServerInfo *pServerInfo)
{ {
mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo)); mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
@ -1259,11 +1176,11 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
mem_copy(m_aNews, (char*)pPacket->m_pData + sizeof(VERSIONSRV_NEWS), NEWS_SIZE); mem_copy(m_aNews, (char*)pPacket->m_pData + sizeof(VERSIONSRV_NEWS), NEWS_SIZE);
IOHANDLE newsFile = m_pStorage->OpenFile("ddnet-news.txt", IOFLAG_WRITE, IStorage::TYPE_SAVE); IOHANDLE NewsFile = m_pStorage->OpenFile("ddnet-news.txt", IOFLAG_WRITE, IStorage::TYPE_SAVE);
if (newsFile) if (NewsFile)
{ {
io_write(newsFile, m_aNews, sizeof(m_aNews)); io_write(NewsFile, m_aNews, sizeof(m_aNews));
io_close(newsFile); io_close(NewsFile);
} }
} }
@ -3080,12 +2997,12 @@ void CClient::Con_DemoSliceEnd(IConsole::IResult *pResult, void *pUserData)
pSelf->DemoSliceEnd(); pSelf->DemoSliceEnd();
} }
void CClient::DemoSlice(const char *pDstPath, bool RemoveChat) void CClient::DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser)
{ {
if (m_DemoPlayer.IsPlaying()) if (m_DemoPlayer.IsPlaying())
{ {
const char *pDemoFileName = m_DemoPlayer.GetDemoFileName(); const char *pDemoFileName = m_DemoPlayer.GetDemoFileName();
m_DemoEditor.Slice(pDemoFileName, pDstPath, g_Config.m_ClDemoSliceBegin, g_Config.m_ClDemoSliceEnd, RemoveChat); m_DemoEditor.Slice(pDemoFileName, pDstPath, g_Config.m_ClDemoSliceBegin, g_Config.m_ClDemoSliceEnd, pfnFilter, pUser);
} }
} }

View file

@ -152,7 +152,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
int m_CurrentInput[2]; int m_CurrentInput[2];
bool m_LastDummy; bool m_LastDummy;
bool m_LastDummy2; bool m_LastDummy2;
CNetObj_PlayerInput HammerInput; bool m_DummySendConnInfo;
// graphs // graphs
CGraph m_InputtimeMarginGraph; CGraph m_InputtimeMarginGraph;
@ -261,10 +261,8 @@ public:
virtual void DummyConnect(); virtual void DummyConnect();
virtual bool DummyConnected(); virtual bool DummyConnected();
virtual bool DummyConnecting(); virtual bool DummyConnecting();
void DummyInfo();
int m_DummyConnected; int m_DummyConnected;
int m_LastDummyConnectTime; int m_LastDummyConnectTime;
int m_Fire;
virtual void GetServerInfo(CServerInfo *pServerInfo); virtual void GetServerInfo(CServerInfo *pServerInfo);
void ServerInfoRequest(); void ServerInfoRequest();
@ -386,7 +384,7 @@ public:
virtual void DemoSliceBegin(); virtual void DemoSliceBegin();
virtual void DemoSliceEnd(); virtual void DemoSliceEnd();
virtual void DemoSlice(const char *pDstPath, bool RemoveChat); virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser);
void RequestDDNetSrvList(); void RequestDDNetSrvList();
bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); } bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); }

View file

@ -12,6 +12,8 @@ enum
const double g_aSpeeds[] = {0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0}; const double g_aSpeeds[] = {0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0};
typedef bool (*DEMOFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
struct CDemoHeader struct CDemoHeader
{ {
unsigned char m_aMarker[7]; unsigned char m_aMarker[7];
@ -84,7 +86,7 @@ class IDemoEditor : public IInterface
MACRO_INTERFACE("demoeditor", 0) MACRO_INTERFACE("demoeditor", 0)
public: public:
virtual void Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, bool RemoveChat) = 0; virtual void Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, DEMOFUNC_FILTER pfnFilter, void *pUser) = 0;
}; };
#endif #endif

View file

@ -7,7 +7,6 @@
#include <engine/storage.h> #include <engine/storage.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <game/generated/protocol.h>
#include "compression.h" #include "compression.h"
#include "demo.h" #include "demo.h"
@ -26,17 +25,21 @@ static const int gs_NumMarkersOffset = 176;
CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta, bool DelayedMapData) CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta, bool DelayedMapData)
{ {
m_File = 0; m_File = 0;
m_pfnFilter = 0;
m_pUser = 0;
m_LastTickMarker = -1; m_LastTickMarker = -1;
m_pSnapshotDelta = pSnapshotDelta; m_pSnapshotDelta = pSnapshotDelta;
m_DelayedMapData = DelayedMapData; m_DelayedMapData = DelayedMapData;
} }
// Record // Record
int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetVersion, const char *pMap, unsigned Crc, const char *pType, unsigned int MapSize, unsigned char *pMapData, bool RemoveChat) int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetVersion, const char *pMap, unsigned Crc, const char *pType, unsigned int MapSize, unsigned char *pMapData, DEMOFUNC_FILTER pfnFilter, void *pUser)
{ {
m_pfnFilter = pfnFilter;
m_pUser = pUser;
m_MapSize = MapSize; m_MapSize = MapSize;
m_pMapData = pMapData; m_pMapData = pMapData;
m_RemoveChat = RemoveChat;
IOHANDLE DemoFile = pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); IOHANDLE DemoFile = pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
if(!DemoFile) if(!DemoFile)
@ -278,23 +281,13 @@ void CDemoRecorder::RecordSnapshot(int Tick, const void *pData, int Size)
void CDemoRecorder::RecordMessage(const void *pData, int Size) void CDemoRecorder::RecordMessage(const void *pData, int Size)
{ {
if (m_RemoveChat) if(m_pfnFilter)
{ {
CUnpacker Unpacker; if(m_pfnFilter(pData, Size, m_pUser))
Unpacker.Reset(pData, Size); {
// unpack msgid and system flag
int Msg = Unpacker.GetInt();
int Sys = Msg&1;
Msg >>= 1;
if(Unpacker.Error())
return;
if(!Sys && Msg == NETMSGTYPE_SV_CHAT)
return; return;
}
} }
Write(CHUNKTYPE_MESSAGE, pData, Size); Write(CHUNKTYPE_MESSAGE, pData, Size);
} }
@ -948,7 +941,7 @@ void CDemoEditor::Init(const char *pNetVersion, class CSnapshotDelta *pSnapshotD
m_pStorage = pStorage; m_pStorage = pStorage;
} }
void CDemoEditor::Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, bool RemoveChat) void CDemoEditor::Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, DEMOFUNC_FILTER pfnFilter, void *pUser)
{ {
class CDemoPlayer DemoPlayer(m_pSnapshotDelta); class CDemoPlayer DemoPlayer(m_pSnapshotDelta);
class CDemoRecorder DemoRecorder(m_pSnapshotDelta); class CDemoRecorder DemoRecorder(m_pSnapshotDelta);
@ -966,7 +959,7 @@ void CDemoEditor::Slice(const char *pDemo, const char *pDst, int StartTick, int
return; return;
const CDemoPlayer::CMapInfo *pMapInfo = m_pDemoPlayer->GetMapInfo(); const CDemoPlayer::CMapInfo *pMapInfo = m_pDemoPlayer->GetMapInfo();
if (m_pDemoRecorder->Start(m_pStorage, m_pConsole, pDst, m_pNetVersion, pMapInfo->m_aName, pMapInfo->m_Crc, "client", 0, 0, RemoveChat) == -1) if (m_pDemoRecorder->Start(m_pStorage, m_pConsole, pDst, m_pNetVersion, pMapInfo->m_aName, pMapInfo->m_Crc, "client", 0, 0, pfnFilter, pUser) == -1)
return; return;

View file

@ -22,7 +22,9 @@ class CDemoRecorder : public IDemoRecorder
bool m_DelayedMapData; bool m_DelayedMapData;
unsigned int m_MapSize; unsigned int m_MapSize;
unsigned char *m_pMapData; unsigned char *m_pMapData;
bool m_RemoveChat;
DEMOFUNC_FILTER m_pfnFilter;
void *m_pUser;
void WriteTickMarker(int Tick, int Keyframe); void WriteTickMarker(int Tick, int Keyframe);
void Write(int Type, const void *pData, int Size); void Write(int Type, const void *pData, int Size);
@ -30,7 +32,7 @@ public:
CDemoRecorder(class CSnapshotDelta *pSnapshotDelta, bool DelayedMapData = false); CDemoRecorder(class CSnapshotDelta *pSnapshotDelta, bool DelayedMapData = false);
CDemoRecorder() {} CDemoRecorder() {}
int Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetversion, const char *pMap, unsigned MapCrc, const char *pType, unsigned int MapSize = 0, unsigned char *pMapData = 0, bool RemoveChat = false); int Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetversion, const char *pMap, unsigned MapCrc, const char *pType, unsigned int MapSize = 0, unsigned char *pMapData = 0, DEMOFUNC_FILTER pfnFilter = 0, void *pUser = 0);
int Stop(bool Finalize = false); int Stop(bool Finalize = false);
void AddDemoMarker(); void AddDemoMarker();
@ -156,7 +158,7 @@ class CDemoEditor : public IDemoEditor, public CDemoPlayer::IListener
public: public:
virtual void Init(const char *pNetVersion, class CSnapshotDelta *pSnapshotDelta, class IConsole *pConsole, class IStorage *pStorage); virtual void Init(const char *pNetVersion, class CSnapshotDelta *pSnapshotDelta, class IConsole *pConsole, class IStorage *pStorage);
virtual void Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, bool RemoveChat); virtual void Slice(const char *pDemo, const char *pDst, int StartTick, int EndTick, DEMOFUNC_FILTER pfnFilter, void *pUser);
virtual void OnDemoPlayerSnapshot(void *pData, int Size); virtual void OnDemoPlayerSnapshot(void *pData, int Size);
virtual void OnDemoPlayerMessage(void *pData, int Size); virtual void OnDemoPlayerMessage(void *pData, int Size);

View file

@ -483,13 +483,13 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine)
// check for highlighted name // check for highlighted name
if (Client()->State() != IClient::STATE_DEMOPLAYBACK) if (Client()->State() != IClient::STATE_DEMOPLAYBACK)
{ {
if(ClientID != m_pClient->Client()->m_LocalIDs[0]) if(ClientID != m_pClient->m_LocalIDs[0])
{ {
// main character // main character
if (LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[0]].m_aName)) if (LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->m_LocalIDs[0]].m_aName))
Highlighted = true; Highlighted = true;
// dummy // dummy
if(m_pClient->Client()->DummyConnected() && LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[1]].m_aName)) if(m_pClient->Client()->DummyConnected() && LineShouldHighlight(pLine, m_pClient->m_aClients[m_pClient->m_LocalIDs[1]].m_aName))
Highlighted = true; Highlighted = true;
} }
} }

View file

@ -74,19 +74,19 @@ void CControls::OnReset()
m_OldMouseX = m_OldMouseY = 0.0f; m_OldMouseX = m_OldMouseY = 0.0f;
} }
void CControls::ResetInput(int dummy) void CControls::ResetInput(int Dummy)
{ {
m_LastData[dummy].m_Direction = 0; m_LastData[Dummy].m_Direction = 0;
//m_LastData.m_Hook = 0; //m_LastData.m_Hook = 0;
// simulate releasing the fire button // simulate releasing the fire button
if((m_LastData[dummy].m_Fire&1) != 0) if((m_LastData[Dummy].m_Fire&1) != 0)
m_LastData[dummy].m_Fire++; m_LastData[Dummy].m_Fire++;
m_LastData[dummy].m_Fire &= INPUT_STATE_MASK; m_LastData[Dummy].m_Fire &= INPUT_STATE_MASK;
m_LastData[dummy].m_Jump = 0; m_LastData[Dummy].m_Jump = 0;
m_InputData[dummy] = m_LastData[dummy]; m_InputData[Dummy] = m_LastData[Dummy];
m_InputDirectionLeft[dummy] = 0; m_InputDirectionLeft[Dummy] = 0;
m_InputDirectionRight[dummy] = 0; m_InputDirectionRight[Dummy] = 0;
} }
void CControls::OnRelease() void CControls::OnRelease()
@ -264,22 +264,20 @@ int CControls::SnapInput(int *pData)
// dummy copy moves // dummy copy moves
if(g_Config.m_ClDummyCopyMoves) if(g_Config.m_ClDummyCopyMoves)
{ {
CNetObj_PlayerInput *DummyInput = &Client()->m_DummyInput; CNetObj_PlayerInput *pDummyInput = &m_pClient->m_DummyInput;
DummyInput->m_Direction = m_InputData[g_Config.m_ClDummy].m_Direction; pDummyInput->m_Direction = m_InputData[g_Config.m_ClDummy].m_Direction;
DummyInput->m_Hook = m_InputData[g_Config.m_ClDummy].m_Hook; pDummyInput->m_Hook = m_InputData[g_Config.m_ClDummy].m_Hook;
DummyInput->m_Jump = m_InputData[g_Config.m_ClDummy].m_Jump; pDummyInput->m_Jump = m_InputData[g_Config.m_ClDummy].m_Jump;
DummyInput->m_PlayerFlags = m_InputData[g_Config.m_ClDummy].m_PlayerFlags; pDummyInput->m_PlayerFlags = m_InputData[g_Config.m_ClDummy].m_PlayerFlags;
DummyInput->m_TargetX = m_InputData[g_Config.m_ClDummy].m_TargetX; pDummyInput->m_TargetX = m_InputData[g_Config.m_ClDummy].m_TargetX;
DummyInput->m_TargetY = m_InputData[g_Config.m_ClDummy].m_TargetY; pDummyInput->m_TargetY = m_InputData[g_Config.m_ClDummy].m_TargetY;
DummyInput->m_WantedWeapon = m_InputData[g_Config.m_ClDummy].m_WantedWeapon; pDummyInput->m_WantedWeapon = m_InputData[g_Config.m_ClDummy].m_WantedWeapon;
pDummyInput->m_Fire += m_InputData[g_Config.m_ClDummy].m_Fire - m_LastData[g_Config.m_ClDummy].m_Fire;
pDummyInput->m_NextWeapon += m_InputData[g_Config.m_ClDummy].m_NextWeapon - m_LastData[g_Config.m_ClDummy].m_NextWeapon;
pDummyInput->m_PrevWeapon += m_InputData[g_Config.m_ClDummy].m_PrevWeapon - m_LastData[g_Config.m_ClDummy].m_PrevWeapon;
m_InputData[!g_Config.m_ClDummy] = *pDummyInput;
DummyInput->m_Fire += m_InputData[g_Config.m_ClDummy].m_Fire - m_LastData[g_Config.m_ClDummy].m_Fire;
DummyInput->m_NextWeapon += m_InputData[g_Config.m_ClDummy].m_NextWeapon - m_LastData[g_Config.m_ClDummy].m_NextWeapon;
DummyInput->m_PrevWeapon += m_InputData[g_Config.m_ClDummy].m_PrevWeapon - m_LastData[g_Config.m_ClDummy].m_PrevWeapon;
m_InputData[!g_Config.m_ClDummy] = *DummyInput;
} }
// stress testing // stress testing

View file

@ -151,9 +151,9 @@ void CEmoticon::OnRender()
CTeeRenderInfo *pTeeInfo; CTeeRenderInfo *pTeeInfo;
if(g_Config.m_ClDummy) if(g_Config.m_ClDummy)
pTeeInfo = &m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[1]].m_RenderInfo; pTeeInfo = &m_pClient->m_aClients[m_pClient->m_LocalIDs[1]].m_RenderInfo;
else else
pTeeInfo = &m_pClient->m_aClients[m_pClient->Client()->m_LocalIDs[0]].m_RenderInfo; pTeeInfo = &m_pClient->m_aClients[m_pClient->m_LocalIDs[0]].m_RenderInfo;
Graphics()->TextureSet(pTeeInfo->m_Texture); Graphics()->TextureSet(pTeeInfo->m_Texture);

View file

@ -245,6 +245,7 @@ class CMenus : public CComponent
void RenderNews(CUIRect MainView); void RenderNews(CUIRect MainView);
// found in menus_demo.cpp // found in menus_demo.cpp
static bool DemoFilterChat(const void *pData, int Size, void *pUser);
void RenderDemoPlayer(CUIRect MainView); void RenderDemoPlayer(CUIRect MainView);
void RenderDemoList(CUIRect MainView); void RenderDemoList(CUIRect MainView);

View file

@ -44,6 +44,24 @@ int CMenus::DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Chec
return UI()->DoButtonLogic(pID, "", Checked, pRect); return UI()->DoButtonLogic(pID, "", Checked, pRect);
} }
bool CMenus::DemoFilterChat(const void *pData, int Size, void *pUser)
{
bool DoFilterChat = *(bool *)pUser;
if(!DoFilterChat)
{
return false;
}
CUnpacker Unpacker;
Unpacker.Reset(pData, Size);
int Msg = Unpacker.GetInt();
int Sys = Msg&1;
Msg >>= 1;
return !Unpacker.Error() && !Sys && Msg == NETMSGTYPE_SV_CHAT;
}
void CMenus::RenderDemoPlayer(CUIRect MainView) void CMenus::RenderDemoPlayer(CUIRect MainView)
{ {
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
@ -116,7 +134,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
char aPath[512]; char aPath[512];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_aCurrentDemoFile); str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_aCurrentDemoFile);
Client()->DemoSlice(aPath, s_RemoveChat); Client()->DemoSlice(aPath, CMenus::DemoFilterChat, &s_RemoveChat);
} }
} }

View file

@ -110,16 +110,6 @@ const char *CGameClient::Version() { return GAME_VERSION; }
const char *CGameClient::NetVersion() { return GAME_NETVERSION; } const char *CGameClient::NetVersion() { return GAME_NETVERSION; }
const char *CGameClient::GetItemName(int Type) { return m_NetObjHandler.GetObjName(Type); } const char *CGameClient::GetItemName(int Type) { return m_NetObjHandler.GetObjName(Type); }
const CNetObj_PlayerInput &CGameClient::getPlayerInput(int dummy)
{
return m_pControls->m_InputData[dummy];
}
void CGameClient::ResetDummyInput()
{
m_pControls->ResetInput(!g_Config.m_ClDummy);
}
void CGameClient::OnConsoleInit() void CGameClient::OnConsoleInit()
{ {
m_pEngine = Kernel()->RequestInterface<IEngine>(); m_pEngine = Kernel()->RequestInterface<IEngine>();
@ -397,10 +387,61 @@ void CGameClient::OnUpdate()
} }
} }
void CGameClient::OnDummySwap()
int CGameClient::OnSnapInput(int *pData)
{ {
return m_pControls->SnapInput(pData); if (g_Config.m_ClDummyResetOnSwitch)
{
m_pControls->ResetInput(!g_Config.m_ClDummy);
}
m_DummyInput = m_pControls->m_InputData[!g_Config.m_ClDummy];
}
int CGameClient::OnSnapInput(int *pData, bool Dummy, bool Force)
{
m_LocalIDs[g_Config.m_ClDummy] = m_Snap.m_LocalClientID;
if (!Dummy)
{
return m_pControls->SnapInput(pData);
}
if(!g_Config.m_ClDummyHammer)
{
if(m_DummyFire != 0)
{
m_DummyInput.m_Fire = m_HammerInput.m_Fire;
m_DummyFire = 0;
}
if(!Force && (!m_DummyInput.m_Direction && !m_DummyInput.m_Jump && !m_DummyInput.m_Hook))
{
return 0;
}
mem_copy(pData, &m_DummyInput, sizeof(m_DummyInput));
return sizeof(m_DummyInput);
}
else
{
if((m_DummyFire / 12.5) - (int)(m_DummyFire / 12.5) > 0.01)
{
m_DummyFire++;
return 0;
}
m_DummyFire++;
m_HammerInput.m_Fire += 2;
m_HammerInput.m_WantedWeapon = 1;
vec2 Main = m_LocalCharacterPos;
vec2 Dummy = m_aClients[m_LocalIDs[!g_Config.m_ClDummy]].m_Predicted.m_Pos;
vec2 Dir = Main - Dummy;
m_HammerInput.m_TargetX = Dir.x;
m_HammerInput.m_TargetY = Dir.y;
mem_copy(pData, &m_HammerInput, sizeof(m_HammerInput));
return sizeof(m_HammerInput);
}
} }
void CGameClient::OnConnected() void CGameClient::OnConnected()
@ -576,13 +617,13 @@ void CGameClient::OnRender()
if(Client()->State() == IClient::STATE_ONLINE && !m_pMenus->IsActive()) { if(Client()->State() == IClient::STATE_ONLINE && !m_pMenus->IsActive()) {
if(m_CheckInfo[0] == 0) { if(m_CheckInfo[0] == 0) {
if( if(
str_comp(m_aClients[Client()->m_LocalIDs[0]].m_aName, g_Config.m_PlayerName) || str_comp(m_aClients[m_LocalIDs[0]].m_aName, g_Config.m_PlayerName) ||
str_comp(m_aClients[Client()->m_LocalIDs[0]].m_aClan, g_Config.m_PlayerClan) || str_comp(m_aClients[m_LocalIDs[0]].m_aClan, g_Config.m_PlayerClan) ||
m_aClients[Client()->m_LocalIDs[0]].m_Country != g_Config.m_PlayerCountry || m_aClients[m_LocalIDs[0]].m_Country != g_Config.m_PlayerCountry ||
str_comp(m_aClients[Client()->m_LocalIDs[0]].m_aSkinName, g_Config.m_ClPlayerSkin) || str_comp(m_aClients[m_LocalIDs[0]].m_aSkinName, g_Config.m_ClPlayerSkin) ||
m_aClients[Client()->m_LocalIDs[0]].m_UseCustomColor != g_Config.m_ClPlayerUseCustomColor || m_aClients[m_LocalIDs[0]].m_UseCustomColor != g_Config.m_ClPlayerUseCustomColor ||
m_aClients[Client()->m_LocalIDs[0]].m_ColorBody != g_Config.m_ClPlayerColorBody || m_aClients[m_LocalIDs[0]].m_ColorBody != g_Config.m_ClPlayerColorBody ||
m_aClients[Client()->m_LocalIDs[0]].m_ColorFeet != g_Config.m_ClPlayerColorFeet m_aClients[m_LocalIDs[0]].m_ColorFeet != g_Config.m_ClPlayerColorFeet
) )
SendInfo(false); SendInfo(false);
else else
@ -595,13 +636,13 @@ void CGameClient::OnRender()
if(Client()->DummyConnected()) { if(Client()->DummyConnected()) {
if(m_CheckInfo[1] == 0) { if(m_CheckInfo[1] == 0) {
if( if(
str_comp(m_aClients[Client()->m_LocalIDs[1]].m_aName, g_Config.m_ClDummyName) || str_comp(m_aClients[m_LocalIDs[1]].m_aName, g_Config.m_ClDummyName) ||
str_comp(m_aClients[Client()->m_LocalIDs[1]].m_aClan, g_Config.m_ClDummyClan) || str_comp(m_aClients[m_LocalIDs[1]].m_aClan, g_Config.m_ClDummyClan) ||
m_aClients[Client()->m_LocalIDs[1]].m_Country != g_Config.m_ClDummyCountry || m_aClients[m_LocalIDs[1]].m_Country != g_Config.m_ClDummyCountry ||
str_comp(m_aClients[Client()->m_LocalIDs[1]].m_aSkinName, g_Config.m_ClDummySkin) || str_comp(m_aClients[m_LocalIDs[1]].m_aSkinName, g_Config.m_ClDummySkin) ||
m_aClients[Client()->m_LocalIDs[1]].m_UseCustomColor != g_Config.m_ClDummyUseCustomColor || m_aClients[m_LocalIDs[1]].m_UseCustomColor != g_Config.m_ClDummyUseCustomColor ||
m_aClients[Client()->m_LocalIDs[1]].m_ColorBody != g_Config.m_ClDummyColorBody || m_aClients[m_LocalIDs[1]].m_ColorBody != g_Config.m_ClDummyColorBody ||
m_aClients[Client()->m_LocalIDs[1]].m_ColorFeet != g_Config.m_ClDummyColorFeet m_aClients[m_LocalIDs[1]].m_ColorFeet != g_Config.m_ClDummyColorFeet
) )
SendDummyInfo(false); SendDummyInfo(false);
else else
@ -713,14 +754,14 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
if(IsDummy) if(IsDummy)
{ {
if(MsgId == NETMSGTYPE_SV_CHAT if(MsgId == NETMSGTYPE_SV_CHAT
&& Client()->m_LocalIDs[0] >= 0 && m_LocalIDs[0] >= 0
&& Client()->m_LocalIDs[1] >= 0) && m_LocalIDs[1] >= 0)
{ {
CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg; CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg;
if((pMsg->m_Team == 1 if((pMsg->m_Team == 1
&& (m_aClients[Client()->m_LocalIDs[0]].m_Team != m_aClients[Client()->m_LocalIDs[1]].m_Team && (m_aClients[m_LocalIDs[0]].m_Team != m_aClients[m_LocalIDs[1]].m_Team
|| m_Teams.Team(Client()->m_LocalIDs[0]) != m_Teams.Team(Client()->m_LocalIDs[1]))) || m_Teams.Team(m_LocalIDs[0]) != m_Teams.Team(m_LocalIDs[1])))
|| pMsg->m_Team > 1) || pMsg->m_Team > 1)
{ {
m_pChat->OnMessage(MsgId, pRawMsg); m_pChat->OnMessage(MsgId, pRawMsg);

View file

@ -307,7 +307,8 @@ public:
virtual void OnNewSnapshot(); virtual void OnNewSnapshot();
virtual void OnPredict(); virtual void OnPredict();
virtual void OnActivateEditor(); virtual void OnActivateEditor();
virtual int OnSnapInput(int *pData); virtual void OnDummySwap();
virtual int OnSnapInput(int *pData, bool Dummy, bool Force);
virtual void OnShutdown(); virtual void OnShutdown();
virtual void OnEnterGame(); virtual void OnEnterGame();
virtual void OnRconLine(const char *pLine); virtual void OnRconLine(const char *pLine);
@ -315,14 +316,10 @@ public:
virtual void OnStartGame(); virtual void OnStartGame();
virtual void OnFlagGrab(int TeamID); virtual void OnFlagGrab(int TeamID);
virtual void ResetDummyInput();
virtual const char *GetItemName(int Type); virtual const char *GetItemName(int Type);
virtual const char *Version(); virtual const char *Version();
virtual const char *NetVersion(); virtual const char *NetVersion();
virtual const CNetObj_PlayerInput &getPlayerInput(int dummy);
// actions // actions
// TODO: move these // TODO: move these
void SendSwitchTeam(int Team); void SendSwitchTeam(int Team);
@ -358,6 +355,11 @@ public:
// DDRace // DDRace
int m_LocalIDs[2];
CNetObj_PlayerInput m_DummyInput;
CNetObj_PlayerInput m_HammerInput;
int m_DummyFire;
class CRaceDemo *m_pRaceDemo; class CRaceDemo *m_pRaceDemo;
class CGhost *m_pGhost; class CGhost *m_pGhost;
class CTeamsCore m_Teams; class CTeamsCore m_Teams;

View file

@ -67,13 +67,13 @@ void BuildPackets()
void ReadNews() void ReadNews()
{ {
IOHANDLE newsFile = io_open("news", IOFLAG_READ); IOHANDLE NewsFile = io_open("news", IOFLAG_READ);
if (!newsFile) if (!NewsFile)
return; return;
io_read(newsFile, m_aNews, NEWS_SIZE); io_read(NewsFile, m_aNews, NEWS_SIZE);
io_close(newsFile); io_close(NewsFile);
} }
void ReadServerList() void ReadServerList()