// only works for PW !!! public eList[] LoadPW(string elFile, string cfgFile, BackgroundWorker worker) { eList[] Li = new eList[0]; // open the element file FileStream fs = File.OpenRead(elFile); BinaryReader br = new BinaryReader(fs); Version = br.ReadInt16(); Signature = br.ReadInt16(); string myConfig; if (cfgFile == null) { myConfig = "*_*_v" + Version; } else { myConfig = cfgFile; } // check if a corresponding configuration file exists string[] configFiles = Directory.GetFiles(Environment.CurrentDirectory + "\\configs", myConfig + ".cfg"); // Application.StartupPath if (configFiles.Length > 0) { // configure an eList array with the configuration file ConfigFile = configFiles[0]; Li = loadConfiguration(ConfigFile); // read the element file for (int l = 0; l < Li.Length; l++) { if (worker != null) { int percentLoaded = (int)Math.Round((((double)l + 1) / (double)Li.Length) * 100.0); worker.ReportProgress(percentLoaded, new object[] { l, Li.Length }); } // read offset if (Li[l].listOffset != null) // if (Li[l].listOffset) { // offset > 0 if (Li[l].listOffset.Length > 0) { Li[l].listOffset = br.ReadBytes(Li[l].listOffset.Length); } } // autodetect offset (for list 20 & 100) else { if (l == 20) { byte[] head = br.ReadBytes(4); byte[] count = br.ReadBytes(4); byte[] body = br.ReadBytes(BitConverter.ToInt32(count, 0)); byte[] tail = br.ReadBytes(4); Li[l].listOffset = new byte[head.Length + count.Length + body.Length + tail.Length]; Array.Copy(head, 0, Li[l].listOffset, 0, head.Length); Array.Copy(count, 0, Li[l].listOffset, 4, count.Length); Array.Copy(body, 0, Li[l].listOffset, 8, body.Length); Array.Copy(tail, 0, Li[l].listOffset, 8 + body.Length, tail.Length); } if (l == 100) { byte[] head = br.ReadBytes(4); byte[] count = br.ReadBytes(4); byte[] body = br.ReadBytes(BitConverter.ToInt32(count, 0)); Li[l].listOffset = new byte[head.Length + count.Length + body.Length]; Array.Copy(head, 0, Li[l].listOffset, 0, head.Length); Array.Copy(count, 0, Li[l].listOffset, 4, count.Length); Array.Copy(body, 0, Li[l].listOffset, 8, body.Length); } } // read conversation list if (l == ConversationListIndex && ConversationListIndex > -1) { // Auto detect only works for Perfect World elements.data !!! if (Li[l].elementTypes[0].Contains("AUTO")) { if (SW != 1) { byte[] pattern = (Encoding.GetEncoding("GBK")).GetBytes("facedata\\"); long sourcePosition = br.BaseStream.Position; // Получаем позицию чтения листа int listLength = -72 - pattern.Length; bool run = true; while (run) { run = false; for (int i = 0; i < pattern.Length; i++) { listLength++; if (br.ReadByte() != pattern[i]) { run = true; break; } } } br.BaseStream.Position = sourcePosition; Li[l].elementTypes[0] = "byte:" + listLength; Li[l].elementValues = new object[1][]; Li[l].elementValues[0] = new object[Li[l].elementTypes.Length]; Li[l].elementValues[0][0] = readValue(br, Li[l].elementTypes[0]); } if (SW == 1) { long MainPosition = br.BaseStream.Position; int Talks = br.ReadInt32(); for (int e = 0; e < Talks; e++) { uint ID = (uint)readValue(br, "uint32"); byte[] Name = (byte[])readValue(br, "wstring:128"); int NUM_WINDOWS = (int)readValue(br, "int32"); for (int j = 0; j < NUM_WINDOWS; j++) { uint ID_WINDOW = (uint)readValue(br, "uint32"); int ID_WINDOW_PARENT = (int)readValue(br, "int32"); uint TALK_TEXT_LEN = (uint)readValue(br, "uint32"); byte[] TALK_TEXT = (byte[])readValue(br, ("wstring:" + TALK_TEXT_LEN * 2)); int NUM_OPTION = (int)readValue(br, "int32"); for (int k = 0; k < NUM_OPTION; k++) { int ID_OPTION = (int)readValue(br, "int32"); byte[] TEXT_OPTION = (byte[])readValue(br, "wstring:128"); uint PARAM_OPTION = (uint)readValue(br, "uint32"); } } int TALK_PROC_TYPE = (int)readValue(br, "int32"); uint ID_PATH = (uint)readValue(br, "uint32"); } int AfterTalkLen = br.ReadInt32(); byte[] AfterTalk = br.ReadBytes(AfterTalkLen); if (AfterTalkLen != AfterTalk.Length) { MessageBox.Show("В данном Элике проблема с окончанием диалогов, \nпосле сохранения может быть не рабочим!"); } long listLength = fs.Position - MainPosition; br.BaseStream.Position = MainPosition; Li[l].elementTypes[0] = "byte:" + listLength; Li[l].elementValues = new object[1][]; Li[l].elementValues[0] = new object[Li[l].elementTypes.Length]; Li[l].elementValues[0][0] = readValue(br, Li[l].elementTypes[0]); } } } // read lists else { try { Li[l].elementValues = new object[br.ReadInt32()][]; } catch { return(Li); } ushort[] FullSize = new ushort[Li[l].elementValues.Length]; uint[] id = new uint[Li[l].elementValues.Length]; uint sum_str_len; long el_size = 0; MemoryStream fsList = new MemoryStream(); BinaryWriter bwList = new BinaryWriter(fsList); if (SW == 1 && l != ConversationListIndex) { ushort nameSize; for (int f = 0; f < Li[l].elementValues.Length; f++) { id[f] = br.ReadUInt32(); nameSize = br.ReadUInt16(); FullSize[f] = nameSize; } if (Li[l].elementValues.Length > 0) { sum_str_len = br.ReadUInt32(); for (int i = 0; i < Li[l].elementValues.Length; i++) { bwList.Write(UnpackMPPC(br.ReadBytes(FullSize[i]))); if (i == 0) { el_size = fsList.Position; } } } } fsList.Position = 0; BinaryReader brSW = new BinaryReader(fsList); // go through all elements of a list // sdfsdf asdl;zcmv,bl for (int e = 0; e < Li[l].elementValues.Length; e++) { Li[l].elementValues[e] = new object[Li[l].elementTypes.Length]; // go through all fields of an element for (int f = 0; f < Li[l].elementValues[e].Length; f++) { if (SW == 1) { Li[l].elementValues[e][f] = readValue(brSW, Li[l].elementTypes[f]); if (e == 0 && f == Li[l].elementValues[e].Length - 1 && fsList.Position != el_size) { MessageBox.Show($"Лист {l}({Li[l].listName})\nТекущий размер: {fsList.Position} байт\nИсходный размер: {el_size} байт\nКол-во предметов: {Li[l].elementValues.Length}"); } } if (SW != 1) { Li[l].elementValues[e][f] = readValue(br, Li[l].elementTypes[f]); } } } brSW.Close(); bwList.Close(); fsList.Flush(); fsList.Close(); } } } else { MessageBox.Show("No corressponding configuration file found!\nVersion: " + Version + "\nPattern: " + "configs\\PW_*_v" + Version + ".cfg"); } br.Close(); fs.Close(); return(Li); }
// add all new elements into the elementValues public ArrayList JoinElements(eList newList, int listID, bool addNew, bool backupNew, bool replaceChanged, bool backupChanged, bool removeMissing, bool backupMissing, string dirBackupNew, string dirBackupChanged, string dirBackupMissing) { object[][] newElementValues = newList.elementValues; string[] newElementTypes = newList.elementTypes; ArrayList report = new ArrayList(); bool exists; // check which elements are missing (removed) for (int n = 0; n < elementValues.Length; n++) { //Application.DoEvents(); exists = false; for (int e = 0; e < newElementValues.Length; e++) { if (GetValue(n, 0) == newList.GetValue(e, 0)) { exists = true; } } if (!exists) { if (dirBackupMissing != null && Directory.Exists(dirBackupMissing)) { ExportItem(dirBackupMissing + "\\List_" + listID.ToString() + "_Item_" + GetValue(n, 0) + ".txt", n); } if (removeMissing) { report.Add("- MISSING ITEM (*removed): " + ((int)elementValues[n][0]).ToString()); RemoveItem(n); n--; } else { report.Add("- MISSING ITEM (*not removed): " + ((int)elementValues[n][0]).ToString()); } } } for (int e = 0; e < newElementValues.Length; e++) { //Application.DoEvents(); // check if the element with this id already exists exists = false; for (int n = 0; n < elementValues.Length; n++) { if (GetValue(n, 0) == newList.GetValue(e, 0)) { exists = true; // check if this item is different if (elementValues[n].Length != newList.elementValues[e].Length) { // invalid amount of values !!! report.Add("<> DIFFERENT ITEM (*not replaced, invalid amount of values): " + GetValue(n, 0)); } else { // compare all values of current element for (int i = 0; i < elementValues[n].Length; i++) { if (GetValue(n, i) != newList.GetValue(e, i)) { if (backupChanged && Directory.Exists(dirBackupChanged)) { ExportItem(dirBackupChanged + "\\List_" + listID.ToString() + "_Item_" + GetValue(n, 0) + ".txt", n); } if (replaceChanged) { report.Add("<> DIFFERENT ITEM (*replaced): " + GetValue(n, 0)); elementValues[n] = newList.elementValues[e]; } else { report.Add("<> DIFFERENT ITEM (*not replaced): " + GetValue(n, 0)); } break; } } } break; } } if (!exists) { if (backupNew && Directory.Exists(dirBackupNew)) { newList.ExportItem(dirBackupNew + "\\List_" + listID.ToString() + "_Item_" + newList.GetValue(e, 0) + ".txt", e); } if (addNew) { AddItem(newElementValues[e]); report.Add("+ NEW ITEM (*added): " + GetValue(elementValues.Length - 1, 0)); } else { report.Add("+ NEW ITEM (*not added): " + GetValue(elementValues.Length - 1, 0)); } } } return(report); }