internal static void ExtendedCardLoad(ChaFile file) { Sideloader.Logger.LogDebug($"Loading card [{file.charaFileName}]"); var extData = ExtendedSave.GetExtendedDataById(file, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(file, UARExtID); List <ResolveInfo> extInfo; if (extData == null || !extData.data.ContainsKey("info")) { Sideloader.Logger.LogDebug("No sideloader marker found"); extInfo = null; } else { var tmpExtInfo = (object[])extData.data["info"]; extInfo = tmpExtInfo.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList(); Sideloader.Logger.LogDebug($"Sideloader marker found, external info count: {extInfo.Count}"); if (Sideloader.DebugLogging.Value) { foreach (ResolveInfo info in extInfo) { Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}"); } } } IterateCardPrefixes(ResolveStructure, file, extInfo); }
internal static void XMLReadPostfix(Control __instance) { foreach (Data data in __instance.Datas) { if (data is Config.EtceteraSystem etceteraSystem) { if (etceteraSystem.rampId >= BaseSlotID) //Saved with a resolved ID, reset it to default { etceteraSystem.rampId = 1; } else { var xmlDoc = XDocument.Load("UserData/config/system.xml"); string rampGUID = xmlDoc.Element("System").Element("Etc").Element("rampGUID")?.Value; if (!rampGUID.IsNullOrWhiteSpace()) { ResolveInfo RampResolveInfo = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.GUID == rampGUID && x.Slot == etceteraSystem.rampId); if (RampResolveInfo == null) //Missing mod, reset ID to default { etceteraSystem.rampId = 1; } else //Restore the resolved ID { etceteraSystem.rampId = RampResolveInfo.LocalSlot; } } } } } }
private static void ExtendedCardLoad(ChaFile file) { Logger.Log(LogLevel.Debug, $"Loading card [{file.charaFileName}]"); var extData = ExtendedSave.GetExtendedDataById(file, UniversalAutoResolver.UARExtID); List <ResolveInfo> extInfo; if (extData == null || !extData.data.ContainsKey("info")) { Logger.Log(LogLevel.Debug, "No sideloader marker found"); extInfo = null; } else { var tmpExtInfo = (object[])extData.data["info"]; extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)).ToList(); Logger.Log(LogLevel.Debug, "Sideloader marker found"); Logger.Log(LogLevel.Debug, $"External info count: {extInfo.Count}"); foreach (ResolveInfo info in extInfo) { Logger.Log(LogLevel.Debug, $"External info: {info.GUID} : {info.Property} : {info.Slot}"); } } IterateCardPrefixes(UniversalAutoResolver.ResolveStructure, file, extInfo); }
internal static void XMLWritePrefix(Control __instance, ref int __state) { __state = -1; foreach (Data data in __instance.Datas) { if (data is Config.EtceteraSystem etceteraSystem) { if (etceteraSystem.rampId >= BaseSlotID) { ResolveInfo RampResolveInfo = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.LocalSlot == etceteraSystem.rampId); if (RampResolveInfo == null) { //ID is a sideloader ID but no resolve info found, set it to the default __state = 1; etceteraSystem.rampId = 1; } else { //Switch out the resolved ID for the original __state = etceteraSystem.rampId; etceteraSystem.rampId = RampResolveInfo.Slot; } } } } }
internal static void ResolveStudioRamp(ExtensibleSaveFormat.PluginData extData, ResolveType resolveType) { #if KK //Set ramp ID to the resolved ID int rampID = Studio.Studio.Instance.sceneInfo.rampG; if (extData != null && extData.data.ContainsKey("rampInfoGUID")) { string rampGUID = (string)extData.data["rampInfoGUID"]; ResolveInfo intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.GUID == rampGUID && x.Slot == rampID); if (intResolve != null) { if (resolveType == ResolveType.Load && Sideloader.DebugLogging.Value) { Sideloader.Logger.LogDebug($"Resolving (Studio Ramp) [{rampID}] {rampID}->{intResolve.LocalSlot}"); } Studio.Studio.Instance.sceneInfo.rampG = intResolve.LocalSlot; } else { ShowGUIDError(rampGUID); } } else if (resolveType == ResolveType.Load) { if (!Lists.InternalDataList[ChaListDefine.CategoryNo.mt_ramp].ContainsKey(rampID)) { //Ramp ID saved to the scene doesn't exist in the items list, try compatibility resolving ResolveInfo intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.Slot == rampID); if (intResolve != null) { //Found a matching sideloader mod if (Sideloader.DebugLogging.Value) { Sideloader.Logger.LogDebug($"Compatibility resolving (Studio Ramp) {rampID}->{intResolve.LocalSlot}"); } Studio.Studio.Instance.sceneInfo.rampG = intResolve.LocalSlot; } else { Sideloader.Logger.Log(BepInEx.Logging.LogLevel.Warning | BepInEx.Logging.LogLevel.Message, $"[UAR] Compatibility resolving (Studio Ramp) failed, no match found for ID {rampID}"); } } } #endif }
internal static void ExtendedCardLoad(ChaFile file) { string cardName = file.charaFileName; if (cardName.IsNullOrEmpty()) { cardName = file.parameter?.fullname?.Trim(); } Sideloader.Logger.LogDebug($"Loading card [{cardName}]"); var extData = ExtendedSave.GetExtendedDataById(file, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(file, UARExtID); List <ResolveInfo> extInfo; if (extData == null || !extData.data.ContainsKey("info")) { Sideloader.Logger.LogDebug("No sideloader marker found"); extInfo = null; } else { var tmpExtInfo = (object[])extData.data["info"]; extInfo = tmpExtInfo.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList(); Sideloader.Logger.LogDebug($"Sideloader marker found, external info count: {extInfo.Count}"); if (Sideloader.DebugLogging.Value) { foreach (ResolveInfo info in extInfo) { Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}"); } } } IterateCardPrefixes(ResolveStructure, file, extInfo); #if AI || HS2 //Resolve the bundleID to the same ID as the hair foreach (var hairPart in file.custom.hair.parts) { if (hairPart.id > BaseSlotID) { hairPart.bundleId = hairPart.id; } } #endif }
internal static void SceneInfoInit(SceneInfo __instance) { var xmlDoc = XDocument.Load("UserData/config/system.xml"); string rampGUID = xmlDoc.Element("System").Element("Etc").Element("rampGUID")?.Value; string rampIDXML = xmlDoc.Element("System").Element("Etc").Element("rampId")?.Value; if (!rampGUID.IsNullOrWhiteSpace() && !rampIDXML.IsNullOrWhiteSpace() && int.TryParse(rampIDXML, out int rampID)) { ResolveInfo RampResolveInfo = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.GUID == rampGUID && x.Slot == rampID); if (RampResolveInfo == null) //Missing mod, reset ID to default { __instance.rampG = 1; } else //Restore the resolved ID { __instance.rampG = RampResolveInfo.LocalSlot; } } }
public static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ChaFile save) { //BepInLogger.Log($"Tried to resolve structure: {structure.GetType().Name}"); var extData = ExtendedSave.GetExtendedDataById(save, UARExtID); if (extData == null || !extData.data.ContainsKey("info")) { //BepInLogger.Log($"No info to load!"); return; } var tmpExtInfo = (object[])extData.data["info"]; var extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)); //BepInLogger.Log($"Internal info count: {LoadedResolutionInfo.Count}"); //foreach (ResolveInfo info in LoadedResolutionInfo) // BepInLogger.Log($"Internal info: {info.ModID} : {info.Property} : {info.Slot}"); //BepInLogger.Log($"External info count: {extInfo.Count()}"); //foreach (ResolveInfo info in extInfo) // BepInLogger.Log($"External info: {info.ModID} : {info.Property} : {info.Slot}"); foreach (var kv in propertyDict) { var extResolve = extInfo.FirstOrDefault(x => x.Property == kv.Key.ToString()); if (extResolve != null) { var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.CanResolve(extResolve)); if (intResolve != null) { BepInLogger.Log($"[UAR] Resolving {extResolve.ModID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } } } }
internal static void XMLWritePostfix(Control __instance, ref int __state) { int rampId = __state; if (rampId >= BaseSlotID) { foreach (Data data in __instance.Datas) { if (data is Config.EtceteraSystem etceteraSystem) { ResolveInfo RampResolveInfo = LoadedResolutionInfo.FirstOrDefault(x => x.Property == "Ramp" && x.LocalSlot == rampId); if (RampResolveInfo != null) { //Restore the resolved ID etceteraSystem.rampId = RampResolveInfo.LocalSlot; var xmlDoc = XDocument.Load("UserData/config/system.xml"); xmlDoc.Element("System").Element("Etc").Element("rampId").AddAfterSelf(new XElement("rampGUID", RampResolveInfo.GUID)); xmlDoc.Save("UserData/config/system.xml"); } } } } }
internal static void MigrateData(ResolveInfo extResolve, ChaListDefine.CategoryNo categoryNo) { if (extResolve.GUID.IsNullOrWhiteSpace()) { return; } var migrationInfoList = GetMigrationInfo(extResolve.GUID); if (migrationInfoList.Any(x => x.MigrationType == MigrationType.StripAll)) { extResolve.GUID = ""; return; } foreach (var migrationInfo in migrationInfoList.Where(x => x.MigrationType == MigrationType.MigrateAll)) { if (Sideloader.GetManifest(migrationInfo.GUIDNew) != null) { Sideloader.Logger.LogInfo($"Migrating GUID {migrationInfo.GUIDOld} -> {migrationInfo.GUIDNew}"); extResolve.GUID = migrationInfo.GUIDNew; return; } } foreach (var migrationInfo in migrationInfoList.Where(x => x.IDOld == extResolve.Slot && categoryNo == extResolve.CategoryNo)) { if (Sideloader.GetManifest(migrationInfo.GUIDNew) != null) { Sideloader.Logger.LogInfo($"Migrating {migrationInfo.GUIDOld}:{migrationInfo.IDOld} -> {migrationInfo.GUIDNew}:{migrationInfo.IDNew}"); extResolve.GUID = migrationInfo.GUIDNew; extResolve.Slot = migrationInfo.IDNew; return; } } }
public bool CanResolve(ResolveInfo other) => GUID == other.GUID && Property == other.Property && Slot == other.Slot;
/// <summary> /// Change the ID of items saved to a card to their resolved IDs /// </summary> internal static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ICollection <ResolveInfo> extInfo, string propertyPrefix = "") { foreach (var kv in propertyDict) { string property = $"{propertyPrefix}{kv.Key}"; //For accessories, make sure we're checking the appropriate category if (kv.Key.Category.ToString().Contains("ao_")) { ChaFileAccessory.PartsInfo AccessoryInfo = (ChaFileAccessory.PartsInfo)structure; if ((int)kv.Key.Category != AccessoryInfo.type) { //If the current category does not match the category saved to the card do not attempt resolving continue; } } ResolveInfo extResolve = extInfo?.FirstOrDefault(x => x.Property == property); if (extResolve == null) { CompatibilityResolve(kv, structure); continue; } if (Sideloader.MigrationEnabled.Value) { MigrateData(extResolve, kv.Key.Category); } //If the GUID is blank or has been made blank by migration do compatibility resolve if (extResolve.GUID.IsNullOrWhiteSpace()) { CompatibilityResolve(kv, structure); continue; } //the property has external slot information var intResolve = TryGetResolutionInfo(extResolve.Slot, kv.Key.ToString(), kv.Key.Category, extResolve.GUID); if (intResolve != null) { //found a match to a corrosponding internal mod if (Sideloader.DebugLogging.Value) { Sideloader.Logger.LogDebug($"Resolving {extResolve.GUID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}"); } kv.Value.SetMethod(structure, intResolve.LocalSlot); } else { #if KK || EC if (Lists.InternalDataList[kv.Key.Category].ContainsKey(kv.Value.GetMethod(structure))) #elif AI || HS2 if (Lists.InternalDataList[(int)kv.Key.Category].ContainsKey(kv.Value.GetMethod(structure))) #endif { #if KK || EC string mainAB = Lists.InternalDataList[kv.Key.Category][kv.Value.GetMethod(structure)].dictInfo[(int)ChaListDefine.KeyType.MainAB]; #elif AI || HS2 string mainAB = Lists.InternalDataList[(int)kv.Key.Category][kv.Value.GetMethod(structure)].dictInfo[(int)ChaListDefine.KeyType.MainAB]; #endif mainAB = mainAB.Replace("chara/", "").Replace(".unity3d", "").Replace(kv.Key.Category.ToString() + "_", "").Replace("/", ""); if (int.TryParse(mainAB, out int x)) { //ID found but it conflicts with a vanilla item. Change the ID to avoid conflicts. ShowGUIDError(extResolve.GUID); if (kv.Key.Category.ToString().Contains("ao_") && Sideloader.KeepMissingAccessories.Value && GetNowSceneNames().Any(sceneName => sceneName == "CustomScene")) { kv.Value.SetMethod(structure, 1); } else { kv.Value.SetMethod(structure, BaseSlotID - 1); } } else { //ID found and it does not conflict with a vanilla item, likely the user has a hard mod version of the mod installed Sideloader.Logger.LogDebug($"Missing mod detected [{extResolve.GUID}] but matching ID found"); } } else { //ID not found. Change the ID to avoid potential future conflicts. ShowGUIDError(extResolve.GUID); if (kv.Key.Category.ToString().Contains("ao_") && Sideloader.KeepMissingAccessories.Value && GetNowSceneNames().Any(sceneName => sceneName == "CustomScene")) { kv.Value.SetMethod(structure, 1); } else { kv.Value.SetMethod(structure, BaseSlotID - 1); } } } } }
private static void ExtendedCoordinateImport(Dictionary <string, PluginData> importedExtendedData) { if (importedExtendedData.TryGetValue(UniversalAutoResolver.UARExtID, out var pluginData)) { if (pluginData != null && pluginData.data.ContainsKey("info")) { var tmpExtInfo = (object[])pluginData.data["info"]; var extInfo = tmpExtInfo.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList(); for (int i = 0; i < extInfo.Count;) { Sideloader.Logger.Log(LogLevel.Debug, $"External info: {extInfo[i].GUID} : {extInfo[i].Property} : {extInfo[i].Slot} : {extInfo[i].CategoryNo}"); if (extInfo[i].Property.EndsWith("ClothesShoesInner")) { //KK had inner shoes, EC does not extInfo.RemoveAt(i); } else { extInfo[i].Property = extInfo[i].Property.Replace("outfit0", "outfit"); //KK originally had only one emblem if (extInfo[i].Property.EndsWith("Emblem")) { extInfo[i].Property += "0"; } //KK has multiple shoes slots, convert to one shoes slot extInfo[i].Property = extInfo[i].Property.Replace("ClothesShoesOuter", "ClothesShoes"); i++; } } importedExtendedData[UniversalAutoResolver.UARExtID] = new PluginData { data = new Dictionary <string, object> { ["info"] = extInfo.Select(x => x.Serialize()).ToList() } }; } } if (Sideloader.DebugLogging.Value && importedExtendedData.TryGetValue(UniversalAutoResolver.UARExtID, out var extData)) { if (extData == null || !extData.data.ContainsKey("info")) { Sideloader.Logger.Log(LogLevel.Debug, "Imported coordinate data: No sideloader marker found"); } else { var tmpExtInfo = (List <byte[]>)extData.data["info"]; var extInfo = tmpExtInfo.Select(ResolveInfo.Deserialize).ToList(); Sideloader.Logger.Log(LogLevel.Debug, $"Imported coordinate data: Sideloader marker found, external info count: {extInfo.Count}"); foreach (ResolveInfo info in extInfo) { Sideloader.Logger.Log(LogLevel.Debug, $"External info: {info.GUID} : {info.Property} : {info.Slot} : {info.CategoryNo}"); } } } }
public static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ChaFile save, string propertyPrefix = "") { var extData = ExtendedSave.GetExtendedDataById(save, UARExtID); IEnumerable <ResolveInfo> extInfo; if (extData == null || !extData.data.ContainsKey("info")) { extInfo = null; //BepInLogger.Log("Nothing to load!"); } else { var tmpExtInfo = (object[])extData.data["info"]; extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)); } //BepInLogger.Log($"Internal info count: {LoadedResolutionInfo.Count}"); //foreach (ResolveInfo info in LoadedResolutionInfo) // BepInLogger.Log($"Internal info: {info.ModID} : {info.Property} : {info.Slot}"); if (extInfo != null && extInfo.Any()) { Logger.Log(LogLevel.Debug, $"External info count: {extInfo.Count()}"); foreach (ResolveInfo info in extInfo) { Logger.Log(LogLevel.Debug, $"External info: {info.GUID} : {info.Property} : {info.Slot}"); } } void CompatibilityResolve(KeyValuePair <CategoryProperty, StructValue <int> > kv) { //check if it's a vanilla item if (!ResourceRedirector.ListLoader.InternalDataList[kv.Key.Category] .ContainsKey(kv.Value.GetMethod(structure))) { //the property does not have external slot information //check if we have a corrosponding item for backwards compatbility var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.Property == kv.Key.ToString() && x.Slot == kv.Value.GetMethod(structure)); if (intResolve != null) { //found a match Logger.Log(LogLevel.Info, $"[UAR] Compatibility resolving {intResolve.Property} from slot {kv.Value.GetMethod(structure)} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } //otherwise ignore if not found } else { //not resolving since we prioritize vanilla items over modded items //BepInLogger.Log($"[UAR] Not resolving item due to vanilla ID range"); //log commented out because it causes too much spam } } foreach (var kv in propertyDict) { if (extInfo != null) { var extResolve = extInfo.FirstOrDefault(x => x.Property == $"{propertyPrefix}{kv.Key.ToString()}"); if (extResolve != null) { //the property has external slot information var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.AppendPropertyPrefix(propertyPrefix).CanResolve(extResolve)); if (intResolve != null) { //found a match to a corrosponding internal mod Logger.Log(LogLevel.Info, $"[UAR] Resolving {extResolve.GUID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } else { //we didn't find a match, check if we have the same GUID loaded if (LoadedResolutionInfo.Any(x => x.GUID == extResolve.GUID)) { //we have the GUID loaded, so the user has an outdated mod Logger.Log(LogLevel.Warning | LogLevel.Message, $"[UAR] WARNING! ({save.parameter.lastname} {save.parameter.firstname}) Outdated mod detected! [{extResolve.GUID}]"); } else { //did not find a match, we don't have the mod Logger.Log(LogLevel.Warning | LogLevel.Message, $"[UAR] WARNING! ({save.parameter.lastname} {save.parameter.firstname}) Missing mod detected! [{extResolve.GUID}]"); } kv.Value.SetMethod(structure, 999999); //set to an invalid ID } } else if (UnityEngine.Event.current.alt) { CompatibilityResolve(kv); } } else { CompatibilityResolve(kv); } } }
public static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ChaFile save, string propertyPrefix = "") { //BepInLogger.Log($"Tried to resolve structure: {structure.GetType().Name}"); var extData = ExtendedSave.GetExtendedDataById(save, UARExtID); IEnumerable <ResolveInfo> extInfo; if (extData == null || !extData.data.ContainsKey("info")) { extInfo = null; //BepInLogger.Log("Nothing to load!"); } else { var tmpExtInfo = (object[])extData.data["info"]; extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)); } //BepInLogger.Log($"Internal info count: {LoadedResolutionInfo.Count}"); //foreach (ResolveInfo info in LoadedResolutionInfo) // BepInLogger.Log($"Internal info: {info.ModID} : {info.Property} : {info.Slot}"); //if (extInfo.Any()) //{ // BepInLogger.Log($"External info count: {extInfo.Count()}"); // foreach (ResolveInfo info in extInfo) // BepInLogger.Log($"External info: {info.ModID} : {info.Property} : {info.Slot}"); //} foreach (var kv in propertyDict) { if (extInfo != null) { var extResolve = extInfo.FirstOrDefault(x => x.Property == $"{propertyPrefix}{kv.Key.ToString()}"); if (extResolve != null) { //the property has external slot information var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.AppendPropertyPrefix(propertyPrefix).CanResolve(extResolve)); if (intResolve != null) { //found a match to a corrosponding internal mod BepInLogger.Log( $"[UAR] Resolving {extResolve.ModID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } else { //did not find a match, we don't have the mod BepInLogger.Log($"[UAR] WARNING! Missing mod detected! [{extResolve.ModID}]", true, ConsoleColor.Yellow); kv.Value.SetMethod(structure, 999999); //set to an invalid ID } } } else { //check if it's a vanilla item if (!ResourceRedirector.ListLoader.InternalDataList[kv.Key.Category] .ContainsKey(kv.Value.GetMethod(structure))) { //the property does not have external slot information //check if we have a corrosponding item for backwards compatbility var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.Property == kv.Key.ToString() && x.Slot == kv.Value.GetMethod(structure)); if (intResolve != null) { //found a match BepInLogger.Log($"[UAR] Compatibility resolving {intResolve.Property} from slot {kv.Value.GetMethod(structure)} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } //otherwise ignore if not found } else { //not resolving since we prioritize vanilla items over modded items //BepInLogger.Log($"[UAR] Not resolving item due to vanilla ID range"); //log commented out because it causes too much spam } } } }
public bool CanResolve(ResolveInfo other) => GUID == other.GUID && Slot == other.Slot;
public bool CanResolve(ResolveInfo other) { return(GUID == other.GUID && Slot == other.Slot); }
private static void ChaFileSaveFilePostHook(ChaFile __instance) { if (DoingImport) { return; } string cardName = __instance.charaFileName; if (cardName.IsNullOrEmpty()) { cardName = __instance.parameter?.fullname?.Trim(); } Sideloader.Logger.LogDebug($"Reloading card [{cardName}]"); var extData = ExtendedSave.GetExtendedDataById(__instance, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(__instance, UARExtID); // Some old ChaFile cards has object[] for "info" List <ResolveInfo> extInfo; if (extData.data["info"] is List <byte[]> lstByte) { extInfo = lstByte.Select(ResolveInfo.Deserialize).ToList(); } else if (extData.data["info"] is object[] objArray) { extInfo = objArray.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList(); } else { Sideloader.Logger.LogError("Unknown data type:" + (extData.data["info"]).GetType()); return; } Sideloader.Logger.LogDebug($"External info count: {extInfo.Count}"); if (Sideloader.DebugLogging.Value) { foreach (ResolveInfo info in extInfo) { Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}"); } } void ResetStructResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, IEnumerable <ResolveInfo> extInfo2, string propertyPrefix = "") { foreach (var kv in propertyDict) { var extResolve = extInfo.FirstOrDefault(x => x.Property == $"{propertyPrefix}{kv.Key}"); if (extResolve != null) { kv.Value.SetMethod(structure, extResolve.LocalSlot); } } } IterateCardPrefixes(ResetStructResolveStructure, __instance, extInfo); #if AI || HS2 //Resolve the bundleID to the same ID as the hair foreach (var hairPart in __instance.custom.hair.parts) { if (hairPart.id > BaseSlotID) { hairPart.bundleId = hairPart.id; } } #endif }
public bool CanResolve(ResolveInfo other) { return(ModID == other.ModID && Property == other.Property && Slot == other.Slot); }
public static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ChaFile save) { //BepInLogger.Log($"Tried to resolve structure: {structure.GetType().Name}"); var extData = ExtendedSave.GetExtendedDataById(save, UARExtID); if (extData == null || !extData.data.ContainsKey("info")) { //BepInLogger.Log($"No info to load!"); return; } var tmpExtInfo = (object[])extData.data["info"]; var extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)); //BepInLogger.Log($"Internal info count: {LoadedResolutionInfo.Count}"); //foreach (ResolveInfo info in LoadedResolutionInfo) // BepInLogger.Log($"Internal info: {info.ModID} : {info.Property} : {info.Slot}"); //BepInLogger.Log($"External info count: {extInfo.Count()}"); //foreach (ResolveInfo info in extInfo) // BepInLogger.Log($"External info: {info.ModID} : {info.Property} : {info.Slot}"); foreach (var kv in propertyDict) { var extResolve = extInfo.FirstOrDefault(x => x.Property == kv.Key.ToString()); if (extResolve != null) { //the property has external slot information var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.CanResolve(extResolve)); if (intResolve != null) { //found a match to a corrosponding internal mod BepInLogger.Log($"[UAR] Resolving {extResolve.ModID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } else { //did not find a match, we don't have the mod BepInLogger.Log($"[UAR] WARNING! Missing mod detected! [{extResolve.ModID}]", true); kv.Value.SetMethod(structure, 999999); //set to an invalid ID } } else { //the property does not have external slot information //check if we have a corrosponding item for backwards compatbility var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.Property == kv.Key.ToString() && x.Slot == kv.Value.GetMethod(structure)); if (intResolve != null) { //found a match BepInLogger.Log($"[UAR] Compatibility resolving {intResolve.Property} from slot {kv.Value.GetMethod(structure)} to slot {intResolve.LocalSlot}"); kv.Value.SetMethod(structure, intResolve.LocalSlot); } //otherwise ignore if not found } } }