Decompiled source of CSV Patcher v1.0.1

Plugins/CSVPatcherPlugin.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Bootstrap;
using HBS.Data;
using HBS.Text;
using HarmonyLib;
using Necro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AbraxisToolSet-Bep")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AbraxisToolSet-Bep")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c88d5f3c-0a16-47c9-891f-51c99c520d90")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CSVPatcherPlugin;

public static class CSVUtil
{
	public static string GetPrefix(string value)
	{
		string result = "";
		int num = 0;
		for (int i = 0; i < value.Length && value[i] != '_'; i++)
		{
			num++;
		}
		if (value.Length == num)
		{
			return result;
		}
		return value.Substring(0, num);
	}

	public static string GetWithoutPrefix(string value)
	{
		int num = 0;
		for (int i = 0; i < value.Length && value[i] != '_'; i++)
		{
			num++;
		}
		if (value.Length == num)
		{
			return value;
		}
		num++;
		return value.Substring(num, value.Length - num);
	}
}
[BepInPlugin("deadjak.necropolis.csvpatcher", "CSV Patcher", "1.0.1")]
public class CSVPatcherPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(DataLoader), "VerifyIntegrity")]
	public class DataLoaderPatch
	{
		private static bool Prefix(byte[] key, string path)
		{
			return false;
		}
	}

	[HarmonyPatch(typeof(MultiplayerTuningData), "Set")]
	public class MultiplayerTuningDataPatch
	{
		public static bool Prefix(MultiplayerTuningData __instance)
		{
			Traverse val = Traverse.Create((object)__instance);
			__instance.ActorAttackAddend = val.Method("GetCouchScaledVariableInt", new object[1] { "Multiplayer.ActorAttackAddend" }).GetValue<int>();
			__instance.NonActorAttackAddend = val.Method("GetCouchScaledVariableInt", new object[1] { "Multiplayer.NonActorAttackAddend" }).GetValue<int>();
			__instance.ActorDefendTraitAddend = val.Method("GetCouchScaledVariableInt", new object[1] { "Multiplayer.ActorDefendTraitAddend" }).GetValue<int>();
			__instance.PvPAttackAddend = val.Method("GetVariableInt", new object[1] { "Multiplayer.PvPAttackAddend" }).GetValue<int>();
			__instance.DanceCard = val.Method("GetCouchScaledVariableInt", new object[1] { "Multiplayer.DanceCard" }).GetValue<int>();
			__instance.stats[Stats.HealthRate] = val.Method("GetCouchScaledVariableFloat", new object[1] { "Multiplayer.BugFix" }).GetValue<float>();
			__instance.stats[Stats.PoisonRate] = val.Method("GetCouchScaledVariableFloat", new object[1] { "Multiplayer.PoisonRate" }).GetValue<float>();
			__instance.GroupCurrencyPickup = val.Method("GetVariableFloat", new object[1] { "Multiplayer.GroupCurrencyPickup" }).GetValue<float>();
			__instance.GroupCraftingPickup = val.Method("GetVariableFloat", new object[1] { "Multiplayer.GroupCraftingPickup" }).GetValue<float>();
			__instance.ResurrectHealth = val.Method("GetVariableFloat", new object[1] { "Multiplayer.ResurrectHealth" }).GetValue<float>();
			__instance.ResurrectExhaustion = val.Method("GetVariableFloat", new object[1] { "Multiplayer.ResurrectExhaustion" }).GetValue<float>();
			__instance.MaxResurrectionSickness = val.Method("GetVariableInt", new object[1] { "Multiplayer.MaxResurrectionSickness" }).GetValue<int>();
			__instance.ResurrectionSicknessHealthModifier = val.Method("GetVariableFloat", new object[1] { "Multiplayer.ResurrectionSicknessHealthModifier" }).GetValue<float>();
			__instance.ResurrectionSicknessExhaustionModifier = val.Method("GetVariableFloat", new object[1] { "Multiplayer.ResurrectionSicknessExhaustionModifier" }).GetValue<float>();
			__instance.GroupCraftingPickup = Mathf.Clamp(__instance.GroupCraftingPickup, 0f, 1f);
			__instance.GroupCurrencyPickup = Mathf.Clamp(__instance.GroupCurrencyPickup, 0f, 1f);
			__instance.ResurrectHealth = Mathf.Clamp(__instance.ResurrectHealth, 0f, 1f);
			__instance.ResurrectExhaustion = Mathf.Clamp(__instance.ResurrectExhaustion, 0f, 1f);
			__instance.ResurrectionSicknessHealthModifier = Mathf.Clamp(__instance.ResurrectionSicknessHealthModifier, 0f, 1f);
			__instance.ResurrectionSicknessExhaustionModifier = Mathf.Clamp(__instance.ResurrectionSicknessExhaustionModifier, 0f, 1f);
			if (__instance.ResurrectHealth == 0f)
			{
				__instance.ResurrectHealth = 0.5f;
			}
			return false;
		}
	}

	private string StockFilesPath = Application.streamingAssetsPath + "/data/TUNING/";

	private string backupFolder = Application.streamingAssetsPath + "/BACKUP_Data";

	public static string CSVPath;

	private void OnApplicationQuit()
	{
		CSVPatcher.RestoreDefaultCSVs();
	}

	private void Awake()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		PluginInfo obj = Chainloader.PluginInfos[((BaseUnityPlugin)this).Info.Metadata.GUID];
		bool flag = Directory.Exists(backupFolder);
		string directoryName = Path.GetDirectoryName(obj.Location);
		Harmony val = new Harmony("CSV Patcher");
		CSVPath = Directory.GetParent(Directory.GetParent(obj.Location).FullName).FullName;
		val.PatchAll();
		if (!flag)
		{
			File.Copy(directoryName + "/Items.csv", StockFilesPath + "Items.csv", overwrite: true);
			File.Copy(directoryName + "/Game Actions.csv", StockFilesPath + "Game Actions.csv", overwrite: true);
			File.Copy(directoryName + "/Items.csv.sig", StockFilesPath + "Items.csv.sig", overwrite: true);
			File.Copy(directoryName + "/Game Actions.csv.sig", StockFilesPath + "Game Actions.csv.sig", overwrite: true);
			CSVPatcher.PatchCSVs();
		}
		else
		{
			CSVPatcher.PatchCSVs();
		}
	}
}
public class CSVPatcher
{
	public static string backupPath = "/BACKUP_data/";

