1. Every time I get try and save the player data with more than one quest... I get this...

    Code:
    (ArgumentException: An element with the same key already exists in the dictionary.)
    Now I understand that this means that the program is trying to insert another item with the same key... BUT my question is... I am trying to obtain this right here...

    Code:
    {
      "players": {
        "USERID": {
          "QUEST1": "0",
          "QUEST2": "0"
        }
      }
    }
    It loads just fine with manually entering in more than 1 quest... But it will not, for the life of me... SAVE more than 1 quest under the same USERID... which is a dictionary... So my question to you is... How can I solve this?

    The Actual CODE:

    Code:
            public void SavePlayerQuestData()
            {
                var data = Interface.GetMod().DataFileSystem.GetDatafile("Quests_PlayerData");
                var qDataTmp = new Dictionary<string, object>();
                for (int i = 0; i < active.Count; i++)
                {
                    var qData = new Dictionary<string, string>();
                    string userID = active[i].Key;
                    string QuestName = active[i].Value.qName;
                    int Progress = GetGatheredAmount(active[i].Value, BasePlayer.FindByID(Convert.ToUInt64(userID)));
                    qData.Add(QuestName, Progress.ToString());
                    //Log(userID + " | " + QuestName + " | " + Progress.ToString());
                    qDataTmp.Add(userID, qData);
                }
                data["players"] = qDataTmp;
                Interface.GetMod().DataFileSystem.SaveDatafile("Quests_PlayerData");
            }
     
  2. Wulf

    Wulf Community Admin

    It looks like your code is trying to add an entry with the same USERID rather than add to the existing one. Someone with more C# experience would need to point you in the right direction.
     
  3. Sad face. I mean my main problem is... Dictionaries do not let you have multiple values with the same key... Which honestly, is retarded as hell... So I ended up having to change a few lines of my code to support something different but similar.

    DictionaryONE
    Code:
      "players": { }
    DictionaryTWO
    Code:
      "players": {
        "USERID": { }
       }
    Values under DictionaryTWO
    Code:
          "gather wood": "0",
          "gather sulfur ore": "0"
     
  4. Calytic

    Calytic Community Admin Community Mod

    This is fundamental to any keyed data structures. You will have to nest your data as your key-value pair combinations become more complex. Both using and avoiding nested data structures will have repercussions throughout the rest of your code. Using them, with Oxide atleast, requires a significant amount of type-casting to/from Dictionary<string, object>(see DynamicConfigFile). In contrast, avoiding nested data structures will increase the complexity of your code as the relationships will be expressed procedurally rather than implicitly through configuration.

    Generally you want to use more abstraction (and consequently use nested data structures) because its conceptually simpler and requires less code in the long run.
     
  5. Why did you use dictionaries? You can just create new class and save it with json. For example (from my pets):

    Code:
            // Create new class with structure to save (public = will be saved by json, private\internal... = will not be saved)
            public class PetInfo
            {
                public uint prefabID;
                public uint parentNPC;
                public float x, y, z;
                public byte[] inventory;
                internal bool NeedToSpawn;            public PetInfo()
                {
                    NeedToSpawn = true;
                }            public PetInfo(NpcAI pet)
                {
                    x = pet.transform.position.x;
                    y = pet.transform.position.y;
                    z = pet.transform.position.z;
                    prefabID = pet.Base.prefabID;
                    parentNPC = pet.Base.net.ID;
                    inventory = pet.inventory.Save().ToProtoBytes();
                    NeedToSpawn = false;
                }
            }
    Code:
                // Your data to save
                Dictionary<string, PetInfo> SaveNpcList = ...;            // Saving into file
                Interface.Oxide.DataFileSystem.WriteObject<Dictionary<string, PetInfo>>("Pets", SaveNpcList);            // Reading from file
                SaveNpcList = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, PetInfo>>("Pets");
     
  6. It's way late right now. But I will look into that... I'm relatively new to writing plugins. :p And C# of this length. :) So, curious... What is the string?

    Interface.Oxide.DataFileSystem.WriteObject<Dictionary<string, PetInfo>>("Pets", SaveNpcList);

    Is "Pets" the string that is stored into Dictionary? Or is that the text that saved into the file? or am I just completely retarded? :p
     
  7. It's just filename)

    Interface.Oxide.DataFileSystem.WriteObject<Dictionary<string, PetInfo>>("Pets", SaveNpcList);
    It's will save SaveNpcList in 'Pets' datafile with Dictionary<string, PetInfo> format ([string] = {...})
     
  8. Thanks a bunch man. Looks like it is working 100%... Going to release it and see what the players can come up with!