using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
namespace NTERA.EmuEra.Game.EraEmu.Sub
{
//難読化用属性。enum.ToString()やenum.Parse()を行うなら(Exclude=true)にすること。
[Obfuscation(Exclude = false)]
internal enum EraDataState
{
OK = 0,//ロード可能
FILENOTFOUND = 1,//ファイルが存在せず
GAME_ERROR = 2,//ゲームが違う
VIRSION_ERROR = 3,//バージョンが違う
ETC_ERROR = 4//その他のエラー
}
internal sealed class EraDataResult
{
public EraDataState State = EraDataState.OK;
public string DataMes = "";
}
///
/// セーブデータ読み取り
///
internal sealed class EraDataReader : IDisposable
{
//public EraDataReader(string filepath)
//{
// file = new FileStream(filepath, FileMode.Open, FileAccess.Read);
// reader = new StreamReader(file, Config.Encode);
//}
public EraDataReader(FileStream file)
{
this.file = file;
file.Seek(0, SeekOrigin.Begin);
reader = new StreamReader(file, Config.Config.Encode);
}
FileStream file;
StreamReader reader;
public const string FINISHER = "__FINISHED";
public const string EMU_1700_START = "__EMUERA_STRAT__";
public const string EMU_1708_START = "__EMUERA_1708_STRAT__";
public const string EMU_1729_START = "__EMUERA_1729_STRAT__";
public const string EMU_1803_START = "__EMUERA_1803_STRAT__";
public const string EMU_1808_START = "__EMUERA_1808_STRAT__";
public const string EMU_SEPARATOR = "__EMU_SEPARATOR__";
#region eramaker
public string ReadString()
{
if (reader == null)
throw new FileEE("無効なストリームです");
string str = reader.ReadLine();
if (str == null)
throw new FileEE("読み取るべき文字列がありません");
return str;
}
public Int64 ReadInt64()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Int64 ret = 0;
string str = reader.ReadLine();
if (str == null)
throw new FileEE("読み取るべき数値がありません");
if (!Int64.TryParse(str, out ret))
throw new FileEE("数値として認識できません");
return ret;
}
public void ReadInt64Array(Int64[] array)
{
if (reader == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int i = -1;
string str = null;
Int64 integer = 0;
i = -1;
while (true)
{
i++;
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
if (i >= array.Length)//配列を超えて保存されていても動じないで読み飛ばす。
continue;
if (!Int64.TryParse(str, out integer))
throw new FileEE("数値として認識できません");
array[i] = integer;
}
for (; i < array.Length; i++)//保存されている値が無いなら0に初期化
array[i] = 0;
}
public void ReadStringArray(string[] array)
{
if (reader == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int i = -1;
string str = null;
i = -1;
while (true)
{
i++;
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
if (i >= array.Length)//配列を超えて保存されていても動じないで読み飛ばす。
continue;
array[i] = str;
}
for (; i < array.Length; i++)//保存されている値が無いなら""に初期化
array[i] = "";
}
#endregion
#region Emuera
int emu_version = -1;
public int DataVersion => emu_version;
public bool SeekEmuStart()
{
if (reader == null)
throw new FileEE("無効なストリームです");
if (reader.EndOfStream)
return false;
while (true)
{
string str = reader.ReadLine();
if (str == null)
return false;
if (str.Equals(EMU_1700_START, StringComparison.Ordinal))
{
emu_version = 1700;
return true;
}
if (str.Equals(EMU_1708_START, StringComparison.Ordinal))
{
emu_version = 1708;
return true;
}
if (str.Equals(EMU_1729_START, StringComparison.Ordinal))
{
emu_version = 1729;
return true;
}
if (str.Equals(EMU_1803_START, StringComparison.Ordinal))
{
emu_version = 1803;
return true;
}
if (str.Equals(EMU_1808_START, StringComparison.Ordinal))
{
emu_version = 1808;
return true;
}
}
}
public Dictionary ReadStringExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary strList = new Dictionary();
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
int index = str.IndexOf(':');
if (index < 0)
throw new FileEE("セーブデータの形式が不正です");
string key = str.Substring(0, index);
string value = str.Substring(index + 1, str.Length - index - 1);
if (!strList.ContainsKey(key))
strList.Add(key, value);
}
return strList;
}
public Dictionary ReadInt64Extended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary intList = new Dictionary();
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
int index = str.IndexOf(':');
if (index < 0)
throw new FileEE("セーブデータの形式が不正です");
string key = str.Substring(0, index);
string valueStr = str.Substring(index + 1, str.Length - index - 1);
Int64 value = 0;
if (!Int64.TryParse(valueStr, out value))
throw new FileEE("数値として認識できません");
if (!intList.ContainsKey(key))
intList.Add(key, value);
}
return intList;
}
public Dictionary> ReadInt64ArrayExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary> ret = new Dictionary>();
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
string key = str;
List valueList = new List();
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
Int64 value = 0;
if (!Int64.TryParse(str, out value))
throw new FileEE("数値として認識できません");
valueList.Add(value);
}
if (!ret.ContainsKey(key))
ret.Add(key, valueList);
}
return ret;
}
public Dictionary> ReadStringArrayExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary> ret = new Dictionary>();
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
string key = str;
List valueList = new List();
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
valueList.Add(str);
}
if (!ret.ContainsKey(key))
ret.Add(key, valueList);
}
return ret;
}
public Dictionary> ReadInt64Array2DExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary> ret = new Dictionary>();
if (emu_version < 1708)
return ret;
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
string key = str;
List valueList = new List();
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
if (str.Length == 0)
{
valueList.Add(new Int64[0]);
continue;
}
string[] tokens = str.Split(',');
Int64[] intTokens = new Int64[tokens.Length];
for (int x = 0; x < tokens.Length; x++)
if (!Int64.TryParse(tokens[x], out intTokens[x]))
throw new FileEE(tokens[x] + "は数値として認識できません");
valueList.Add(intTokens);
}
if (!ret.ContainsKey(key))
ret.Add(key, valueList);
}
return ret;
}
public Dictionary> ReadStringArray2DExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary> ret = new Dictionary>();
if (emu_version < 1708)
return ret;
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
throw new FileEE("StringArray2Dのロードには対応していません");
}
return ret;
}
public Dictionary>> ReadInt64Array3DExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary>> ret = new Dictionary>>();
if (emu_version < 1729)
return ret;
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
string key = str;
List> valueList = new List>();
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
break;
if (str.Contains("{"))
{
List tokenList = new List();
while (true)
{
str = reader.ReadLine();
if (str == "}")
break;
if (str.Length == 0)
{
tokenList.Add(new Int64[0]);
continue;
}
string[] tokens = str.Split(',');
Int64[] intTokens = new Int64[tokens.Length];
for (int x = 0; x < tokens.Length; x++)
if (!Int64.TryParse(tokens[x], out intTokens[x]))
throw new FileEE(tokens[x] + "は数値として認識できません");
tokenList.Add(intTokens);
}
valueList.Add(tokenList);
}
}
if (!ret.ContainsKey(key))
ret.Add(key, valueList);
}
return ret;
}
public Dictionary>> ReadStringArray3DExtended()
{
if (reader == null)
throw new FileEE("無効なストリームです");
Dictionary>> ret = new Dictionary>>();
if (emu_version < 1729)
return ret;
string str = null;
while (true)
{
str = reader.ReadLine();
if (str == null)
throw new FileEE("予期しないセーブデータの終端です");
if (str.Equals(FINISHER, StringComparison.Ordinal))
throw new FileEE("セーブデータの形式が不正です");
if (str.Equals(EMU_SEPARATOR, StringComparison.Ordinal))
break;
throw new FileEE("StringArray2Dのロードには対応していません");
}
return ret;
}
#endregion
#region IDisposable メンバ
public void Dispose()
{
if (reader != null)
reader.Close();
else if (file != null)
file.Close();
file = null;
reader = null;
}
#endregion
public void Close()
{
Dispose();
}
}
///
/// セーブデータ書き込み
///
internal sealed class EraDataWriter : IDisposable
{
//public EraDataWriter(string filepath)
//{
// FileStream file = new FileStream(filepath, FileMode.Create, FileAccess.Write);
// writer = new StreamWriter(file, Config.SaveEncode);
// //writer = new StreamWriter(filepath, false, Config.SaveEncode);
//}
public EraDataWriter(FileStream file)
{
this.file = file;
writer = new StreamWriter(file, Config.Config.SaveEncode);
}
public const string FINISHER = EraDataReader.FINISHER;
public const string EMU_START = EraDataReader.EMU_1808_START;
public const string EMU_SEPARATOR = EraDataReader.EMU_SEPARATOR;
FileStream file;
StreamWriter writer;
#region eramaker
public void Write(Int64 integer)
{
if (writer == null)
throw new FileEE("無効なストリームです");
writer.WriteLine(integer.ToString());
}
public void Write(string str)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (str == null)
writer.WriteLine("");
else
writer.WriteLine(str);
}
public void Write(Int64[] array)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int count = -1;
for (int i = 0; i < array.Length; i++)
if (array[i] != 0)
count = i;
count++;
for (int i = 0; i < count; i++)
writer.WriteLine(array[i].ToString());
writer.WriteLine(FINISHER);
}
public void Write(string[] array)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int count = -1;
for (int i = 0; i < array.Length; i++)
if (!string.IsNullOrEmpty(array[i]))
count = i;
count++;
for (int i = 0; i < count; i++)
{
if (array[i] == null)
writer.WriteLine("");
else
writer.WriteLine(array[i]);
}
writer.WriteLine(FINISHER);
}
#endregion
#region Emuera
public void EmuStart()
{
if (writer == null)
throw new FileEE("無効なストリームです");
writer.WriteLine(EMU_START);
}
public void EmuSeparete()
{
if (writer == null)
throw new FileEE("無効なストリームです");
writer.WriteLine(EMU_SEPARATOR);
}
public void WriteExtended(string key, Int64 value)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (value == 0)
return;
writer.WriteLine("{0}:{1}", key, value);
}
public void WriteExtended(string key, string value)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (string.IsNullOrEmpty(value))
return;
writer.WriteLine("{0}:{1}", key, value);
}
public void WriteExtended(string key, Int64[] array)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int count = -1;
for (int i = 0; i < array.Length; i++)
if (array[i] != 0)
count = i;
count++;
if (count == 0)
return;
writer.WriteLine(key);
for (int i = 0; i < count; i++)
writer.WriteLine(array[i].ToString());
writer.WriteLine(FINISHER);
}
public void WriteExtended(string key, string[] array)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array == null)
throw new FileEE("無効な配列が渡されました");
int count = -1;
for (int i = 0; i < array.Length; i++)
if (!string.IsNullOrEmpty(array[i]))
count = i;
count++;
if (count == 0)
return;
writer.WriteLine(key);
for (int i = 0; i < count; i++)
{
if (array[i] == null)
writer.WriteLine("");
else
writer.WriteLine(array[i]);
}
writer.WriteLine(FINISHER);
}
public void WriteExtended(string key, Int64[,] array2D)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array2D == null)
throw new FileEE("無効な配列が渡されました");
int countX = 0;
int length0 = array2D.GetLength(0);
int length1 = array2D.GetLength(1);
int[] countY = new int[length0];
for (int x = 0; x < length0; x++)
{
for (int y = 0; y < length1; y++)
{
if (array2D[x, y] != 0)
{
countX = x + 1;
countY[x] = y + 1;
}
}
}
if (countX == 0)
return;
writer.WriteLine(key);
for (int x = 0; x < countX; x++)
{
if (countY[x] == 0)
{
writer.WriteLine("");
continue;
}
StringBuilder builder = new StringBuilder("");
for (int y = 0; y < countY[x]; y++)
{
builder.Append(array2D[x, y].ToString());
if (y != countY[x] - 1)
builder.Append(",");
}
writer.WriteLine(builder.ToString());
}
writer.WriteLine(FINISHER);
}
public void WriteExtended(string key, string[,] array2D)
{
throw new NotImplementedException("まだ実装してないよ");
}
public void WriteExtended(string key, Int64[, ,] array3D)
{
if (writer == null)
throw new FileEE("無効なストリームです");
if (array3D == null)
throw new FileEE("無効な配列が渡されました");
int countX = 0;
int length0 = array3D.GetLength(0);
int length1 = array3D.GetLength(1);
int length2 = array3D.GetLength(2);
int[] countY = new int[length0];
int[,] countZ = new int[length0, length1];
for (int x = 0; x < length0; x++)
{
for (int y = 0; y < length1; y++)
{
for (int z = 0; z < length2; z++)
{
if (array3D[x, y, z] != 0)
{
countX = x + 1;
countY[x] = y + 1;
countZ[x, y] = z + 1;
}
}
}
}
if (countX == 0)
return;
writer.WriteLine(key);
for (int x = 0; x < countX; x++)
{
writer.WriteLine(x + "{");
if (countY[x] == 0)
{
writer.WriteLine("}");
continue;
}
for (int y = 0; y < countY[x]; y++)
{
StringBuilder builder = new StringBuilder("");
if (countZ[x, y] == 0)
{
writer.WriteLine("");
continue;
}
for (int z = 0; z < countZ[x, y]; z++)
{
builder.Append(array3D[x, y, z].ToString());
if (z != countZ[x, y] - 1)
builder.Append(",");
}
writer.WriteLine(builder.ToString());
}
writer.WriteLine("}");
}
writer.WriteLine(FINISHER);
}
public void WriteExtended(string key, string[, ,] array2D)
{
throw new NotImplementedException("まだ実装してないよ");
}
#endregion
#region IDisposable メンバ
public void Dispose()
{
if (writer != null)
writer.Close();
else if (file != null)
file.Close();
writer = null;
file = null;
}
#endregion
public void Close()
{
Dispose();
}
}
}