	public const string MOD_DATA_PATH = "/BepInEx/plugins/";

	public static readonly SimpleListCSV itemCSV = new SimpleListCSV();

	public static readonly SimpleListCSV creatureCSV = new SimpleListCSV();

	public static readonly SimpleListCSV gameActionsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV shopListCSV = new SimpleListCSV();

	public static readonly SimpleListCSV spawnTablesCSV = new SimpleListCSV();

	public static readonly SimpleListCSV colorPalettsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV BHObjectives = new SimpleListCSV();

	public static readonly SimpleListCSV animActionsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV AIRegionsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV AIDispositionCSV = new SimpleListCSV();

	public static readonly SimpleListCSV creditsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV rigsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV stringsCSV = new SimpleListCSV();

	public static readonly SimpleListCSV worldLocationsCSV = new SimpleListCSV();

	public static readonly MultiElementListCSV variablesCSV = new MultiElementListCSV();

	public static readonly MultiElementListCSV lootTableCSV = new MultiElementListCSV();

	public static readonly Dictionary<string, ICSVFile> csvFiles = new Dictionary<string, ICSVFile>
	{
		{ "Items", itemCSV },
		{ "Creatures", creatureCSV },
		{ "Game Actions", gameActionsCSV },
		{ "Shop List", shopListCSV },
		{ "Spawn Tables", spawnTablesCSV },
		{ "ColorPalettes", colorPalettsCSV },
		{ "BH Objectives", BHObjectives },
		{ "Anim Actions", animActionsCSV },
		{ "AI Regions", AIRegionsCSV },
		{ "AI Dispositions", AIDispositionCSV },
		{ "Credits", creditsCSV },
		{ "Rigs", rigsCSV },
		{ "Variables", variablesCSV },
		{ "Loot Tables", lootTableCSV },
		{ "Strings", stringsCSV },
		{ "World Locations", worldLocationsCSV }
	};

