/// <summary> /// Method to retrieve a list of BoneModifiers from a selected card in the maker, without loading a character. /// </summary> public static List <BoneModifier> GetBoneModifiersFromCard() { ChaFile file = Utilities.GetSelectedCharacter(); PluginData bonedata = ExtendedSave.GetExtendedDataById(file, "KKABMPlugin.ABMData"); List <BoneModifier> modifiers = new List <BoneModifier>(); if (bonedata != null) { try { switch (bonedata.version) { // Only support for version 2 case 2: modifiers = LZ4MessagePackSerializer.Deserialize <List <BoneModifier> >((byte[])bonedata.data["boneData"]); break; default: throw new NotSupportedException($"Save version {bonedata.version} is not supported"); } } catch (Exception ex) { Logger.Log(LogLevel.Error, "[KK_Archetypes] Failed to load KKABMX extended data - " + ex); } } return(modifiers); }
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); }
public static string GetRegistrationID(this ChaFile chaFile) { string result = null; chaFile.SafeProc(a => result = a.GetHashCode().ToString(CultureInfo.InvariantCulture.NumberFormat)); return(result); }
public bool HaveNamesChanged(ChaFile chaFile) { //return trackedRegistrationIDs.Contains(chaFile.GetRegistrationID()); var current = HashSetPool <string> .Get(); try { foreach (var name in GetNamesToRegister(chaFile)) { current.Add(name.Key); } lock (_lock) { if (!_regIDtoNamesMap.TryGetValue(chaFile.GetRegistrationID(), out var registered)) { registered = new HashSet <string>(); } return(!registered.SetEquals(current)); } } finally { HashSetPool <string> .Release(current); } }
private static bool SetCoordinateBytes(ChaFile __instance, byte[] data, Version ver) { List <byte[]> list = MessagePackSerializer.Deserialize <List <byte[]> >(data); int coordinateCount = list.Count; //Ensure the card doesn't have too few coordinates (typically happens converting a KKS card to KK) #if KK if (coordinateCount < 7) { coordinateCount = 7; } #elif KKS if (coordinateCount < 4) { coordinateCount = 4; } #endif //Reinitialize the array with the new length __instance.coordinate = new ChaFileCoordinate[coordinateCount]; for (int i = 0; i < coordinateCount; i++) { __instance.coordinate[i] = new ChaFileCoordinate(); } //Load all the coordinates for (int i = 0; i < list.Count; i++) { __instance.coordinate[i].LoadBytes(list[i], ver); } return(false); }
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); }
public static void ChaFileLoadFileHook(ChaFile file, BlockHeader header, BinaryReader reader) { var info = header.SearchInfo(Marker); if (info != null && info.version == Version.ToString()) { var originalPosition = reader.BaseStream.Position; try { var basePosition = originalPosition - header.lstInfo.Sum(x => x.size); reader.BaseStream.Position = basePosition + info.pos; var data = reader.ReadBytes((int)info.size); reader.BaseStream.Position = originalPosition; var dictionary = MessagePackDeserialize <Dictionary <string, PluginData> >(data); _internalCharaDictionary.Set(file, dictionary); } catch (Exception e) { _internalCharaDictionary.Set(file, new Dictionary <string, PluginData>()); _logger.Log(LogLevel.Warning, $"Invalid or corrupted extended data in card \"{file.charaFileName}\" - {e.Message}"); reader.BaseStream.Position = originalPosition; } } else { _internalCharaDictionary.Set(file, new Dictionary <string, PluginData>()); } CardReadEvent(file); }
internal static void UpdateTreeForChar(ChaFile chaFile, Action <string> callback) { if (chaFile == null) { return; } void Handler(string fullName) { if (string.IsNullOrEmpty(fullName)) { return; } var match = Singleton <IllusionStudio> .Instance.dicInfo .Where(e => e.Value is OCIChar ociChar && ociChar.charInfo.chaFile == chaFile) .Select(e => e.Key).FirstOrDefault(); if (match == null) { return; } match.textName = fullName; callback?.Invoke(fullName); } chaFile.TranslateFullName(Handler); }
private static bool ShouldProcess(Component component, ChaFile chaFile) { return(component != null && chaFile != null && TranslationHelper.Instance.CurrentCardLoadTranslationEnabled && (!chaFile.TryGetTranslationHelperController(out var controller) || (!controller.TranslationInProgress && !controller.IsTranslated))); }
// rewrite our fake ids to the actual real ones again public override void OnCardSave(ChaFile f, BinaryWriter w, List <object> blocks, bool nopng) { var map = f.dict.Get <GuidMap>("guidmap"); map.items.Clear(); map.baseprefix = null; coordRewriter.map = map; customRewriter.map = map; foreach (var b in blocks) { var coords = b as ChaFileCoordinate[]; if (coords != null) { for (int i = 0; i < coords.Length; i++) { map.baseprefix = "coordinate[" + i + "]"; coordRewriter.FromFake(coords[i]); } } else if (b is ChaFileCustom) { map.baseprefix = "custom"; customRewriter.FromFake(b); } } }
internal void ExtendedSave_CardBeingLoaded(ChaFile file) { if (file != null && CurrentCardLoadTranslationMode != CardLoadTranslationMode.Disabled) { file.StartMonitoredCoroutine(CardNameManager.TranslateCardNames(file)); } }
public static void SaveFileHook(ChaFile __instance, bool __result, BinaryWriter bw, bool savePng) { if (!__result) { return; } ExtensibleSaveFormat.writeEvent(__instance); Dictionary <string, PluginData> extendedData = ExtensibleSaveFormat.GetAllExtendedData(__instance); if (extendedData == null) { return; } byte[] bytes = MessagePackSerializer.Serialize(extendedData); bw.Write(Marker); bw.Write(Version); foreach (KeyValuePair <string, PluginData> kv in extendedData) { PluginData dict = kv.Value as PluginData; } bw.Write((int)bytes.Length); bw.Write(bytes); }
/// <summary> /// Card saving /// </summary> private void ExtendedCardSave(ChaFile file) { PluginData ExtendedData = ExtendedSave.GetExtendedDataById(file, "KK_FutaMod"); if (ExtendedData != null && ExtendedData.data.ContainsKey("Futa")) { if (Singleton <CustomBase> .IsInstance() && Singleton <CustomBase> .Instance.chaCtrl != null) { //Saving card from chara maker, get the status from the character ExtendedData.data["Futa"] = file.status.visibleSonAlways; ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData); } else { //Not in chara maker, keep the existing extended data ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData); } } else { if (Singleton <CustomBase> .IsInstance() && Singleton <CustomBase> .Instance.chaCtrl != null) { //Saving a character in chara maker that doesn't have extended data ExtendedData = new PluginData(); ExtendedData.data = new Dictionary <string, object> { { "Futa", file.status.visibleSonAlways } }; ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData); } } }
public static bool Prefix_ChaFile_SaveFile(ChaFile __instance, BinaryWriter bw, bool savePng, int lang) { if (playerController == null) { return(true); } if (PlayerDeath.Value == DeathType.PermaDeath && playerController.ChaFileControl == __instance) { if (playerController["health"] == 0) { return(false); } } else if (AgentDeath.Value == DeathType.PermaDeath) { foreach (var controller in agentControllers.Where(n => n != null)) { if (controller.ChaFileControl == __instance && controller["health"] == 0) { return(false); } } } return(true); }
private static void ChaFileSaveFileHook(ChaFile file, BlockHeader header, ref long[] array3) { Dictionary <string, PluginData> extendedData = GetAllExtendedData(file); if (extendedData == null) { currentlySavingData = null; return; } currentlySavingData = MessagePackSerializer.Serialize(extendedData); //get offset long offset = array3.Sum(); long length = currentlySavingData.LongLength; //insert our custom data length at the end Array.Resize(ref array3, array3.Length + 1); array3[array3.Length - 1] = length; //add info about our data to the block header BlockHeader.Info info = new BlockHeader.Info { name = Marker, version = DataVersion.ToString(), pos = offset, size = length }; header.lstInfo.Add(info); }
private static void ChaFileLoadFileHook(ChaFile file, BlockHeader header, BinaryReader reader) { var info = header.SearchInfo(Marker); if (info != null && info.version == DataVersion.ToString()) { long originalPosition = reader.BaseStream.Position; long basePosition = originalPosition - header.lstInfo.Sum(x => x.size); reader.BaseStream.Position = basePosition + info.pos; byte[] data = reader.ReadBytes((int)info.size); reader.BaseStream.Position = originalPosition; cardReadEventCalled = true; try { var dictionary = MessagePackSerializer.Deserialize <Dictionary <string, PluginData> >(data); internalCharaDictionary.Set(file, dictionary); } catch (Exception e) { internalCharaDictionary.Set(file, new Dictionary <string, PluginData>()); Logger.LogWarning($"Invalid or corrupted extended data in card \"{file.charaFileName}\" - {e.Message}"); } CardReadEvent(file); } else { internalCharaDictionary.Set(file, new Dictionary <string, PluginData>()); } }
/// <summary> /// Method to load data from KKATData. /// </summary> /// <param key>Key to load</param> internal static void LoadHairColor(string key = null) { if (!_toggleHaircolor.Value) { return; } if (KK_Archetypes.Data.HaircolorDict.Count == 0) { return; } ChaFileHair add; if (key == null) { add = Utilities.GetRandomValue(KK_Archetypes.Data.HaircolorDict); } else { add = KK_Archetypes.Data.HaircolorDict[key]; } ChaFile file = MakerAPI.GetCharacterControl().chaFile; ChaFileHair curr = file.custom.hair; HairColorWriter(add, curr); file.custom.face.eyebrowColor = Utilities.GetSlightlyDarkerColor(curr.parts[0].baseColor); file.custom.body.underhairColor = file.custom.face.eyebrowColor; }
internal IEnumerator RegisterReplacements(ChaFile file) { if (file == null) { yield break; } //Logger.LogDebug($"RegisterReplacements {file} {file.parameter.fullname}"); if (!RegistrationGameModes.Contains(CurrentGameMode)) { yield break; } yield return(CardNameManager.WaitOnCard(file)); if (RegistrationManager.IsTracked(file)) { if (!RegistrationManager.HaveNamesChanged(file)) { yield break; } RegistrationManager.Untrack(file); } RegistrationManager.Track(file); }
public static void ChaFileSaveFilePostHook(ChaFile __instance, bool __result, BinaryWriter bw, bool savePng) { Logger.Log(LogLevel.Debug, $"Reloading card [{__instance.charaFileName}]"); var extData = ExtendedSave.GetExtendedDataById(__instance, UniversalAutoResolver.UARExtID); var tmpExtInfo = (List <byte[]>)extData.data["info"]; var extInfo = tmpExtInfo.Select(ResolveInfo.Unserialize).ToList(); 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 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.ToString()}"); if (extResolve != null) { kv.Value.SetMethod(structure, extResolve.LocalSlot); Logger.Log(LogLevel.Debug, $"[UAR] Resetting {extResolve.GUID}:{extResolve.Property} to internal slot {extResolve.LocalSlot}"); } } } IterateCardPrefixes(ResetStructResolveStructure, __instance, extInfo); }
public static void ChaFileLoadFileHook(ChaFile file, BlockHeader header, BinaryReader reader) { var info = header.SearchInfo(Marker); if (info != null && info.version == Version.ToString()) { long originalPosition = reader.BaseStream.Position; long basePosition = originalPosition - header.lstInfo.Sum(x => x.size); reader.BaseStream.Position = basePosition + info.pos; byte[] data = reader.ReadBytes((int)info.size); reader.BaseStream.Position = originalPosition; var dictionary = MessagePackSerializer.Deserialize <Dictionary <string, PluginData> >(data); cardReadEventCalled = true; ExtendedSave.internalCharaDictionary.Set(file, dictionary); ExtendedSave.cardReadEvent(file); } else { ExtendedSave.internalCharaDictionary.Set(file, new Dictionary <string, PluginData>()); } }
public override void OnCardLoad(ChaFile f, BlockHeader bh, bool nopng, bool nostatus) { try { TryImport(f.dict.Get <KKEx>("kkex"), f.dict.Get <FakeID.GuidMap>("guidmap")); } catch { }; }
public bool CardNeedsTranslation(ChaFile file) { var sex = file.GetSex(); return(file.EnumerateNames().Any(name => StringUtils.ContainsJapaneseChar(name.Value) && !NoTranslate[new NameScope(sex, file.GetNameType(name.Key))].Contains(name.Value))); }
public bool IsTracked(ChaFile chaFile) { //return trackedRegistrationIDs.Contains(chaFile.GetRegistrationID()); lock (_lock) { return(_regIDtoCardMap.ContainsKey(chaFile.GetRegistrationID())); } }
public override void OnCardSave(ChaFile f, BinaryWriter w, List <object> blocks, bool nopng) { blocks.Add(f.dict.Get <KKEx>("kkex")); try { Ext.Raise <ExtendedSave>(null, "CardBeingSaved", f); } catch { }; }
public static void CopyChaFile(ChaFile dst, ChaFile src) { PluginData ExtendedData = ExtendedSave.GetExtendedDataById(src, "KK_FutaMod"); if (ExtendedData != null && ExtendedData.data.ContainsKey("Futa")) { ExtendedSave.SetExtendedDataById(dst, "KK_FutaMod", ExtendedData); } }
public static Coroutine StartMonitoredCoroutine(this ChaFile chaFile, IEnumerator enumerator) { ChaControl chaControl = null; chaFile.SafeProc(cf => chaControl = cf.GetChaControl()); return(chaControl != null ? chaControl.StartMonitoredCoroutine(enumerator) : TranslationHelper.Instance.StartCoroutine(enumerator)); }
public static void ChaFileSaveFilePostHook(ChaFile __instance, bool __result, BinaryWriter bw, bool savePng) { if (!__result || currentlySavingData == null) { return; } bw.Write(currentlySavingData); }
private static void CardBeingSaved(ChaFile file) { var toRemove = ListInfoNameTranslatedMap.Keys.Where(k => System.IO.Path.GetFileName(k) == file.charaFileName).ToList(); foreach (var path in toRemove) { ListInfoNameTranslatedMap.Remove(path); } }
public static PluginData GetExtendedDataById(ChaFile file, string id) { PluginData extendedSection = null; if (internalDictionary.Get(file).TryGetValue(id, out extendedSection)) { return(extendedSection); } return(null); }
internal static void ChaFile_SaveFile_Postfix(ChaFile __instance) { // ReSharper disable once UseNullPropagation if (__instance == null) { return; } __instance.GetTranslationHelperController() .SafeProcObject(c => c.OnCardSaveComplete(KoikatuAPI.GetCurrentGameMode())); }
void Start() { //加载资源 foreach (Sprite s in heroSprites) { GameObject go = new GameObject(); go.name = s.name.Substring(0, s.name.IndexOf('.')); SpriteRenderer sr = go.AddComponent<SpriteRenderer>(); sr.sprite = s; go.transform.parent = this.transform; //存进字典方便查找 spriteDic[go.name] = go; //加载旋转信息 SpriteInfo si = go.AddComponent<SpriteInfo>(); List<SpriteData> sd = PListFile.Parse(Application.dataPath + "/" + resourceFolder + "plist"); for (int i = 0; i < sd.Count; i++) { if (sd[i].name.Equals(s.name)) if (sd[i].rotated == true) { si.needRotated = true; } } //load animation file string path = Application.dataPath + "/" + resourceFolder + "cha"; ChaLoader cl = new ChaLoader(); animation = cl.Parse(path); //组织animation到Dic,方便索引 dictionary for fast search for (int i = 0; i < animation.animationList.Count; i++) { animations[animation.animationList[i].name] = animation.animationList[i]; } } }
public ChaFile Parse(string path) { FileInfo sourceFile = null; sourceFile = new FileInfo(path); if (sourceFile == null || !sourceFile.Exists) { Debug.LogError("File not exist or error:" + path); return null; } BinaryReader reader = new BinaryReader(sourceFile.OpenRead()); ChaFile cf = new ChaFile(); #region Read ChaFile //1.4 bytes,length of the name int cfNameLength = reader.ReadInt32(); //2.name char[] name = new char[cfNameLength]; reader.Read(name, 0, cfNameLength); cf.name = new string(name); //3.bone count int cfBoneNumber = reader.ReadInt32(); //4.all bone infomation for (int i = 0; i < cfBoneNumber; i++) { BoneS bs = new BoneS(); #region Read BoneS //4.1 bone name Length int boneNameLength = reader.ReadInt32(); #region 其他方法 // reader.Read(boneNameLength, 0, 4); // int nameLength = boneNameLength + (boneNameLength[1] << 8) + (boneNameLength[2] << 16) + (boneNameLength[3] << 24); #endregion bs.nameLength = boneNameLength; //bone name char[] boneName = new char[boneNameLength]; reader.Read(boneName, 0, boneNameLength); bs.name = new string(boneName); //texture name length int textureNameLength = reader.ReadInt32(); bs.textureNameLength = textureNameLength; //texture name char[] textureName = new char[textureNameLength]; reader.Read(textureName, 0, textureNameLength); bs.textureName = new string(textureName); //bone id int id = reader.ReadInt32(); bs.index = id; //add cf.boneList.Add(bs); #endregion } int cfAniamtionNumber = reader.ReadInt32(); for (int i = 0; i < cfAniamtionNumber; i++) { sAnimation sa = new sAnimation(); #region Read sAnimation cf.animationList.Add(sa); //name length int nameLength = reader.ReadInt32(); //name char[] animationName = new char[nameLength]; reader.Read(animationName, 0, nameLength); sa.name = new string(animationName); //4bytes unknovn.0Xc0 byte[] c = reader.ReadBytes(4); //frame count int frameCount = reader.ReadInt32(); //frame for (int index = 0; index < frameCount; index++) { frame f = new frame(); #region Read frame sa.frames.Add(f); //frame type int ft = reader.ReadInt32(); f.type = ft; #region 处理掉不需要的数据 if (ft == 1) { int ftTag = reader.ReadInt32(); int ftNameLength = reader.ReadInt32(); if (ft == 0) { byte[] ftName = reader.ReadBytes(4); } else { byte[] ftName = reader.ReadBytes(ftNameLength); } byte[] ftAudioInfo = reader.ReadBytes(32); if (ft == 1) { ftTag = reader.ReadInt32(); } } #endregion //bone data count int bc = reader.ReadInt32(); for (int j = 0; j < bc; j++) { boneData bd = new boneData(); #region Read boneData f.boneList.Add(bd); //bone index byte[] bIndex = reader.ReadBytes(2); bd.boneIndex = (short)(bIndex[0] + (bIndex[1] << 8)); //bone transparent bd.transparent = reader.ReadByte(); //bone data(float:6) bd.data[0] = reader.ReadSingle(); bd.data[1] = reader.ReadSingle(); bd.data[2] = reader.ReadSingle(); bd.data[3] = reader.ReadSingle(); bd.data[4] = reader.ReadSingle(); bd.data[5] = reader.ReadSingle(); //offset bd.data[1] *= -1.0f; bd.data[2] *= -1.0f; bd.data[4] *= 0.1f * 4f; bd.data[5] *= -0.1f * 4f; #endregion } #endregion } #endregion } #endregion return cf; }