From 2b4f212ce29f13336ac9a8dde1cf51a8362cc36e Mon Sep 17 00:00:00 2001 From: lava76 Date: Mon, 4 Apr 2022 21:04:15 +0200 Subject: [PATCH 01/19] Use a different approach to check entity for modstorage Only needs to keep track of players. See comments in CF_ModStorageModule.c near the top. --- JM/CF/Defines/CFDefines.c | 5 +- .../ModStorage/CF_ModStorage.c | 2 +- .../ModStorage/CF_ModStorageModule.c | 96 +++++++------------ .../Entities/AdvancedCommunication.c | 38 ++++---- .../CommunityFramework/Entities/AnimalBase.c | 38 ++++---- .../Entities/BuildingBase.c | 38 ++++---- .../CommunityFramework/Entities/CarScript.c | 38 ++++---- .../Entities/DayZPlayerImplement.c | 38 ++++---- .../Entities/HelicopterScript.c | 38 ++++---- .../CommunityFramework/Entities/ItemBase.c | 38 ++++---- .../CommunityFramework/Entities/ZombieBase.c | 38 ++++---- .../ModStorage/CF_ModStorageObject.c | 22 +++-- .../ModStorage/modstorage_prepare.c | 4 +- 13 files changed, 210 insertions(+), 223 deletions(-) diff --git a/JM/CF/Defines/CFDefines.c b/JM/CF/Defines/CFDefines.c index 3b26fa74..41c3c39a 100644 --- a/JM/CF/Defines/CFDefines.c +++ b/JM/CF/Defines/CFDefines.c @@ -7,11 +7,10 @@ #define CF_GHOSTICONS -//#define CF_MODSTORAGE +#define CF_MODSTORAGE //#define CF_MODSTORAGE_TEST //#define CF_MODSTORAGE_TRACE -#define CF_MODSTORAGE_DISABLE -#define CF_MODSTORAGE_MODULE_DISABLE +//#define CF_MODSTORAGE_MODULE_DISABLE #define CF_SURFACES diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c index bd502b24..0ce1d913 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c @@ -9,7 +9,7 @@ class CF_ModStorage static const int VERSION = 4; static const int GAME_VERSION_FIRST_INSTALL = 116; - static const int GAME_VERSION_WIPE_FILE = 127; + static const int GAME_VERSION_WIPE_FILE = 129; static const int MODSTORAGE_INITIAL_IMPLEMENTATION = 2; diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c index d699b7bf..54507a86 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -8,64 +8,48 @@ #endif class CF_ModStorageModule : CF_ModuleGame { - static const string m_FileName = "modstorageids.bin"; + static const string m_FileName = "modstorageplayers.bin"; protected string m_FilePath; - protected autoptr map>>>> m_IDs = new map>>>>(); + //! We only need to keep track of players, because if m_FileName exists, + //! we already know that all items that are not in player inventory are OK to load from modstorage + //! because they have been saved prior (as long as the server ran for a couple minutes at least) + protected autoptr map> m_IDs = new map>(); protected bool m_IsLoaded; + protected bool m_FileExist; protected autoptr FileSerializer m_Serializer; /** - * @brief Checks if the persistent ID is in the map. If they aren't in the map then add and write to the file + * @brief Checks if the item has a player root and if the player ID is in the map. If they aren't in the map then add and write to the file */ - void AddEntity(int b1, int b2, int b3, int b4) + void AddEntity(EntityAI entity) { Load(); - if (!_AddEntity(b1, b2, b3, b4, false)) + Man player = entity.GetHierarchyRootPlayer(); + if (!player || !player.GetIdentity() || !_AddPlayer(player.GetIdentity().GetId(), false)) { return; } - m_Serializer.Write(b1); - m_Serializer.Write(b2); - m_Serializer.Write(b3); - m_Serializer.Write(b4); + m_Serializer.Write(player.GetIdentity().GetId()); } /** - * @brief Checks to see if the persistent ID is loaded + * @brief Checks to see if the item has a player root and if the player ID is in the map */ - bool IsEntity(int b1, int b2, int b3, int b4) + bool IsEntity(EntityAI entity) { Load(); - auto map_b1 = m_IDs[b1]; - if (!map_b1) + Man player = entity.GetHierarchyRootPlayer(); + if (!player || !player.GetIdentity()) { - return false; + return m_FileExist; } - auto map_b2 = map_b1[b2]; - if (!map_b2) - { - return false; - } - - auto map_b3 = map_b2[b3]; - if (!map_b3) - { - return false; - } - - auto val_b4 = map_b3[b4]; - if (!val_b4) - { - return false; - } - - return true; + return m_IDs[player.GetIdentity().GetId()] != null; } /** @@ -101,16 +85,23 @@ class CF_ModStorageModule : CF_ModuleGame // Clear existing ids m_IDs.Clear(); - if (FileExist(m_FilePath)) + m_FileExist = FileExist(m_FilePath); + if (m_FileExist) { FileHandle handle = OpenFile(m_FilePath, FileMode.READ); if (handle != 0) { - // Reads 4 ints (16 bytes) at a time - int data[4]; - while (ReadFile(handle, data, 16) > 0) + // Reads 48 bytes (character count + ID string length) at a time + int count[4]; + string data[44]; + while (ReadFile(handle, count, 4) > 0 && ReadFile(handle, data, 44) > 0) { - _AddEntity(data[0], data[1], data[2], data[3], true); + string id; + for (int i = 0; i < 44; i++) + { + id += data[i]; + } + _AddPlayer(id, true); } CloseFile(handle); @@ -131,34 +122,11 @@ class CF_ModStorageModule : CF_ModuleGame * * @return True if newly added entity */ - private bool _AddEntity(int b1, int b2, int b3, int b4, bool loaded) + private bool _AddPlayer(string id, bool loaded) { - auto map_b1 = m_IDs[b1]; - if (!map_b1) - { - map_b1 = new map>>>(); - m_IDs[b1] = map_b1; - } - - auto map_b2 = map_b1[b2]; - if (!map_b2) - { - map_b2 = new map>>(); - map_b1[b2] = map_b2; - } - - auto map_b3 = map_b2[b3]; - if (!map_b3) - { - map_b3 = new map>(); - map_b2[b3] = map_b3; - } - - auto val_b4 = map_b3[b4]; - if (!val_b4) + if (!m_IDs[id]) { - val_b4 = new Param1(loaded); - map_b3[b4] = val_b4; + m_IDs[id] = new Param1(loaded); return true; } diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/AdvancedCommunication.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/AdvancedCommunication.c index e86ceeef..8313d9a2 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/AdvancedCommunication.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/AdvancedCommunication.c @@ -1,23 +1,25 @@ modded class AdvancedCommunication { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/AnimalBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/AnimalBase.c index f8e33cc7..b9ac4568 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/AnimalBase.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/AnimalBase.c @@ -1,23 +1,25 @@ modded class AnimalBase { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/BuildingBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BuildingBase.c index b71375e5..5f66f6e9 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/BuildingBase.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BuildingBase.c @@ -1,23 +1,25 @@ modded class BuildingBase { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/CarScript.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/CarScript.c index 22582dbb..15c98aec 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/CarScript.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/CarScript.c @@ -1,23 +1,25 @@ modded class CarScript { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/DayZPlayerImplement.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/DayZPlayerImplement.c index 61f86c66..c6509c0f 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/DayZPlayerImplement.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/DayZPlayerImplement.c @@ -1,23 +1,25 @@ modded class DayZPlayerImplement { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/HelicopterScript.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/HelicopterScript.c index bc6819f8..cd853f2e 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/HelicopterScript.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/HelicopterScript.c @@ -1,23 +1,25 @@ modded class HelicopterScript { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ItemBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ItemBase.c index ff3de84d..e03ccd5a 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ItemBase.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ItemBase.c @@ -1,23 +1,25 @@ modded class ItemBase { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @param storage Map of 'CF_ModStorage' classes diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ZombieBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ZombieBase.c index 5aa034f8..f9cb87cb 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ZombieBase.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ZombieBase.c @@ -1,23 +1,25 @@ modded class ZombieBase { -// autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); -// -// override void OnStoreSave(ParamsWriteContext ctx) -// { -// super.OnStoreSave(ctx); -// -// m_CF_ModStorage.OnStoreSave(ctx); -// } -// -// override bool OnStoreLoad(ParamsReadContext ctx, int version) -// { -// if (!super.OnStoreLoad(ctx, version)) -// { -// return false; -// } -// -// return m_CF_ModStorage.OnStoreLoad(ctx, version); -// } +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif /** * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c index c7511343..1127a34c 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c @@ -1,4 +1,4 @@ -#ifndef CF_MODSTORAGE_DISABLE +#ifdef CF_MODSTORAGE class CF_ModStorageObject : CF_ModStorageBase { T m_Entity; @@ -7,6 +7,8 @@ class CF_ModStorageObject : CF_ModStorageBase CF_ModStorageModule m_Module; + bool m_HasModStorage; + void CF_ModStorageObject(T entity) { m_Entity = entity; @@ -34,14 +36,17 @@ class CF_ModStorageObject : CF_ModStorageBase return; } -#ifndef CF_MODSTORAGE_MODULE_DISABLE - int b1, b2, b3, b4; - m_Entity.GetPersistentID(b1, b2, b3, b4); - // Add the entity to the file so on next load the game knows that it can read the modstorage for the entity - m_Module.AddEntity(b1, b2, b3, b4); + if (!m_HasModStorage) + { +#ifndef CF_MODSTORAGE_MODULE_DISABLE + // Add the entity to the file so on next load the game knows that it can read the modstorage for the entity + m_Module.AddEntity(m_Entity); #endif + m_HasModStorage = true; + } + // Write the CF modstorage version ctx.Write(CF_ModStorage.VERSION); @@ -84,13 +89,10 @@ class CF_ModStorageObject : CF_ModStorageBase } #ifndef CF_MODSTORAGE_MODULE_DISABLE - int b1, b2, b3, b4; - m_Entity.GetPersistentID(b1, b2, b3, b4); - // If the version is less than the wipe file, the entity will be added automatically in 'OnStoreSave' if (version >= CF_ModStorage.GAME_VERSION_WIPE_FILE) { - if (!m_Module.IsEntity(b1, b2, b3, b4)) + if (!m_Module.IsEntity(m_Entity)) { // Since the entity wasn't found we can assume that CF is freshly loaded // Highly unlikely anything else happened that can cause this diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/modstorage_prepare.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/modstorage_prepare.c index fbc8d1be..faa4769d 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/modstorage_prepare.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/modstorage_prepare.c @@ -1,3 +1,4 @@ +#ifndef CF_MODSTORAGE modded class BuildingBase { override void OnStoreSave(ParamsWriteContext ctx) @@ -180,4 +181,5 @@ modded class AdvancedCommunication return true; } -} \ No newline at end of file +} +#endif From 87d8598612368d3a11495937f183e7527c54bd33 Mon Sep 17 00:00:00 2001 From: lava76 Date: Mon, 4 Apr 2022 21:30:09 +0200 Subject: [PATCH 02/19] Need to reset id to empty string --- .../3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c index 54507a86..c6c62874 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -96,7 +96,7 @@ class CF_ModStorageModule : CF_ModuleGame string data[44]; while (ReadFile(handle, count, 4) > 0 && ReadFile(handle, data, 44) > 0) { - string id; + string id = ""; for (int i = 0; i < 44; i++) { id += data[i]; From 70ba9cc69520b92ebcacc20f31112ca6c997eca9 Mon Sep 17 00:00:00 2001 From: lava76 Date: Mon, 4 Apr 2022 22:46:13 +0200 Subject: [PATCH 03/19] ffs --- .../ModStorage/CF_ModStorageModule.c | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c index c6c62874..4610d8a6 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -88,24 +88,16 @@ class CF_ModStorageModule : CF_ModuleGame m_FileExist = FileExist(m_FilePath); if (m_FileExist) { - FileHandle handle = OpenFile(m_FilePath, FileMode.READ); - if (handle != 0) + m_Serializer = new FileSerializer(); + m_Serializer.Open(m_FilePath, FileMode.READ); + string id; + while (true) { - // Reads 48 bytes (character count + ID string length) at a time - int count[4]; - string data[44]; - while (ReadFile(handle, count, 4) > 0 && ReadFile(handle, data, 44) > 0) - { - string id = ""; - for (int i = 0; i < 44; i++) - { - id += data[i]; - } - _AddPlayer(id, true); - } - - CloseFile(handle); + m_Serializer.Read(id); // always returns true + if (!id) break; + _AddPlayer(id, true); } + m_Serializer.Close(); m_Serializer = new FileSerializer(); m_Serializer.Open(m_FilePath, FileMode.APPEND); From 63f5d9af3a5117286a307d6ed771dc5a95568968 Mon Sep 17 00:00:00 2001 From: lava76 Date: Tue, 5 Apr 2022 02:50:07 +0200 Subject: [PATCH 04/19] Fixed wrong type --- .../3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c index 4610d8a6..6467a59e 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -118,7 +118,7 @@ class CF_ModStorageModule : CF_ModuleGame { if (!m_IDs[id]) { - m_IDs[id] = new Param1(loaded); + m_IDs[id] = new Param1(loaded); return true; } From 9c4e57188a288fb03d4c8c5e41794e090a677d26 Mon Sep 17 00:00:00 2001 From: lava76 Date: Wed, 6 Apr 2022 02:16:07 +0200 Subject: [PATCH 05/19] Worked around issue of NULL identity in OnStoreLoad --- .../Entities/ManBase/PlayerBase.c | 29 +++++++++++++++++++ .../ModStorage/CF_ModStorageModule.c | 8 ++--- .../Mission/MissionServer.c | 4 +++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c rename JM/CF/Scripts/{3_Game => 4_World}/CommunityFramework/ModStorage/CF_ModStorageModule.c (92%) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c new file mode 100644 index 00000000..96bfa180 --- /dev/null +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c @@ -0,0 +1,29 @@ +#ifdef CF_MODSTORAGE +modded class PlayerBase +{ + protected static ref TStringArray s_CF_QueuedIdentityIDs = new TStringArray(); + protected string m_CF_QueuedIdentityID; + + static void CF_QueueIdentityId(string id) + { + s_CF_QueuedIdentityIDs.Insert(id); + } + + static string CF_DequeueIdentityId() + { + string id = s_CF_QueuedIdentityIDs[0]; + s_CF_QueuedIdentityIDs.RemoveOrdered(0); + return id; + } + + string CF_GetQueuedIdentityId() + { + if (!m_CF_QueuedIdentityID) + { + m_CF_QueuedIdentityID = CF_DequeueIdentityId(); + } + + return m_CF_QueuedIdentityID; + } +}; +#endif diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c similarity index 92% rename from JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c rename to JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c index 6467a59e..c93c0c00 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -6,7 +6,7 @@ #ifndef CF_MODSTORAGE_MODULE_DISABLE [CF_RegisterModule(CF_ModStorageModule)] #endif -class CF_ModStorageModule : CF_ModuleGame +class CF_ModStorageModule : CF_ModuleWorld { static const string m_FileName = "modstorageplayers.bin"; protected string m_FilePath; @@ -43,13 +43,13 @@ class CF_ModStorageModule : CF_ModuleGame { Load(); - Man player = entity.GetHierarchyRootPlayer(); - if (!player || !player.GetIdentity()) + PlayerBase player = PlayerBase.Cast(entity.GetHierarchyRootPlayer()); + if (!player || !player.CF_GetQueuedIdentityId()) { return m_FileExist; } - return m_IDs[player.GetIdentity().GetId()] != null; + return m_IDs[player.CF_GetQueuedIdentityId()] != null; } /** diff --git a/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c b/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c index 3a3102e7..35be1b81 100644 --- a/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c +++ b/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c @@ -143,6 +143,10 @@ modded class MissionServer yaw = args.Yaw; preloadTimeout = args.PreloadTimeout; +#ifdef CF_MODSTORAGE + PlayerBase.CF_QueueIdentityId(identity.GetId()); +#endif + // must call before vanilla super.OnClientPrepareEvent(identity, useDB, pos, yaw, preloadTimeout); } From 05c03542d30a2d3ec733fc27a259f3cc3e4659ab Mon Sep 17 00:00:00 2001 From: lava76 Date: Thu, 7 Apr 2022 22:01:22 +0200 Subject: [PATCH 06/19] Use queued ID in AddEntity as well Player may get booted before the game has had a chance to assign his identity, which will cause his inventory to be persisted immediately, so we need to add him for next load --- .../CommunityFramework/ModStorage/CF_ModStorageModule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c index c93c0c00..be577e59 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -27,13 +27,13 @@ class CF_ModStorageModule : CF_ModuleWorld { Load(); - Man player = entity.GetHierarchyRootPlayer(); - if (!player || !player.GetIdentity() || !_AddPlayer(player.GetIdentity().GetId(), false)) + PlayerBase player = PlayerBase.Cast(entity.GetHierarchyRootPlayer()); + if (!player || !player.CF_GetQueuedIdentityId() || !_AddPlayer(player.CF_GetQueuedIdentityId(), false)) { return; } - m_Serializer.Write(player.GetIdentity().GetId()); + m_Serializer.Write(player.CF_GetQueuedIdentityId()); } /** From bfb2779a4fea4d5837c671edf51808c355aacb96 Mon Sep 17 00:00:00 2001 From: lava76 Date: Thu, 7 Apr 2022 22:01:45 +0200 Subject: [PATCH 07/19] Make sure player doesn't get a stale queued ID and prefer identity ID --- .../Entities/ManBase/PlayerBase.c | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c index 96bfa180..192c4955 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/ManBase/PlayerBase.c @@ -1,4 +1,3 @@ -#ifdef CF_MODSTORAGE modded class PlayerBase { protected static ref TStringArray s_CF_QueuedIdentityIDs = new TStringArray(); @@ -18,12 +17,37 @@ modded class PlayerBase string CF_GetQueuedIdentityId() { - if (!m_CF_QueuedIdentityID) + //! Always prefer identity when it is available + if (GetIdentity()) { - m_CF_QueuedIdentityID = CF_DequeueIdentityId(); + if (m_CF_QueuedIdentityID != GetIdentity().GetId()) + { + CF_Log.Warn("Queued identity ID %1 doesn't match actual ID %2 for player %3", m_CF_QueuedIdentityID, GetIdentity().GetId(), ToString()); + m_CF_QueuedIdentityID = GetIdentity().GetId(); + } + } + else if (!m_CF_QueuedIdentityID && s_CF_QueuedIdentityIDs.Count()) + { + array identities(); + GetDayZGame().GetPlayerIndentities(identities); + string id; + while (s_CF_QueuedIdentityIDs.Count()) + { + id = CF_DequeueIdentityId(); + if (!id) break; + //! Make sure this is not a stale ID. If it's not in the list, + //! the player didn't finish connecting (client crash, connection error etc) + foreach (PlayerIdentity identity: identities) + { + if (id == identity.GetId()) + { + m_CF_QueuedIdentityID = id; + return m_CF_QueuedIdentityID; + } + } + } } return m_CF_QueuedIdentityID; } }; -#endif From b4211d7a9f0255bfe5a73ceca13e3258a9cd938c Mon Sep 17 00:00:00 2001 From: lava76 Date: Thu, 7 Apr 2022 22:48:15 +0200 Subject: [PATCH 08/19] v5, fixed memory leak leading to CTD and storage corruption, optimization - ModStorage is now at version 5 (version 4 will be read and converted) - Moved from saving/reading all data as string to handling each data type separately (fixes memory leak in case of read errors) - Fixed unloaded mods array not being resized to correct size if read failed - Optimization: Do not save mods without data --- .../ModStorage/CF_ModStorage.c | 204 +++++++++++++++--- .../ModStorage/CF_ModStorageData.c | 54 +++++ .../CommunityFramework/Mods/ModLoader.c | 56 ++++- .../ModStorage/CF_ModStorageObject.c | 22 +- 4 files changed, 303 insertions(+), 33 deletions(-) create mode 100644 JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageData.c diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c index 0ce1d913..86e9cc48 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c @@ -6,13 +6,15 @@ */ class CF_ModStorage { - static const int VERSION = 4; + static const int VERSION = 5; static const int GAME_VERSION_FIRST_INSTALL = 116; static const int GAME_VERSION_WIPE_FILE = 129; static const int MODSTORAGE_INITIAL_IMPLEMENTATION = 2; + int m_CF_Version; + ModStructure m_Mod; int m_Version; @@ -20,9 +22,15 @@ class CF_ModStorage int m_HashA; int m_HashB; + // v4 string m_Data; string m_Value; + // v5 + ref array m_Entries; + int m_Idx; + int m_MaxIdx; + void CF_ModStorage(ModStructure mod) { m_Mod = mod; @@ -40,91 +48,151 @@ class CF_ModStorage return m_Mod; } + string GetModName() + { + if (m_Mod) + { + return m_Mod.GetName(); + } + + return "unknown<" + m_HashA + "," + m_HashB + ">"; + } + bool Read(out bool value) { - m_Data.ParseStringEx(m_Value); + if (m_CF_Version < VERSION) + { + m_Data.ParseStringEx(m_Value); - value = m_Value == "1"; + value = m_Value == "1"; + } + else + { + if (m_Idx > m_MaxIdx || m_Entries[m_Idx].ValueType() != bool) + return false; + + value = CF_ModStorageData.Cast(m_Entries[m_Idx++]).Get(); + } return true; } bool Read(out int value) { - m_Data.ParseStringEx(m_Value); + if (m_CF_Version < VERSION) + { + m_Data.ParseStringEx(m_Value); - value = m_Value.ToInt(); + value = m_Value.ToInt(); + } + else + { + if (m_Idx > m_MaxIdx || m_Entries[m_Idx].ValueType() != int) + return false; + + value = CF_ModStorageData.Cast(m_Entries[m_Idx++]).Get(); + } return true; } bool Read(out float value) { - m_Data.ParseStringEx(m_Value); + if (m_CF_Version < VERSION) + { + m_Data.ParseStringEx(m_Value); - value = m_Value.ToFloat(); + value = m_Value.ToFloat(); + } + else + { + if (m_Idx > m_MaxIdx || m_Entries[m_Idx].ValueType() != float) + return false; + + value = CF_ModStorageData.Cast(m_Entries[m_Idx++]).Get(); + } return true; } bool Read(out vector value) { - m_Data.ParseStringEx(m_Value); + if (m_CF_Version < VERSION) + { + m_Data.ParseStringEx(m_Value); - value = m_Value.ToVector(); + value = m_Value.ToVector(); + } + else + { + if (m_Idx > m_MaxIdx || m_Entries[m_Idx].ValueType() != vector) + return false; + + value = CF_ModStorageData.Cast(m_Entries[m_Idx++]).Get(); + } return true; } bool Read(out string value) { - m_Data.ParseStringEx(m_Value); + if (m_CF_Version < VERSION) + { + m_Data.ParseStringEx(m_Value); - value = m_Value; + value = m_Value; + } + else + { + if (m_Idx > m_MaxIdx || m_Entries[m_Idx].ValueType() != string) + return false; + + value = CF_ModStorageData.Cast(m_Entries[m_Idx++]).Get(); + } return true; } void Write(bool value) { - if (value) - { - m_Data += " 1"; - } - else - { - m_Data += " 0"; - } + _Insert(value); } void Write(int value) { - m_Data += " " + value.ToString(); + _Insert(value); } void Write(float value) { - m_Data += " " + value.ToString(); + _Insert(value); } void Write(vector value) { - m_Data += " \"" + value.ToString(false) + "\""; + _Insert(value); } void Write(string value) { - m_Data += " \"" + value + "\""; + _Insert(value); } void _CopyStreamTo(Serializer ctx) { + int cf_version = m_CF_Version; string data; - if (m_Data.Length() > 0) + + if (cf_version < VERSION) { - data = m_Data.Substring(1, m_Data.Length() - 1); + if (m_Data.Length() > 0) + { + data = m_Data.Substring(1, m_Data.Length() - 1); + } } + auto tmp = m_Entries; + // force resetting early so we can write the latest version _ResetStream(); @@ -133,17 +201,71 @@ class CF_ModStorage ctx.Write(m_Version); - ctx.Write(data); + if (cf_version < VERSION) + { + ctx.Write(data); + return; + } + + ctx.Write(tmp.Count()); + foreach (auto entry: tmp) + { + switch (entry.ValueType()) + { + case bool: + CF_ModStorageData entryBool = CF_ModStorageData.Cast(entry); + ctx.Write(CF_ModStorageDataType.BOOL); + ctx.Write(entryBool.Get()); + break; + case int: + CF_ModStorageData entryInt = CF_ModStorageData.Cast(entry); + ctx.Write(CF_ModStorageDataType.INT); + ctx.Write(entryInt.Get()); + break; + case float: + CF_ModStorageData entryFloat = CF_ModStorageData.Cast(entry); + ctx.Write(CF_ModStorageDataType.FLOAT); + ctx.Write(entryFloat.Get()); + break; + case vector: + CF_ModStorageData entryVector = CF_ModStorageData.Cast(entry); + ctx.Write(CF_ModStorageDataType.VECTOR); + vector v = entryVector.Get(); + ctx.Write(v[0]); + ctx.Write(v[1]); + ctx.Write(v[2]); + break; + case string: + CF_ModStorageData entryString = CF_ModStorageData.Cast(entry); + ctx.Write(CF_ModStorageDataType.STRING); + ctx.Write(entryString.Get()); + break; + default: + CF_Log.Error("Failed to write unknown data type %1 for mod %2", entry.Type().ToString(), GetModName()); + } + } } // Read and Write functions can't be called, so we can't reset the stream void _ResetStream() { + m_Idx = 0; + if (!m_Mod) { + if (!m_Entries) + { + m_Entries = new array(); + m_MaxIdx = -1; + } return; } + m_CF_Version = VERSION; + + m_Entries = new array(); + m_MaxIdx = -1; + m_Data = string.Empty; m_HashA = m_Mod.m_CF_HashA; @@ -151,4 +273,34 @@ class CF_ModStorage m_Version = m_Mod.GetStorageVersion(); } + + void _Insert(bool b) + { + m_Entries.Insert(new CF_ModStorageData(b)); + m_MaxIdx++; + } + + void _Insert(int i) + { + m_Entries.Insert(new CF_ModStorageData(i)); + m_MaxIdx++; + } + + void _Insert(float f) + { + m_Entries.Insert(new CF_ModStorageData(f)); + m_MaxIdx++; + } + + void _Insert(vector v) + { + m_Entries.Insert(new CF_ModStorageData(v)); + m_MaxIdx++; + } + + void _Insert(string s) + { + m_Entries.Insert(new CF_ModStorageData(s)); + m_MaxIdx++; + } }; diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageData.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageData.c new file mode 100644 index 00000000..52340cb0 --- /dev/null +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorageData.c @@ -0,0 +1,54 @@ +enum CF_ModStorageDataType +{ + INVALID = -1, + BOOL, + INT, + FLOAT, + VECTOR, + STRING + + //! TODO + //ARRAY_BOOL, + //ARRAY_INT, + //ARRAY_FLOAT, + //ARRAY_VECTOR, + //ARRAY_STRING +}; + +class CF_ModStorageDataBase +{ + typename ValueType() + { + return typename; + } + + string ValueString() + { + return ""; + } +}; + +class CF_ModStorageData: CF_ModStorageDataBase +{ + T m_Value; + + void CF_ModStorageData(T value) + { + m_Value = value; + } + + T Get() + { + return m_Value; + } + + override typename ValueType() + { + return T; + } + + override string ValueString() + { + return string.ToString(m_Value); + } +}; diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c index 82a3b18e..878fda31 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c @@ -70,14 +70,66 @@ modded class ModLoader storage.m_HashB = hashB; } + storage.m_CF_Version = version; + if (!ctx.Read(storage.m_Version)) return false; - if (!ctx.Read(storage.m_Data)) return false; + bool hasData; + if (version < CF_ModStorage.VERSION) + { + if (!ctx.Read(storage.m_Data)) return false; + hasData = storage.m_Data.Length() > 0; + } + else + { + int entries; + if (!ctx.Read(entries)) return false; + hasData = entries > 0; + while (entries > 0) + { + int type = -1; + if (!ctx.Read(type)) return false; + switch (type) + { + case CF_ModStorageDataType.BOOL: + bool b = false; + if (!ctx.Read(b)) return false; + storage._Insert(b); + break; + case CF_ModStorageDataType.INT: + int i = 0; + if (!ctx.Read(i)) return false; + storage._Insert(i); + break; + case CF_ModStorageDataType.FLOAT: + float f = 0; + if (!ctx.Read(f)) return false; + storage._Insert(f); + break; + case CF_ModStorageDataType.VECTOR: + int x = 0, y = 0, z = 0; + if (!ctx.Read(x)) return false; + if (!ctx.Read(y)) return false; + if (!ctx.Read(z)) return false; + storage._Insert(Vector(x, y, z)); + break; + case CF_ModStorageDataType.STRING: + string s = ""; + if (!ctx.Read(s)) return false; + storage._Insert(s); + break; + default: + CF_Log.Error("Failed to read unknown data type %1 for mod %2", type.ToString(), storage.GetModName()); + return false; + } + entries--; + } + } if (exists) { loadedMods.Insert(storage.GetMod().GetName(), storage); } - else + else if (hasData) { unloadedMods[stackIndex] = storage; stackIndex++; diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c index 1127a34c..969f14b6 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c @@ -58,12 +58,21 @@ class CF_ModStorageObject : CF_ModStorageBase m_Entity.CF_OnStoreSave(ModLoader.s_CF_ModStorageMap); - ctx.Write(ModLoader.s_CF_ModStorages.Count() + m_UnloadedMods.Count()); - + int modsWithDataCount; foreach (auto mod2 : ModLoader.s_CF_ModStorages) { - // also resets the stream for next 'OnStoreSave' - mod2._CopyStreamTo(ctx); + if (mod2.m_MaxIdx > -1) modsWithDataCount++; + } + + ctx.Write(modsWithDataCount + m_UnloadedMods.Count()); + + if (modsWithDataCount) + { + foreach (auto mod3 : ModLoader.s_CF_ModStorages) + { + // also resets the stream for next 'OnStoreSave' + if (mod3.m_MaxIdx > -1) mod3._CopyStreamTo(ctx); + } } foreach (auto unloadedMod : m_UnloadedMods) @@ -131,12 +140,15 @@ class CF_ModStorageObject : CF_ModStorageBase if (!ModLoader._CF_ReadModStorage(ctx, cf_version, m_UnloadedMods, unloadedModsRead, loadedMods)) { CF_Log.Error("Failed to read modstorage for entity Type=%1, Position=%2", m_Entity.GetType(), m_Entity.GetPosition().ToString()); - return false; + break; } } m_UnloadedMods.Resize(unloadedModsRead); + if (modsRead < numMods) + return false; + m_Entity.CF_OnStoreLoad(loadedMods); // Reset the stream for 'OnStoreSave' From 3f0023a948b17038e6f6729bbe580542e154db58 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 8 Apr 2022 20:28:47 +0200 Subject: [PATCH 09/19] Ignore ModStorage module on client (main menu) --- .../CommunityFramework/ModStorage/CF_ModStorageModule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c index be577e59..e33affb5 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -25,6 +25,9 @@ class CF_ModStorageModule : CF_ModuleWorld */ void AddEntity(EntityAI entity) { + if (!g_Game.IsDedicatedServer()) + return; + Load(); PlayerBase player = PlayerBase.Cast(entity.GetHierarchyRootPlayer()); @@ -41,6 +44,9 @@ class CF_ModStorageModule : CF_ModuleWorld */ bool IsEntity(EntityAI entity) { + if (!g_Game.IsDedicatedServer()) + return true; + Load(); PlayerBase player = PlayerBase.Cast(entity.GetHierarchyRootPlayer()); From b6dce8c2ac24e7ad966542be3b564ca0c755211b Mon Sep 17 00:00:00 2001 From: lava76 Date: Sat, 9 Apr 2022 21:04:17 +0200 Subject: [PATCH 10/19] Fixed wrong data types being read for vector components --- JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c index 878fda31..0d9beb27 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c @@ -106,7 +106,7 @@ modded class ModLoader storage._Insert(f); break; case CF_ModStorageDataType.VECTOR: - int x = 0, y = 0, z = 0; + float x = 0, y = 0, z = 0; if (!ctx.Read(x)) return false; if (!ctx.Read(y)) return false; if (!ctx.Read(z)) return false; From 05733f19c52f7d504a370fbde5de139365056e31 Mon Sep 17 00:00:00 2001 From: lava76 Date: Sat, 9 Apr 2022 21:04:57 +0200 Subject: [PATCH 11/19] Disable ModStorage on client completely --- JM/CF/Defines/CFDefines.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/JM/CF/Defines/CFDefines.c b/JM/CF/Defines/CFDefines.c index 41c3c39a..07af500a 100644 --- a/JM/CF/Defines/CFDefines.c +++ b/JM/CF/Defines/CFDefines.c @@ -7,7 +7,9 @@ #define CF_GHOSTICONS +#ifdef SERVER #define CF_MODSTORAGE +#endif //#define CF_MODSTORAGE_TEST //#define CF_MODSTORAGE_TRACE //#define CF_MODSTORAGE_MODULE_DISABLE From d40996099246d673fe8012bc5db3331a6bbe37fc Mon Sep 17 00:00:00 2001 From: lava76 Date: Sat, 9 Apr 2022 21:24:53 +0200 Subject: [PATCH 12/19] Revert "Disable ModStorage on client completely" This reverts commit 05733f19c52f7d504a370fbde5de139365056e31. --- JM/CF/Defines/CFDefines.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/JM/CF/Defines/CFDefines.c b/JM/CF/Defines/CFDefines.c index 07af500a..41c3c39a 100644 --- a/JM/CF/Defines/CFDefines.c +++ b/JM/CF/Defines/CFDefines.c @@ -7,9 +7,7 @@ #define CF_GHOSTICONS -#ifdef SERVER #define CF_MODSTORAGE -#endif //#define CF_MODSTORAGE_TEST //#define CF_MODSTORAGE_TRACE //#define CF_MODSTORAGE_MODULE_DISABLE From e6485fe8d79e6c005688a28c89943a81cb751a57 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 22 Apr 2022 14:02:50 +0200 Subject: [PATCH 13/19] Bail on old ModStorage data to avoid possible CTD if corrupted storage --- JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c index 0d9beb27..a933ecef 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/Mods/ModLoader.c @@ -76,8 +76,11 @@ modded class ModLoader bool hasData; if (version < CF_ModStorage.VERSION) { - if (!ctx.Read(storage.m_Data)) return false; - hasData = storage.m_Data.Length() > 0; + //! Bail on old ModStorage data to avoid possible CTD if corrupted storage + int numberOfBytes; + ctx.Read(numberOfBytes); + CF_Log.Error("Reading deprecated modstorage v" + version + " is not supported, discarding " + numberOfBytes + " bytes for mod " + storage.GetModName()); + return false; } else { From 3d9ffa27e9b01c3e24a0cf9df5f2370cd8ff79e2 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 12 Jul 2024 13:20:57 +0200 Subject: [PATCH 14/19] Defines moved to config.cpp --- JM/CF/Defines/CFDefines.c | 17 ----------------- JM/CF/Scripts/config.cpp | 5 +++-- 2 files changed, 3 insertions(+), 19 deletions(-) delete mode 100644 JM/CF/Defines/CFDefines.c diff --git a/JM/CF/Defines/CFDefines.c b/JM/CF/Defines/CFDefines.c deleted file mode 100644 index 41c3c39a..00000000 --- a/JM/CF/Defines/CFDefines.c +++ /dev/null @@ -1,17 +0,0 @@ -#define CF_MODULE_CONFIG - -#define CF_EXPRESSION -//#define CF_EXPRESSION_TEST - -//#define CF_TRACE_ENABLED - -#define CF_GHOSTICONS - -#define CF_MODSTORAGE -//#define CF_MODSTORAGE_TEST -//#define CF_MODSTORAGE_TRACE -//#define CF_MODSTORAGE_MODULE_DISABLE - -#define CF_SURFACES - -#define CF_MODULES diff --git a/JM/CF/Scripts/config.cpp b/JM/CF/Scripts/config.cpp index 89e8fa24..fdc6cc40 100644 --- a/JM/CF/Scripts/config.cpp +++ b/JM/CF/Scripts/config.cpp @@ -39,7 +39,7 @@ class CfgMods //"CF_TRACE_ENABLED", "CF_TRACE_STACK_NAME_ASSUMPTION_FIX", "CF_GHOSTICONS", - //"CF_MODSTORAGE", + "CF_MODSTORAGE", //"CF_MODSTORAGE_TEST", //"CF_MODSTORAGE_TRACE", "CF_MODSTORAGE_DISABLE", @@ -47,7 +47,8 @@ class CfgMods "CF_SURFACES", "CF_MODULES", "CF_REF_FIX", - "CF_BUGFIX_REF" // Same as CF_REF_FIX but for mods that already anticipated a different name + "CF_BUGFIX_REF", // Same as CF_REF_FIX but for mods that already anticipated a different name + "CF_BUGFIX_XML" }; dependencies[] = { "Core", "Game", "World", "Mission" }; From 778768a3a7e5d7fa56c79722b428f5a9ed722f94 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 12 Jul 2024 13:21:24 +0200 Subject: [PATCH 15/19] Sync with origin --- .../CommunityFramework/Mission/MissionServer.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c b/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c index 35be1b81..72cdd449 100644 --- a/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c +++ b/JM/CF/Scripts/5_Mission/CommunityFramework/Mission/MissionServer.c @@ -121,7 +121,9 @@ modded class MissionServer auto args = new CF_EventNewPlayerArgs(player, identity, pos, ctx); CF_ModuleWorldManager.OnClientNew(this, args); - player = args.Player; + + //TODO: allow the args to override these 'out' variables again, 'CF_ModuleWorldManager.OnClientNew' deletes 'args' before this can be used + //player = args.Player; return player; } @@ -137,17 +139,17 @@ modded class MissionServer CF_ModuleWorldManager.OnClientPrepare(this, args); - //identity = args.Identity; - useDB = args.UseDatabase; - pos = args.Position; - yaw = args.Yaw; - preloadTimeout = args.PreloadTimeout; + //TODO: allow the args to override these 'out' variables again, 'CF_ModuleWorldManager.OnClientPrepare' deletes 'args' before this can be used + //useDB = args.UseDatabase; + //pos = args.Position; + //yaw = args.Yaw; + //preloadTimeout = args.PreloadTimeout; #ifdef CF_MODSTORAGE PlayerBase.CF_QueueIdentityId(identity.GetId()); #endif - // must call before vanilla + // must call module code before vanilla super.OnClientPrepareEvent(identity, useDB, pos, yaw, preloadTimeout); } }; From 292236a7beddb7caf6f3529d732cd88b66acc2b9 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 23 Aug 2024 00:24:03 +0200 Subject: [PATCH 16/19] Removed MS disable defines --- .../CommunityFramework/ModStorage/CF_ModStorageModule.c | 2 -- .../CommunityFramework/ModStorage/CF_ModStorageObject.c | 4 ---- JM/CF/Scripts/config.cpp | 2 -- 3 files changed, 8 deletions(-) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c index e33affb5..83ba8a55 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageModule.c @@ -3,9 +3,7 @@ * * @brief Does not support unloading CF from the mods. Once loaded it can't be removed */ -#ifndef CF_MODSTORAGE_MODULE_DISABLE [CF_RegisterModule(CF_ModStorageModule)] -#endif class CF_ModStorageModule : CF_ModuleWorld { static const string m_FileName = "modstorageplayers.bin"; diff --git a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c index 1aa6dc5b..1deb5101 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/ModStorage/CF_ModStorageObject.c @@ -39,10 +39,8 @@ class CF_ModStorageObject : CF_ModStorageBase if (!m_HasModStorage) { -#ifndef CF_MODSTORAGE_MODULE_DISABLE // Add the entity to the file so on next load the game knows that it can read the modstorage for the entity m_Module.AddEntity(m_Entity); -#endif m_HasModStorage = true; } @@ -97,7 +95,6 @@ class CF_ModStorageObject : CF_ModStorageBase return true; } -#ifndef CF_MODSTORAGE_MODULE_DISABLE // If the version is less than the wipe file, the entity will be added automatically in 'OnStoreSave' if (version >= CF_ModStorage.GAME_VERSION_WIPE_FILE) { @@ -110,7 +107,6 @@ class CF_ModStorageObject : CF_ModStorageBase return true; } } -#endif int cf_version; if (!ctx.Read(cf_version)) diff --git a/JM/CF/Scripts/config.cpp b/JM/CF/Scripts/config.cpp index fdc6cc40..a113a9fb 100644 --- a/JM/CF/Scripts/config.cpp +++ b/JM/CF/Scripts/config.cpp @@ -42,8 +42,6 @@ class CfgMods "CF_MODSTORAGE", //"CF_MODSTORAGE_TEST", //"CF_MODSTORAGE_TRACE", - "CF_MODSTORAGE_DISABLE", - "CF_MODSTORAGE_MODULE_DISABLE", "CF_SURFACES", "CF_MODULES", "CF_REF_FIX", From 4b335b38067ce9a066bce8e9385d27f7c8f151c3 Mon Sep 17 00:00:00 2001 From: lava76 Date: Fri, 27 Sep 2024 11:36:33 +0200 Subject: [PATCH 17/19] Added BoatScript CF_ModStorage support --- .../CommunityFramework/Entities/BoatScript.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c new file mode 100644 index 00000000..f95be083 --- /dev/null +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c @@ -0,0 +1,40 @@ +#ifndef DAYZ_1_25 +modded class BoatScript +{ +#ifdef CF_MODSTORAGE + autoptr CF_ModStorageBase m_CF_ModStorage = new CF_ModStorageObject(this); + + override void OnStoreSave(ParamsWriteContext ctx) + { + super.OnStoreSave(ctx); + + m_CF_ModStorage.OnStoreSave(ctx); + } + + override bool OnStoreLoad(ParamsReadContext ctx, int version) + { + if (!super.OnStoreLoad(ctx, version)) + { + return false; + } + + return m_CF_ModStorage.OnStoreLoad(ctx, version); + } +#endif + + /** + * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreSave + */ + void CF_OnStoreSave(CF_ModStorageMap storage) + { + } + + /** + * @brief Refer to CF/ModStorage implementation of ItemBase::CF_OnStoreLoad + */ + bool CF_OnStoreLoad(CF_ModStorageMap storage) + { + return true; + } +}; +#endif From 1b4adbd52b7a86fb51565cabc057ebebb48cc84d Mon Sep 17 00:00:00 2001 From: lava76 Date: Sat, 4 Jan 2025 22:06:43 +0100 Subject: [PATCH 18/19] Deal with BoatScript CF data not being present --- .../4_World/CommunityFramework/Entities/BoatScript.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c index f95be083..75b297e3 100644 --- a/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c +++ b/JM/CF/Scripts/4_World/CommunityFramework/Entities/BoatScript.c @@ -1,4 +1,3 @@ -#ifndef DAYZ_1_25 modded class BoatScript { #ifdef CF_MODSTORAGE @@ -18,6 +17,11 @@ modded class BoatScript return false; } + //! Since CF wasn't updated when DayZ 1.26 released, BoatScript storage data does not carry + //! CF data *at all* if the entity isn't tracked, so we have to return early + if (!CF_Modules.Get().IsEntity(this)) + return true; + return m_CF_ModStorage.OnStoreLoad(ctx, version); } #endif @@ -37,4 +41,3 @@ modded class BoatScript return true; } }; -#endif From 71f1907d6a7ad34390d2ceec557b9e4f654dea15 Mon Sep 17 00:00:00 2001 From: lava76 Date: Thu, 16 Jan 2025 16:51:41 +0100 Subject: [PATCH 19/19] Bumped storage version to 141 (DayZ 1.27) --- .../3_Game/CommunityFramework/ModStorage/CF_ModStorage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c index 86e9cc48..aa0778c6 100644 --- a/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c +++ b/JM/CF/Scripts/3_Game/CommunityFramework/ModStorage/CF_ModStorage.c @@ -9,7 +9,7 @@ class CF_ModStorage static const int VERSION = 5; static const int GAME_VERSION_FIRST_INSTALL = 116; - static const int GAME_VERSION_WIPE_FILE = 129; + static const int GAME_VERSION_WIPE_FILE = 141; //! DayZ 1.27 GAME_STORAGE_VERSION static const int MODSTORAGE_INITIAL_IMPLEMENTATION = 2;