	public static void PatchCSVs()
	{
		string path = ResolveBackupPath(string.Empty);
		string path2 = ResolveResourcePath(string.Empty);
		if (!Directory.Exists(path))
		{
			CopyFilesRecursively(new DirectoryInfo(path2), new DirectoryInfo(path));
		}
		foreach (KeyValuePair<string, ICSVFile> csvFile in csvFiles)
		{
			if (csvFile.Key != "Strings" && csvFile.Key != "World Locations")
			{
				string path3 = $"TUNING/{csvFile.Key}.csv";
				csvFile.Value.ReadFromFile(ResolveResourcePath(path3));
			}
			else
			{
				string path4 = $"text/{csvFile.Key}.csv";
				csvFile.Value.ReadFromFile(ResolveResourcePath(path4));
			}
		}
		string cSVPath = CSVPatcherPlugin.CSVPath;
		Debug.Log((object)("Mod Path is " + cSVPath));
		string[] files = Directory.GetFiles(cSVPath, "*.csv", SearchOption.AllDirectories);
		foreach (string path5 in files)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path5);
			if (csvFiles.ContainsKey(fileNameWithoutExtension))
			{
				try
				{
					csvFiles[fileNameWithoutExtension].PatchFromFile(path5);
					Debug.Log((object)$"Patched {fileNameWithoutExtension}.csv");
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			}
		}
		foreach (KeyValuePair<string, ICSVFile> csvFile2 in csvFiles)
		{
			if (csvFile2.Key != "Strings" && csvFile2.Key != "World Locations")
			{
				string path6 = $"TUNING/{csvFile2.Key}.csv";
				csvFile2.Value.WriteToFile(ResolveResourcePath(path6));
			}
			else
			{
				string path7 = $"text/{csvFile2.Key}.csv";
				csvFile2.Value.WriteToFile(ResolveResourcePath(path7));
			}
		}
	}

	public static void RestoreDefaultCSVs()
	{
		string path = ResolveBackupPath(string.Empty);
		string path2 = ResolveResourcePath(string.Empty);
		if (Directory.Exists(path2))
		{
			Directory.Delete(path2, recursive: true);
		}
		CopyFilesRecursively(new DirectoryInfo(path), new DirectoryInfo(path2));
		if (Directory.Exists(path))
		{
			Directory.Delete(path, recursive: true);
		}
		itemCSV.Clear();
	}

	public static string ResolveBackupPath(string path)
	{
		return Application.streamingAssetsPath + backupPath + path;
	}

	public static string ResolveResourcePath(string path)
	{
		return Application.streamingAssetsPath + "/data/" + path;
	}

	public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
	{
		DirectoryInfo[] directories = source.GetDirectories();
		foreach (DirectoryInfo directoryInfo in directories)
		{
			CopyFilesRecursively(directoryInfo, target.CreateSubdirectory(directoryInfo.Name));
		}
		FileInfo[] files = source.GetFiles();
		foreach (FileInfo fileInfo in files)
		{
			fileInfo.CopyTo(Path.Combine(target.FullName, fileInfo.Name));
		}
	}
}
public interface ICSVFile
{
	void PatchFromFile(string path);

	void ReadFromFile(string path);

	void WriteToFile(string path);
}
public class MultiElementListCSV : ICSVFile
{
	public class MultiElementEntry
	{
		public string[] firstValues;

		public string[][] otherEntries;

		public string ID => firstValues[0];
	}

	public Dictionary<string, MultiElementEntry> entries = new Dictionary<string, MultiElementEntry>();

	public MultiElementEntry defEntry;

	public const string patchAddPrefix = "patchAdd";

	public const string patchOverPrefix = "patchOver";

	public const string patchAppendPrefix = "patchAppend";

	public const string elementRemoveTag = "[remove]";

	public const string elementSkipTag = "[skip]";

