From a3246ed09970324b61123cae2d4a62ca419eea21 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Tue, 14 Jul 2015 22:08:29 +0200 Subject: [PATCH 01/12] Save the config into the map when the server loads the map --- src/engine/server.h | 1 + src/engine/server/server.cpp | 1 + src/engine/shared/console.cpp | 2 +- src/game/mapitems.h | 5 ++ src/game/server/gamecontext.cpp | 118 ++++++++++++++++++++++++++++++++ src/game/server/gamecontext.h | 4 ++ 6 files changed, 130 insertions(+), 1 deletion(-) diff --git a/src/engine/server.h b/src/engine/server.h index de854523b..e2909065c 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -174,6 +174,7 @@ protected: public: virtual void OnInit() = 0; virtual void OnConsoleInit() = 0; + virtual void OnMapChange(char *pNewMapName, int MapNameSize) = 0; virtual void OnShutdown() = 0; virtual void OnTick() = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index f50e24e1b..c3b9f15fa 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1477,6 +1477,7 @@ int CServer::LoadMap(const char *pMapName) //DATAFILE *df; char aBuf[512]; str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName); + GameServer()->OnMapChange(aBuf, sizeof(aBuf)); /*df = datafile_load(buf); if(!df) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index ecc396f2b..9afc02f18 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -458,7 +458,7 @@ void CConsole::ExecuteFile(const char *pFilename, int ClientID) // exec the file IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL); - char aBuf[8192]; + char aBuf[128]; if(File) { char *pLine; diff --git a/src/game/mapitems.h b/src/game/mapitems.h index 3051a1faf..44c6fcbf4 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -221,6 +221,11 @@ struct CMapItemInfo int m_License; } ; +struct CMapItemInfoSettings : CMapItemInfo +{ + int m_Settings; +} ; + struct CMapItemImage { int m_Version; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index b87b636a9..9f1bbfe75 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include "gamecontext.h" #include #include @@ -56,6 +59,7 @@ void CGameContext::Construct(int Resetting) m_NumMutes = 0; } m_ChatResponseTargetID = -1; + m_aDeleteTempfile[0] = 0; } CGameContext::CGameContext(int Resetting) @@ -2285,6 +2289,8 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_World.SetGameServer(this); m_Events.SetGameServer(this); + DeleteTempfile(); + //if(!data) // only load once //data = load_data_from_memory(internal_data); @@ -2514,8 +2520,120 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) #endif } +void CGameContext::DeleteTempfile() +{ + if(m_aDeleteTempfile[0] != 0) + { + IStorage *pStorage = Kernel()->RequestInterface(); + pStorage->RemoveFile(m_aDeleteTempfile, IStorage::TYPE_SAVE); + m_aDeleteTempfile[0] = 0; + } +} + +void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize) +{ + IStorage *pStorage = Kernel()->RequestInterface(); + + char aConfig[128]; + char aTemp[128]; + str_format(aConfig, sizeof(aConfig), "maps/%s.cfg", g_Config.m_SvMap); + str_format(aTemp, sizeof(aTemp), "%s.temp.%d", pNewMapName, pid(), pNewMapName); + + IOHANDLE File = pStorage->OpenFile(aConfig, IOFLAG_READ, IStorage::TYPE_ALL); + if(!File) + { + // No map-specific config, just return. + return; + } + CLineReader LineReader; + LineReader.Init(File); + + array aLines; + char *pLine; + int TotalLength = 0; + while((pLine = LineReader.Get())) + { + int Length = str_length(pLine) + 1; + char *pCopy = (char *)mem_alloc(Length, 1); + mem_copy(pCopy, pLine, Length); + aLines.add(pCopy); + TotalLength += Length; + } + + char *pSettings = (char *)mem_alloc(TotalLength, 1); + int Offset = 0; + for(int i = 0; i < aLines.size(); i++) + { + int Length = str_length(aLines[i]) + 1; + mem_copy(pSettings + Offset, aLines[i], Length); + mem_free(aLines[i]); + } + + CDataFileReader Reader; + Reader.Open(pStorage, pNewMapName, IStorage::TYPE_ALL); + + CDataFileWriter Writer; + Writer.Open(pStorage, aTemp); + + int SettingsIndex = Reader.NumData(); + for(int i = 0; i < Reader.NumItems(); i++) + { + int TypeID; + int ItemID; + int *pData = (int *)Reader.GetItem(i, &TypeID, &ItemID); + // GetItemSize returns item size including header, remove that. + int Size = Reader.GetItemSize(i) - sizeof(int) * 2; + CMapItemInfoSettings MapInfo; + if(TypeID == MAPITEMTYPE_INFO && ItemID == 0) + { + CMapItemInfoSettings *pInfo = (CMapItemInfoSettings *)pData; + if(Size >= (int)sizeof(CMapItemInfoSettings)) + { + SettingsIndex = pInfo->m_Settings; + char *pMapSettings = (char *)Reader.GetData(SettingsIndex); + int DataSize = Reader.GetUncompressedDataSize(SettingsIndex); + if(DataSize == TotalLength && mem_comp(pSettings, pMapSettings, Size) == 0) + { + // Configs coincide, no need to update map. + return; + } + Reader.UnloadData(pInfo->m_Settings); + } + else + { + *(CMapItemInfo *)&MapInfo = *(CMapItemInfo *)pInfo; + MapInfo.m_Settings = SettingsIndex; + pData = (int *)&MapInfo; + Size = sizeof(MapInfo); + } + } + Writer.AddItem(TypeID, ItemID, Size, pData); + } + + for(int i = 0; i < Reader.NumData() || i == SettingsIndex; i++) + { + if(i == SettingsIndex) + { + Writer.AddData(TotalLength, pSettings); + continue; + } + unsigned char *pData = (unsigned char *)Reader.GetData(i); + int Size = Reader.GetUncompressedDataSize(i); + Writer.AddData(Size, pData); + Reader.UnloadData(i); + } + + dbg_msg("mapchange", "imported settings"); + Reader.Close(); + Writer.Finish(); + + str_copy(pNewMapName, aTemp, MapNameSize); + str_copy(m_aDeleteTempfile, aTemp, sizeof(m_aDeleteTempfile)); +} + void CGameContext::OnShutdown() { + DeleteTempfile(); Layers()->Dest(); Collision()->Dest(); delete m_pController; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index afc113d39..7d7e4c146 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -137,6 +137,9 @@ public: char m_ZoneEnterMsg[NUM_TUNINGZONES][256]; // 0 is used for switching from or to area without tunings char m_ZoneLeaveMsg[NUM_TUNINGZONES][256]; + char m_aDeleteTempfile[128]; + void DeleteTempfile(); + enum { VOTE_ENFORCE_UNKNOWN=0, @@ -191,6 +194,7 @@ public: // engine events virtual void OnInit(); virtual void OnConsoleInit(); + virtual void OnMapChange(char *pNewMapName, int MapNameSize); virtual void OnShutdown(); virtual void OnTick(); From 7bd0f276d4fec925131bf226c5c85cbca5f2eedd Mon Sep 17 00:00:00 2001 From: SushiTee Date: Wed, 13 Jul 2011 22:38:32 +0200 Subject: [PATCH 02/12] saving server settings within the map and loading them on init --- src/engine/map.h | 1 + src/engine/shared/map.cpp | 1 + src/game/editor/editor.cpp | 140 ++++++++++++++++++++++++++++++-- src/game/editor/editor.h | 15 ++++ src/game/editor/io.cpp | 51 +++++++++++- src/game/server/gamecontext.cpp | 33 ++++++++ src/game/server/gamecontext.h | 2 + 7 files changed, 232 insertions(+), 11 deletions(-) diff --git a/src/engine/map.h b/src/engine/map.h index e9bac7906..a831cd202 100644 --- a/src/engine/map.h +++ b/src/engine/map.h @@ -14,6 +14,7 @@ public: virtual void *GetDataSwapped(int Index) = 0; virtual void UnloadData(int Index) = 0; virtual void *GetItem(int Index, int *Type, int *pID) = 0; + virtual int GetItemSize(int Index) = 0; virtual void GetType(int Type, int *pStart, int *pNum) = 0; virtual void *FindItem(int Type, int ID) = 0; virtual int NumItems() = 0; diff --git a/src/engine/shared/map.cpp b/src/engine/shared/map.cpp index 7bda44643..923dc8308 100644 --- a/src/engine/shared/map.cpp +++ b/src/engine/shared/map.cpp @@ -16,6 +16,7 @@ public: virtual void *GetDataSwapped(int Index) { return m_DataFile.GetDataSwapped(Index); } virtual void UnloadData(int Index) { m_DataFile.UnloadData(Index); } virtual void *GetItem(int Index, int *pType, int *pID) { return m_DataFile.GetItem(Index, pType, pID); } + virtual int GetItemSize(int Index) { return m_DataFile.GetItemSize(Index); } virtual void GetType(int Type, int *pStart, int *pNum) { m_DataFile.GetType(Type, pStart, pNum); } virtual void *FindItem(int Type, int ID) { return m_DataFile.FindItem(Type, ID); } virtual int NumItems() { return m_DataFile.NumItems(); } diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index a03126ac5..e3a718065 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4096,7 +4096,20 @@ void CEditor::RenderStatusbar(CUIRect View) if(MouseButton == 2) m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+3)%4; else if(MouseButton == 1) - m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+1)%4; + + if(MouseButton) + { + m_ShowServerSettingsEditor = false; + } + + View.VSplitRight(100.0f, &View, &Button); + Button.VSplitRight(10.0f, &Button, 0); + static int s_SettingsButton = 0; + if(DoButton_Editor(&s_SettingsButton, "Server settings", m_ShowServerSettingsEditor, &Button, 0, "Toggles the server settings editor.")) + { + m_ShowEnvelopeEditor = 0; + m_ShowServerSettingsEditor ^= 1; + } if (g_Config.m_ClEditorUndo) { @@ -4707,6 +4720,110 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) } } +void CEditor::RenderServerSettingsEditor(CUIRect View) +{ + static int s_CommandSelectedIndex = -1; + + CUIRect ToolBar; + View.HSplitTop(20.0f, &ToolBar, &View); + ToolBar.Margin(2.0f, &ToolBar); + + // do the toolbar + { + CUIRect Button; + + // command line + ToolBar.VSplitLeft(5.0f, 0, &Button); + UI()->DoLabel(&Button, "Command:", 12.0f, -1); + + Button.VSplitLeft(70.0f, 0, &Button); + Button.VSplitLeft(180.0f, &Button, 0); + DoEditBox(&m_CommandBox, &Button, m_aSettingsCommand, sizeof(m_aSettingsCommand), 12.0f, &m_CommandBox); + + // buttons + ToolBar.VSplitRight(50.0f, &ToolBar, &Button); + static int s_AddButton = 0; + if(DoButton_Editor(&s_AddButton, "Add", 0, &Button, 0, "Add a command to command list.")) + { + if(m_aSettingsCommand[0] != 0 && str_find(m_aSettingsCommand, " ")) + { + bool Found = false; + for(int i = 0; i < m_Map.m_lSettings.size(); i++) + if(!str_comp(m_Map.m_lSettings[i].m_aCommand, m_aSettingsCommand)) + { + Found = true; + break; + } + + if(!Found) + { + CEditorMap::CSetting Setting; + str_copy(Setting.m_aCommand, m_aSettingsCommand, sizeof(Setting.m_aCommand)); + m_Map.m_lSettings.add(Setting); + } + } + } + + if(m_Map.m_lSettings.size()) + { + ToolBar.VSplitRight(50.0f, &ToolBar, &Button); + Button.VSplitRight(5.0f, &Button, 0); + static int s_AddButton = 0; + if(DoButton_Editor(&s_AddButton, "Del", 0, &Button, 0, "Delete a command from the command list.")) + if(s_CommandSelectedIndex > -1 && s_CommandSelectedIndex < m_Map.m_lSettings.size()) + m_Map.m_lSettings.remove_index(s_CommandSelectedIndex); + } + } + + View.HSplitTop(2.0f, 0, &View); + RenderBackground(View, ms_CheckerTexture, 32.0f, 0.1f); + + CUIRect ListBox; + View.Margin(1.0f, &ListBox); + + float ListHeight = 17.0f * m_Map.m_lSettings.size(); + static int s_ScrollBar = 0; + static float s_ScrollValue = 0; + + float ScrollDifference = ListHeight - ListBox.h; + + if(ListHeight > ListBox.h) // Do we even need a scrollbar? + { + CUIRect Scroll; + ListBox.VSplitRight(15.0f, &ListBox, &Scroll); + ListBox.VSplitRight(3.0f, &ListBox, 0); // extra spacing + Scroll.HMargin(5.0f, &Scroll); + s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue); + } + + float ListStartAt = ScrollDifference * s_ScrollValue; + if(ListStartAt < 0.0f) + ListStartAt = 0.0f; + + float ListStopAt = ListHeight - ScrollDifference * (1 - s_ScrollValue); + float ListCur = 0; + + UI()->ClipEnable(&ListBox); + for(int i = 0; i < m_Map.m_lSettings.size(); i++) + { + if(ListCur > ListStopAt) + break; + + if(ListCur >= ListStartAt) + { + CUIRect Button; + ListBox.HSplitTop(15.0f, &Button, &ListBox); + ListBox.HSplitTop(2.0f, 0, &ListBox); + Button.VSplitLeft(5.0f, 0, &Button); + + if(DoButton_MenuItem(&m_Map.m_lSettings[i], m_Map.m_lSettings[i].m_aCommand, s_CommandSelectedIndex == i, &Button, 0, 0)) + s_CommandSelectedIndex = i; + } + ListCur += 17.0f; + } + UI()->ClipDisable(); +} + int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) { static int s_NewMapButton = 0; @@ -4874,8 +4991,8 @@ void CEditor::Render() // render checker RenderBackground(View, ms_CheckerTexture, 32.0f, 1.0f); - CUIRect MenuBar, CModeBar, ToolBar, StatusBar, EnvelopeEditor, UndoList, ToolBox; - m_ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE && m_EditBoxActive == 0; + CUIRect MenuBar, CModeBar, ToolBar, StatusBar, ExtraEditor, UndoList, ToolBox; + m_ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE && m_EditBoxActive == 0 && UI()->LastActiveItem() != &m_CommandBox; if(m_GuiActive) { @@ -4892,12 +5009,15 @@ void CEditor::Render() size *= 2.0f; else if(m_ShowEnvelopeEditor == 3) size *= 3.0f; - View.HSplitBottom(size, &View, &EnvelopeEditor); + View.HSplitBottom(size, &View, &ExtraEditor); } if (m_ShowUndo && !m_ShowPicker) { View.HSplitBottom(250.0f, &View, &UndoList); } + + if(m_ShowServerSettingsEditor && !m_ShowPicker) + View.HSplitBottom(250.0f, &View, &ExtraEditor); } // a little hack for now @@ -4963,10 +5083,10 @@ void CEditor::Render() if(m_GuiActive) { - if(m_ShowEnvelopeEditor) + if(m_ShowEnvelopeEditor || m_ShowServerSettingsEditor) { - RenderBackground(EnvelopeEditor, ms_BackgroundTexture, 128.0f, Brightness); - EnvelopeEditor.Margin(2.0f, &EnvelopeEditor); + RenderBackground(ExtraEditor, ms_BackgroundTexture, 128.0f, Brightness); + ExtraEditor.Margin(2.0f, &ExtraEditor); } if(m_ShowUndo) { @@ -4991,9 +5111,11 @@ void CEditor::Render() RenderModebar(CModeBar); if(m_ShowEnvelopeEditor && !m_ShowPicker) - RenderEnvelopeEditor(EnvelopeEditor); + RenderEnvelopeEditor(ExtraEditor); if(m_ShowUndo) RenderUndoList(UndoList); + if(m_ShowServerSettingsEditor) + RenderServerSettingsEditor(ExtraEditor); } if(m_Dialog == DIALOG_FILE) @@ -5215,6 +5337,8 @@ void CEditorMap::Clean() m_MapInfo.Reset(); + m_lSettings.clear(); + m_pGameLayer = 0x0; m_pGameGroup = 0x0; diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 6c0843763..f0162d210 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -376,6 +376,12 @@ public: }; CMapInfo m_MapInfo; + struct CSetting + { + char m_aCommand[64]; + }; + array m_lSettings; + class CLayerGame *m_pGameLayer; CLayerGroup *m_pGameGroup; @@ -678,11 +684,15 @@ public: m_ShowEnvelopeEditor = 0; m_ShowUndo = 0; m_UndoScrollValue = 0.0f; + m_ShowServerSettingsEditor = false; m_ShowEnvelopePreview = 0; m_SelectedQuadEnvelope = -1; m_SelectedEnvelopePoint = -1; + m_CommandBox = 0.0f; + m_aSettingsCommand[0] = 0; + ms_CheckerTexture = 0; ms_BackgroundTexture = 0; ms_CursorTexture = 0; @@ -842,6 +852,7 @@ public: int m_ShowEnvelopeEditor; int m_ShowEnvelopePreview; //Values: 0-Off|1-Selected Envelope|2-All + bool m_ShowServerSettingsEditor; bool m_ShowPicker; int m_SelectedLayer; @@ -871,6 +882,9 @@ public: static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); + float m_CommandBox; + char m_aSettingsCommand[64]; + void DoMapBorder(); int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); @@ -959,6 +973,7 @@ public: void RenderStatusbar(CUIRect View); void RenderEnvelopeEditor(CUIRect View); void RenderUndoList(CUIRect View); + void RenderServerSettingsEditor(CUIRect View); void RenderMenubar(CUIRect Menubar); void RenderFileDialog(); diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index 93fad4b7f..d75041d3e 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -238,7 +238,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) // save map info { - CMapItemInfo Item; + CMapItemInfoSettings Item; Item.m_Version = 1; if(m_MapInfo.m_aAuthor[0]) @@ -258,6 +258,26 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) else Item.m_License = -1; + Item.m_Settings = -1; + if(m_lSettings.size()) + { + int Size = 0; + for(int i = 0; i < m_lSettings.size(); i++) + { + Size += str_length(m_lSettings[i].m_aCommand) + 1; + } + + char *pSettings = (char *)mem_alloc(Size, 1); + char *pNext = pSettings; + for(int i = 0; i < m_lSettings.size(); i++) + { + int Length = str_length(m_lSettings[i].m_aCommand) + 1; + mem_copy(pNext, m_lSettings[i].m_aCommand, Length); + } + Item.m_Settings = df.AddData(Size, pSettings); + mem_free(pSettings); + } + df.AddItem(MAPITEMTYPE_INFO, 0, sizeof(Item), &Item); } @@ -589,9 +609,16 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag // load map info { - CMapItemInfo *pItem = (CMapItemInfo *)DataFile.FindItem(MAPITEMTYPE_INFO, 0); - if(pItem && pItem->m_Version == 1) + int Start, Num; + DataFile.GetType(MAPITEMTYPE_INFO, &Start, &Num); + for(int i = Start; i < Start + Num; i++) { + int ItemSize = DataFile.GetItemSize(Start) - 8; + int ItemID; + CMapItemInfoSettings *pItem = (CMapItemInfoSettings *)DataFile.GetItem(i, 0, &ItemID); + if(!pItem || ItemID != 0) + continue; + if(pItem->m_Author > -1) str_copy(m_MapInfo.m_aAuthor, (char *)DataFile.GetData(pItem->m_Author), sizeof(m_MapInfo.m_aAuthor)); if(pItem->m_MapVersion > -1) @@ -600,6 +627,24 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag str_copy(m_MapInfo.m_aCredits, (char *)DataFile.GetData(pItem->m_Credits), sizeof(m_MapInfo.m_aCredits)); if(pItem->m_License > -1) str_copy(m_MapInfo.m_aLicense, (char *)DataFile.GetData(pItem->m_License), sizeof(m_MapInfo.m_aLicense)); + + if(pItem->m_Version != 1 || ItemSize < (int)sizeof(CMapItemInfoSettings)) + break; + + if(!(pItem->m_Settings > -1)) + break; + + int Size = DataFile.GetUncompressedDataSize(pItem->m_Settings); + char *pSettings = (char *)DataFile.GetData(pItem->m_Settings); + char *pNext = pSettings; + while(pNext < pSettings + Size) + { + int StrSize = str_length(pNext) + 1; + CSetting Setting; + str_copy(Setting.m_aCommand, pNext, sizeof(Setting.m_aCommand)); + m_lSettings.add(Setting); + pNext += StrSize; + } } } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 9f1bbfe75..4acbea0ac 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2300,6 +2300,8 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_Layers.Init(Kernel()); m_Collision.Init(&m_Layers); + LoadMapSettings(); + // reset everything here //world = new GAMEWORLD; //players = new CPlayer[MAX_CLIENTS]; @@ -2641,6 +2643,37 @@ void CGameContext::OnShutdown() Clear(); } +void CGameContext::LoadMapSettings() +{ + IMap *pMap = Kernel()->RequestInterface(); + int Start, Num; + pMap->GetType(MAPITEMTYPE_INFO, &Start, &Num); + for(int i = Start; i < Start + Num; i++) + { + int ItemID; + CMapItemInfoSettings *pItem = (CMapItemInfoSettings *)pMap->GetItem(i, 0, &ItemID); + int ItemSize = pMap->GetItemSize(i) - 8; + if(!pItem || ItemID != 0) + continue; + + if(ItemSize < (int)sizeof(CMapItemInfoSettings)) + break; + if(!(pItem->m_Settings > -1)) + break; + + int Size = pMap->GetUncompressedDataSize(pItem->m_Settings); + char *pSettings = (char *)pMap->GetData(pItem->m_Settings); + char *pNext = pSettings; + while(pNext < pSettings + Size) + { + int StrSize = str_length(pNext) + 1; + Console()->ExecuteLine(pNext); + pNext += StrSize; + } + pMap->UnloadData(pItem->m_Settings); + } +} + void CGameContext::OnSnap(int ClientID) { // add tuning to demo diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 7d7e4c146..a306fafdd 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -191,6 +191,8 @@ public: // //void SwapTeams(); + void LoadMapSettings(); + // engine events virtual void OnInit(); virtual void OnConsoleInit(); From c025dc2235c44bae4570872563d73c4d02a85e98 Mon Sep 17 00:00:00 2001 From: SushiTee Date: Wed, 13 Jul 2011 22:38:32 +0200 Subject: [PATCH 03/12] saving server settings within the map and loading them on init --- src/game/editor/editor.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index e3a718065..366a493e2 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4743,7 +4743,8 @@ void CEditor::RenderServerSettingsEditor(CUIRect View) // buttons ToolBar.VSplitRight(50.0f, &ToolBar, &Button); static int s_AddButton = 0; - if(DoButton_Editor(&s_AddButton, "Add", 0, &Button, 0, "Add a command to command list.")) + if(DoButton_Editor(&s_AddButton, "Add", 0, &Button, 0, "Add a command to command list.") + || ((Input()->KeyDown(KEY_RETURN) || Input()->KeyDown(KEY_KP_ENTER)) && UI()->LastActiveItem() == &m_CommandBox)) { if(m_aSettingsCommand[0] != 0 && str_find(m_aSettingsCommand, " ")) { @@ -4769,7 +4770,8 @@ void CEditor::RenderServerSettingsEditor(CUIRect View) ToolBar.VSplitRight(50.0f, &ToolBar, &Button); Button.VSplitRight(5.0f, &Button, 0); static int s_AddButton = 0; - if(DoButton_Editor(&s_AddButton, "Del", 0, &Button, 0, "Delete a command from the command list.")) + if(DoButton_Editor(&s_AddButton, "Del", 0, &Button, 0, "Delete a command from the command list.") + || Input()->KeyDown(KEY_DELETE)) if(s_CommandSelectedIndex > -1 && s_CommandSelectedIndex < m_Map.m_lSettings.size()) m_Map.m_lSettings.remove_index(s_CommandSelectedIndex); } @@ -4794,6 +4796,20 @@ void CEditor::RenderServerSettingsEditor(CUIRect View) ListBox.VSplitRight(3.0f, &ListBox, 0); // extra spacing Scroll.HMargin(5.0f, &Scroll); s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue); + + if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&ListBox)) + { + int ScrollNum = (int)((ListHeight-ListBox.h)/17.0f)+1; + if(ScrollNum > 0) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + s_ScrollValue = clamp(s_ScrollValue - 1.0f/ScrollNum, 0.0f, 1.0f); + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f); + } + else + ScrollNum = 0; + } } float ListStartAt = ScrollDifference * s_ScrollValue; From 6a17d2700d58a56ca4648cb847c928e08498b25b Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 15 Jul 2015 11:38:42 +0200 Subject: [PATCH 04/12] Fix saving the config into the map --- src/game/server/gamecontext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 4acbea0ac..03722d255 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2568,6 +2568,7 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize) { int Length = str_length(aLines[i]) + 1; mem_copy(pSettings + Offset, aLines[i], Length); + Offset += Length; mem_free(aLines[i]); } From bf1f7d6ccdacf4708727c0081c7a1658ae79c511 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 15 Jul 2015 14:02:21 +0200 Subject: [PATCH 05/12] (Safely) execute settings embedded in maps --- src/engine/console.h | 5 ++ src/engine/shared/config.h | 3 +- src/engine/shared/config_variables.h | 28 +++++----- src/engine/shared/console.cpp | 82 ++++++++++++++++++++++++++-- src/engine/shared/console.h | 2 +- src/game/server/gamecontext.cpp | 34 ++++++------ src/game/variables.h | 8 +-- 7 files changed, 121 insertions(+), 41 deletions(-) diff --git a/src/engine/console.h b/src/engine/console.h index 3ba5cdb08..3d6794c07 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -26,6 +26,9 @@ public: TEMPCMD_PARAMS_LENGTH=16, MAX_PRINT_CB=4, + + CLIENT_ID_GAME=-2, + CLIENT_ID_NO_GAME=-3, }; // TODO: rework this interface to reduce the amount of virtual calls @@ -94,6 +97,8 @@ public: virtual void SetAccessLevel(int AccessLevel) = 0; + virtual void ResetServerGameSettings() = 0; + // DDRace bool m_Cheated; diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 8c9512aa9..d1fcc1a31 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -30,7 +30,8 @@ enum // DDRace CMDFLAG_TEST=64, - CFGFLAG_CHAT = 128 + CFGFLAG_CHAT=128, + CFGFLAG_GAME=256, }; #endif diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 498f8b65c..b94c87887 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -166,16 +166,16 @@ MACRO_CONFIG_INT(DbgResizable, dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables MACRO_CONFIG_STR(SvWelcome, sv_welcome, 64, "", CFGFLAG_SERVER, "Message that will be displayed to players who join the server") MACRO_CONFIG_INT(SvReservedSlots, sv_reserved_slots, 0, 0, 16, CFGFLAG_SERVER, "The number of slots that are reserved for special players") MACRO_CONFIG_STR(SvReservedSlotsPass, sv_reserved_slots_pass, 32, "", CFGFLAG_SERVER, "The password that is required to use a reserved slot") -MACRO_CONFIG_INT(SvHit, sv_hit, 1, 0, 1, CFGFLAG_SERVER, "Whether players can hammer/grenade/laser eachother or not") -MACRO_CONFIG_INT(SvEndlessDrag, sv_endless_drag, 0, 0, 1, CFGFLAG_SERVER, "Turns endless hooking on/off") +MACRO_CONFIG_INT(SvHit, sv_hit, 1, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether players can hammer/grenade/laser eachother or not") +MACRO_CONFIG_INT(SvEndlessDrag, sv_endless_drag, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Turns endless hooking on/off") MACRO_CONFIG_INT(SvTestingCommands, sv_test_cmds, 0, 0, 1, CFGFLAG_SERVER, "Turns testing commands aka cheats on/off") -MACRO_CONFIG_INT(SvFreezeDelay, sv_freeze_delay, 3, 1, 30, CFGFLAG_SERVER, "How many seconds the players will remain frozen (applies to all except delayed freeze in switch layer & deepfreeze)") +MACRO_CONFIG_INT(SvFreezeDelay, sv_freeze_delay, 3, 1, 30, CFGFLAG_SERVER|CFGFLAG_GAME, "How many seconds the players will remain frozen (applies to all except delayed freeze in switch layer & deepfreeze)") MACRO_CONFIG_INT(ClDDRaceBinds, cl_race_binds, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Enable Default DDRace builds when pressing the reset binds button") MACRO_CONFIG_INT(ClDDRaceBindsSet, cl_race_binds_set, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Whether the DDRace binds set or not (this is automated you don't need to use this)") MACRO_CONFIG_INT(SvEndlessSuperHook, sv_endless_super_hook, 0, 0, 1, CFGFLAG_SERVER, "Endless hook for super players on/off") MACRO_CONFIG_INT(SvHideScore, sv_hide_score, 0, 0, 1, CFGFLAG_SERVER, "Whether players scores will be announced or not") -MACRO_CONFIG_INT(SvSaveWorseScores, sv_save_worse_scores, 1, 0, 1, CFGFLAG_SERVER, "Whether to save worse scores when you already have a better one") -MACRO_CONFIG_INT(SvPauseable, sv_pauseable, 1, 0, 1, CFGFLAG_SERVER, "Whether players can pause their char or not") +MACRO_CONFIG_INT(SvSaveWorseScores, sv_save_worse_scores, 1, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether to save worse scores when you already have a better one") +MACRO_CONFIG_INT(SvPauseable, sv_pauseable, 1, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether players can pause their char or not") MACRO_CONFIG_INT(SvPauseMessages, sv_pause_messages, 0, 0, 1, CFGFLAG_SERVER, "Whether to show messages when a player pauses and resumes") MACRO_CONFIG_INT(SvPauseTime, sv_pause_time, 0, 0, 1, CFGFLAG_SERVER, "Whether '/pause' and 'sv_max_dc_restore' pauses the time of player or not") MACRO_CONFIG_INT(SvPauseFrequency, sv_pause_frequency, 1, 0, 9999, CFGFLAG_SERVER, "The minimum allowed delay between pauses") @@ -233,16 +233,16 @@ MACRO_CONFIG_STR(SvRulesLine8, sv_rules_line8, 40, "", CFGFLAG_SERVER, "Rules li MACRO_CONFIG_STR(SvRulesLine9, sv_rules_line9, 40, "", CFGFLAG_SERVER, "Rules line 9") MACRO_CONFIG_STR(SvRulesLine10, sv_rules_line10, 40, "", CFGFLAG_SERVER, "Rules line 10") -MACRO_CONFIG_INT(SvTeam, sv_team, 1, 0, 3, CFGFLAG_SERVER, "Teams configuration (0 = off, 1 = on but optional, 2 = must play only with teams, 3 = forced random team only for you)") -MACRO_CONFIG_INT(SvTeamMaxSize, sv_max_team_size, MAX_CLIENTS, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum team size (from 2 to 16)") -MACRO_CONFIG_INT(SvTeamLock, sv_team_lock, 1, 0, 1, CFGFLAG_SERVER, "Enable team lock") -MACRO_CONFIG_INT(SvMapVote, sv_map_vote, 1, 0, 1, CFGFLAG_SERVER, "Whether to allow /map") +MACRO_CONFIG_INT(SvTeam, sv_team, 1, 0, 3, CFGFLAG_SERVER|CFGFLAG_GAME, "Teams configuration (0 = off, 1 = on but optional, 2 = must play only with teams, 3 = forced random team only for you)") +MACRO_CONFIG_INT(SvTeamMaxSize, sv_max_team_size, MAX_CLIENTS, 1, MAX_CLIENTS, CFGFLAG_SERVER|CFGFLAG_GAME, "Maximum team size (from 2 to 16)") +MACRO_CONFIG_INT(SvTeamLock, sv_team_lock, 1, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Enable team lock") +MACRO_CONFIG_INT(SvMapVote, sv_map_vote, 1, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether to allow /map") MACRO_CONFIG_STR(SvAnnouncementFileName, sv_announcement_filename, 24, "announcement.txt", CFGFLAG_SERVER, "file which will have the announcement, each one at a line") MACRO_CONFIG_INT(SvAnnouncementInterval, sv_announcement_interval, 300, 1, 9999, CFGFLAG_SERVER, "time(minutes) in which the announcement will be displayed from the announcement file") MACRO_CONFIG_INT(SvAnnouncementRandom, sv_announcement_random, 1, 0, 1, CFGFLAG_SERVER, "Whether announcements are sequential or random") -MACRO_CONFIG_INT(SvOldLaser, sv_old_laser, 0, 0, 1, CFGFLAG_SERVER, "Whether lasers can hit you if you shot them and that they pull you towards the bounce origin (0 for DDRace Beta) or lasers can't hit you if you shot them, and they pull others towards the shooter") +MACRO_CONFIG_INT(SvOldLaser, sv_old_laser, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether lasers can hit you if you shot them and that they pull you towards the bounce origin (0 for DDRace Beta) or lasers can't hit you if you shot them, and they pull others towards the shooter") MACRO_CONFIG_INT(SvSlashMe, sv_slash_me, 0, 0, 1, CFGFLAG_SERVER, "Whether /me is active on the server or not") MACRO_CONFIG_INT(SvRejoinTeam0, sv_rejoin_team_0, 1, 0, 1, CFGFLAG_SERVER, "Make a team automatically rejoin team 0 after finish (only if not locked)") @@ -287,7 +287,7 @@ MACRO_CONFIG_INT(ClRaceShowGhost, cl_race_show_ghost, 1, 0, 1, CFGFLAG_CLIENT|CF MACRO_CONFIG_INT(ClRaceSaveGhost, cl_race_save_ghost, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Save ghost") MACRO_CONFIG_INT(ClDDRaceScoreBoard, cl_ddrace_scoreboard, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable DDRace Scoreboard ") MACRO_CONFIG_INT(ClShowDecisecs, cl_show_decisecs, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show deciseconds in game time") -MACRO_CONFIG_INT(SvResetPickups, sv_reset_pickups, 0, 0, 1, CFGFLAG_SERVER, "Whether the weapons are reset on passing the start tile or not") +MACRO_CONFIG_INT(SvResetPickups, sv_reset_pickups, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Whether the weapons are reset on passing the start tile or not") MACRO_CONFIG_INT(ClShowOthers, cl_show_others, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show players in other teams") MACRO_CONFIG_INT(ClShowOthersAlpha, cl_show_others_alpha, 40, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show players in other teams (alpha value, 0 invisible, 100 fully visible)") MACRO_CONFIG_INT(ClOverlayEntities, cl_overlay_entities, 0, 0, 100, CFGFLAG_CLIENT, "Overlay game tiles with a percentage of opacity") @@ -304,8 +304,8 @@ MACRO_CONFIG_INT(SvShowOthersDefault, sv_show_others_default, 0, 0, 1, CFGFLAG_S MACRO_CONFIG_INT(SvShowAllDefault, sv_show_all_default, 0, 0, 1, CFGFLAG_SERVER, "Whether players see all tees by default") MACRO_CONFIG_INT(SvMaxAfkTime, sv_max_afk_time, 0, 0, 9999, CFGFLAG_SERVER, "The time in seconds a player is allowed to be afk (0 = disabled)") MACRO_CONFIG_INT(SvMaxAfkVoteTime, sv_max_afk_vote_time, 300, 0, 9999, CFGFLAG_SERVER, "The time in seconds a player can be afk and his votes still count (0 = disabled)") -MACRO_CONFIG_INT(SvPlasmaRange, sv_plasma_range, 700, 1, 99999, CFGFLAG_SERVER, "How far will the plasma gun track tees") -MACRO_CONFIG_INT(SvPlasmaPerSec, sv_plasma_per_sec, 3, 0, 50, CFGFLAG_SERVER, "How many shots does the plasma gun fire per seconds") +MACRO_CONFIG_INT(SvPlasmaRange, sv_plasma_range, 700, 1, 99999, CFGFLAG_SERVER|CFGFLAG_GAME, "How far will the plasma gun track tees") +MACRO_CONFIG_INT(SvPlasmaPerSec, sv_plasma_per_sec, 3, 0, 50, CFGFLAG_SERVER|CFGFLAG_GAME, "How many shots does the plasma gun fire per seconds") MACRO_CONFIG_INT(SvVotePause, sv_vote_pause, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to pause players (instead of moving to spectators)") MACRO_CONFIG_INT(SvVotePauseTime, sv_vote_pause_time, 10, 0, 360, CFGFLAG_SERVER, "The time (in seconds) players have to wait in pause when paused by vote") MACRO_CONFIG_INT(SvTuneReset, sv_tune_reset, 1, 0, 1, CFGFLAG_SERVER, "Whether tuning is reset after each map change or not") @@ -326,7 +326,7 @@ MACRO_CONFIG_INT(SvEvents, sv_events, 1, 0, 1, CFGFLAG_SERVER, "Enable triggerin MACRO_CONFIG_INT(SvRankCheats, sv_rank_cheats, 0, 0, 1, CFGFLAG_SERVER, "Enable ranks after cheats have been used (file based server only)") MACRO_CONFIG_INT(SvShutdownWhenEmpty, sv_shutdown_when_empty, 0, 0, 1, CFGFLAG_SERVER, "Shutdown server as soon as noone is on it anymore") MACRO_CONFIG_INT(SvKillProtection, sv_kill_protection, 20, 0, 9999, CFGFLAG_SERVER, "0 - Disable, 1-9999 minutes") -MACRO_CONFIG_INT(SvSoloServer, sv_solo_server, 0, 0, 1, CFGFLAG_SERVER, "Set server to solo mode (no player interactions, has to be set before loading the map)") +MACRO_CONFIG_INT(SvSoloServer, sv_solo_server, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Set server to solo mode (no player interactions, has to be set before loading the map)") MACRO_CONFIG_STR(SvClientSuggestion, sv_client_suggestion, 128, "Get DDNet client from DDNet.tw to use all features on DDNet!", CFGFLAG_SERVER, "Broadcast to display to players without DDNet client") MACRO_CONFIG_STR(SvClientSuggestionOld, sv_client_suggestion_old, 128, "Your DDNet client is old, update it on DDNet.tw!", CFGFLAG_SERVER, "Broadcast to display to players with an old version of DDNet client") MACRO_CONFIG_STR(SvClientSuggestionBot, sv_client_suggestion_bot, 128, "Your client has bots and can be remote controlled!\nPlease use another client like DDNet client from DDNet.tw", CFGFLAG_SERVER, "Broadcast to display to players with a known botting client") diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 9afc02f18..36d618956 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -323,7 +323,29 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID) if(pCommand) { - if(pCommand->GetAccessLevel() >= m_AccessLevel) + if(ClientID == IConsole::CLIENT_ID_GAME + && !(pCommand->m_Flags & CFGFLAG_GAME)) + { + if(Stroke) + { + char aBuf[96]; + str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a map.", Result.m_pCommand); + Print(OUTPUT_LEVEL_STANDARD, "console", aBuf); + } + } + else if(ClientID == IConsole::CLIENT_ID_NO_GAME + && pCommand->m_Flags & CFGFLAG_GAME) + { + if(Stroke) + { + char aBuf[96]; + str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a non-map config file.", Result.m_pCommand); + Print(OUTPUT_LEVEL_STANDARD, "console", aBuf); + str_format(aBuf, sizeof(aBuf), "Hint: Put the command in '%s.cfg' instead of '%s.map.cfg' ", g_Config.m_SvMap, g_Config.m_SvMap); + Print(OUTPUT_LEVEL_STANDARD, "console", aBuf); + } + } + else if(pCommand->GetAccessLevel() >= m_AccessLevel) { int IsStrokeCommand = 0; if(Result.m_pCommand[0] == '+') @@ -560,6 +582,7 @@ struct CIntVariableData int *m_pVariable; int m_Min; int m_Max; + int m_OldValue; }; struct CStrVariableData @@ -567,6 +590,7 @@ struct CStrVariableData IConsole *m_pConsole; char *m_pStr; int m_MaxSize; + char *m_pOldValue; }; static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData) @@ -587,10 +611,12 @@ static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData) } *(pData->m_pVariable) = Val; + if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME) + pData->m_OldValue = Val; } else { - char aBuf[1024]; + char aBuf[32]; str_format(aBuf, sizeof(aBuf), "Value: %d", *(pData->m_pVariable)); pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf); } @@ -622,6 +648,9 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData) } else str_copy(pData->m_pStr, pString, pData->m_MaxSize); + + if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME) + str_copy(pData->m_pOldValue, pData->m_pStr, pData->m_MaxSize); } else { @@ -732,13 +761,14 @@ CConsole::CConsole(int FlagMask) // TODO: this should disappear #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ { \ - static CIntVariableData Data = { this, &g_Config.m_##Name, Min, Max }; \ + static CIntVariableData Data = { this, &g_Config.m_##Name, Min, Max, Def }; \ Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \ } #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ { \ - static CStrVariableData Data = { this, g_Config.m_##Name, Len }; \ + static char OldValue[Len] = Def; \ + static CStrVariableData Data = { this, g_Config.m_##Name, Len, OldValue }; \ Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \ } @@ -1008,6 +1038,50 @@ void CConsole::ConUserCommandStatus(IResult *pResult, void *pUser) pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf); } +void CConsole::ResetServerGameSettings() +{ + #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ + { \ + if((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME) && str_comp(#ScriptName, "sv_test_cmds") != 0) \ + { \ + CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_SERVER); \ + void *pUserData = pCommand->m_pUserData; \ + FCommandCallback pfnCallback = pCommand->m_pfnCallback; \ + while(pfnCallback == Con_Chain) \ + { \ + CChain *pChainInfo = (CChain *)pUserData; \ + pUserData = pChainInfo->m_pCallbackUserData; \ + pfnCallback = pChainInfo->m_pfnCallback; \ + } \ + CIntVariableData *pData = (CIntVariableData *)pUserData; \ + *pData->m_pVariable = pData->m_OldValue; \ + } \ + } + + #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ + { \ + if((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME)) \ + { \ + CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_SERVER); \ + void *pUserData = pCommand->m_pUserData; \ + FCommandCallback pfnCallback = pCommand->m_pfnCallback; \ + while(pfnCallback == Con_Chain) \ + { \ + CChain *pChainInfo = (CChain *)pUserData; \ + pUserData = pChainInfo->m_pCallbackUserData; \ + pfnCallback = pChainInfo->m_pfnCallback; \ + } \ + CStrVariableData *pData = (CStrVariableData *)pUserData; \ + str_copy(pData->m_pOldValue, pData->m_pStr, pData->m_MaxSize); \ + } \ + } + + #include "config_variables.h" + + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR +} + int CConsole::CResult::GetVictim() { return m_Victim; diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index 5b0177163..18825c8d8 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -195,7 +195,7 @@ public: virtual void Print(int Level, const char *pFrom, const char *pStr, bool Highlighted = false); void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); } - + void ResetServerGameSettings(); // DDRace static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 03722d255..6c841fab4 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2246,15 +2246,15 @@ void CGameContext::OnConsoleInit() m_ChatPrintCBIndex = Console()->RegisterPrintCallback(0, SendChatResponse, this); - Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value"); - Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning"); - Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning"); - Console()->Register("tune_zone", "isi", CFGFLAG_SERVER, ConTuneZone, this, "Tune in zone a variable to value"); - Console()->Register("tune_zone_dump", "i", CFGFLAG_SERVER, ConTuneDumpZone, this, "Dump zone tuning in zone x"); - Console()->Register("tune_zone_reset", "?i", CFGFLAG_SERVER, ConTuneResetZone, this, "reset zone tuning in zone x or in all zones"); - Console()->Register("tune_zone_enter", "is", CFGFLAG_SERVER, ConTuneSetZoneMsgEnter, this, "which message to display on zone enter; use 0 for normal area"); - Console()->Register("tune_zone_leave", "is", CFGFLAG_SERVER, ConTuneSetZoneMsgLeave, this, "which message to display on zone leave; use 0 for normal area"); - Console()->Register("switch_open", "i", CFGFLAG_SERVER, ConSwitchOpen, this, "Whether a switch is open by default (otherwise closed)"); + Console()->Register("tune", "si", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneParam, this, "Tune variable to value"); + Console()->Register("tune_reset", "", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneReset, this, "Reset tuning"); + Console()->Register("tune_dump", "", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneDump, this, "Dump tuning"); + Console()->Register("tune_zone", "isi", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneZone, this, "Tune in zone a variable to value"); + Console()->Register("tune_zone_dump", "i", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneDumpZone, this, "Dump zone tuning in zone x"); + Console()->Register("tune_zone_reset", "?i", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneResetZone, this, "reset zone tuning in zone x or in all zones"); + Console()->Register("tune_zone_enter", "is", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneSetZoneMsgEnter, this, "which message to display on zone enter; use 0 for normal area"); + Console()->Register("tune_zone_leave", "is", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneSetZoneMsgLeave, this, "which message to display on zone leave; use 0 for normal area"); + Console()->Register("switch_open", "i", CFGFLAG_SERVER|CFGFLAG_GAME, ConSwitchOpen, this, "Whether a switch is open by default (otherwise closed)"); Console()->Register("pause_game", "", CFGFLAG_SERVER, ConPause, this, "Pause/unpause game"); Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map"); Console()->Register("random_map", "?i", CFGFLAG_SERVER, ConRandomMap, this, "Random map"); @@ -2300,8 +2300,6 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_Layers.Init(Kernel()); m_Collision.Init(&m_Layers); - LoadMapSettings(); - // reset everything here //world = new GAMEWORLD; //players = new CPlayer[MAX_CLIENTS]; @@ -2355,11 +2353,8 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) Console()->ExecuteFile(g_Config.m_SvResetFile); - char buf[512]; - str_format(buf, sizeof(buf), "maps/%s.cfg", g_Config.m_SvMap); - Console()->ExecuteFile(buf); - str_format(buf, sizeof(buf), "maps/%s.map.cfg", g_Config.m_SvMap); - Console()->ExecuteFile(buf); + LoadMapSettings(); + /* // select gametype if(str_comp(g_Config.m_SvGametype, "mod") == 0) m_pController = new CGameControllerMOD(this); @@ -2637,6 +2632,7 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize) void CGameContext::OnShutdown() { DeleteTempfile(); + Console()->ResetServerGameSettings(); Layers()->Dest(); Collision()->Dest(); delete m_pController; @@ -2668,11 +2664,15 @@ void CGameContext::LoadMapSettings() while(pNext < pSettings + Size) { int StrSize = str_length(pNext) + 1; - Console()->ExecuteLine(pNext); + Console()->ExecuteLine(pNext, IConsole::CLIENT_ID_GAME); pNext += StrSize; } pMap->UnloadData(pItem->m_Settings); } + + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "maps/%s.map.cfg", g_Config.m_SvMap); + Console()->ExecuteFile(aBuf, IConsole::CLIENT_ID_NO_GAME); } void CGameContext::OnSnap(int ClientID) diff --git a/src/game/variables.h b/src/game/variables.h index 6c8a7c79f..d5d005841 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -145,10 +145,10 @@ MACRO_CONFIG_INT(SvVoteSpectateRejoindelay, sv_vote_spectate_rejoindelay, 3, 0, MACRO_CONFIG_INT(SvVoteKick, sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players") MACRO_CONFIG_INT(SvVoteKickMin, sv_vote_kick_min, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Minimum number of players required to start a kick vote") MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick") -MACRO_CONFIG_INT(SvOldTeleportWeapons, sv_old_teleport_weapons, 0, 0, 1, CFGFLAG_SERVER, "Teleporting of all weapons (deprecated, use special entities instead)"); -MACRO_CONFIG_INT(SvOldTeleportHook, sv_old_teleport_hook, 0, 0, 1, CFGFLAG_SERVER, "Hook through teleporter (deprecated, use special entities instead)"); -MACRO_CONFIG_INT(SvTeleportHoldHook, sv_teleport_hold_hook, 0, 0, 1, CFGFLAG_SERVER, "Hold hook when teleported"); -MACRO_CONFIG_INT(SvTeleportLoseWeapons, sv_teleport_lose_weapons, 0, 0, 1, CFGFLAG_SERVER, "Lose weapons when teleported (useful for some race maps)"); +MACRO_CONFIG_INT(SvOldTeleportWeapons, sv_old_teleport_weapons, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Teleporting of all weapons (deprecated, use special entities instead)"); +MACRO_CONFIG_INT(SvOldTeleportHook, sv_old_teleport_hook, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Hook through teleporter (deprecated, use special entities instead)"); +MACRO_CONFIG_INT(SvTeleportHoldHook, sv_teleport_hold_hook, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Hold hook when teleported"); +MACRO_CONFIG_INT(SvTeleportLoseWeapons, sv_teleport_lose_weapons, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Lose weapons when teleported (useful for some race maps)"); MACRO_CONFIG_INT(SvMapUpdateRate, sv_mapupdaterate, 5, 1, 100, CFGFLAG_SERVER, "64 player id <-> vanilla id players map update rate") From a8d3f3bbc53c32109c92fb7b8e6793d790307c2e Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 15 Jul 2015 17:43:24 +0200 Subject: [PATCH 06/12] Only revert configs that have both SERVER and GAME flags on map change --- src/engine/shared/console.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 36d618956..42a64b443 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -1042,7 +1042,7 @@ void CConsole::ResetServerGameSettings() { #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ { \ - if((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME) && str_comp(#ScriptName, "sv_test_cmds") != 0) \ + if(((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME)) == (CFGFLAG_SERVER|CFGFLAG_GAME)) \ { \ CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_SERVER); \ void *pUserData = pCommand->m_pUserData; \ @@ -1060,7 +1060,7 @@ void CConsole::ResetServerGameSettings() #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ { \ - if((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME)) \ + if(((Flags) & (CFGFLAG_SERVER|CFGFLAG_GAME)) == (CFGFLAG_SERVER|CFGFLAG_GAME)) \ { \ CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_SERVER); \ void *pUserData = pCommand->m_pUserData; \ From db696c0e78c318406111791c4733cc130022e8fc Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 15 Jul 2015 17:50:29 +0200 Subject: [PATCH 07/12] Fix the 54e61bfe39 cherry-pick, re-add missing line --- src/game/editor/editor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 366a493e2..0c26e0fdf 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4096,6 +4096,7 @@ void CEditor::RenderStatusbar(CUIRect View) if(MouseButton == 2) m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+3)%4; else if(MouseButton == 1) + m_ShowEnvelopeEditor = (m_ShowEnvelopeEditor+1)%4; if(MouseButton) { From d13ebf93a2688069c93766951da675b20a9db438 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Fri, 21 Aug 2015 23:02:50 +0200 Subject: [PATCH 08/12] Add `config_store` and `config_retrieve` tool --- src/engine/shared/datafile.cpp | 15 ++-- src/engine/shared/datafile.h | 2 + src/engine/shared/storage.cpp | 10 +++ src/engine/storage.h | 1 + src/game/server/gamecontext.cpp | 27 +++++--- src/tools/config_common.h | 37 ++++++++++ src/tools/config_retrieve.cpp | 58 ++++++++++++++++ src/tools/config_store.cpp | 119 ++++++++++++++++++++++++++++++++ 8 files changed, 257 insertions(+), 12 deletions(-) create mode 100644 src/tools/config_common.h create mode 100644 src/tools/config_retrieve.cpp create mode 100644 src/tools/config_store.cpp diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 5f011cc51..9e242547a 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -452,13 +452,16 @@ CDataFileWriter::~CDataFileWriter() m_pDatas = 0; } -bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) +bool CDataFileWriter::OpenFile(class IStorage *pStorage, const char *pFilename) { dbg_assert(!m_File, "a file already exists"); m_File = pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); - if(!m_File) - return false; + return m_File != 0; +} +void CDataFileWriter::Init() +{ + dbg_assert(!m_File, "a file already exists"); m_NumItems = 0; m_NumDatas = 0; m_NumItemTypes = 0; @@ -469,8 +472,12 @@ bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) m_pItemTypes[i].m_First = -1; m_pItemTypes[i].m_Last = -1; } +} - return true; +bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) +{ + Init(); + return OpenFile(pStorage, pFilename); } int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h index c452c6c9f..0c2e07a97 100644 --- a/src/engine/shared/datafile.h +++ b/src/engine/shared/datafile.h @@ -80,6 +80,8 @@ class CDataFileWriter public: CDataFileWriter(); ~CDataFileWriter(); + void Init(); + bool OpenFile(class IStorage *pStorage, const char *pFilename); bool Open(class IStorage *pStorage, const char *Filename); int AddData(int Size, void *pData); int AddDataSwapped(int Size, void *pData); diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index aa3857acb..e6a40f851 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -433,3 +433,13 @@ public: }; IStorage *CreateStorage(const char *pApplicationName, int StorageType, int NumArgs, const char **ppArguments) { return CStorage::Create(pApplicationName, StorageType, NumArgs, ppArguments); } + +IStorage *CreateLocalStorage() +{ + CStorage *pStorage = new CStorage(); + if(pStorage) + { + pStorage->AddPath("$CURRENTDIR"); + } + return pStorage; +} diff --git a/src/engine/storage.h b/src/engine/storage.h index 05a3ac540..9cb0a5a19 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -33,6 +33,7 @@ public: }; extern IStorage *CreateStorage(const char *pApplicationName, int StorageType, int NumArgs, const char **ppArguments); +extern IStorage *CreateLocalStorage(); #endif diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 6c841fab4..c034be4b4 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2534,7 +2534,7 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize) char aConfig[128]; char aTemp[128]; str_format(aConfig, sizeof(aConfig), "maps/%s.cfg", g_Config.m_SvMap); - str_format(aTemp, sizeof(aTemp), "%s.temp.%d", pNewMapName, pid(), pNewMapName); + str_format(aTemp, sizeof(aTemp), "%s.temp.%d", pNewMapName, pid()); IOHANDLE File = pStorage->OpenFile(aConfig, IOFLAG_READ, IStorage::TYPE_ALL); if(!File) @@ -2587,15 +2587,25 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize) CMapItemInfoSettings *pInfo = (CMapItemInfoSettings *)pData; if(Size >= (int)sizeof(CMapItemInfoSettings)) { - SettingsIndex = pInfo->m_Settings; - char *pMapSettings = (char *)Reader.GetData(SettingsIndex); - int DataSize = Reader.GetUncompressedDataSize(SettingsIndex); - if(DataSize == TotalLength && mem_comp(pSettings, pMapSettings, Size) == 0) + if(pInfo->m_Settings > -1) { - // Configs coincide, no need to update map. - return; + SettingsIndex = pInfo->m_Settings; + char *pMapSettings = (char *)Reader.GetData(SettingsIndex); + int DataSize = Reader.GetUncompressedDataSize(SettingsIndex); + if(DataSize == TotalLength && mem_comp(pSettings, pMapSettings, Size) == 0) + { + // Configs coincide, no need to update map. + return; + } + Reader.UnloadData(pInfo->m_Settings); + } + else + { + MapInfo = *pInfo; + MapInfo.m_Settings = SettingsIndex; + pData = (int *)&MapInfo; + Size = sizeof(MapInfo); } - Reader.UnloadData(pInfo->m_Settings); } else { @@ -2668,6 +2678,7 @@ void CGameContext::LoadMapSettings() pNext += StrSize; } pMap->UnloadData(pItem->m_Settings); + break; } char aBuf[128]; diff --git a/src/tools/config_common.h b/src/tools/config_common.h new file mode 100644 index 000000000..acf735e3c --- /dev/null +++ b/src/tools/config_common.h @@ -0,0 +1,37 @@ +#include +#include + +int main(int argc, const char **argv) +{ + dbg_logger_stdout(); + IStorage *pStorage = CreateLocalStorage(); + if(argc == 1) + { + dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]); + return -1; + } + for(int i = 1; i < argc; i++) + { + char aConfig[2048]; + + size_t Len = str_length(argv[i]) + 1; // including '\0' + if(Len > sizeof(aConfig)) + { + dbg_msg("config_common", "can't process overlong filename '%s'", argv[i]); + continue; + } + + if(Len < sizeof(".map") || str_comp(argv[i] + Len - sizeof(".map"), ".map") != 0) + { + dbg_msg("config_common", "can't process non-map file '%s'", argv[i]); + continue; + } + + str_copy(aConfig, argv[i], sizeof(aConfig)); + aConfig[Len - sizeof(".map")] = 0; + str_append(aConfig, ".cfg", sizeof(aConfig)); + dbg_msg("config_common", "processing '%s'", argv[i]); + Process(pStorage, argv[i], aConfig); + } + return 0; +} diff --git a/src/tools/config_retrieve.cpp b/src/tools/config_retrieve.cpp new file mode 100644 index 000000000..606f9ecaa --- /dev/null +++ b/src/tools/config_retrieve.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) +{ + CDataFileReader Map; + if(!Map.Open(pStorage, pMapName, 2)) + { + dbg_msg("config_retrieve", "error opening map '%s'", pMapName); + return; + } + bool ConfigFound = false; + int Start, Num; + Map.GetType(MAPITEMTYPE_INFO, &Start, &Num); + for(int i = Start; i < Start + Num; i++) + { + int ItemID; + CMapItemInfoSettings *pItem = (CMapItemInfoSettings *)Map.GetItem(i, 0, &ItemID); + int ItemSize = Map.GetItemSize(i) - 8; + if(!pItem || ItemID != 0) + continue; + + if(ItemSize < (int)sizeof(CMapItemInfoSettings)) + break; + if(!(pItem->m_Settings > -1)) + break; + + ConfigFound = true; + IOHANDLE Config = io_open(pConfigName, IOFLAG_WRITE); + if(!Config) + { + dbg_msg("config_retrieve", "error opening config for writing '%s'", pConfigName); + return; + } + + int Size = Map.GetUncompressedDataSize(pItem->m_Settings); + char *pSettings = (char *)Map.GetData(pItem->m_Settings); + char *pNext = pSettings; + while(pNext < pSettings + Size) + { + int StrSize = str_length(pNext) + 1; + io_write(Config, pNext, StrSize - 1); + io_write_newline(Config); + pNext += StrSize; + } + Map.UnloadData(pItem->m_Settings); + io_close(Config); + break; + } + Map.Close(); + if(!ConfigFound) + { + fs_remove(pConfigName); + } +} +#include "config_common.h" diff --git a/src/tools/config_store.cpp b/src/tools/config_store.cpp new file mode 100644 index 000000000..b49abf55c --- /dev/null +++ b/src/tools/config_store.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) +{ + IOHANDLE File = pStorage->OpenFile(pConfigName, IOFLAG_READ, IStorage::TYPE_ALL); + array aLines; + char *pSettings = NULL; + if(!File) + { + dbg_msg("config_store", "config '%s' not found", pConfigName); + return; + } + + CLineReader LineReader; + LineReader.Init(File); + + char *pLine; + int TotalLength = 0; + while((pLine = LineReader.Get())) + { + int Length = str_length(pLine) + 1; + char *pCopy = (char *)mem_alloc(Length, 1); + mem_copy(pCopy, pLine, Length); + aLines.add(pCopy); + TotalLength += Length; + } + + pSettings = (char *)mem_alloc(TotalLength, 1); + int Offset = 0; + for(int i = 0; i < aLines.size(); i++) + { + int Length = str_length(aLines[i]) + 1; + mem_copy(pSettings + Offset, aLines[i], Length); + Offset += Length; + mem_free(aLines[i]); + } + + CDataFileReader Reader; + Reader.Open(pStorage, pMapName, IStorage::TYPE_ALL); + + CDataFileWriter Writer; + Writer.Init(); + + int SettingsIndex = Reader.NumData(); + for(int i = 0; i < Reader.NumItems(); i++) + { + int TypeID; + int ItemID; + int *pData = (int *)Reader.GetItem(i, &TypeID, &ItemID); + // GetItemSize returns item size including header, remove that. + int Size = Reader.GetItemSize(i) - sizeof(int) * 2; + CMapItemInfoSettings MapInfo; + if(TypeID == MAPITEMTYPE_INFO && ItemID == 0) + { + CMapItemInfoSettings *pInfo = (CMapItemInfoSettings *)pData; + if(Size >= (int)sizeof(CMapItemInfoSettings)) + { + MapInfo = *pInfo; + pData = (int *)&MapInfo; + Size = sizeof(MapInfo); + if(pInfo->m_Settings > -1) + { + SettingsIndex = pInfo->m_Settings; + char *pMapSettings = (char *)Reader.GetData(SettingsIndex); + int DataSize = Reader.GetUncompressedDataSize(SettingsIndex); + if(DataSize == TotalLength && mem_comp(pSettings, pMapSettings, Size) == 0) + { + dbg_msg("config_store", "configs coincide, not updating map"); + return; + } + Reader.UnloadData(pInfo->m_Settings); + } + else + { + MapInfo = *pInfo; + MapInfo.m_Settings = SettingsIndex; + pData = (int *)&MapInfo; + Size = sizeof(MapInfo); + } + } + else + { + *(CMapItemInfo *)&MapInfo = *(CMapItemInfo *)pInfo; + MapInfo.m_Settings = SettingsIndex; + pData = (int *)&MapInfo; + Size = sizeof(MapInfo); + } + } + Writer.AddItem(TypeID, ItemID, Size, pData); + } + + for(int i = 0; i < Reader.NumData() || i == SettingsIndex; i++) + { + if(i == SettingsIndex) + { + Writer.AddData(TotalLength, pSettings); + continue; + } + unsigned char *pData = (unsigned char *)Reader.GetData(i); + int Size = Reader.GetUncompressedDataSize(i); + Writer.AddData(Size, pData); + Reader.UnloadData(i); + } + + Reader.Close(); + if(!Writer.Open(pStorage, pMapName)) + { + dbg_msg("config_store", "couldn't open map file '%s' for writing", pMapName); + return; + } + Writer.Finish(); + dbg_msg("config_store", "imported settings"); +} +#include "config_common.h" From 53d7e0dd4c27aa9ae0aa2443d9d5a40403b92398 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 26 Aug 2015 13:18:44 +0200 Subject: [PATCH 09/12] Fix file opening in config_* tools --- src/engine/shared/storage.cpp | 5 +++++ src/tools/config_retrieve.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index e6a40f851..439044aac 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -439,6 +439,11 @@ IStorage *CreateLocalStorage() CStorage *pStorage = new CStorage(); if(pStorage) { + if(!fs_getcwd(pStorage->m_aCurrentdir, sizeof(pStorage->m_aCurrentdir))) + { + delete pStorage; + return NULL; + } pStorage->AddPath("$CURRENTDIR"); } return pStorage; diff --git a/src/tools/config_retrieve.cpp b/src/tools/config_retrieve.cpp index 606f9ecaa..a5b4db93a 100644 --- a/src/tools/config_retrieve.cpp +++ b/src/tools/config_retrieve.cpp @@ -6,7 +6,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) { CDataFileReader Map; - if(!Map.Open(pStorage, pMapName, 2)) + if(!Map.Open(pStorage, pMapName, IStorage::TYPE_ALL)) { dbg_msg("config_retrieve", "error opening map '%s'", pMapName); return; @@ -28,7 +28,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) break; ConfigFound = true; - IOHANDLE Config = io_open(pConfigName, IOFLAG_WRITE); + IOHANDLE Config = pStorage->OpenFile(pConfigName, IOFLAG_WRITE, IStorage::TYPE_ALL); if(!Config) { dbg_msg("config_retrieve", "error opening config for writing '%s'", pConfigName); From a945cca8a5aeb323d8235ecea9caeca94c89a2ed Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 27 Aug 2015 00:36:10 +0200 Subject: [PATCH 10/12] Fix datafile building before the file is open --- src/engine/shared/datafile.cpp | 4 ---- src/tools/config_store.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 9e242547a..1de438511 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -482,8 +482,6 @@ bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) { - if(!m_File) return 0; - dbg_assert(Type >= 0 && Type < 0xFFFF, "incorrect type"); dbg_assert(m_NumItems < 1024, "too many items"); dbg_assert(Size%sizeof(int) == 0, "incorrect boundary"); @@ -518,8 +516,6 @@ int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) int CDataFileWriter::AddData(int Size, void *pData) { - if(!m_File) return 0; - dbg_assert(m_NumDatas < 1024, "too much data"); CDataInfo *pInfo = &m_pDatas[m_NumDatas]; diff --git a/src/tools/config_store.cpp b/src/tools/config_store.cpp index b49abf55c..38a54a786 100644 --- a/src/tools/config_store.cpp +++ b/src/tools/config_store.cpp @@ -108,7 +108,7 @@ void Process(IStorage *pStorage, const char *pMapName, const char *pConfigName) } Reader.Close(); - if(!Writer.Open(pStorage, pMapName)) + if(!Writer.OpenFile(pStorage, pMapName)) { dbg_msg("config_store", "couldn't open map file '%s' for writing", pMapName); return; From 7d9228f3d5a526b2ec6e1a7cf58dd32f0faca6af Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 27 Aug 2015 12:47:13 +0200 Subject: [PATCH 11/12] Fix a severe bug with config saving Thought I had fixed that long ago... --- src/game/editor/io.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index d75041d3e..e1797da53 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -273,6 +273,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) { int Length = str_length(m_lSettings[i].m_aCommand) + 1; mem_copy(pNext, m_lSettings[i].m_aCommand, Length); + pNext += Length; } Item.m_Settings = df.AddData(Size, pSettings); mem_free(pSettings); From e954e555336d0b57344dfb93180fec5c8eefe9bb Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 27 Aug 2015 13:00:43 +0200 Subject: [PATCH 12/12] Removed `*_dump` and `*_reset` from the list of game commands --- src/game/server/gamecontext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index c034be4b4..021d4f857 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2247,11 +2247,11 @@ void CGameContext::OnConsoleInit() m_ChatPrintCBIndex = Console()->RegisterPrintCallback(0, SendChatResponse, this); Console()->Register("tune", "si", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneParam, this, "Tune variable to value"); - Console()->Register("tune_reset", "", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneReset, this, "Reset tuning"); - Console()->Register("tune_dump", "", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneDump, this, "Dump tuning"); + Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning"); + Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning"); Console()->Register("tune_zone", "isi", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneZone, this, "Tune in zone a variable to value"); - Console()->Register("tune_zone_dump", "i", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneDumpZone, this, "Dump zone tuning in zone x"); - Console()->Register("tune_zone_reset", "?i", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneResetZone, this, "reset zone tuning in zone x or in all zones"); + Console()->Register("tune_zone_dump", "i", CFGFLAG_SERVER, ConTuneDumpZone, this, "Dump zone tuning in zone x"); + Console()->Register("tune_zone_reset", "?i", CFGFLAG_SERVER, ConTuneResetZone, this, "reset zone tuning in zone x or in all zones"); Console()->Register("tune_zone_enter", "is", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneSetZoneMsgEnter, this, "which message to display on zone enter; use 0 for normal area"); Console()->Register("tune_zone_leave", "is", CFGFLAG_SERVER|CFGFLAG_GAME, ConTuneSetZoneMsgLeave, this, "which message to display on zone leave; use 0 for normal area"); Console()->Register("switch_open", "i", CFGFLAG_SERVER|CFGFLAG_GAME, ConSwitchOpen, this, "Whether a switch is open by default (otherwise closed)");