diff options
| author | oy <Tom_Adams@web.de> | 2011-03-13 10:41:10 +0100 |
|---|---|---|
| committer | oy <Tom_Adams@web.de> | 2011-03-13 10:41:10 +0100 |
| commit | be8f669333b01e32465c515728fccabaa627bd37 (patch) | |
| tree | 7d15faa5df6a9f7149d25c3b2e0fcb93c16dca8d /src | |
| parent | a04eb45354cfbdc32f92438400c11071ecf1bb6c (diff) | |
| download | zcatch-be8f669333b01e32465c515728fccabaa627bd37.tar.gz zcatch-be8f669333b01e32465c515728fccabaa627bd37.zip | |
added extended demo infos in the demo browser
Diffstat (limited to 'src')
| -rw-r--r-- | src/engine/client/client.cpp | 10 | ||||
| -rw-r--r-- | src/engine/demo.h | 15 | ||||
| -rw-r--r-- | src/engine/shared/demo.cpp | 128 | ||||
| -rw-r--r-- | src/engine/shared/demo.h | 16 | ||||
| -rw-r--r-- | src/game/client/components/menus.h | 4 | ||||
| -rw-r--r-- | src/game/client/components/menus_demo.cpp | 77 | ||||
| -rw-r--r-- | src/game/client/components/scoreboard.cpp | 2 |
7 files changed, 166 insertions, 86 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 125991c1..5ed0b37b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2120,11 +2120,11 @@ const char *CClient::DemoPlayer_Play(const char *pFilename, int StorageType) return "error loading demo"; // load map - Crc = (m_DemoPlayer.Info()->m_Header.m_aCrc[0]<<24)| - (m_DemoPlayer.Info()->m_Header.m_aCrc[1]<<16)| - (m_DemoPlayer.Info()->m_Header.m_aCrc[2]<<8)| - (m_DemoPlayer.Info()->m_Header.m_aCrc[3]); - pError = LoadMapSearch(m_DemoPlayer.Info()->m_Header.m_aMap, Crc); + Crc = (m_DemoPlayer.Info()->m_Header.m_aMapCrc[0]<<24)| + (m_DemoPlayer.Info()->m_Header.m_aMapCrc[1]<<16)| + (m_DemoPlayer.Info()->m_Header.m_aMapCrc[2]<<8)| + (m_DemoPlayer.Info()->m_Header.m_aMapCrc[3]); + pError = LoadMapSearch(m_DemoPlayer.Info()->m_Header.m_aMapName, Crc); if(pError) { DisconnectWithReason(pError); diff --git a/src/engine/demo.h b/src/engine/demo.h index a6841a9e..1ba888a9 100644 --- a/src/engine/demo.h +++ b/src/engine/demo.h @@ -5,6 +5,19 @@ #include "kernel.h" +struct CDemoHeader +{ + unsigned char m_aMarker[7]; + unsigned char m_Version; + char m_aNetversion[64]; + char m_aMapName[64]; + char m_aMapSize[4]; + unsigned char m_aMapCrc[4]; + char m_aType[8]; + char m_aLength[4]; + char m_aTimestamp[20]; +}; + class IDemoPlayer : public IInterface { MACRO_INTERFACE("demoplayer", 0) @@ -34,7 +47,7 @@ public: virtual void Unpause() = 0; virtual const CInfo *BaseInfo() const = 0; virtual char *GetDemoName() = 0; - virtual bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, char *pMap, int BufferSize) const = 0; + virtual bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const = 0; virtual int GetDemoType() const = 0; }; diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 586e7318..87d0951c 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -2,7 +2,6 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include <base/system.h> #include <engine/console.h> -#include <engine/shared/protocol.h> #include <engine/storage.h> #include "demo.h" #include "memheap.h" @@ -11,12 +10,8 @@ #include "network.h" static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0}; -static const unsigned char gs_ActVersion = 2; -static const unsigned char gs_VersionWithMap = 2; - -//Versions : -//1 : 0.5.0 -//2 : 0.5.3/0.6.0, includes the map +static const unsigned char gs_ActVersion = 3; +static const int gs_LengthOffset = 152; CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta) @@ -72,25 +67,21 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con mem_copy(Header.m_aMarker, gs_aHeaderMarker, sizeof(Header.m_aMarker)); Header.m_Version = gs_ActVersion; str_copy(Header.m_aNetversion, pNetVersion, sizeof(Header.m_aNetversion)); - str_copy(Header.m_aMap, pMap, sizeof(Header.m_aMap)); + str_copy(Header.m_aMapName, pMap, sizeof(Header.m_aMapName)); + int MapSize = io_length(MapFile); + Header.m_aMapSize[0] = (MapSize>>24)&0xff; + Header.m_aMapSize[1] = (MapSize>>16)&0xff; + Header.m_aMapSize[2] = (MapSize>>8)&0xff; + Header.m_aMapSize[3] = (MapSize)&0xff; + Header.m_aMapCrc[0] = (Crc>>24)&0xff; + Header.m_aMapCrc[1] = (Crc>>16)&0xff; + Header.m_aMapCrc[2] = (Crc>>8)&0xff; + Header.m_aMapCrc[3] = (Crc)&0xff; str_copy(Header.m_aType, pType, sizeof(Header.m_aType)); - Header.m_aCrc[0] = (Crc>>24)&0xff; - Header.m_aCrc[1] = (Crc>>16)&0xff; - Header.m_aCrc[2] = (Crc>>8)&0xff; - Header.m_aCrc[3] = (Crc)&0xff; + // Header.m_Length - add this on stop + str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp)); io_write(m_File, &Header, sizeof(Header)); - - // write map - // write map size - int MapSize = io_length(MapFile); - unsigned char aBufMapSize[4]; - aBufMapSize[0] = (MapSize>>24)&0xff; - aBufMapSize[1] = (MapSize>>16)&0xff; - aBufMapSize[2] = (MapSize>>8)&0xff; - aBufMapSize[3] = (MapSize)&0xff; - io_write(m_File, &aBufMapSize, sizeof(aBufMapSize)); - // write map data while(1) { @@ -253,6 +244,16 @@ int CDemoRecorder::Stop() { if(!m_File) return -1; + + // add the demo length to the header + io_seek(m_File, gs_LengthOffset, IOSEEK_START); + int DemoLength = Length()/SERVER_TICK_SPEED; + char aLength[4]; + aLength[0] = (DemoLength>>24)&0xff; + aLength[1] = (DemoLength>>16)&0xff; + aLength[2] = (DemoLength>>8)&0xff; + aLength[3] = (DemoLength)&0xff; + io_write(m_File, aLength, sizeof(aLength)); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Stopped recording"); io_close(m_File); @@ -542,7 +543,6 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const mem_zero(&m_Info, sizeof(m_Info)); m_Info.m_Info.m_FirstTick = -1; m_Info.m_Info.m_LastTick = -1; - //m_Info.start_tick = -1; m_Info.m_NextTick = -1; m_Info.m_Info.m_CurrentTick = -1; m_Info.m_PreviousTick = -1; @@ -561,6 +561,16 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_File = 0; return -1; } + + if(m_Info.m_Header.m_Version < gs_ActVersion) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "demo version %d is not supported", m_Info.m_Header.m_Version); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_player", aBuf); + io_close(m_File); + m_File = 0; + return -1; + } // get demo type if(!str_comp(m_Info.m_Header.m_aType, "client")) @@ -569,40 +579,34 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_DemoType = DEMOTYPE_SERVER; else DEMOTYPE_INVALID; - // get map - if(m_Info.m_Header.m_Version >= gs_VersionWithMap) - { - // get map size - unsigned char aBufMapSize[4]; - io_read(m_File, &aBufMapSize, sizeof(aBufMapSize)); - int MapSize = (aBufMapSize[0]<<24) | (aBufMapSize[1]<<16) | (aBufMapSize[2]<<8) | (aBufMapSize[3]); - - // check if we already have the map - // TODO: improve map checking (maps folder, check crc) - int Crc = (m_Info.m_Header.m_aCrc[0]<<24) | (m_Info.m_Header.m_aCrc[1]<<16) | (m_Info.m_Header.m_aCrc[2]<<8) | (m_Info.m_Header.m_aCrc[3]); - char aMapFilename[128]; - str_format(aMapFilename, sizeof(aMapFilename), "downloadedmaps/%s_%08x.map", m_Info.m_Header.m_aMap, Crc); - IOHANDLE MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_READ, IStorage::TYPE_ALL); + // read map + int MapSize = (m_Info.m_Header.m_aMapSize[0]<<24) | (m_Info.m_Header.m_aMapSize[1]<<16) | (m_Info.m_Header.m_aMapSize[2]<<8) | (m_Info.m_Header.m_aMapSize[3]); + + // check if we already have the map + // TODO: improve map checking (maps folder, check crc) + int Crc = (m_Info.m_Header.m_aMapCrc[0]<<24) | (m_Info.m_Header.m_aMapCrc[1]<<16) | (m_Info.m_Header.m_aMapCrc[2]<<8) | (m_Info.m_Header.m_aMapCrc[3]); + char aMapFilename[128]; + str_format(aMapFilename, sizeof(aMapFilename), "downloadedmaps/%s_%08x.map", m_Info.m_Header.m_aMapName, Crc); + IOHANDLE MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_READ, IStorage::TYPE_ALL); - if(MapFile) - { - io_skip(m_File, MapSize); - io_close(MapFile); - } - else if(MapSize > 0) - { - // get map data - unsigned char *pMapData = (unsigned char *)mem_alloc(MapSize, 1); - io_read(m_File, pMapData, MapSize); + if(MapFile) + { + io_skip(m_File, MapSize); + io_close(MapFile); + } + else if(MapSize > 0) + { + // get map data + unsigned char *pMapData = (unsigned char *)mem_alloc(MapSize, 1); + io_read(m_File, pMapData, MapSize); - // save map - MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); - io_write(MapFile, pMapData, MapSize); - io_close(MapFile); + // save map + MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); + io_write(MapFile, pMapData, MapSize); + io_close(MapFile); - // free data - mem_free(pMapData); - } + // free data + mem_free(pMapData); } @@ -758,22 +762,24 @@ char *CDemoPlayer::GetDemoName() return pDemoShortName; } -bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, char *pMap, int BufferSize) const +bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const { + if(!pDemoHeader) + return false; + + mem_zero(pDemoHeader, sizeof(CDemoHeader)); + IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType); if(!File) return false; - CDemoHeader Header; - io_read(File, &Header, sizeof(Header)); - if(mem_comp(Header.m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) != 0) + io_read(File, pDemoHeader, sizeof(CDemoHeader)); + if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_ActVersion) { io_close(File); return false; } - str_copy(pMap, Header.m_aMap, BufferSize); - io_close(File); return true; } diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h index ad7566c7..ad8e82b5 100644 --- a/src/engine/shared/demo.h +++ b/src/engine/shared/demo.h @@ -4,17 +4,9 @@ #define ENGINE_SHARED_DEMO_H #include <engine/demo.h> -#include "snapshot.h" +#include <engine/shared/protocol.h> -struct CDemoHeader -{ - unsigned char m_aMarker[7]; - unsigned char m_Version; - char m_aNetversion[64]; - char m_aMap[64]; - unsigned char m_aCrc[4]; - char m_aType[8]; -}; +#include "snapshot.h" class CDemoRecorder : public IDemoRecorder { @@ -39,7 +31,7 @@ public: bool IsRecording() const { return m_File != 0; } - int Length() const { return m_LastTickMarker - m_FirstTick; } + int Length() const { return (m_LastTickMarker - m_FirstTick)/SERVER_TICK_SPEED; } }; class CDemoPlayer : public IDemoPlayer @@ -119,7 +111,7 @@ public: int SetPos(float Precent); const CInfo *BaseInfo() const { return &m_Info.m_Info; } char *GetDemoName(); - bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, char *pMap, int BufferSize) const; + bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const; int GetDemoType() const; int Update(); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 1a2e5cf5..0ad63669 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -6,6 +6,8 @@ #include <base/vmath.h> #include <base/tl/sorted_array.h> +#include <engine/demo.h> + #include <game/client/component.h> #include <game/client/ui.h> @@ -177,7 +179,7 @@ class CMenus : public CComponent bool m_InfosLoaded; bool m_Valid; - char m_aMap[64]; + CDemoHeader m_Info; bool operator<(const CDemoItem &Other) { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index d489b8db..011b1e5e 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -441,7 +441,6 @@ int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, if(IsDir) { str_format(Item.m_aName, sizeof(Item.m_aName), "%s/", pName); - Item.m_aMap[0] = 0; Item.m_Valid = false; } else @@ -495,13 +494,13 @@ void CMenus::RenderDemoList(CUIRect MainView) { char aBuffer[512]; str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename); - Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, Item->m_aMap, sizeof(Item->m_aMap)); + Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, &Item->m_Info); Item->m_InfosLoaded = true; } if(!Item->m_Valid) str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel)); else - str_format(aFooterLabel, sizeof(aFooterLabel), "%s: %s", Localize("Map"), Item->m_aMap); + str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); } } @@ -509,7 +508,7 @@ void CMenus::RenderDemoList(CUIRect MainView) RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); MainView.Margin(10.0f, &MainView); - CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon; + CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon, ListBox; MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar); ButtonBar.HSplitTop(5.0f, 0, &ButtonBar); ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect); @@ -518,10 +517,78 @@ void CMenus::RenderDemoList(CUIRect MainView) ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar); ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(120.0f, &RenameRect, &ButtonBar); + MainView.HSplitBottom(140.0f, &ListBox, &MainView); + + // render demo info + MainView.VMargin(5.0f, &MainView); + MainView.HSplitBottom(5.0f, &MainView, 0); + RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); + if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) + { + CUIRect Left, Right, Labels; + MainView.Margin(20.0f, &MainView); + MainView.VSplitMid(&Labels, &MainView); + + // left side + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Created:"), 14.0f, -1); + UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Type:"), 14.0f, -1); + UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Length:"), 14.0f, -1); + int Length = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]); + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); + UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Version:"), 14.0f, -1); + str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version); + UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); + + // right side + Labels = MainView; + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Map:"), 14.0f, -1); + UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(20.0f, 0, &Left); + Left.VSplitLeft(100.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Size:"), 14.0f, -1); + Length = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]); + str_format(aBuf, sizeof(aBuf), Localize("%d Bytes"), Length); + UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(20.0f, 0, &Left); + Left.VSplitLeft(100.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Crc:"), 14.0f, -1); + unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); + str_format(aBuf, sizeof(aBuf), "%08x", Crc); + UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); + Labels.HSplitTop(5.0f, 0, &Labels); + Labels.HSplitTop(20.0f, &Left, &Labels); + Left.VSplitLeft(120.0f, &Left, &Right); + UI()->DoLabelScaled(&Left, Localize("Netversion:"), 14.0f, -1); + UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, -1); + } static int s_DemoListId = 0; static float s_ScrollValue = 0; - UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); + UiDoListboxStart(&s_DemoListId, &ListBox, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { CListboxItem Item = UiDoListboxNextItem((void*)(&r.front())); diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 95b620c4..c208cddc 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -270,7 +270,7 @@ void CScoreboard::RenderRecordingNotification(float x) //draw the text char aBuf[64]; - int Seconds = m_pClient->DemoRecorder()->Length()/SERVER_TICK_SPEED; + int Seconds = m_pClient->DemoRecorder()->Length(); str_format(aBuf, sizeof(aBuf), Localize("REC %3d:%02d"), Seconds/60, Seconds%60); TextRender()->Text(0, x+50.0f, 10.0f, 20.0f, aBuf, -1); } |