	public void ReadFromFile(string path)
	{
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("File not found at " + path);
		}
		string[] array = File.ReadAllLines(path);
		Path.GetFileNameWithoutExtension(path);
		List<string> list = new List<string>();
		StringUtil.SplitCSV(array[0], list, true);
		defEntry = new MultiElementEntry
		{
			firstValues = list.ToArray()
		};
		int num = 0;
		int num2 = 0;
		MultiElementEntry multiElementEntry = null;
		List<string[]> list2 = new List<string[]>();
		for (int i = 1; i < array.Length; i++)
		{
			if (array[i].Length == 0)
			{
				continue;
			}
			List<string> list3 = new List<string>();
			StringUtil.SplitCSV(array[i], list3, true);
			if (list3.Count <= 1)
			{
				num2++;
				continue;
			}
			bool flag = true;
			foreach (string item in list3)
			{
				if (item != string.Empty)
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				num++;
			}
			else if (list3[0] != string.Empty)
			{
				if (multiElementEntry != null)
				{
					multiElementEntry.otherEntries = list2.ToArray();
					list2.Clear();
					entries[multiElementEntry.ID] = multiElementEntry;
				}
				multiElementEntry = new MultiElementEntry
				{
					firstValues = list3.ToArray()
				};
			}
			else
			{
				list2.Add(list3.ToArray());
			}
		}
		if (multiElementEntry != null)
		{
			multiElementEntry.otherEntries = list2.ToArray();
			list2.Clear();
			entries[multiElementEntry.ID] = multiElementEntry;
		}
	}

	public void WriteToFile(string path)
	{
		try
		{
			List<string> list = new List<string>();
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
			string text = string.Empty;
			string[] firstValues = defEntry.firstValues;
			foreach (string text2 in firstValues)
			{
				text = text + text2 + ",";
			}
			list.Add(text);
			foreach (MultiElementEntry value in entries.Values)
			{
				try
				{
					string text3 = string.Empty;
					List<string> list2 = new List<string>();
					firstValues = value.firstValues;
					foreach (string text4 in firstValues)
					{
						StringUtil.SplitCSV(text4, list2, true);
						text3 = ((list2.Count <= 1) ? (text3 + text4 + ",") : (text3 + "\"" + text4 + "\","));
					}
					list.Add(text3);
					string[][] otherEntries = value.otherEntries;
					foreach (string[] obj in otherEntries)
					{
						text3 = string.Empty;
						firstValues = obj;
						foreach (string text5 in firstValues)
						{
							StringUtil.SplitCSV(text5, list2, true);
							text3 = ((list2.Count <= 1) ? (text3 + text5 + ",") : (text3 + "\"" + text5 + "\","));
						}
						list.Add(text3);
					}
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
					Debug.LogError((object)("Failed to write entry " + value.ID + " to file"));
				}
			}
			Debug.Log((object)$"Writing {list.Count} lines to file {fileNameWithoutExtension}, out of {entries.Values.Count} entries");
			File.WriteAllLines(path, list.ToArray());
		}
		catch (Exception ex2)
		{
			Debug.LogError((object)ex2);
		}
	}

	public void PatchFromFile(string path)
	{
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("File not found at " + path);
		}
		string[] array = File.ReadAllLines(path);
		List<MultiElementEntry> list = new List<MultiElementEntry>();
		MultiElementEntry multiElementEntry = null;
		List<string[]> list2 = new List<string[]>();
		for (int i = 0; i < array.Length; i++)
		{
			if (array[i].Length == 0)
			{
				continue;
			}
			List<string> list3 = new List<string>();
			StringUtil.SplitCSV(array[i], list3, true);
			if (list3.Count <= 1)
			{
				continue;
			}
			bool flag = true;
			foreach (string item in list3)
			{
				if (item != string.Empty)
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				continue;
			}
			if (list3[0] != string.Empty)
			{
				if (multiElementEntry != null)
				{
					multiElementEntry.otherEntries = list2.ToArray();
					list2.Clear();
					list.Add(multiElementEntry);
				}
				multiElementEntry = new MultiElementEntry
				{
					firstValues = list3.ToArray()
				};
			}
			else
			{
				list2.Add(list3.ToArray());
			}
		}
		if (multiElementEntry != null)
		{
			multiElementEntry.otherEntries = list2.ToArray();
			list2.Clear();
			list.Add(multiElementEntry);
		}
		foreach (MultiElementEntry item2 in list)
		{
			string withoutPrefix = CSVUtil.GetWithoutPrefix(item2.ID);
			string prefix = CSVUtil.GetPrefix(item2.ID);
			if (prefix == "patchOver")
			{
				PatchOver(item2, withoutPrefix);
			}
			else if (prefix == "patchAdd")
			{
				PatchAdd(item2, withoutPrefix);
			}
			else
			{
				Debug.Log((object)$"Patching failed with entry {item2.ID}, no prefixes where matched.");
			}
		}
	}

	public void AddEntry(MultiElementEntry entry)
	{
		try
		{
			entries[entry.ID] = entry;
		}
		catch (Exception ex)
		{
			Debug.LogError((object)ex);
		}
	}

	public void Clear()
	{
		entries.Clear();
		defEntry = null;
	}

	public void PatchAdd(MultiElementEntry newEntry, string entryIDWithoutPrefix)
	{
		if (!entries.ContainsKey(entryIDWithoutPrefix))
		{
			newEntry.firstValues[0] = entryIDWithoutPrefix;
			AddEntry(newEntry);
			return;
		}
		MultiElementEntry multiElementEntry = entries[entryIDWithoutPrefix];
		for (int i = 1; i < newEntry.firstValues.Length; i++)
		{
			if (i == 1 && newEntry.firstValues[i] != string.Empty && newEntry.firstValues[i] != "[skip]")
			{
				multiElementEntry.firstValues[i] += ", ";
			}
			if (newEntry.firstValues[i] == "[skip]")
			{
				multiElementEntry.firstValues[i] += string.Empty;
			}
			else
			{
				multiElementEntry.firstValues[i] += newEntry.firstValues[i];
			}
		}
		for (int j = 0; j < newEntry.otherEntries.Length; j++)
		{
			for (int k = 0; k < newEntry.otherEntries[j].Length; k++)
			{
				if (multiElementEntry.otherEntries[j][k] != string.Empty && newEntry.otherEntries[j][k] != "[skip]")
				{
					multiElementEntry.otherEntries[j][k] += ", ";
				}
				if (newEntry.otherEntries[j][k] == "[skip]")
				{
					multiElementEntry.otherEntries[j][k] += string.Empty;
				}
				else
				{
					multiElementEntry.otherEntries[j][k] += newEntry.otherEntries[j][k];
				}
			}
		}
		entries[entryIDWithoutPrefix] = multiElementEntry;
	}

	public void PatchOver(MultiElementEntry newEntry, string entryIDWithoutPrefix)
	{
		if (!entries.ContainsKey(entryIDWithoutPrefix))
		{
			newEntry.firstValues[0] = entryIDWithoutPrefix;
			AddEntry(newEntry);
			return;
		}
		MultiElementEntry multiElementEntry = entries[entryIDWithoutPrefix];
		for (int i = 1; i < newEntry.firstValues.Length; i++)
		{
			string text = newEntry.firstValues[i];
			if (!(text == string.Empty) && !(text == "[skip]"))
			{
				if (text == "[remove]")
				{
					multiElementEntry.firstValues[i] = string.Empty;
				}
				else
				{
					multiElementEntry.firstValues[i] = text;
				}
			}
		}
		int num = 0;
		bool flag = false;
		for (int j = 0; j < newEntry.otherEntries.Length; j++)
		{
			string value = newEntry.otherEntries[j][1];
			if (CSVUtil.GetPrefix(value) == "patchAppend")
			{
				string withoutPrefix = CSVUtil.GetWithoutPrefix(value);
				Debug.Log((object)("Hey We are Appending! It's " + withoutPrefix));
				newEntry.otherEntries[j][1] = withoutPrefix;
				string[][] array = new string[newEntry.otherEntries.Length - j + multiElementEntry.otherEntries.Length][];
				Debug.Log((object)("Temp's Length is " + array.Length + "While PatchEntry's Length is " + multiElementEntry.otherEntries.Length));
				for (int k = 0; k < array.Length; k++)
				{
					if (k < multiElementEntry.otherEntries.Length)
					{
						array[k] = new string[multiElementEntry.otherEntries[k].Length];
					}
					else
					{
						array[k] = new string[4];
					}
				}
				Debug.Log((object)"Bouta fit patchEntries into temp!");
				for (int l = 0; l < multiElementEntry.otherEntries.Length; l++)
				{
					Debug.Log((object)"Starting k again!");
					for (int m = 0; m < multiElementEntry.otherEntries[l].Length; m++)
					{
						Debug.Log((object)("k is" + l + " and l is " + m));
						array[l][m] = multiElementEntry.otherEntries[l][m];
					}
				}
				for (int n = 0; n < array.Length; n++)
				{
					for (int num2 = 0; num2 < array[n].Length; num2++)
					{
						if (string.IsNullOrEmpty(array[n][num2]))
						{
							array[n][num2] = string.Empty;
						}
					}
				}
				num = multiElementEntry.otherEntries.Length;
				flag = true;
				multiElementEntry.otherEntries = array;
				Debug.Log((object)("patchEntry Length is now " + multiElementEntry.otherEntries.Length));
			}
			for (int num3 = 0; num3 < newEntry.otherEntries[j].Length; num3++)
			{
				Debug.Log((object)("I sure hope it is not having a problem storing an element? I is " + j + "and j is " + num3));
				string text2 = newEntry.otherEntries[j][num3];
				if (text2 == string.Empty || text2 == "[skip]")
				{
					continue;
				}
				if (text2 == "[remove]")
				{
					if (flag)
					{
						Debug.Log((object)"Appending a Empty");
						multiElementEntry.otherEntries[num][num3] = string.Empty;
					}
					else
					{
						multiElementEntry.otherEntries[j][num3] = string.Empty;
					}
				}
				else if (flag)
				{
					Debug.Log((object)("Appending a new entry, its " + multiElementEntry.otherEntries[num][num3]));
					multiElementEntry.otherEntries[num][num3] = text2;
				}
				else
				{
					multiElementEntry.otherEntries[j][num3] = text2;
				}
			}
			if (flag)
			{
				num++;
				Debug.Log((object)("NewI is now " + num));
			}
		}
		entries[entryIDWithoutPrefix] = multiElementEntry;
	}
}
public class SimpleListCSV : ICSVFile
{
	public class ListEntry
	{
		public string[] values;

