From 6c378b972b70b0556d3b434b26baa0b9ffe490f1 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sat, 18 Nov 2017 03:08:16 +0100 Subject: [PATCH 1/3] Add support for extra chunks in teehistorian This allows to add rarely-used chunks without increasing the file format version. --- CMakeLists.txt | 3 ++ datasrc/compile.py | 3 +- datasrc/network.py | 2 +- src/engine/shared/protocol_ex.cpp | 2 +- src/engine/shared/protocol_ex_msgs.h | 2 +- src/engine/shared/uuid_manager.cpp | 5 ++++ src/engine/shared/uuid_manager.h | 1 + src/game/server/gamecontext.cpp | 1 + src/game/server/teehistorian.cpp | 38 ++++++++++++++++++++++-- src/game/server/teehistorian.h | 4 +++ src/game/teehistorian_ex.cpp | 10 +++++++ src/game/teehistorian_ex.h | 15 ++++++++++ src/game/teehistorian_ex_chunks.h | 1 + src/test/teehistorian.cpp | 43 ++++++++++++++++++++++++---- 14 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 src/game/teehistorian_ex.cpp create mode 100644 src/game/teehistorian_ex.h create mode 100644 src/game/teehistorian_ex_chunks.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb3ef7a6..7ed813393 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -636,6 +636,9 @@ set_glob(GAME_SHARED GLOB src/game mapitems.h teamscore.cpp teamscore.h + teehistorian_ex.cpp + teehistorian_ex.h + teehistorian_ex_chunks.h tuning.h variables.h version.h diff --git a/datasrc/compile.py b/datasrc/compile.py index a84899c5d..b9ec780e0 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -107,7 +107,7 @@ if gen_network_header: non_extended = [o for o in network.Objects if o.ex is None] extended = [o for o in network.Objects if o.ex is not None] for l in create_enum_table(["NETOBJTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETOBJTYPES"): print(l) - for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_GAME_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"): print(l) + for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_TEEHISTORIAN_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"): print(l) print("") non_extended = [o for o in network.Messages if o.ex is None] @@ -343,6 +343,7 @@ if gen_network_source: lines += ['void RegisterGameUuids(CUuidManager *pManager)'] lines += ['{'] + lines += ['\tRegisterTeehistorianUuids(pManager);'] for item in network.Objects + network.Messages: if item.ex is not None: diff --git a/datasrc/network.py b/datasrc/network.py index 31823a50b..22b75defa 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -12,7 +12,7 @@ Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA"] RawHeader = ''' #include -#include +#include enum { diff --git a/src/engine/shared/protocol_ex.cpp b/src/engine/shared/protocol_ex.cpp index bc2104e79..8004183be 100644 --- a/src/engine/shared/protocol_ex.cpp +++ b/src/engine/shared/protocol_ex.cpp @@ -6,7 +6,7 @@ #include -void RegisterUuids(class CUuidManager *pManager) +void RegisterUuids(CUuidManager *pManager) { #define UUID(id, name) pManager->RegisterName(id, name); #include "protocol_ex_msgs.h" diff --git a/src/engine/shared/protocol_ex_msgs.h b/src/engine/shared/protocol_ex_msgs.h index eb660da61..cac1c1198 100644 --- a/src/engine/shared/protocol_ex_msgs.h +++ b/src/engine/shared/protocol_ex_msgs.h @@ -21,4 +21,4 @@ UUID(NETMSG_WHATIS, "what-is@ddnet.tw") UUID(NETMSG_ITIS, "it-is@ddnet.tw") UUID(NETMSG_IDONTKNOW, "i-dont-know@ddnet.tw") -UUID(NETMSG_RCONTYPE, "rcon-type@ddnet.tw") +UUID(NETMSG_RCONTYPE, "rcon-type@ddnet.tw") diff --git a/src/engine/shared/uuid_manager.cpp b/src/engine/shared/uuid_manager.cpp index 45c1222c0..f4f609e84 100644 --- a/src/engine/shared/uuid_manager.cpp +++ b/src/engine/shared/uuid_manager.cpp @@ -110,6 +110,11 @@ int CUuidManager::LookupUuid(CUuid Uuid) const return UUID_UNKNOWN; } +int CUuidManager::NumUuids() const +{ + return m_aNames.size(); +} + int CUuidManager::UnpackUuid(CUnpacker *pUnpacker) const { CUuid Temp; diff --git a/src/engine/shared/uuid_manager.h b/src/engine/shared/uuid_manager.h index c3b4ced7c..18cd73135 100644 --- a/src/engine/shared/uuid_manager.h +++ b/src/engine/shared/uuid_manager.h @@ -42,6 +42,7 @@ public: CUuid GetUuid(int ID) const; const char *GetName(int ID) const; int LookupUuid(CUuid Uuid) const; + int NumUuids() const; int UnpackUuid(CUnpacker *pUnpacker) const; int UnpackUuid(CUnpacker *pUnpacker, CUuid *pOut) const; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index d0af0f102..19cc964f1 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2585,6 +2585,7 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) GameInfo.m_pConfig = &g_Config; GameInfo.m_pTuning = Tuning(); + GameInfo.m_pUuids = &g_UuidManager; char aMapName[128]; Server()->GetMapInfo(aMapName, sizeof(aMapName), &GameInfo.m_MapSize, &GameInfo.m_MapCrc); diff --git a/src/game/server/teehistorian.cpp b/src/game/server/teehistorian.cpp index c5be827c6..0b317e900 100644 --- a/src/game/server/teehistorian.cpp +++ b/src/game/server/teehistorian.cpp @@ -6,7 +6,11 @@ static const char TEEHISTORIAN_NAME[] = "teehistorian@ddnet.tw"; static const CUuid TEEHISTORIAN_UUID = CalculateUuid(TEEHISTORIAN_NAME); -static const char TEEHISTORIAN_VERSION[] = "1"; +static const char TEEHISTORIAN_VERSION[] = "2"; + +#define UUID(id, name) static const CUuid UUID_ ## id = CalculateUuid(name); +#include +#undef UUID enum { @@ -21,6 +25,7 @@ enum TEEHISTORIAN_JOIN, TEEHISTORIAN_DROP, TEEHISTORIAN_CONSOLE_COMMAND, + TEEHISTORIAN_EX, }; static char EscapeJsonChar(char c) @@ -196,11 +201,35 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo) #include #undef MACRO_TUNING_PARAM - str_format(aJson, sizeof(aJson), "}}"); + str_format(aJson, sizeof(aJson), "},\"uuids\":["); + Write(aJson, str_length(aJson)); + + for(int i = 0; i < pGameInfo->m_pUuids->NumUuids(); i++) + { + str_format(aJson, sizeof(aJson), "%s\"%s\"", + i == 0 ? "" : ",", + E(aBuffer1, pGameInfo->m_pUuids->GetName(OFFSET_UUID + i))); + Write(aJson, str_length(aJson)); + } + + str_format(aJson, sizeof(aJson), "]}"); Write(aJson, str_length(aJson)); Write("", 1); // Null termination. } +void CTeeHistorian::WriteExtra(CUuid Uuid, const void *pData, int DataSize) +{ + EnsureTickWritten(); + + CPacker Ex; + Ex.Reset(); + Ex.AddInt(-TEEHISTORIAN_EX); + Ex.AddRaw(&Uuid, sizeof(Uuid)); + Ex.AddInt(DataSize); + Write(Ex.Data(), Ex.Size()); + Write(pData, DataSize); +} + void CTeeHistorian::BeginTick(int Tick) { @@ -484,6 +513,11 @@ void CTeeHistorian::RecordConsoleCommand(int ClientID, int FlagMask, const char Write(Buffer.Data(), Buffer.Size()); } +void CTeeHistorian::RecordTestExtra() +{ + WriteExtra(UUID_TEEHISTORIAN_TEST, "", 0); +} + void CTeeHistorian::EndInputs() { dbg_assert(m_State == STATE_INPUTS, "invalid teehistorian state"); diff --git a/src/game/server/teehistorian.h b/src/game/server/teehistorian.h index 06954bb0d..9ef6596f3 100644 --- a/src/game/server/teehistorian.h +++ b/src/game/server/teehistorian.h @@ -7,6 +7,7 @@ struct CConfiguration; class CTuningParams; +class CUuidManager; class CTeeHistorian { @@ -29,6 +30,7 @@ public: CConfiguration *m_pConfig; CTuningParams *m_pTuning; + CUuidManager *m_pUuids; }; CTeeHistorian(); @@ -51,6 +53,7 @@ public: void RecordPlayerJoin(int ClientID); void RecordPlayerDrop(int ClientID, const char *pReason); void RecordConsoleCommand(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult); + void RecordTestExtra(); void EndInputs(); void EndTick(); @@ -59,6 +62,7 @@ public: private: void WriteHeader(const CGameInfo *pGameInfo); + void WriteExtra(CUuid Uuid, const void *pData, int DataSize); void EnsureTickWrittenPlayerData(int ClientID); void EnsureTickWritten(); void WriteTick(); diff --git a/src/game/teehistorian_ex.cpp b/src/game/teehistorian_ex.cpp new file mode 100644 index 000000000..3c771f7d6 --- /dev/null +++ b/src/game/teehistorian_ex.cpp @@ -0,0 +1,10 @@ +#include "teehistorian_ex.h" + +#include + +void RegisterTeehistorianUuids(CUuidManager *pManager) +{ + #define UUID(id, name) pManager->RegisterName(id, name); + #include "teehistorian_ex_chunks.h" + #undef UUID +} diff --git a/src/game/teehistorian_ex.h b/src/game/teehistorian_ex.h new file mode 100644 index 000000000..77aa67b3f --- /dev/null +++ b/src/game/teehistorian_ex.h @@ -0,0 +1,15 @@ +#ifndef GAME_TEEHISTORIAN_EX_H +#define GAME_TEEHISTORIAN_EX_H +#include + +enum +{ + __TEEHISTORIAN_UUID_HELPER=OFFSET_GAME_UUID-1, + #define UUID(id, name) id, + #include "teehistorian_ex_chunks.h" + #undef UUID + OFFSET_TEEHISTORIAN_UUID +}; + +void RegisterTeehistorianUuids(class CUuidManager *pManager); +#endif // GAME_TEEHISTORIAN_EX_H diff --git a/src/game/teehistorian_ex_chunks.h b/src/game/teehistorian_ex_chunks.h new file mode 100644 index 000000000..2aa23e781 --- /dev/null +++ b/src/game/teehistorian_ex_chunks.h @@ -0,0 +1 @@ +UUID(TEEHISTORIAN_TEST, "teehistorian-test@ddnet.tw") diff --git a/src/test/teehistorian.cpp b/src/test/teehistorian.cpp index d11dabe23..67a9bbbff 100644 --- a/src/test/teehistorian.cpp +++ b/src/test/teehistorian.cpp @@ -5,12 +5,15 @@ #include #include +void RegisterGameUuids(CUuidManager *pManager); + class TeeHistorian : public ::testing::Test { protected: CTeeHistorian m_TH; CConfiguration m_Config; CTuningParams m_Tuning; + CUuidManager m_UuidManager; CTeeHistorian::CGameInfo m_GameInfo; CPacker m_Buffer; @@ -35,6 +38,9 @@ protected: #undef MACRO_CONFIG_STR #undef MACRO_CONFIG_INT + RegisterUuids(&m_UuidManager); + RegisterGameUuids(&m_UuidManager); + mem_zero(&m_GameInfo, sizeof(m_GameInfo)); m_GameInfo.m_GameUuid = CalculateUuid("test@ddnet.tw"); @@ -51,6 +57,7 @@ protected: m_GameInfo.m_pConfig = &m_Config; m_GameInfo.m_pTuning = &m_Tuning; + m_GameInfo.m_pUuids = &m_UuidManager; Reset(&m_GameInfo); } @@ -71,8 +78,9 @@ protected: void Expect(const unsigned char *pOutput, int OutputSize) { static CUuid TEEHISTORIAN_UUID = CalculateUuid("teehistorian@ddnet.tw"); - static const char PREFIX1[] = "{\"comment\":\"teehistorian@ddnet.tw\",\"version\":\"1\",\"game_uuid\":\"a1eb7182-796e-3b3e-941d-38ca71b2a4a8\",\"server_version\":\"DDNet test\",\"start_time\":\""; - static const char PREFIX2[] = "\",\"server_name\":\"server name\",\"server_port\":\"8303\",\"game_type\":\"game type\",\"map_name\":\"Kobra 3 Solo\",\"map_size\":\"903514\",\"map_crc\":\"eceaf25c\",\"config\":{},\"tuning\":{}}"; + static const char PREFIX1[] = "{\"comment\":\"teehistorian@ddnet.tw\",\"version\":\"2\",\"game_uuid\":\"a1eb7182-796e-3b3e-941d-38ca71b2a4a8\",\"server_version\":\"DDNet test\",\"start_time\":\""; + static const char PREFIX2[] = "\",\"server_name\":\"server name\",\"server_port\":\"8303\",\"game_type\":\"game type\",\"map_name\":\"Kobra 3 Solo\",\"map_size\":\"903514\",\"map_crc\":\"eceaf25c\",\"config\":{},\"tuning\":{},\"uuids\":["; + static const char PREFIX3[] = "]}"; char aTimeBuf[64]; str_timestamp_ex(m_GameInfo.m_StartTime, aTimeBuf, sizeof(aTimeBuf), "%Y-%m-%d %H:%M:%S %z"); @@ -83,6 +91,15 @@ protected: Buffer.AddRaw(PREFIX1, str_length(PREFIX1)); Buffer.AddRaw(aTimeBuf, str_length(aTimeBuf)); Buffer.AddRaw(PREFIX2, str_length(PREFIX2)); + for(int i = 0; i < m_UuidManager.NumUuids(); i++) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s\"%s\"", + i == 0 ? "" : ",", + m_UuidManager.GetName(OFFSET_UUID + i)); + Buffer.AddRaw(aBuf, str_length(aBuf)); + } + Buffer.AddRaw(PREFIX3, str_length(PREFIX3)); Buffer.AddRaw("", 1); Buffer.AddRaw(pOutput, OutputSize); @@ -93,13 +110,12 @@ protected: void ExpectFull(const unsigned char *pOutput, int OutputSize) { - ASSERT_FALSE(m_Buffer.Error()); - const ::testing::TestInfo *pTestInfo = ::testing::UnitTest::GetInstance()->current_test_info(); const char *pTestName = pTestInfo->name(); - if(m_Buffer.Size() != OutputSize + if(m_Buffer.Error() + || m_Buffer.Size() != OutputSize || mem_comp(m_Buffer.Data(), pOutput, OutputSize) != 0) { char aFilename[64]; @@ -118,6 +134,7 @@ protected: io_close(File); } + ASSERT_FALSE(m_Buffer.Error()); ASSERT_EQ(m_Buffer.Size(), OutputSize); ASSERT_TRUE(mem_comp(m_Buffer.Data(), pOutput, OutputSize) == 0); } @@ -273,3 +290,19 @@ TEST_F(TeeHistorian, TickExplicitPlayerMessage) Finish(); Expect(EXPECTED, sizeof(EXPECTED)); } + +TEST_F(TeeHistorian, ExtraMessage) +{ + const unsigned char EXPECTED[] = { + 0x41, 0x00, // TICK_SKIP dt=0 + // EX uuid=6bb8ba88-0f0b-382e-8dae-dbf4052b8b7d data="" + 0x4a, + 0x6b, 0xb8, 0xba, 0x88, 0x0f, 0x0b, 0x38, 0x2e, + 0x8d, 0xae, 0xdb, 0xf4, 0x05, 0x2b, 0x8b, 0x7d, + 0x00, + 0x40, // FINISH + }; + Tick(1); Inputs(); m_TH.RecordTestExtra(); + Finish(); + Expect(EXPECTED, sizeof(EXPECTED)); +} From 22080c840f787034d7f0097f324c70dcb0af9e3d Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 11 Jan 2018 16:01:13 +0100 Subject: [PATCH 2/3] Move teehistorian UUIDs into engine --- CMakeLists.txt | 6 +++--- datasrc/compile.py | 3 +-- datasrc/network.py | 2 +- src/engine/shared/global_uuid_manager.cpp | 2 ++ src/engine/shared/protocol_ex.h | 2 +- src/{game => engine/shared}/teehistorian_ex.cpp | 0 src/{game => engine/shared}/teehistorian_ex.h | 6 +++--- src/{game => engine/shared}/teehistorian_ex_chunks.h | 0 src/game/server/teehistorian.cpp | 2 +- src/test/teehistorian.cpp | 1 + 10 files changed, 13 insertions(+), 11 deletions(-) rename src/{game => engine/shared}/teehistorian_ex.cpp (100%) rename src/{game => engine/shared}/teehistorian_ex.h (68%) rename src/{game => engine/shared}/teehistorian_ex_chunks.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ed813393..ac92eed94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -614,6 +614,9 @@ set_glob(ENGINE_SHARED GLOB src/engine/shared snapshot.cpp snapshot.h storage.cpp + teehistorian_ex.cpp + teehistorian_ex.h + teehistorian_ex_chunks.h uuid_manager.cpp uuid_manager.h websockets.cpp @@ -636,9 +639,6 @@ set_glob(GAME_SHARED GLOB src/game mapitems.h teamscore.cpp teamscore.h - teehistorian_ex.cpp - teehistorian_ex.h - teehistorian_ex_chunks.h tuning.h variables.h version.h diff --git a/datasrc/compile.py b/datasrc/compile.py index b9ec780e0..a84899c5d 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -107,7 +107,7 @@ if gen_network_header: non_extended = [o for o in network.Objects if o.ex is None] extended = [o for o in network.Objects if o.ex is not None] for l in create_enum_table(["NETOBJTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETOBJTYPES"): print(l) - for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_TEEHISTORIAN_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"): print(l) + for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_GAME_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"): print(l) print("") non_extended = [o for o in network.Messages if o.ex is None] @@ -343,7 +343,6 @@ if gen_network_source: lines += ['void RegisterGameUuids(CUuidManager *pManager)'] lines += ['{'] - lines += ['\tRegisterTeehistorianUuids(pManager);'] for item in network.Objects + network.Messages: if item.ex is not None: diff --git a/datasrc/network.py b/datasrc/network.py index 22b75defa..0bb46bc7b 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -12,7 +12,7 @@ Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA"] RawHeader = ''' #include -#include +#include enum { diff --git a/src/engine/shared/global_uuid_manager.cpp b/src/engine/shared/global_uuid_manager.cpp index 40b56e03c..e7223b9da 100644 --- a/src/engine/shared/global_uuid_manager.cpp +++ b/src/engine/shared/global_uuid_manager.cpp @@ -1,4 +1,5 @@ #include "protocol_ex.h" +#include "teehistorian_ex.h" #include "uuid_manager.h" #include @@ -7,6 +8,7 @@ static CUuidManager CreateGlobalUuidManager() { CUuidManager Manager; RegisterUuids(&Manager); + RegisterTeehistorianUuids(&Manager); RegisterGameUuids(&Manager); return Manager; } diff --git a/src/engine/shared/protocol_ex.h b/src/engine/shared/protocol_ex.h index 42129b716..279300be9 100644 --- a/src/engine/shared/protocol_ex.h +++ b/src/engine/shared/protocol_ex.h @@ -14,7 +14,7 @@ enum #define UUID(id, name) id, #include "protocol_ex_msgs.h" #undef UUID - OFFSET_GAME_UUID, + OFFSET_TEEHISTORIAN_UUID, UNPACKMESSAGE_ERROR=0, UNPACKMESSAGE_OK, diff --git a/src/game/teehistorian_ex.cpp b/src/engine/shared/teehistorian_ex.cpp similarity index 100% rename from src/game/teehistorian_ex.cpp rename to src/engine/shared/teehistorian_ex.cpp diff --git a/src/game/teehistorian_ex.h b/src/engine/shared/teehistorian_ex.h similarity index 68% rename from src/game/teehistorian_ex.h rename to src/engine/shared/teehistorian_ex.h index 77aa67b3f..2dcc63eae 100644 --- a/src/game/teehistorian_ex.h +++ b/src/engine/shared/teehistorian_ex.h @@ -1,14 +1,14 @@ #ifndef GAME_TEEHISTORIAN_EX_H #define GAME_TEEHISTORIAN_EX_H -#include +#include "protocol_ex.h" enum { - __TEEHISTORIAN_UUID_HELPER=OFFSET_GAME_UUID-1, + __TEEHISTORIAN_UUID_HELPER=OFFSET_TEEHISTORIAN_UUID-1, #define UUID(id, name) id, #include "teehistorian_ex_chunks.h" #undef UUID - OFFSET_TEEHISTORIAN_UUID + OFFSET_GAME_UUID }; void RegisterTeehistorianUuids(class CUuidManager *pManager); diff --git a/src/game/teehistorian_ex_chunks.h b/src/engine/shared/teehistorian_ex_chunks.h similarity index 100% rename from src/game/teehistorian_ex_chunks.h rename to src/engine/shared/teehistorian_ex_chunks.h diff --git a/src/game/server/teehistorian.cpp b/src/game/server/teehistorian.cpp index 0b317e900..828cb045f 100644 --- a/src/game/server/teehistorian.cpp +++ b/src/game/server/teehistorian.cpp @@ -9,7 +9,7 @@ static const CUuid TEEHISTORIAN_UUID = CalculateUuid(TEEHISTORIAN_NAME); static const char TEEHISTORIAN_VERSION[] = "2"; #define UUID(id, name) static const CUuid UUID_ ## id = CalculateUuid(name); -#include +#include #undef UUID enum diff --git a/src/test/teehistorian.cpp b/src/test/teehistorian.cpp index 67a9bbbff..2cf7e2fdc 100644 --- a/src/test/teehistorian.cpp +++ b/src/test/teehistorian.cpp @@ -39,6 +39,7 @@ protected: #undef MACRO_CONFIG_INT RegisterUuids(&m_UuidManager); + RegisterTeehistorianUuids(&m_UuidManager); RegisterGameUuids(&m_UuidManager); mem_zero(&m_GameInfo, sizeof(m_GameInfo)); From 9d9bfee53fcc1487b8acc3675261122ebfb44eda Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 11 Jan 2018 15:55:32 +0100 Subject: [PATCH 3/3] Move to ISO 8601-compliant timestamps https://en.wikipedia.org/w/index.php?title=ISO_8601&oldid=819129098 --- src/game/server/teehistorian.cpp | 2 +- src/test/teehistorian.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/server/teehistorian.cpp b/src/game/server/teehistorian.cpp index 828cb045f..77d1d9f5f 100644 --- a/src/game/server/teehistorian.cpp +++ b/src/game/server/teehistorian.cpp @@ -124,7 +124,7 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo) char aStartTime[128]; FormatUuid(pGameInfo->m_GameUuid, aGameUuid, sizeof(aGameUuid)); - str_timestamp_ex(pGameInfo->m_StartTime, aStartTime, sizeof(aStartTime), "%Y-%m-%d %H:%M:%S %z"); + str_timestamp_ex(pGameInfo->m_StartTime, aStartTime, sizeof(aStartTime), "%Y-%m-%dT%H:%M:%S%z"); char aCommentBuffer[128]; char aServerVersionBuffer[128]; diff --git a/src/test/teehistorian.cpp b/src/test/teehistorian.cpp index 2cf7e2fdc..58a48d391 100644 --- a/src/test/teehistorian.cpp +++ b/src/test/teehistorian.cpp @@ -84,7 +84,7 @@ protected: static const char PREFIX3[] = "]}"; char aTimeBuf[64]; - str_timestamp_ex(m_GameInfo.m_StartTime, aTimeBuf, sizeof(aTimeBuf), "%Y-%m-%d %H:%M:%S %z"); + str_timestamp_ex(m_GameInfo.m_StartTime, aTimeBuf, sizeof(aTimeBuf), "%Y-%m-%dT%H:%M:%S%z"); CPacker Buffer; Buffer.Reset();