[From Galileo's Geist: FactionManager save/load: Questions/Suggestions
Posted: Sun Nov 12, 2023 4:09 pm
[Re-posting Galileo's Geist's forum post while we work out an access issue.]
Hi all! Just got Love/Hate after much thought, and really like the tool, but running into an issue with loading saved FactionManager data. Perhaps a misunderstanding, perhaps not. Anyway, here's my big question/suggestion, with some background first.
Here is essentially what I'm doing:
I have my own save system already built which I'm adding onto simply by adding JSON components. I have the following test save data within that JSON:
Some of the Faction Members represented there were created at runtime thusly:
On top of a custom, preexisting FactionDatabase asset that had:
And the data string was saved with:
I then changed my runtime code to create a different, smaller set of Faction Members and their Factions. So I run the game, it loads the first two Factions from the FactionDatabase, then adds these three on top:
At this point I try my loading system. Whether or not I clear FactionManager data/Factions first runs into this same issue, so I'll represent it in the case of not doing any data clearing or Faction deletion before the 'Load Game' step. When I execute the following (data string hardcoded for clarity)...
My FactionManager shows the following Faction list in the inspector:
And for reference, here is the FactionManager#DeserializeFromString() method in the source code (Version 1.10.40.1):
As you can see:
Hi all! Just got Love/Hate after much thought, and really like the tool, but running into an issue with loading saved FactionManager data. Perhaps a misunderstanding, perhaps not. Anyway, here's my big question/suggestion, with some background first.
Here is essentially what I'm doing:
I have my own save system already built which I'm adding onto simply by adding JSON components. I have the following test save data within that JSON:
Code: Select all
"factionManagerData": "7,0,Player,0,0,0,0,0,0,0,2,STAND-IN,0,0,0,0,0,0,0,3,Hu_1 (Wanderer),0,0,0,0,0,0,0,4,Hu_2 (to-ny),0,0,0,0,0,0,0,5,Hu_3 (fredyryk),0,0,0,0,0,0,0,6,Hu_4 (sammy sam),0,0,0,0,0,0,0,7,Hu_5 (g'iles),0,0,0,0,0,0,0,"
Code: Select all
int newFactionId = FactionManager.instance.factionDatabase.CreateNewFaction(
newHu.TitleTag,
$"Faction for: {newHu.TitleTag}"
);
And the data string was saved with:
Code: Select all
string factionManagerData = FactionManager.instance.SerializeToString();
At this point I try my loading system. Whether or not I clear FactionManager data/Factions first runs into this same issue, so I'll represent it in the case of not doing any data clearing or Faction deletion before the 'Load Game' step. When I execute the following (data string hardcoded for clarity)...
Code: Select all
string factionManagerData = "7,0,Player,0,0,0,0,0,0,0,2,STAND-IN,0,0,0,0,0,0,0,3,Hu_1 (Wanderer),0,0,0,0,0,0,0,4,Hu_2 (to-ny),0,0,0,0,0,0,0,5,Hu_3 (fredyryk),0,0,0,0,0,0,0,6,Hu_4 (sammy sam),0,0,0,0,0,0,0,7,Hu_5 (g'iles),0,0,0,0,0,0,0,";
FactionManager.instance.DeserializeFromString(factionManagerData)
And for reference, here is the FactionManager#DeserializeFromString() method in the source code (Version 1.10.40.1):
Spoiler
Code: Select all
public void DeserializeFromString(string s)
{
if (string.IsOrEmpty(s) || factionDatabase == ) return;
var traitCount = factionDatabase.relationshipTraitDefinitions.Length;
var data = new Queue<string>(s.Split(','));
if (data.Count < 1) return;
// Get faction count:
var factionCount = SafeConvert.ToInt(data.Dequeue());
for (int f = 0; f < Mathf.Min(factionCount, factionDatabase.factions.Length); f++)
{
var faction = factionDatabase.factions[f];
// Get faction ID and name:
faction.id = SafeConvert.ToInt(data.Dequeue());
faction.name = SafeConvert.FromSerializedElement(data.Dequeue());
// Get faction personality trait values:
for (int p = 0; p < faction.traits.Length; p++)
{
faction.traits[p] = SafeConvert.ToFloat(data.Dequeue());
}
// Get faction parents:
var parents = new List<int>();
var parentCount = SafeConvert.ToInt(data.Dequeue());
for (int p = 0; p < parentCount; p++)
{
parents.Add(SafeConvert.ToInt(data.Dequeue()));
}
faction.parents = parents.ToArray();
// Release faction's old relationships:
for (int r = 0; r < faction.relationships.Count; r++)
{
var relationship = faction.relationships[r];
Relationship.Release(relationship);
}
faction.relationships.Clear();
// Get faction's relationships:
var relationshipCount = SafeConvert.ToInt(data.Dequeue());
for (int r = 0; r < relationshipCount; r++)
{
var id = SafeConvert.ToInt(data.Dequeue());
var inheritable = (SafeConvert.ToInt(data.Dequeue()) == 1);
var traits = new float[traitCount];
for (int i = 0; i < traitCount; i++)
{
traits[i] = SafeConvert.ToFloat(data.Dequeue());
}
var relationship = Relationship.GetNew(id, inheritable, traits);
faction.relationships.Add(relationship);
}
}
}
- FactionManager instance serialization and deserialization does not include the Faction#description field. This not only removes the information while serializing but allows for misalignment as it does not clear existing 'description' fields during deserialization. I assume this is just a small oversight, and should either be fully supported or fully ignored.
- It appears that FactionManager#DeserializeFromString() will only load individual Faction data into existing Faction objects in the manager's list, and so it capped by that count. It's possible this is intentional, but I am surprised by this behavior. To me, this means the De/Serialization features effectively do not support runtime Faction generation and deletion. I could write workarounds for this, but that gives me concern, and again, I don't want to go down that path if it represents a deeper misunderstanding on my part that will only cause me more friction in the future, especially as I'm still grasping the finer details of the edit-vs-runtime relationship between FactionManager / FactionManager#FactionDatabase / FactionDabase.asset / FactionManager#factions. Anyway, my gut says there should be a more confident way to save and load the entirety of the FactionManager and its memory-representation of the FactionDatabase.