		public int rowNumber;

		public string group => values[0];

		public string ID => values[1];

		public int row => rowNumber;
	}

	public Dictionary<string, ListEntry> entries = new Dictionary<string, ListEntry>();

	public Dictionary<int, ListEntry> animEntries = new Dictionary<int, ListEntry>();

	public ListEntry defEntry;

	public bool useGroups = true;

	public bool shopList;

	public bool animList;

	public int totRowCount;

	public const string patchAddPrefix = "patchAdd";

	public const string patchOverPrefix = "patchOver";

	public const string patchAnimPrefix = "patchAnim";

	public const string elementRemoveTag = "[remove]";

	public void ReadFromFile(string path)
	{
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("File not found at " + path);
		}
		string[] array = File.ReadAllLines(path);
		string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
		List<string> list = new List<string>();
		StringUtil.SplitCSV(array[0], list, true);
		defEntry = new ListEntry
		{
			values = list.ToArray()
		};
		defEntry.rowNumber = 1;
		string text = defEntry.values[0];
		useGroups = text == "Group ID" || text == "Group" || text == "GroupID";
		if (fileNameWithoutExtension == "Shop List")
		{
			shopList = true;
		}
		else if (fileNameWithoutExtension == "Anim Actions")
		{
			animList = true;
			useGroups = false;
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 1;
		if (fileNameWithoutExtension != "Strings")
		{
			for (int i = 1; i < array.Length; i++)
			{
				try
				{
					num5++;
					if (array[i].Length == 0)
					{
						num3++;
						continue;
					}
					List<string> list2 = new List<string>();
					StringUtil.SplitCSV(array[i], list2, true);
					if (list2.Count <= 1)
					{
						num2++;
						continue;
					}
					bool flag = true;
					foreach (string item in list2)
					{
						if (item != string.Empty)
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						num++;
						continue;
					}
					ListEntry listEntry = new ListEntry
					{
						values = list2.ToArray()
					};
					listEntry.rowNumber = num5;
					AddEntry(listEntry);
					num4++;
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
					Debug.LogError((object)("Failed to read entry " + array[i]));
				}
			}
		}
		else
		{
			List<string> list3 = new List<string>();
			string file = GetFile(path);
			List<string> list4 = ParseLine(file.Substring(0, file.IndexOf('\n')));
			List<string> file_lines = SplitFileIntoLines(file, list4.Count);
			file_lines = TrimEntries(file_lines);
			for (int j = 1; j < file_lines.Count(); j++)
			{
				list3 = ParseLine(file_lines[j]);
				ListEntry entry = new ListEntry
				{
					values = list3.ToArray()
				};
				AddEntry(entry);
				num4++;
			}
		}
		totRowCount = num5;
		Debug.Log((object)$"File {fileNameWithoutExtension} had {num} empty entries, {num2} no-line entries, {num3} skips, and {num4} normal entries, {array.Length} total lines in the file");
	}

	public void PatchFromFile(string path)
	{
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("File not found at " + path);
		}
		string[] array = File.ReadAllLines(path);
		for (int i = 0; i < array.Length; i++)
		{
			List<string> list = new List<string>();
			StringUtil.SplitCSV(array[i], list, true);
			ListEntry listEntry = new ListEntry
			{
				values = list.ToArray()
			};
			string text = null;
			string text2 = null;
			if (useGroups || shopList)
			{
				text = CSVUtil.GetPrefix(listEntry.ID);
				text2 = CSVUtil.GetWithoutPrefix(listEntry.ID);
				listEntry.rowNumber = ++totRowCount;
			}
			else if (animList)
			{
				text = CSVUtil.GetPrefix(listEntry.ID);
				text2 = CSVUtil.GetWithoutPrefix(listEntry.ID);
				try
				{
					listEntry.rowNumber = Convert.ToInt32(listEntry.group);
				}
				catch (FormatException)
				{
					Debug.Log((object)("Error Patching Anim Actions - Input string is not a sequence of digits. " + listEntry.group));
				}
				catch (OverflowException)
				{
					Debug.Log((object)("Error Patching Anim Actions - Row Number cannot fir in an Int32." + listEntry.group));
				}
			}
			else
			{
				text = CSVUtil.GetPrefix(listEntry.group);
				text2 = CSVUtil.GetWithoutPrefix(listEntry.group);
			}
			switch (text)
			{
			case "patchAdd":
				PatchAdd(listEntry, text2);
				break;
			case "patchOver":
				PatchOver(listEntry, text2);
				break;
			case "patchAnim":
				AnimPatchAdd(listEntry, text2);
				break;
			}
		}
	}

	public void WriteToFile(string path)
	{
		try
		{
			List<string> list = new List<string>();
			Path.GetFileNameWithoutExtension(path);
			string text = string.Empty;
			string[] values = defEntry.values;
			foreach (string text2 in values)
			{
				text = text + text2 + ",";
			}
			list.Add(text);
			if (!animList)
			{
				foreach (ListEntry value in entries.Values)
				{
					string text3 = string.Empty;
					List<string> list2 = new List<string>();
					values = value.values;
					foreach (string text4 in values)
					{
						StringUtil.SplitCSV(text4, list2, true);
						text3 = ((list2.Count <= 1) ? (text3 + text4 + ",") : (text3 + "\"" + text4 + "\","));
					}
					list.Add(text3);
				}
			}
			else
			{
				foreach (ListEntry value2 in animEntries.Values)
				{
					string text5 = string.Empty;
					List<string> list3 = new List<string>();
					values = value2.values;
					foreach (string text6 in values)
					{
						StringUtil.SplitCSV(text6, list3, true);
						text5 = ((list3.Count <= 1) ? (text5 + text6 + ",") : (text5 + "\"" + text6 + "\","));
					}
					list.Add(text5);
				}
			}
			File.WriteAllLines(path, list.ToArray());
		}
		catch (Exception ex)
		{
			Debug.LogError((object)ex);
		}
	}

	public void AddEntry(ListEntry entry)
	{
		try
		{
			if (useGroups || shopList)
			{
				entries[entry.ID] = entry;
			}
			else if (animList)
			{
				animEntries[entry.rowNumber] = entry;
			}
			else
			{
				entries[entry.group] = entry;
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)ex);
		}
	}

	public void Clear()
	{
		entries.Clear();
		defEntry = null;
	}

	public void PatchAdd(ListEntry newEntry, string entryIDWithoutPrefix, string groupID = "MODDED")
	{
		if (!entries.ContainsKey(entryIDWithoutPrefix))
		{
			if (useGroups)
			{
				newEntry.values[0] = newEntry.group;
				newEntry.values[1] = entryIDWithoutPrefix;
			}
			else if (shopList || animList)
			{
				newEntry.values[0] = newEntry.group;
				newEntry.values[1] = entryIDWithoutPrefix;
			}
			else
			{
				newEntry.values[0] = entryIDWithoutPrefix;
			}
			AddEntry(newEntry);
			return;
		}
		ListEntry listEntry = entries[entryIDWithoutPrefix];
		int num = 1;
		if (useGroups)
		{
			num++;
		}
		for (int i = num; i < newEntry.values.Length; i++)
		{
			if (listEntry.values[i] != null || listEntry.values[i] != "" || listEntry.values[i] != " ")
			{
				listEntry.values[i] += ", ";
			}
			listEntry.values[i] += newEntry.values[i];
		}
		entries[entryIDWithoutPrefix] = listEntry;
	}

	public void AnimPatchAdd(ListEntry newEntry, string entryIDWithoutPrefix, string groupID = "MODDED")
	{
		if (newEntry.values.Length <= 1)
		{
			return;
		}
		if (!animEntries.ContainsKey(newEntry.row))
		{
			newEntry.rowNumber = animEntries.Count + 1;
			newEntry.values[0] = groupID;
			newEntry.values[1] = entryIDWithoutPrefix;
			AddEntry(newEntry);
			return;
		}
		newEntry.values[1] = entryIDWithoutPrefix;
		ListEntry listEntry = animEntries[newEntry.row];
		int num = 1;
		if (useGroups)
		{
			num++;
		}
		for (int i = num; i < newEntry.values.Length; i++)
		{
			if (!(listEntry.values[i] != newEntry.values[i]))
			{
				continue;
			}
			if (i == 1)
			{
				if (listEntry.values[i] != null || listEntry.values[i] != "" || listEntry.values[i] != " ")
				{
					listEntry.values[i] += ", ";
				}
				listEntry.values[i] += newEntry.values[i];
				continue;
			}
			string text = newEntry.values[i];
			if (!(text == string.Empty))
			{
				if (text == "[remove]")
				{
					listEntry.values[i] = string.Empty;
				}
				else
				{
					listEntry.values[i] = text;
				}
			}
		}
		animEntries[newEntry.row] = listEntry;
	}

	public void PatchOver(ListEntry newEntry, string entryIDWithoutPrefix, string groupID = "MODDED")
	{
		if (!entries.ContainsKey(entryIDWithoutPrefix))
		{
			if (useGroups)
			{
				newEntry.values[0] = newEntry.group;
				newEntry.values[1] = entryIDWithoutPrefix;
			}
			else if (shopList || animList)
			{
				newEntry.values[0] = newEntry.group;
				newEntry.values[1] = entryIDWithoutPrefix;
			}
			else
			{
				newEntry.values[0] = entryIDWithoutPrefix;
			}
			AddEntry(newEntry);
			return;
		}
		ListEntry listEntry = entries[entryIDWithoutPrefix];
		int num = 1;
		if (useGroups)
		{
			num++;
		}
		for (int i = num; i < newEntry.values.Length; i++)
		{
			string text = newEntry.values[i];
			if (!(text == string.Empty))
			{
				if (text == "[remove]")
				{
					listEntry.values[i] = string.Empty;
				}
				else
				{
					listEntry.values[i] = text;
				}
			}
		}
		entries[entryIDWithoutPrefix] = listEntry;
	}

	public static List<string> ParseLine(string line)
	{
		List<string> list = new List<string>();
		int num = 0;
		int i = 0;
		int length = line.Length;
		int num2 = 0;
		int num3 = 0;
		for (; i < length; i++)
		{
			string @char = GetChar(line, i);
			if (@char == "," && num3 == 0)
			{
				num2++;
			}
			if (@char == "\"")
			{
				num3 = 1 - num3;
			}
			if (num2 == 1)
			{
				list.Add(line.Substring(num, i - num));
				num = i + 1;
				num2 = 0;
			}
		}
		return TrimEntries(list);
	}

	private static List<string> TrimEntries(List<string> file_lines)
	{
		List<string> list = new List<string>();
		foreach (string file_line in file_lines)
		{
			list.Add(file_line.Trim());
		}
		return list;
	}

	private static List<string> SplitFileIntoLines(string file_contents, int header_count)
	{
		List<string> list = new List<string>();
		int num = 0;
		int i = 0;
		int length = file_contents.Length;
		int num2 = 0;
		int num3 = 0;
		for (; i < length; i++)
		{
			string @char = GetChar(file_contents, i);
			if (@char == "," && num3 == 0)
			{
				num2++;
			}
			if (@char == "\"")
			{
				num3 = 1 - num3;
			}
			if (num2 == header_count)
			{
				list.Add(file_contents.Substring(num, i - num + 1));
				num = i + 1;
				num2 = 0;
			}
		}
		return list;
	}

	private static string GetChar(string input, int cur_pos)
	{
		return input.Substring(cur_pos, 1);
	}

	private static string GetFile(string path)
	{
		return File.ReadAllText(path);
	}
}